@vanduo-oss/framework 1.5.0 → 1.6.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.
Files changed (40) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +33 -6
  3. package/css/components/expanding-cards.css +94 -25
  4. package/css/components/navbar.css +11 -0
  5. package/css/components/popover.css +97 -0
  6. package/css/components/theme-customizer.css +53 -0
  7. package/css/core/colors-fib-base.css +524 -0
  8. package/css/core/colors-palette.css +786 -0
  9. package/css/core/colors.css +54 -46
  10. package/css/core/tokens.css +19 -19
  11. package/css/vanduo.css +8 -1
  12. package/dist/build-info.json +3 -3
  13. package/dist/vanduo-core.css +1588 -86
  14. package/dist/vanduo-core.css.map +1 -1
  15. package/dist/vanduo-core.min.css +2 -2
  16. package/dist/vanduo-core.min.css.map +1 -1
  17. package/dist/vanduo.cjs.js +394 -9
  18. package/dist/vanduo.cjs.js.map +3 -3
  19. package/dist/vanduo.cjs.min.js +16 -10
  20. package/dist/vanduo.cjs.min.js.map +4 -4
  21. package/dist/vanduo.css +1588 -86
  22. package/dist/vanduo.css.map +1 -1
  23. package/dist/vanduo.esm.js +394 -9
  24. package/dist/vanduo.esm.js.map +3 -3
  25. package/dist/vanduo.esm.min.js +16 -10
  26. package/dist/vanduo.esm.min.js.map +4 -4
  27. package/dist/vanduo.js +394 -9
  28. package/dist/vanduo.js.map +3 -3
  29. package/dist/vanduo.min.css +2 -2
  30. package/dist/vanduo.min.css.map +1 -1
  31. package/dist/vanduo.min.js +16 -10
  32. package/dist/vanduo.min.js.map +4 -4
  33. package/js/components/doc-search.js +9 -4
  34. package/js/components/expanding-cards.js +15 -3
  35. package/js/components/popover.js +295 -0
  36. package/js/components/search.js +108 -0
  37. package/js/components/theme-customizer.js +54 -1
  38. package/js/index.js +2 -0
  39. package/js/utils/helpers.js +12 -4
  40. package/package.json +7 -4
package/CHANGELOG.md CHANGED
@@ -8,6 +8,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8
8
  Full release notes — covering the framework, the documentation site, and
9
9
  ecosystem packages side by side — live at <https://vanduo.dev/#changelog>.
10
10
 
11
+ ## [1.6.0] - 2026-06-27
12
+
13
+ Additive release. Adds the Popover and Search primitives and an optional
14
+ Fibonacci palette; **Open Color remains the default look.** One HTML-sanitization
15
+ behavior change to note (see Security).
16
+
17
+ ### Added
18
+ - **Popover component** (`window.VanduoPopover`) — a general popover primitive separate from `.vd-bubble`: click / hover / focus triggers (combinable via `data-vd-popover-trigger`), external-panel composition through `data-vd-popover-target`, `.vd-popover-sm` / `.vd-popover-lg` size variants, and auto-placement flip on viewport overflow (`data-vd-popover-flip`). New `css/components/popover.css` + `js/components/popover.js`, wired into `css/vanduo.css` and `js/index.js`. Playwright spec at `tests/components/popover.spec.ts`.
19
+ - **Search helper** (`window.VanduoSearch`) — a registry so consumers can register their own data sources: `register(source)` / `unregister(name)` / `list()` / `query(text, options?)`. Sources return `Promise<Result[]>`; results merge across sources with an optional per-source limit. New `js/components/search.js`; spec at `tests/components/search.spec.ts`.
20
+ - **Optional Fibonacci palette** — a golden-angle generated palette (`--vd-fib-*` + `--vd-golden-1..8` accent track), opt in at runtime via `data-palette="fibonacci"` on `<html>`. Open Color (`--vd-oc-*`) is the default and `data-primary` / `data-neutral` remaps work under either palette.
21
+
22
+ ### Changed
23
+ - Dependencies updated to latest; pnpm config migrated to `pnpm-workspace.yaml`.
24
+
25
+ ### Security
26
+ - **Behavior change — `sanitizeHtml` denies inline `style` by default.** Rich HTML passed to Bubble / Popover now has `style` attributes stripped unless explicitly allowed, closing an attribute-injection vector. Move inline styles to classes.
27
+ - `escapeHtml` is now quote-safe for attribute contexts.
28
+
29
+ ## [1.5.1] - 2026-06-20
30
+
31
+ ### Enhanced
32
+ - **Expanding Cards — mobile** — Below `768px`, panels stack vertically and expand in place using the same flex-grow redistribution as the desktop strip (replacing progressive hide and non-animatable `order` reorder). Inactive rows render as compact stripes with icon + title; labels and subtitles transition smoothly. `ArrowUp`/`ArrowDown` keyboard navigation added alongside left/right.
33
+
34
+ ### Fixed
35
+ - **Expanding Cards — photo backgrounds** — Active panels use `background-size: cover` and `background-repeat: no-repeat` so wide expanded cards no longer show tiled repeats on the sides.
36
+ - **Expanding Cards — mobile polish** — Resolved mobile layout overflow clipping and keyboard focus edge cases.
37
+
11
38
  ## [1.5.0] - 2026-06-18
12
39
 
13
40
  ### Added
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Vanduo Framework v1.5.0
1
+ # Vanduo Framework v1.6.0
2
2
 
3
3
  <p align="center">
4
4
  <img src="vanduo-banner.svg" alt="Vanduo Framework Banner" width="100%">
@@ -17,7 +17,7 @@ Vanduo is a zero-dependency UI framework built with HTML, CSS, and vanilla JavaS
17
17
  ## Highlights
18
18
 
19
19
  - Zero runtime dependencies
20
- - 47+ components across layout, navigation, overlays, search, and effects
20
+ - 48+ components across layout, navigation, overlays, search, and effects
21
21
  - Scoped runtime APIs for dynamic DOM work
22
22
  - Strict design token API under `--vd-*`
23
23
  - Built-in dark, light, and system theming
@@ -25,7 +25,24 @@ Vanduo is a zero-dependency UI framework built with HTML, CSS, and vanilla JavaS
25
25
  - Theme Switcher menu variant for icon-only light/dark/system selection in navbars
26
26
  - Playwright-based browser coverage across Chromium, Firefox, and WebKit
27
27
 
28
- ## What's New in 1.5.0
28
+ ## What's New in 1.6.0
29
+
30
+ Additive release — two new primitives and an optional palette, plus one HTML-sanitization behavior change to note.
31
+
32
+ - **New — Popover component** (`window.VanduoPopover`) — a general popover primitive with click / hover / focus triggers, external-panel composition via `data-vd-popover-target`, size variants, and auto-placement flip on overflow — alongside the existing `.vd-bubble`.
33
+ - **New — Search helper** (`window.VanduoSearch`) — a small registry letting consumers register their own data sources (`register` / `unregister` / `list` / `query`) behind a single search surface; results merge across sources.
34
+ - **New — Optional Fibonacci palette** — a golden-angle generated palette, opt in at runtime via `data-palette="fibonacci"` on `<html>`. **Open Color remains the default look.**
35
+ - **Behavior change — HTML sanitization denies inline styles by default** — `sanitizeHtml` (used by Bubble / Popover rich content) now strips `style` attributes, closing an attribute-injection vector. Move inline styles to classes; opt back in only where you fully trust the source.
36
+ - **Hardening** — `escapeHtml` is now quote-safe for attribute contexts.
37
+ - **Tooling** — dependencies updated to latest; pnpm config migrated to `pnpm-workspace.yaml`.
38
+
39
+ ## Previous: 1.5.1
40
+
41
+ - **Expanding Cards — mobile** — below `768px`, panels stack vertically and expand in place using the same flex-grow redistribution as the desktop strip (replacing progressive hide and non-animatable `order` reorder). Inactive rows render as compact stripes with icon + title; labels and subtitles transition smoothly. `ArrowUp`/`ArrowDown` keyboard navigation added alongside left/right.
42
+ - **Expanding Cards — photo backgrounds** — active panels use `background-size: cover` and `background-repeat: no-repeat` so wide expanded cards no longer show tiled repeats on the sides.
43
+ - **Expanding Cards — polish** — mobile overflow clipping and keyboard focus edge cases resolved.
44
+
45
+ ## Previous: 1.5.0
29
46
 
30
47
  - **Layout primitives** — new CSS-only layout containers — `.vd-box`, `.vd-stack`, `.vd-inline`, `.vd-center`, `.vd-frame` (golden-ratio aspect box), `.vd-cover`, and `.vd-switcher` (container-query-free responsive row→column) — with a `data-*` API (`data-pad`, `data-gap`, `data-align`, `data-justify`, `data-round`, `data-ratio`…) that consumes the existing Fibonacci spacing/radius and semantic tokens. They are the composition layer between utilities and components — *utilities style an element; primitives arrange elements*. Zero JS, zero new public tokens.
31
48
  - **Hex grid is now a standalone package** — `VdHexGrid` was never part of the bundle; its source has moved out of the framework tree. Install [`@vanduo-oss/hex-grid`](https://www.npmjs.com/package/@vanduo-oss/hex-grid) directly.
@@ -52,8 +69,8 @@ Vanduo is a zero-dependency UI framework built with HTML, CSS, and vanilla JavaS
52
69
  ### CDN
53
70
 
54
71
  ```html
55
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/vanduo-oss/framework@v1.5.0/dist/vanduo.min.css">
56
- <script src="https://cdn.jsdelivr.net/gh/vanduo-oss/framework@v1.5.0/dist/vanduo.min.js"></script>
72
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/vanduo-oss/framework@v1.6.0/dist/vanduo.min.css">
73
+ <script src="https://cdn.jsdelivr.net/gh/vanduo-oss/framework@v1.6.0/dist/vanduo.min.js"></script>
57
74
  <script>
58
75
  Vanduo.init();
59
76
  </script>
@@ -104,7 +121,10 @@ Vanduo.getComponent('docSearch');
104
121
 
105
122
  Vanduo `1.4.1` treats `--vd-*` as the only shipped custom-property namespace:
106
123
 
107
- - Palette: `--vd-red-*`, `--vd-primary-*`, `--vd-gray-*`, and related scales
124
+ - Palette: `--vd-red-*`, `--vd-primary-*`, `--vd-gray-*`, and related scales. The
125
+ default palette is **Open Color** (`--vd-oc-*`); **Fibonacci** (golden-angle
126
+ generated, `--vd-fib-*`, with a `--vd-golden-1..8` accent track) is opt-in via
127
+ `data-palette="fibonacci"`. See [TOKENS.md](TOKENS.md#palette-system-open-color-default--fibonacci-optional).
108
128
  - Colors: `--vd-color-*`
109
129
  - Backgrounds: `--vd-bg-*`
110
130
  - Text: `--vd-text-*`
@@ -168,6 +188,13 @@ CI runs **Chromium Desktop smoke tests on pull requests** and the **full cross-b
168
188
  - QA strategy: [QA-Automation-Strategy.md](QA-Automation-Strategy.md)
169
189
  - Contributor workflow: [CONTRIBUTING.md](CONTRIBUTING.md)
170
190
 
191
+ ## Ecosystem
192
+
193
+ - [`@vanduo-oss/vd2`](https://github.com/vanduo-oss/vd2) — the
194
+ Vue 3 + vite-ssg documentation site that mirrors the framework
195
+ surface in Vue components. Consumes `@vanduo-oss/framework` for
196
+ CSS tokens and class names only.
197
+
171
198
  ## License
172
199
 
173
200
  MIT - see [LICENSE](LICENSE).
@@ -33,7 +33,8 @@
33
33
  border-radius: 30px;
34
34
  cursor: pointer;
35
35
  background: var(--vd-expanding-card-bg, var(--vd-expanding-card-bg-default, #e6e9ed));
36
- background-size: auto 120%;
36
+ background-repeat: no-repeat;
37
+ background-size: cover;
37
38
  background-position: center;
38
39
  transition: 0.5s cubic-bezier(0.05, 0.61, 0.41, 0.95);
39
40
  }
@@ -68,7 +69,6 @@
68
69
  max-width: 600px;
69
70
  margin: 0;
70
71
  border-radius: 40px;
71
- background-size: auto 100%;
72
72
  }
73
73
 
74
74
  .vd-expanding-card.is-active .vd-expanding-card-shadow {
@@ -164,44 +164,113 @@
164
164
  transition-delay: 0.1s;
165
165
  }
166
166
 
167
- /* Progressive hide: narrow viewports hide rightmost cards (matches original) */
168
- @media screen and (max-width: 718px) {
167
+ /* Mobile: vertical stack, expand in place (mirrors desktop flex-grow model) */
168
+ @media screen and (max-width: 767.98px) {
169
169
  .vd-expanding-cards {
170
- min-width: 520px;
170
+ --vd-expanding-card-mobile-stripe: 56px;
171
+ --vd-expanding-card-mobile-active: clamp(200px, 55vw, 280px);
172
+ --vd-expanding-card-mobile-gap: 8px;
173
+
174
+ flex-direction: column;
175
+ align-items: stretch;
176
+ overflow: hidden;
177
+ min-width: 0;
178
+ max-width: 100%;
179
+ width: 100%;
180
+ height: min(
181
+ 72vh,
182
+ calc(
183
+ var(--vd-expanding-card-mobile-active) +
184
+ 5 * (var(--vd-expanding-card-mobile-stripe) + var(--vd-expanding-card-mobile-gap))
185
+ )
186
+ );
187
+ gap: var(--vd-expanding-card-mobile-gap);
171
188
  }
172
189
 
173
- .vd-expanding-card:nth-child(5) {
174
- display: none;
190
+ .vd-expanding-card {
191
+ min-width: 0;
192
+ width: 100%;
193
+ margin: 0;
194
+ flex: 1 1 var(--vd-expanding-card-mobile-stripe);
195
+ min-height: var(--vd-expanding-card-mobile-stripe);
196
+ transition:
197
+ flex 0.5s cubic-bezier(0.05, 0.61, 0.41, 0.95),
198
+ min-height 0.5s cubic-bezier(0.05, 0.61, 0.41, 0.95),
199
+ border-radius 0.5s cubic-bezier(0.05, 0.61, 0.41, 0.95),
200
+ margin 0.5s cubic-bezier(0.05, 0.61, 0.41, 0.95);
175
201
  }
176
- }
177
202
 
178
- @media screen and (max-width: 638px) {
179
- .vd-expanding-cards {
180
- min-width: 440px;
203
+ .vd-expanding-card.is-active {
204
+ flex: 10000 1 var(--vd-expanding-card-mobile-active);
205
+ min-height: var(--vd-expanding-card-mobile-active);
206
+ max-width: none;
207
+ border-radius: 32px;
181
208
  }
182
209
 
183
- .vd-expanding-card:nth-child(4) {
184
- display: none;
210
+ .vd-expanding-card:not(.is-active) {
211
+ flex: 1 1 var(--vd-expanding-card-mobile-stripe);
212
+ min-height: var(--vd-expanding-card-mobile-stripe);
213
+ border-radius: 28px;
185
214
  }
186
- }
187
215
 
188
- @media screen and (max-width: 558px) {
189
- .vd-expanding-cards {
190
- min-width: 360px;
216
+ .vd-expanding-card.is-active .vd-expanding-card-shadow {
217
+ box-shadow:
218
+ inset 0 -120px 120px -120px black,
219
+ inset 0 -120px 120px -100px black;
191
220
  }
192
221
 
193
- .vd-expanding-card:nth-child(3) {
194
- display: none;
222
+ .vd-expanding-card:not(.is-active) .vd-expanding-card-shadow {
223
+ bottom: 0;
224
+ height: 100%;
225
+ box-shadow: inset 0 0 80px 0 rgb(0 0 0 / 35%);
195
226
  }
196
- }
197
227
 
198
- @media screen and (max-width: 478px) {
199
- .vd-expanding-cards {
200
- min-width: 280px;
228
+ .vd-expanding-card.is-active .vd-expanding-card-label {
229
+ bottom: 20px;
230
+ left: 20px;
231
+ top: auto;
232
+ transform: none;
233
+ align-items: flex-end;
234
+ }
235
+
236
+ .vd-expanding-card:not(.is-active) .vd-expanding-card-label {
237
+ bottom: 8px;
238
+ left: 12px;
239
+ top: auto;
240
+ right: auto;
241
+ height: 40px;
242
+ transform: none;
243
+ align-items: center;
244
+ }
245
+
246
+ .vd-expanding-card:not(.is-active) .vd-expanding-card-info {
247
+ min-width: 0;
248
+ flex: 1;
249
+ white-space: nowrap;
250
+ overflow: hidden;
251
+ text-overflow: ellipsis;
252
+ }
253
+
254
+ .vd-expanding-card:not(.is-active) .vd-expanding-card-info > div {
255
+ left: 0;
256
+ opacity: 1;
257
+ }
258
+
259
+ .vd-expanding-card:not(.is-active) .vd-expanding-card-subtitle {
260
+ opacity: 0;
261
+ max-height: 0;
262
+ overflow: hidden;
263
+ }
264
+
265
+ .vd-expanding-card.is-active .vd-expanding-card-subtitle {
266
+ opacity: 1;
267
+ max-height: 2em;
201
268
  }
202
269
 
203
- .vd-expanding-card:nth-child(2) {
204
- display: none;
270
+ .vd-expanding-card:not(.is-active) .vd-expanding-card-title {
271
+ font-size: 1rem;
272
+ overflow: hidden;
273
+ text-overflow: ellipsis;
205
274
  }
206
275
  }
207
276
 
@@ -82,6 +82,17 @@
82
82
  -webkit-backdrop-filter: none;
83
83
  }
84
84
 
85
+ /* Strong frosted surface once scroll activates glass (beyond vd-glass-xl) */
86
+ .vd-navbar-glass.vd-navbar-scrolled {
87
+ --vd-glass-blur: 80px;
88
+ --vd-glass-saturate: 2.6;
89
+ }
90
+
91
+ .vd-navbar-fixed.vd-navbar-glass.vd-navbar-scrolled,
92
+ .vd-navbar-fixed-top.vd-navbar-glass.vd-navbar-scrolled {
93
+ box-shadow: var(--vd-glass-shadow);
94
+ }
95
+
85
96
  /* Navbar Container - matches .vd-container-responsive breakpoints for alignment with page content */
86
97
  .vd-navbar-container {
87
98
  display: flex;
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Vanduo Framework - Popover Component
3
+ * Multi-trigger (click | hover | focus) popover with auto-placement flip.
4
+ * Sibling to .vd-bubble (which is click-only rich HTML); this is the general
5
+ * primitive documented in docs/sections/components/popover.html.
6
+ */
7
+
8
+ :root {
9
+ --vd-popover-bg: var(--vd-card-bg, #fff);
10
+ --vd-popover-text: var(--vd-text-primary, #212529);
11
+ --vd-popover-border-color: var(--vd-border-color, #dee2e6);
12
+ --vd-popover-shadow: 0 0.5rem 1.3125rem rgba(0, 0, 0, 0.12);
13
+ --vd-popover-padding: 0.8125rem;
14
+ --vd-popover-radius: var(--vd-border-radius, 0.5rem);
15
+ --vd-popover-max-width: 21rem;
16
+ --vd-popover-min-width: 8rem;
17
+ --vd-popover-z-index: 1060;
18
+ --vd-popover-arrow-size: 8px;
19
+ --vd-popover-font-size: var(--vd-font-size-sm, 0.875rem);
20
+ }
21
+
22
+ [data-theme="dark"] {
23
+ --vd-popover-bg: var(--vd-card-bg, #2d2d44);
24
+ --vd-popover-border-color: var(--vd-border-color, #3d3d5c);
25
+ --vd-popover-shadow: 0 0.5rem 1.3125rem rgba(0, 0, 0, 0.3);
26
+ }
27
+
28
+ @media (prefers-color-scheme: dark) {
29
+ :root:not([data-theme]) {
30
+ --vd-popover-bg: var(--vd-card-bg, #2d2d44);
31
+ --vd-popover-border-color: var(--vd-border-color, #3d3d5c);
32
+ --vd-popover-shadow: 0 0.5rem 1.3125rem rgba(0, 0, 0, 0.3);
33
+ }
34
+ }
35
+
36
+ .vd-popover-panel {
37
+ position: absolute;
38
+ z-index: var(--vd-popover-z-index);
39
+ min-width: var(--vd-popover-min-width);
40
+ max-width: var(--vd-popover-max-width);
41
+ padding: var(--vd-popover-padding);
42
+ background: var(--vd-popover-bg);
43
+ color: var(--vd-popover-text);
44
+ border: 1px solid var(--vd-popover-border-color);
45
+ border-radius: var(--vd-popover-radius);
46
+ box-shadow: var(--vd-popover-shadow);
47
+ font-size: var(--vd-popover-font-size);
48
+ animation: vd-popover-enter 0.18s ease-out;
49
+ }
50
+
51
+ .vd-popover-panel[hidden] {
52
+ display: none !important;
53
+ }
54
+
55
+ .vd-popover-panel::before {
56
+ content: '';
57
+ position: absolute;
58
+ width: 0;
59
+ height: 0;
60
+ border: var(--vd-popover-arrow-size) solid transparent;
61
+ }
62
+
63
+ .vd-popover-panel[data-placement="bottom"]::before {
64
+ bottom: 100%;
65
+ left: 50%;
66
+ transform: translateX(-50%);
67
+ border-bottom-color: var(--vd-popover-border-color);
68
+ }
69
+
70
+ .vd-popover-panel[data-placement="top"]::before {
71
+ top: 100%;
72
+ left: 50%;
73
+ transform: translateX(-50%);
74
+ border-top-color: var(--vd-popover-border-color);
75
+ }
76
+
77
+ .vd-popover-panel[data-placement="left"]::before {
78
+ left: 100%;
79
+ top: 50%;
80
+ transform: translateY(-50%);
81
+ border-left-color: var(--vd-popover-border-color);
82
+ }
83
+
84
+ .vd-popover-panel[data-placement="right"]::before {
85
+ right: 100%;
86
+ top: 50%;
87
+ transform: translateY(-50%);
88
+ border-right-color: var(--vd-popover-border-color);
89
+ }
90
+
91
+ .vd-popover-sm { --vd-popover-padding: 0.5rem; --vd-popover-font-size: var(--vd-font-size-xs, 0.75rem); }
92
+ .vd-popover-lg { --vd-popover-padding: 1.3125rem; --vd-popover-max-width: 34rem; }
93
+
94
+ @keyframes vd-popover-enter {
95
+ from { opacity: 0; transform: scale(0.96); }
96
+ to { opacity: 1; transform: scale(1); }
97
+ }
@@ -223,6 +223,57 @@ body > .vd-theme-customizer-panel.is-open {
223
223
  z-index: 1;
224
224
  }
225
225
 
226
+ /* Palette toggle (Fibonacci default / Open Color optional) */
227
+ .tc-palette-group {
228
+ display: flex;
229
+ gap: 0;
230
+ }
231
+
232
+ .tc-palette-btn {
233
+ flex: 1;
234
+ display: flex;
235
+ align-items: center;
236
+ justify-content: center;
237
+ padding: 0.5rem 0.5rem;
238
+ background: transparent;
239
+ border: 1px solid var(--vd-border-color);
240
+ color: var(--vd-text-primary);
241
+ font-size: var(--vd-font-size-xs);
242
+ font-weight: var(--vd-font-weight-medium);
243
+ cursor: pointer;
244
+ transition: all 0.15s ease;
245
+ }
246
+
247
+ .tc-palette-btn:first-child {
248
+ border-radius: calc(var(--vd-radius-scale, 0.25) * 0.5rem) 0 0 calc(var(--vd-radius-scale, 0.25) * 0.5rem);
249
+ }
250
+
251
+ .tc-palette-btn:last-child {
252
+ border-radius: 0 calc(var(--vd-radius-scale, 0.25) * 0.5rem) calc(var(--vd-radius-scale, 0.25) * 0.5rem) 0;
253
+ }
254
+
255
+ .tc-palette-btn:not(:first-child) {
256
+ margin-left: -1px;
257
+ }
258
+
259
+ .tc-palette-btn:hover {
260
+ background-color: var(--vd-bg-secondary);
261
+ z-index: 1;
262
+ }
263
+
264
+ .tc-palette-btn:focus-visible {
265
+ outline: 2px solid var(--vd-color-primary);
266
+ outline-offset: 1px;
267
+ z-index: 2;
268
+ }
269
+
270
+ .tc-palette-btn.is-active {
271
+ background-color: var(--vd-bg-dark);
272
+ border-color: var(--vd-bg-dark);
273
+ color: var(--vd-text-inverse);
274
+ z-index: 1;
275
+ }
276
+
226
277
  /* Font Select */
227
278
  .tc-font-select {
228
279
  width: 100%;
@@ -647,6 +698,7 @@ body > .vd-theme-customizer-panel.is-open {
647
698
  [data-theme="dark"] .customizer-radius-btn.is-active,
648
699
  [data-theme="dark"] .customizer-mode-btn.is-active,
649
700
  [data-theme="dark"] .tc-radius-btn.is-active,
701
+ [data-theme="dark"] .tc-palette-btn.is-active,
650
702
  [data-theme="dark"] .tc-mode-btn.is-active {
651
703
  background-color: var(--vd-gray-2);
652
704
  border-color: var(--vd-gray-2);
@@ -667,6 +719,7 @@ body > .vd-theme-customizer-panel.is-open {
667
719
  :root:not([data-theme]) .customizer-radius-btn.is-active,
668
720
  :root:not([data-theme]) .customizer-mode-btn.is-active,
669
721
  :root:not([data-theme]) .tc-radius-btn.is-active,
722
+ :root:not([data-theme]) .tc-palette-btn.is-active,
670
723
  :root:not([data-theme]) .tc-mode-btn.is-active {
671
724
  background-color: var(--vd-gray-2);
672
725
  border-color: var(--vd-gray-2);