@vanduo-oss/framework 1.5.1 → 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.
package/CHANGELOG.md CHANGED
@@ -8,16 +8,32 @@ 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.5.1] - 2026-06-20
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.
12
21
 
13
22
  ### Changed
14
- - Opened `dev-v151` development branch for the v1.5.1 patch cycle.
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
15
30
 
16
31
  ### Enhanced
17
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.
18
33
 
19
34
  ### Fixed
20
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.
21
37
 
22
38
  ## [1.5.0] - 2026-06-18
23
39
 
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Vanduo Framework v1.5.1
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,9 +25,22 @@ 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.1
28
+ ## What's New in 1.6.0
29
29
 
30
- - Development branch opened for the v1.5.1 patch cycle (`dev-v151`).
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.
31
44
 
32
45
  ## Previous: 1.5.0
33
46
 
@@ -56,8 +69,8 @@ Vanduo is a zero-dependency UI framework built with HTML, CSS, and vanilla JavaS
56
69
  ### CDN
57
70
 
58
71
  ```html
59
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/vanduo-oss/framework@v1.5.1/dist/vanduo.min.css">
60
- <script src="https://cdn.jsdelivr.net/gh/vanduo-oss/framework@v1.5.1/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>
61
74
  <script>
62
75
  Vanduo.init();
63
76
  </script>
@@ -108,7 +121,10 @@ Vanduo.getComponent('docSearch');
108
121
 
109
122
  Vanduo `1.4.1` treats `--vd-*` as the only shipped custom-property namespace:
110
123
 
111
- - 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).
112
128
  - Colors: `--vd-color-*`
113
129
  - Backgrounds: `--vd-bg-*`
114
130
  - Text: `--vd-text-*`
@@ -172,6 +188,13 @@ CI runs **Chromium Desktop smoke tests on pull requests** and the **full cross-b
172
188
  - QA strategy: [QA-Automation-Strategy.md](QA-Automation-Strategy.md)
173
189
  - Contributor workflow: [CONTRIBUTING.md](CONTRIBUTING.md)
174
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
+
175
198
  ## License
176
199
 
177
200
  MIT - see [LICENSE](LICENSE).
@@ -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);