bulma-turbo-themes 0.8.1 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/README.md +86 -25
- data/_layouts/default.html +158 -51
- data/assets/css/custom.css +30 -0
- data/assets/css/themes/base.css +2 -0
- data/assets/css/themes/bulma-dark.css +1 -96
- data/assets/css/themes/bulma-light.css +1 -96
- data/assets/css/themes/catppuccin-frappe.css +1 -99
- data/assets/css/themes/catppuccin-latte.css +1 -99
- data/assets/css/themes/catppuccin-macchiato.css +1 -99
- data/assets/css/themes/catppuccin-mocha.css +1 -99
- data/assets/css/themes/critical.css +1 -0
- data/assets/css/themes/dracula.css +1 -212
- data/assets/css/themes/github-dark.css +1 -103
- data/assets/css/themes/github-light.css +1 -103
- data/assets/img/bulma-logo-dark.webp +0 -0
- data/assets/img/bulma-logo.webp +0 -0
- data/assets/img/catppuccin-logo-latte.webp +0 -0
- data/assets/img/catppuccin-logo-macchiato.webp +0 -0
- data/assets/img/dracula-logo.webp +0 -0
- data/assets/img/github-logo-dark.webp +0 -0
- data/assets/img/github-logo-light.webp +0 -0
- data/assets/js/theme-selector.js +409 -211
- data/assets/js/theme-selector.min.js +1 -0
- data/lib/bulma-turbo-themes/version.rb +1 -1
- metadata +12 -3
- data/assets/css/themes/global.css +0 -460
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '0248000a92c219c5c6c2ef953937cfab605a3a95569eb5d4f1299f54ee454ffa'
|
|
4
|
+
data.tar.gz: 147029c64c3eb2921ea8479729f63c64cd781f0e75cc89cefdd549768fb5cf3c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3a6e217f897de1f3a5780b8381e2e47656cd12a43705a1f60aaa151cfda2bb480e64ff1ec3ba1846190c1d184db523bf4a45fc1754eacc0cf0db45268ca295f9
|
|
7
|
+
data.tar.gz: 919028a99aebd28eb2fec246aaed5b0d61df8eeaf73f946c92067ead7fb30f7cc727858340fb9006ccdae41b97ddf859c2bc03ab8f111040598eaf6b1d5ad115
|
data/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,24 @@ The format is based on Keep a Changelog and this project adheres to SemVer.
|
|
|
10
10
|
|
|
11
11
|
- TBD
|
|
12
12
|
|
|
13
|
+
## [0.9.0] - 2025-12-05
|
|
14
|
+
|
|
15
|
+
### ✨ Added
|
|
16
|
+
|
|
17
|
+
- migrate theme system to SASS (#143)
|
|
18
|
+
|
|
19
|
+
### 🐛 Fixed
|
|
20
|
+
|
|
21
|
+
- enable platformCommit for Renovate to sign commits
|
|
22
|
+
- correct JavaScript reference in gem layout (#106)
|
|
23
|
+
|
|
24
|
+
### 🔧 Changed
|
|
25
|
+
|
|
26
|
+
- add missing egress endpoints for Bun download (#149)
|
|
27
|
+
- update actions/setup-node digest to 633bb92 (#110)
|
|
28
|
+
- update peter-evans/create-pull-request digest to 271a8d0 (#109)
|
|
29
|
+
- update actions/setup-node digest to 2028fbc (#108)
|
|
30
|
+
|
|
13
31
|
## [0.8.1] - 2025-11-16
|
|
14
32
|
|
|
15
33
|
### 🐛 Fixed
|
data/README.md
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Modern, accessible theme packs and a drop-in theme selector for Bulma 1.x.
|
|
4
4
|
|
|
5
|
+
[](https://bun.sh/)
|
|
5
6
|
[](https://nodejs.org/)
|
|
6
7
|
[](https://codecov.io/gh/TurboCoder13/bulma-turbo-themes)
|
|
7
8
|
[](LICENSE)
|
|
@@ -23,6 +24,9 @@ Modern, accessible theme packs and a drop-in theme selector for Bulma 1.x.
|
|
|
23
24
|
- Accessible theme selector with keyboard and screen reader support
|
|
24
25
|
- Inline or link-based CSS delivery; CSP-friendly
|
|
25
26
|
- Tested with coverage, Lighthouse CI, and stylelint
|
|
27
|
+
- Advanced Bulma customization (breakpoints, spacing, shadows, mixins)
|
|
28
|
+
- Lazy-loaded themes with performance optimizations
|
|
29
|
+
- Full Bulma Sass variable integration
|
|
26
30
|
|
|
27
31
|
## Installation
|
|
28
32
|
|
|
@@ -49,11 +53,19 @@ bundle exec jekyll serve
|
|
|
49
53
|
|
|
50
54
|
Assets are automatically available - no copying needed!
|
|
51
55
|
|
|
56
|
+
### Advanced Theming
|
|
57
|
+
|
|
58
|
+
For advanced customization options including custom breakpoints, spacing, shadows, and Bulma mixins, see the [Advanced Theming Guide](docs/ADVANCED-THEMING.md).
|
|
59
|
+
|
|
52
60
|
### For Non-Jekyll Projects
|
|
53
61
|
|
|
54
|
-
Install via npm:
|
|
62
|
+
Install via Bun (recommended) or npm:
|
|
55
63
|
|
|
56
64
|
```bash
|
|
65
|
+
# Using Bun (recommended - 5-10x faster)
|
|
66
|
+
bun add @turbocoder13/bulma-turbo-themes
|
|
67
|
+
|
|
68
|
+
# Using npm
|
|
57
69
|
npm install @turbocoder13/bulma-turbo-themes
|
|
58
70
|
```
|
|
59
71
|
|
|
@@ -76,18 +88,24 @@ npm install @turbocoder13/bulma-turbo-themes
|
|
|
76
88
|
1. Add selector markup and initialize:
|
|
77
89
|
|
|
78
90
|
```html
|
|
79
|
-
<div class="
|
|
80
|
-
<
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
91
|
+
<div class="navbar-item has-dropdown is-hoverable">
|
|
92
|
+
<button
|
|
93
|
+
class="navbar-link"
|
|
94
|
+
id="theme-flavor-trigger"
|
|
95
|
+
type="button"
|
|
96
|
+
aria-haspopup="true"
|
|
97
|
+
aria-expanded="false"
|
|
98
|
+
aria-controls="theme-flavor-menu"
|
|
99
|
+
>
|
|
100
|
+
<span class="icon is-small" id="theme-flavor-trigger-icon"></span>
|
|
101
|
+
Theme
|
|
102
|
+
</button>
|
|
103
|
+
<div class="navbar-dropdown" id="theme-flavor-menu" aria-labelledby="theme-flavor-trigger">
|
|
87
104
|
<div class="dropdown-content" id="theme-flavor-items"></div>
|
|
88
105
|
</div>
|
|
89
|
-
|
|
90
|
-
|
|
106
|
+
</div>
|
|
107
|
+
<div class="select is-rounded is-small is-hidden">
|
|
108
|
+
<select id="theme-flavor-select" aria-label="Theme flavor" disabled></select>
|
|
91
109
|
</div>
|
|
92
110
|
```
|
|
93
111
|
|
|
@@ -110,18 +128,24 @@ npm install @turbocoder13/bulma-turbo-themes
|
|
|
110
128
|
1. Add selector markup and initialize:
|
|
111
129
|
|
|
112
130
|
```html
|
|
113
|
-
<div class="
|
|
114
|
-
<
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
131
|
+
<div class="navbar-item has-dropdown is-hoverable">
|
|
132
|
+
<button
|
|
133
|
+
class="navbar-link"
|
|
134
|
+
id="theme-flavor-trigger"
|
|
135
|
+
type="button"
|
|
136
|
+
aria-haspopup="true"
|
|
137
|
+
aria-expanded="false"
|
|
138
|
+
aria-controls="theme-flavor-menu"
|
|
139
|
+
>
|
|
140
|
+
<span class="icon is-small" id="theme-flavor-trigger-icon"></span>
|
|
141
|
+
Theme
|
|
142
|
+
</button>
|
|
143
|
+
<div class="navbar-dropdown" id="theme-flavor-menu" aria-labelledby="theme-flavor-trigger">
|
|
121
144
|
<div class="dropdown-content" id="theme-flavor-items"></div>
|
|
122
145
|
</div>
|
|
123
|
-
|
|
124
|
-
|
|
146
|
+
</div>
|
|
147
|
+
<div class="select is-rounded is-small is-hidden">
|
|
148
|
+
<select id="theme-flavor-select" aria-label="Theme flavor" disabled></select>
|
|
125
149
|
</div>
|
|
126
150
|
```
|
|
127
151
|
|
|
@@ -146,16 +170,53 @@ This project includes comprehensive testing:
|
|
|
146
170
|
Run tests:
|
|
147
171
|
|
|
148
172
|
```bash
|
|
173
|
+
# Using Bun (recommended)
|
|
174
|
+
bun run test # Unit tests with coverage
|
|
175
|
+
bun run e2e # All E2E tests
|
|
176
|
+
bun run e2e:smoke # Smoke tests only
|
|
177
|
+
bun run e2e:visual # Visual regression tests
|
|
178
|
+
bun run e2e:a11y # Accessibility tests
|
|
179
|
+
bun run e2e:ui # Playwright UI mode
|
|
180
|
+
|
|
181
|
+
# Using npm (also works)
|
|
149
182
|
npm test # Unit tests with coverage
|
|
150
183
|
npm run e2e # All E2E tests
|
|
151
|
-
npm run e2e:smoke # Smoke tests only
|
|
152
|
-
npm run e2e:visual # Visual regression tests
|
|
153
|
-
npm run e2e:a11y # Accessibility tests
|
|
154
|
-
npm run e2e:ui # Playwright UI mode
|
|
155
184
|
```
|
|
156
185
|
|
|
157
186
|
For detailed E2E testing documentation, see `docs/E2E-TESTING.md`.
|
|
158
187
|
|
|
188
|
+
## Development Setup
|
|
189
|
+
|
|
190
|
+
### Prerequisites
|
|
191
|
+
|
|
192
|
+
- **Bun** 1.3+ (recommended) - [Install Bun](https://bun.sh/docs/installation)
|
|
193
|
+
- **Node.js** 22+ (alternative)
|
|
194
|
+
- **Ruby** 3.3+ with Bundler (for Jekyll demo site)
|
|
195
|
+
|
|
196
|
+
### Quick Start
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
# Clone and install
|
|
200
|
+
git clone https://github.com/TurboCoder13/bulma-turbo-themes.git
|
|
201
|
+
cd bulma-turbo-themes
|
|
202
|
+
bun install
|
|
203
|
+
bundle install
|
|
204
|
+
|
|
205
|
+
# Build and serve
|
|
206
|
+
bun run build
|
|
207
|
+
bun run build:themes
|
|
208
|
+
bun run serve
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Why Bun?
|
|
212
|
+
|
|
213
|
+
This project uses [Bun](https://bun.sh/) as its primary JavaScript runtime for:
|
|
214
|
+
|
|
215
|
+
- **5-10x faster** package installation
|
|
216
|
+
- **10x faster** script startup time
|
|
217
|
+
- **~40% reduction** in CI build times
|
|
218
|
+
- Full npm compatibility (works with all existing packages)
|
|
219
|
+
|
|
159
220
|
## Documentation
|
|
160
221
|
|
|
161
222
|
- Code of Conduct: see `CODE_OF_CONDUCT.md`
|
data/_layouts/default.html
CHANGED
|
@@ -8,15 +8,108 @@
|
|
|
8
8
|
data-theme-label="{{ site.data.i18n.en.theme_label }}"
|
|
9
9
|
data-current-theme-title-template="{{ site.data.i18n.en.current_theme_title }}"
|
|
10
10
|
/>
|
|
11
|
+
<!--
|
|
12
|
+
CSP Security Trade-off: 'unsafe-inline' for script-src
|
|
13
|
+
========================================================
|
|
14
|
+
Why required: The inline theme-blocking script (lines 19-87 below) must run
|
|
15
|
+
synchronously before first paint to prevent Flash of Unstyled Content (FOUC).
|
|
16
|
+
Without it, users would see the wrong theme briefly before it snaps to their
|
|
17
|
+
saved preference — a jarring experience.
|
|
18
|
+
|
|
19
|
+
Why not use nonces/hashes:
|
|
20
|
+
- Nonces require server-side generation (not possible with static Jekyll/GitHub Pages)
|
|
21
|
+
- Hashes are brittle and break on any script change, causing CI failures
|
|
22
|
+
|
|
23
|
+
Mitigations in place:
|
|
24
|
+
- Inline script validates theme IDs against allowlist (prevents class injection)
|
|
25
|
+
- URL sanitization prevents XSS via manipulated data-baseurl
|
|
26
|
+
- No eval() or dynamic code execution
|
|
27
|
+
- All other scripts are external files
|
|
28
|
+
|
|
29
|
+
Future tightening: Service worker precomputed theme class, or migration to SSR
|
|
30
|
+
with nonce-based CSP.
|
|
31
|
+
|
|
32
|
+
See: docs/adr/0004-csp-unsafe-inline-for-theme-blocking-script.md
|
|
33
|
+
-->
|
|
34
|
+
<!-- Note: frame-ancestors can only be set via HTTP header, not meta tag, so it's omitted here -->
|
|
11
35
|
<meta
|
|
12
36
|
http-equiv="Content-Security-Policy"
|
|
13
|
-
content="default-src 'self'; script-src 'self'; style-src 'self'
|
|
37
|
+
content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data:; font-src 'self' https://fonts.gstatic.com data:; connect-src 'self' https://fonts.googleapis.com https://fonts.gstatic.com; object-src 'none'; base-uri 'self'; form-action 'self'; upgrade-insecure-requests"
|
|
14
38
|
/>
|
|
15
39
|
<title>{{ page.title | default: site.title }}</title>
|
|
16
40
|
{% seo %}
|
|
41
|
+
<!-- Blocking script to apply theme immediately from localStorage -->
|
|
42
|
+
<!-- This prevents FOUC by setting theme class before first paint -->
|
|
43
|
+
<script>
|
|
44
|
+
(function () {
|
|
45
|
+
try {
|
|
46
|
+
var STORAGE_KEY = 'bulma-theme-flavor';
|
|
47
|
+
var DEFAULT_THEME = 'catppuccin-mocha';
|
|
48
|
+
// Valid theme IDs - must match THEMES array in theme-selector.js
|
|
49
|
+
var VALID_THEMES = [
|
|
50
|
+
'bulma-light',
|
|
51
|
+
'bulma-dark',
|
|
52
|
+
'catppuccin-latte',
|
|
53
|
+
'catppuccin-frappe',
|
|
54
|
+
'catppuccin-macchiato',
|
|
55
|
+
'catppuccin-mocha',
|
|
56
|
+
'dracula',
|
|
57
|
+
'github-light',
|
|
58
|
+
'github-dark',
|
|
59
|
+
];
|
|
60
|
+
var savedTheme = localStorage.getItem(STORAGE_KEY) || DEFAULT_THEME;
|
|
61
|
+
// Validate theme ID against allowed list to prevent invalid class/URL injection
|
|
62
|
+
if (VALID_THEMES.indexOf(savedTheme) === -1) {
|
|
63
|
+
savedTheme = DEFAULT_THEME;
|
|
64
|
+
}
|
|
65
|
+
var themeClass = 'theme-' + savedTheme;
|
|
66
|
+
|
|
67
|
+
// Apply theme class using classList to preserve existing classes
|
|
68
|
+
// First remove any existing theme classes
|
|
69
|
+
var classList = document.documentElement.classList;
|
|
70
|
+
var classesToRemove = [];
|
|
71
|
+
for (var i = 0; i < classList.length; i++) {
|
|
72
|
+
if (classList[i].indexOf('theme-') === 0) {
|
|
73
|
+
classesToRemove.push(classList[i]);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
classesToRemove.forEach(function (cls) {
|
|
77
|
+
classList.remove(cls);
|
|
78
|
+
});
|
|
79
|
+
// Add the new theme class
|
|
80
|
+
classList.add(themeClass);
|
|
81
|
+
|
|
82
|
+
// Preload theme CSS for faster loading
|
|
83
|
+
var baseUrl = document.documentElement.getAttribute('data-baseurl') || '';
|
|
84
|
+
// Sanitize baseUrl to prevent XSS attacks
|
|
85
|
+
function sanitizeUrlPath(path) {
|
|
86
|
+
if (!path) return '';
|
|
87
|
+
// Remove or encode dangerous characters that could be interpreted as HTML/JS
|
|
88
|
+
return path.replace(/[<>"'`&]/g, '').replace(/\\/g, '');
|
|
89
|
+
}
|
|
90
|
+
var sanitizedBaseUrl = sanitizeUrlPath(baseUrl);
|
|
91
|
+
// Resolve path relative to site root
|
|
92
|
+
var base = sanitizedBaseUrl
|
|
93
|
+
? window.location.origin + sanitizedBaseUrl + '/'
|
|
94
|
+
: window.location.origin + '/';
|
|
95
|
+
var themePath = new URL('assets/css/themes/' + savedTheme + '.css', base).pathname;
|
|
96
|
+
|
|
97
|
+
// Create preload link
|
|
98
|
+
var preloadLink = document.createElement('link');
|
|
99
|
+
preloadLink.rel = 'preload';
|
|
100
|
+
preloadLink.as = 'style';
|
|
101
|
+
preloadLink.href = themePath;
|
|
102
|
+
document.head.appendChild(preloadLink);
|
|
103
|
+
|
|
104
|
+
// Store theme info for later use
|
|
105
|
+
window.__INITIAL_THEME__ = savedTheme;
|
|
106
|
+
} catch (e) {
|
|
107
|
+
// Silently fail if localStorage is not available
|
|
108
|
+
console.warn('Unable to load saved theme:', e);
|
|
109
|
+
}
|
|
110
|
+
})();
|
|
111
|
+
</script>
|
|
17
112
|
<link rel="icon" href="{{ '/favicon.ico' | relative_url }}" />
|
|
18
|
-
<link rel="dns-prefetch" href="https://cdn.jsdelivr.net" />
|
|
19
|
-
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
|
|
20
113
|
<link
|
|
21
114
|
rel="icon"
|
|
22
115
|
type="image/png"
|
|
@@ -34,32 +127,51 @@
|
|
|
34
127
|
href="{{ '/assets/img/bulma-logo.png' | relative_url }}"
|
|
35
128
|
color="#111827"
|
|
36
129
|
/>
|
|
130
|
+
<!--
|
|
131
|
+
Critical CSS removed - was causing theme override issues.
|
|
132
|
+
Theme CSS uses CSS variables for colors, but hardcoded critical CSS
|
|
133
|
+
was overriding them. The theme CSS is preloaded for fast loading.
|
|
134
|
+
-->
|
|
135
|
+
<!-- Base CSS (shared styles, loaded asynchronously) -->
|
|
37
136
|
<link
|
|
137
|
+
id="theme-base-css"
|
|
38
138
|
rel="preload"
|
|
39
139
|
as="style"
|
|
40
|
-
href="
|
|
41
|
-
|
|
42
|
-
/>
|
|
43
|
-
<link
|
|
44
|
-
rel="stylesheet"
|
|
45
|
-
href="https://cdn.jsdelivr.net/npm/bulma@1.0.2/css/bulma.min.css"
|
|
46
|
-
integrity="sha384-tl5h4XuWmVzPeVWU0x8bx0j/5iMwCBduLEgZ+2lH4Wjda+4+q3mpCww74dgAB3OX"
|
|
47
|
-
crossorigin="anonymous"
|
|
140
|
+
href="{{ '/assets/css/themes/base.css' | relative_url }}"
|
|
141
|
+
onload="this.rel = 'stylesheet'"
|
|
48
142
|
/>
|
|
49
|
-
<
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
href="{{ '/assets/css/themes/global.css' | relative_url }}"
|
|
53
|
-
/>
|
|
54
|
-
<link id="theme-flavor-css" rel="stylesheet" href="#" />
|
|
143
|
+
<noscript>
|
|
144
|
+
<link rel="stylesheet" href="{{ '/assets/css/themes/base.css' | relative_url }}" />
|
|
145
|
+
</noscript>
|
|
55
146
|
<link rel="stylesheet" href="{{ '/assets/css/custom.css' | relative_url }}" />
|
|
56
|
-
|
|
147
|
+
<!-- Use minified JS in production for ~50% smaller payload -->
|
|
148
|
+
{% if jekyll.environment == 'production' %}
|
|
149
|
+
<script type="module" src="{{ '/assets/js/theme-selector.min.js' | relative_url }}"></script>
|
|
150
|
+
{% else %}
|
|
151
|
+
<script type="module" src="{{ '/assets/js/theme-selector.js' | relative_url }}"></script>
|
|
152
|
+
{% endif %}
|
|
57
153
|
<script>
|
|
58
154
|
document.addEventListener('DOMContentLoaded', () => {
|
|
59
155
|
// Initialize navbar highlighting
|
|
60
156
|
if (window.initNavbar) {
|
|
61
157
|
window.initNavbar(document);
|
|
62
158
|
}
|
|
159
|
+
|
|
160
|
+
// Initialize burger menu toggle
|
|
161
|
+
const burgers = document.querySelectorAll('.navbar-burger');
|
|
162
|
+
burgers.forEach((burger) => {
|
|
163
|
+
burger.addEventListener('click', () => {
|
|
164
|
+
const targetId = burger.dataset.target;
|
|
165
|
+
const target = document.getElementById(targetId);
|
|
166
|
+
if (target) {
|
|
167
|
+
burger.classList.toggle('is-active');
|
|
168
|
+
target.classList.toggle('is-active');
|
|
169
|
+
// Update aria-expanded
|
|
170
|
+
const isExpanded = burger.classList.contains('is-active');
|
|
171
|
+
burger.setAttribute('aria-expanded', String(isExpanded));
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
});
|
|
63
175
|
});
|
|
64
176
|
</script>
|
|
65
177
|
</head>
|
|
@@ -212,43 +324,38 @@
|
|
|
212
324
|
</div>
|
|
213
325
|
</div>
|
|
214
326
|
<div class="navbar-end">
|
|
215
|
-
<div class="navbar-item">
|
|
216
|
-
<
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
327
|
+
<div class="navbar-item has-dropdown is-hoverable" data-testid="theme-dropdown">
|
|
328
|
+
<button
|
|
329
|
+
class="theme-trigger-icon"
|
|
330
|
+
id="theme-flavor-trigger"
|
|
331
|
+
type="button"
|
|
332
|
+
aria-haspopup="true"
|
|
333
|
+
aria-expanded="false"
|
|
334
|
+
aria-controls="theme-flavor-menu"
|
|
335
|
+
aria-label="Select theme"
|
|
336
|
+
data-testid="theme-trigger"
|
|
337
|
+
>
|
|
338
|
+
<img
|
|
339
|
+
id="theme-flavor-trigger-icon"
|
|
340
|
+
src="{{ '/assets/img/catppuccin-logo-macchiato.png' | relative_url }}"
|
|
341
|
+
alt="Current theme"
|
|
342
|
+
width="32"
|
|
343
|
+
height="32"
|
|
344
|
+
/>
|
|
345
|
+
</button>
|
|
226
346
|
<div
|
|
227
|
-
class="dropdown is-right
|
|
228
|
-
id="theme-flavor-
|
|
229
|
-
|
|
347
|
+
class="navbar-dropdown is-right"
|
|
348
|
+
id="theme-flavor-menu"
|
|
349
|
+
aria-labelledby="theme-flavor-trigger"
|
|
350
|
+
data-testid="theme-menu"
|
|
351
|
+
role="menu"
|
|
230
352
|
>
|
|
231
|
-
|
|
232
|
-
<button
|
|
233
|
-
class="button is-small is-rounded is-flavor-trigger theme-flavor-trigger"
|
|
234
|
-
aria-haspopup="true"
|
|
235
|
-
aria-controls="theme-flavor-menu"
|
|
236
|
-
aria-label="Theme"
|
|
237
|
-
data-testid="theme-trigger"
|
|
238
|
-
>
|
|
239
|
-
<span class="icon is-small" id="theme-flavor-trigger-icon"></span>
|
|
240
|
-
</button>
|
|
241
|
-
</div>
|
|
242
|
-
<div
|
|
243
|
-
class="dropdown-menu"
|
|
244
|
-
id="theme-flavor-menu"
|
|
245
|
-
role="menu"
|
|
246
|
-
data-testid="theme-menu"
|
|
247
|
-
>
|
|
248
|
-
<div class="dropdown-content" id="theme-flavor-items"></div>
|
|
249
|
-
</div>
|
|
353
|
+
<!-- Theme items populated by JS -->
|
|
250
354
|
</div>
|
|
251
355
|
</div>
|
|
356
|
+
<div class="select is-rounded is-small is-hidden">
|
|
357
|
+
<select id="theme-flavor-select" aria-label="Theme flavor" disabled></select>
|
|
358
|
+
</div>
|
|
252
359
|
</div>
|
|
253
360
|
</div>
|
|
254
361
|
</div>
|
data/assets/css/custom.css
CHANGED
|
@@ -30,3 +30,33 @@
|
|
|
30
30
|
width: 1rem;
|
|
31
31
|
height: 1rem;
|
|
32
32
|
}
|
|
33
|
+
|
|
34
|
+
/* Theme switch loading indicator */
|
|
35
|
+
|
|
36
|
+
.theme-flavor-trigger.is-loading {
|
|
37
|
+
opacity: 0.7;
|
|
38
|
+
pointer-events: none;
|
|
39
|
+
position: relative;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.theme-flavor-trigger.is-loading::after {
|
|
43
|
+
content: '';
|
|
44
|
+
position: absolute;
|
|
45
|
+
width: 16px;
|
|
46
|
+
height: 16px;
|
|
47
|
+
top: 50%;
|
|
48
|
+
left: 50%;
|
|
49
|
+
margin-left: -8px;
|
|
50
|
+
margin-top: -8px;
|
|
51
|
+
border: 2px solid transparent;
|
|
52
|
+
border-top-color: currentcolor;
|
|
53
|
+
border-radius: 50%;
|
|
54
|
+
animation: theme-loading-spin 0.6s linear infinite;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@keyframes theme-loading-spin {
|
|
58
|
+
|
|
59
|
+
to {
|
|
60
|
+
transform: rotate(360deg);
|
|
61
|
+
}
|
|
62
|
+
}
|