@vanduo-oss/framework 1.5.1 → 1.7.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 (58) hide show
  1. package/CHANGELOG.md +34 -2
  2. package/README.md +25 -154
  3. package/SKILL.md +58 -0
  4. package/css/components/accordion.css +80 -0
  5. package/css/components/alerts.css +65 -0
  6. package/css/components/avatar.css +2 -1
  7. package/css/components/badges.css +2 -1
  8. package/css/components/buttons.css +44 -0
  9. package/css/components/cards.css +26 -0
  10. package/css/components/code-snippet.css +23 -0
  11. package/css/components/collections.css +21 -1
  12. package/css/components/flow.css +20 -0
  13. package/css/components/forms.css +12 -1
  14. package/css/components/modals.css +69 -0
  15. package/css/components/navbar.css +11 -0
  16. package/css/components/popover.css +97 -0
  17. package/css/components/preloader.css +31 -0
  18. package/css/components/progress.css +46 -0
  19. package/css/components/separator.css +50 -0
  20. package/css/components/skeleton.css +42 -0
  21. package/css/components/slider.css +92 -0
  22. package/css/components/tabs.css +46 -0
  23. package/css/components/theme-customizer.css +53 -0
  24. package/css/core/colors-fib-base.css +524 -0
  25. package/css/core/colors-palette.css +786 -0
  26. package/css/core/colors.css +54 -46
  27. package/css/core/helpers.css +17 -0
  28. package/css/core/tokens.css +19 -19
  29. package/css/utilities/table.css +9 -0
  30. package/css/vanduo.css +11 -1
  31. package/dist/build-info.json +3 -3
  32. package/dist/vanduo-core.css +2147 -93
  33. package/dist/vanduo-core.css.map +1 -1
  34. package/dist/vanduo-core.min.css +2 -2
  35. package/dist/vanduo-core.min.css.map +1 -1
  36. package/dist/vanduo.cjs.js +387 -6
  37. package/dist/vanduo.cjs.js.map +3 -3
  38. package/dist/vanduo.cjs.min.js +16 -10
  39. package/dist/vanduo.cjs.min.js.map +4 -4
  40. package/dist/vanduo.css +2147 -93
  41. package/dist/vanduo.css.map +1 -1
  42. package/dist/vanduo.esm.js +387 -6
  43. package/dist/vanduo.esm.js.map +3 -3
  44. package/dist/vanduo.esm.min.js +16 -10
  45. package/dist/vanduo.esm.min.js.map +4 -4
  46. package/dist/vanduo.js +387 -6
  47. package/dist/vanduo.js.map +3 -3
  48. package/dist/vanduo.min.css +2 -2
  49. package/dist/vanduo.min.css.map +1 -1
  50. package/dist/vanduo.min.js +16 -10
  51. package/dist/vanduo.min.js.map +4 -4
  52. package/js/components/doc-search.js +9 -4
  53. package/js/components/popover.js +295 -0
  54. package/js/components/search.js +108 -0
  55. package/js/components/theme-customizer.js +54 -1
  56. package/js/index.js +2 -0
  57. package/js/utils/helpers.js +12 -4
  58. package/package.json +8 -4
package/CHANGELOG.md CHANGED
@@ -8,16 +8,48 @@ 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.7.0] - 2026-06-29
12
+
13
+ Additive minor backing the `@vanduo-oss/vue` 0.3.0 release. Adds CSS for new
14
+ components plus alias classes the Vue components render, so the framework
15
+ stylesheet (which `@vanduo-oss/vue` ships as its CSS) styles every class. No
16
+ vanilla class names changed; every rule is additive and container-level rules
17
+ that could collide with legacy base styles are gated with `:has()`.
18
+
19
+ ### Added
20
+ - **Separator + Slider components** — new `css/components/separator.css` (`.vd-separator`, `-vertical`, `-labeled`, `-label`) and `css/components/slider.css` (`.vd-slider` range input, `.vd-slider-field`/`-row`/`-value`), wired into `css/vanduo.css`. (`VdSwitch` reuses `.vd-form-switch`; `VdMenu` reuses `.vd-dropdown`.)
21
+ - **Unified status-palette aliases** — `.vd-input-danger` + `.vd-badge-danger` (aliases of the `-error` validation/variant), `.vd-alert-secondary` (new), plus `.vd-form-label` and `.vd-form-radio-icon` form helpers — backing the unified `primary/secondary/success/warning/danger/info` vocabulary in `@vanduo-oss/vue`.
22
+ - **Accordion component** — new `css/components/accordion.css` (`.vd-accordion`, `-item`, `-header`, `-icon`, `-panel`), wired into `css/vanduo.css`. Previously no accordion CSS existed.
23
+ - **Panel-based modal aliases** (`css/components/modals.css`) — `.vd-modal.vd-modal-open` (container open state), `.vd-modal-open .vd-modal-backdrop` (backdrop visibility), `.vd-modal-panel` (merges the legacy `.vd-modal-dialog` + `.vd-modal-content` box), and `.vd-modal-panel-{sm,md,lg}` sizes. Fixes invisible `VdModal` dialogs.
24
+ - **Component sub-element aliases** — `.vd-alert-body` / `.vd-alert-dismiss` (alerts), `.vd-btn-spinner` (a real loading spinner element; legacy `::after` suppressed when present), `.vd-card-interactive` (cards), `.vd-progress-track` / `-fill` / `-label` + `.vd-progress.is-indeterminate` (progress), `.vd-avatar-img` (alias for `.vd-avatar img`), `.vd-tab` / `.vd-tab-panels` (tabs), `.vd-code-snippet-pre` (code snippet), `.vd-collection-list` / `-text-secondary` (collections), `.vd-flow-controls` / `-position` (flow), `.vd-skeleton-lines` / `-text-short` / `-card-header` / `-card-body` / `-card-{sm,md,lg,xl}` (skeleton), `.vd-preloader-spinner` (preloader), and `.vd-table-caption` (tables).
25
+ - **Utilities** — `.vd-muted` and `.vd-visually-hidden` (`css/core/helpers.css`).
26
+
27
+ ## [1.6.0] - 2026-06-27
28
+
29
+ Additive release. Adds the Popover and Search primitives and an optional
30
+ Fibonacci palette; **Open Color remains the default look.** One HTML-sanitization
31
+ behavior change to note (see Security).
32
+
33
+ ### Added
34
+ - **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`.
35
+ - **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`.
36
+ - **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
37
 
13
38
  ### Changed
14
- - Opened `dev-v151` development branch for the v1.5.1 patch cycle.
39
+ - Dependencies updated to latest; pnpm config migrated to `pnpm-workspace.yaml`.
40
+
41
+ ### Security
42
+ - **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.
43
+ - `escapeHtml` is now quote-safe for attribute contexts.
44
+
45
+ ## [1.5.1] - 2026-06-20
15
46
 
16
47
  ### Enhanced
17
48
  - **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
49
 
19
50
  ### Fixed
20
51
  - **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.
52
+ - **Expanding Cards — mobile polish** — Resolved mobile layout overflow clipping and keyboard focus edge cases.
21
53
 
22
54
  ## [1.5.0] - 2026-06-18
23
55
 
package/README.md CHANGED
@@ -1,178 +1,49 @@
1
- # Vanduo Framework v1.5.1
2
-
3
- <p align="center">
4
- <img src="vanduo-banner.svg" alt="Vanduo Framework Banner" width="100%">
5
- </p>
6
-
7
1
  <p align="center">
8
- <a href="https://www.npmjs.com/package/@vanduo-oss/framework"><img src="https://img.shields.io/npm/v/@vanduo-oss/framework?style=flat-square&color=3b82f6" alt="NPM Version"></a>
9
- <a href="https://github.com/vanduo-oss/framework/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/vanduo-oss/framework/ci.yml?branch=main&style=flat-square&color=10b981" alt="Build Status"></a>
10
- <a href="https://github.com/vanduo-oss/framework/blob/main/LICENSE"><img src="https://img.shields.io/github/license/vanduo-oss/framework?style=flat-square&color=64748b" alt="License"></a>
2
+ <img src="vanduo-banner.svg" alt="Vanduo Framework" width="100%">
11
3
  </p>
12
4
 
13
- Vanduo is a zero-dependency UI framework built with HTML, CSS, and vanilla JavaScript. It ships a full component bundle, scoped runtime initialization, and a strict canonical `--vd-*` token API.
14
-
15
- [Browse Docs](https://vanduo.dev/#docs)
16
-
17
- ## Highlights
18
-
19
- - Zero runtime dependencies
20
- - 47+ components across layout, navigation, overlays, search, and effects
21
- - Scoped runtime APIs for dynamic DOM work
22
- - Strict design token API under `--vd-*`
23
- - Built-in dark, light, and system theming
24
- - Theme customizer with color, font, and radius controls
25
- - Theme Switcher menu variant for icon-only light/dark/system selection in navbars
26
- - Playwright-based browser coverage across Chromium, Firefox, and WebKit
27
-
28
- ## What's New in 1.5.1
29
-
30
- - Development branch opened for the v1.5.1 patch cycle (`dev-v151`).
31
-
32
- ## Previous: 1.5.0
33
-
34
- - **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.
35
- - **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.
36
-
37
- ## Previous: 1.4.6
38
-
39
- - **Leaner default CSS** — `css/vanduo.css` now bundles the `regular` + `fill` icon weights only (~45% smaller minified CSS). Need all six weights? Import `css/icons/icons-all.css`.
40
- - **No-icons core build** — new `dist/vanduo-core.min.css` (`@vanduo-oss/framework/css/core`) drops the bundled icons entirely (~123 KB lighter) for consumers who ship their own icon set.
41
- - **Smaller package** — the build ships only the icon weights the bundle actually uses into `dist/icons/`, instead of all six.
42
- - **TypeScript types** — a hand-written `dist/vanduo.d.ts` for the `Vanduo` runtime, exposed via the `types` field.
43
- - **In-repo changelog** — a new [CHANGELOG.md](CHANGELOG.md) (Keep a Changelog), now validated by `check:versions`.
44
- - **Version-consistency now covers prose** — `pnpm check:versions` validates README, `SECURITY.md`, `llms.txt`, and `CHANGELOG.md`, not just the dist banners.
45
- - **Lint guard** — raw `innerHTML` assignment is now flagged by ESLint outside the sanitization helpers.
46
- - **Parallax & print fixes (now tested)** — speed/direction classes and the print stylesheet's hide-list now use the canonical `vd-` prefix, with new Playwright regression specs; removed the unused internal `doc-tabs` styles from the bundle.
5
+ # @vanduo-oss/framework
47
6
 
48
- ## Previous: 1.4.5
7
+ [![npm](https://img.shields.io/npm/v/@vanduo-oss/framework.svg)](https://www.npmjs.com/package/@vanduo-oss/framework)
8
+ [![CI](https://img.shields.io/github/actions/workflow/status/vanduo-oss/framework/ci.yml?branch=main)](https://github.com/vanduo-oss/framework/actions/workflows/ci.yml)
9
+ [![license: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)
49
10
 
50
- - **Rounded-corner background fixes** draggable surfaces and input-group addons use `background-clip: padding-box` so opaque fills no longer bleed past border arcs at large `data-radius` presets.
51
- - **Background-clip audit** — Playwright `@audit` harness at `tests/audit/background-clip-audit.spec.ts` for regression checks.
52
- - Normative API: [openspec/specs/draggable/spec.md](openspec/specs/draggable/spec.md).
11
+ > The zero-build **Vanilla** engine of the Vanduo design system.
53
12
 
54
- ## Quick Start
13
+ Drop-in HTML/CSS/JS — 48+ components driven by `.vd-*` classes and `data-vd-*` attributes, an imperative `window.Vanduo` runtime, and a strict `--vd-*` token API. Zero runtime dependencies; consumes design tokens from [`@vanduo-oss/core`](https://www.npmjs.com/package/@vanduo-oss/core). Need Vue 3 instead? See [`@vanduo-oss/vue`](https://www.npmjs.com/package/@vanduo-oss/vue).
55
14
 
56
- ### CDN
15
+ ## Install
57
16
 
58
- ```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>
61
- <script>
62
- Vanduo.init();
63
- </script>
64
- ```
65
-
66
- > **Production tip:** harden CDN tags with Subresource Integrity — add `integrity="sha384-…" crossorigin="anonymous"`. Copy the hash from [jsdelivr.com](https://www.jsdelivr.com/) (per-file "SRI" button) or generate it with `openssl dgst -sha384 -binary dist/vanduo.min.js | openssl base64 -A`.
67
-
68
- ### Local Dist Files
69
-
70
- ```html
71
- <link rel="stylesheet" href="dist/vanduo.min.css">
72
- <script src="dist/vanduo.min.js"></script>
73
- <script>
74
- Vanduo.init();
75
- </script>
76
- ```
77
-
78
- ### Package Install
79
-
80
- ```bash
17
+ ```sh
81
18
  pnpm add @vanduo-oss/framework
82
19
  ```
83
20
 
84
21
  ```js
85
- import '@vanduo-oss/framework/css';
86
- import { Vanduo } from '@vanduo-oss/framework';
22
+ import "@vanduo-oss/framework/css";
23
+ import { Vanduo } from "@vanduo-oss/framework";
87
24
 
88
25
  Vanduo.init();
89
26
  ```
90
27
 
91
- ## Runtime API
92
-
93
- ```js
94
- Vanduo.init(root);
95
- Vanduo.initComponents(root);
96
- Vanduo.reinit('lazyLoad', root);
97
- Vanduo.destroy(root);
98
- Vanduo.destroyAll();
99
- Vanduo.getComponent('docSearch');
100
- ```
101
-
102
- - Omit `root` to target the full document.
103
- - Pass an `Element` to initialize or destroy only a subtree.
104
- - Canonical component registry names use `lowerCamelCase`.
105
- - `LazyLoad` remains available as a compatibility alias for `lazyLoad` in `1.4.x`.
106
-
107
- ## Token API
108
-
109
- Vanduo `1.4.1` treats `--vd-*` as the only shipped custom-property namespace:
110
-
111
- - Palette: `--vd-red-*`, `--vd-primary-*`, `--vd-gray-*`, and related scales
112
- - Colors: `--vd-color-*`
113
- - Backgrounds: `--vd-bg-*`
114
- - Text: `--vd-text-*`
115
- - Borders: `--vd-border-*`
116
- - Shadows: `--vd-shadow-*`
117
- - Components/effects: `--vd-btn-*`, `--vd-card-*`, `--vd-morph-*`, and related internals
118
-
119
- Legacy unprefixed token aliases were removed in `1.4.1`; update custom themes and overrides to use the `--vd-*` equivalents.
120
-
121
- ```css
122
- .cta {
123
- color: var(--vd-text-inverse);
124
- background: var(--vd-color-primary);
125
- border-color: var(--vd-border-color);
126
- }
127
- ```
128
-
129
- More detail lives in [TOKENS.md](TOKENS.md).
130
-
131
- ## CSS Bundle Notes
132
-
133
- - `css/vanduo.css` remains the main framework entrypoint in `1.4.1`.
134
- - The main bundle still includes framework-wide form defaults for native inputs and textareas.
135
- - New component styling should prefer `.vd-*` hooks over new raw element selectors.
136
-
137
- ## Project Structure
138
-
139
- ```text
140
- framework/
141
- ├── css/ # Foundation, utilities, effects, components
142
- ├── js/ # Runtime, lifecycle, components
143
- ├── dist/ # Built artifacts
144
- ├── tests/ # Playwright fixtures and specs
145
- ├── scripts/ # Build, verification, and inventory scripts
146
- ├── openspec/ # Spec-driven change proposals and component specs
147
- └── docs/*.md # Release and architecture notes
148
- ```
149
-
150
- ## Development
28
+ ## Quick start (no build)
151
29
 
152
- ```bash
153
- corepack enable
154
- pnpm install
155
- pnpm run lint
156
- pnpm run build
157
- pnpm run check:versions
158
- pnpm test
159
- pnpm run stats:css
30
+ ```html
31
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/vanduo-oss/framework@v1.7.0/dist/vanduo.min.css">
32
+ <script src="https://cdn.jsdelivr.net/gh/vanduo-oss/framework@v1.7.0/dist/vanduo.min.js"></script>
33
+ <script>
34
+ Vanduo.init();
35
+ </script>
160
36
  ```
161
37
 
162
- CI runs **Chromium Desktop smoke tests on pull requests** and the **full cross-browser Playwright matrix on push to `main`** (see [`.github/workflows/tests.yml`](.github/workflows/tests.yml) and [QA-Automation-Strategy.md](QA-Automation-Strategy.md)).
38
+ > **Production tip:** pin the version and add Subresource Integrity (`integrity="sha384-…" crossorigin="anonymous"`) to CDN tags. Get the hash from the per-file "SRI" button on [jsdelivr.com](https://www.jsdelivr.com/).
163
39
 
164
- ## Release Notes
40
+ ## Documentation
165
41
 
166
- - Changelog: [CHANGELOG.md](CHANGELOG.md)
167
- - Architecture notes: [ARCHITECTURE.md](ARCHITECTURE.md)
168
- - Token model: [TOKENS.md](TOKENS.md)
169
- - Theme Switcher spec: [openspec/specs/theme-switcher/spec.md](openspec/specs/theme-switcher/spec.md)
170
- - Draggable spec: [openspec/specs/draggable/spec.md](openspec/specs/draggable/spec.md)
171
- - Changelog policy: [openspec/specs/changelog/spec.md](openspec/specs/changelog/spec.md)
172
- - QA strategy: [QA-Automation-Strategy.md](QA-Automation-Strategy.md)
173
- - Contributor workflow: [CONTRIBUTING.md](CONTRIBUTING.md)
42
+ - Docs & live demos — https://vanduo.dev
43
+ - Agent / LLM reference — [SKILL.md](./SKILL.md)
44
+ - Token model [TOKENS.md](./TOKENS.md) · Architecture — [ARCHITECTURE.md](./ARCHITECTURE.md)
45
+ - Changelog [CHANGELOG.md](./CHANGELOG.md) · Security — [SECURITY.md](./SECURITY.md)
174
46
 
175
47
  ## License
176
48
 
177
- MIT - see [LICENSE](LICENSE).
178
- Third-party notices are listed in [THIRD-PARTY-LICENSES](THIRD-PARTY-LICENSES).
49
+ [MIT](./LICENSE) © Vanduo — third-party notices in [THIRD-PARTY-LICENSES](./THIRD-PARTY-LICENSES).
package/SKILL.md ADDED
@@ -0,0 +1,58 @@
1
+ ---
2
+ name: vanduo-framework
3
+ description: Use when building UIs with @vanduo-oss/framework — the zero-build "Vanilla" HTML/CSS/JS engine of the Vanduo design system (data-attribute components + an imperative window.Vanduo runtime). Covers install (CDN/ESM/IIFE), the runtime API, the --vd-* token model, security, and caveats.
4
+ ---
5
+
6
+ # @vanduo-oss/framework
7
+
8
+ The **Vanilla (zero-build) engine** of the Vanduo design system: drop-in HTML/CSS/JS — 48+ components driven by `.vd-*` classes + `data-vd-*` attributes, an imperative `window.Vanduo` runtime, and a strict `--vd-*` token API. Consumes the values from `@vanduo-oss/core`. No build step required.
9
+
10
+ ## Install
11
+
12
+ ```sh
13
+ pnpm add @vanduo-oss/framework # Node >=18
14
+ ```
15
+
16
+ ```html
17
+ <!-- or CDN (pin a version; add SRI in production) -->
18
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/vanduo-oss/framework@v1.7.0/dist/vanduo.min.css">
19
+ <script src="https://cdn.jsdelivr.net/gh/vanduo-oss/framework@v1.7.0/dist/vanduo.min.js"></script>
20
+ <script>Vanduo.init()</script>
21
+ ```
22
+
23
+ Build variants in `dist/`: `vanduo.min.css` (or `vanduo-core.min.css`, no bundled icons), `vanduo.esm.js` (bundler), `vanduo.cjs.js` (CJS), `vanduo.min.js` (IIFE → global `window.Vanduo`). Subpaths: `@vanduo-oss/framework/css`, `/css/core`, `/iife`.
24
+
25
+ ## Architecture
26
+
27
+ - **Component model** — `.vd-*` classes for styling + `data-vd-*` attributes that the runtime wires up (modal, flow, bubble, stepper, etc.).
28
+ - **Runtime** — `Vanduo.init()` once on load auto-initializes components; `reinit`/`destroy` handle dynamic DOM.
29
+ - **Tokens** — everything themable via `--vd-*` CSS custom properties (Open Color default; opt-in Fibonacci palette via `data-palette="fibonacci"` on `<html>`).
30
+ - **ESM vs IIFE** — ESM bundles into an app; IIFE runs standalone and populates `window.Vanduo`.
31
+
32
+ ## API
33
+
34
+ Runtime (`window.Vanduo`): `init(root?)`, `initComponents(root?)`, `reinit(name, root?)`, `destroy(root?)`, `destroyAll()`, `getComponent(name)`, `register(name, comp, opts?)`. Registry names are `lowerCamelCase`.
35
+
36
+ Component methods via `Vanduo.components.*` — e.g. `toast.show({title,message,type,duration})`, `flow.next/prev/goTo`, `bubble.show/hide`, `stepper.setStep/next/prev`, `rating.get/setValue`, `transfer.getSelected`, `tree.getChecked`, `spotlight.start/next/prev/stop`, `validate.validateForm/addRule`, `waypoint.refresh`.
37
+
38
+ Helpers (global): `sanitizeHtml(html, {allowStyle?, allowSvg?})`, `escapeHtml(str)`, `ready(cb)`, `safeStorageGet/Set`, `debounce`, `throttle`.
39
+
40
+ CSS entrypoints: `/css` (full), `/css/core` (tokens + components, no icons). Token namespaces: `--vd-color/bg/text/border/shadow-*`, `--vd-btn/card/morph-*`, palette scales `--vd-oc-*` / `--vd-fib-*`.
41
+
42
+ ## Security
43
+
44
+ - `sanitizeHtml()` — whitelist-based; **denies inline `style` by default** (attribute-injection vector), opt back in only for trusted source. Bubble/Popover restrict links to `http/https/mailto`.
45
+ - `escapeHtml()` is quote-safe for attribute contexts.
46
+ - ESLint flags raw `innerHTML` assignment outside the sanitize helpers (`no-restricted-syntax`).
47
+ - No bundled-style nonce injection — apply your own CSP; harden CDN tags with Subresource Integrity.
48
+
49
+ ## Caveats
50
+
51
+ - No-build consumers use CDN or local `/dist`; bare ESM specifiers need a bundler/import map.
52
+ - ES2022, modern browsers (no IE11 shims).
53
+ - Theming persists to `localStorage` (`vanduo-theme-preference`); `data-palette="fibonacci"` is runtime opt-in (Open Color is default).
54
+ - Hex grid and music player are **separate packages** (`@vanduo-oss/hex-grid`, `@vanduo-oss/music-player`).
55
+
56
+ ## Docs
57
+
58
+ Full documentation and live demos: https://vanduo.dev
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Vanduo Framework - Accordion
3
+ * Added in 1.6.1 to back @vanduo-oss/vue's VdAccordion.
4
+ *
5
+ * VdAccordion renders:
6
+ * ul.vd-accordion
7
+ * li.vd-accordion-item(.is-open)
8
+ * button.vd-accordion-header > span + span.vd-accordion-icon
9
+ * div.vd-accordion-panel (toggled via v-show)
10
+ */
11
+
12
+ :root {
13
+ --vd-accordion-border-color: var(--vd-border-color);
14
+ --vd-accordion-header-bg: transparent;
15
+ --vd-accordion-header-bg-hover: var(--vd-bg-secondary);
16
+ --vd-accordion-padding-x: 1.3125rem; /* 21px - fib */
17
+ --vd-accordion-padding-y: 0.8125rem; /* 13px - fib */
18
+ }
19
+
20
+ .vd-accordion {
21
+ margin: 0;
22
+ padding: 0;
23
+ list-style: none;
24
+ border: 1px solid var(--vd-accordion-border-color);
25
+ border-radius: var(--vd-btn-border-radius);
26
+ overflow: hidden;
27
+ }
28
+
29
+ .vd-accordion-item {
30
+ border-top: 1px solid var(--vd-accordion-border-color);
31
+ }
32
+
33
+ .vd-accordion-item:first-child {
34
+ border-top: none;
35
+ }
36
+
37
+ .vd-accordion-header {
38
+ display: flex;
39
+ align-items: center;
40
+ justify-content: space-between;
41
+ gap: 0.75rem;
42
+ width: 100%;
43
+ padding: var(--vd-accordion-padding-y) var(--vd-accordion-padding-x);
44
+ background: var(--vd-accordion-header-bg);
45
+ border: none;
46
+ cursor: pointer;
47
+ font-size: var(--vd-font-size-base);
48
+ font-weight: var(--vd-font-weight-medium);
49
+ color: var(--vd-text-primary);
50
+ text-align: left;
51
+ transition: background-color 0.15s ease;
52
+ }
53
+
54
+ .vd-accordion-header:hover {
55
+ background: var(--vd-accordion-header-bg-hover);
56
+ }
57
+
58
+ .vd-accordion-header:focus-visible {
59
+ outline: 2px solid var(--vd-color-primary);
60
+ outline-offset: -2px;
61
+ }
62
+
63
+ .vd-accordion-icon {
64
+ flex-shrink: 0;
65
+ font-size: 1.25rem;
66
+ line-height: 1;
67
+ color: var(--vd-text-secondary);
68
+ }
69
+
70
+ .vd-accordion-panel {
71
+ padding: var(--vd-accordion-padding-y) var(--vd-accordion-padding-x);
72
+ color: var(--vd-text-primary);
73
+ border-top: 1px solid var(--vd-accordion-border-color);
74
+ }
75
+
76
+ @media (prefers-reduced-motion: reduce) {
77
+ .vd-accordion-header {
78
+ transition: none;
79
+ }
80
+ }
@@ -94,6 +94,23 @@
94
94
  color: var(--vd-alert-info-text);
95
95
  }
96
96
 
97
+ /* Secondary variant (added 1.7.0 for the unified status palette) */
98
+ .vd-alert-secondary {
99
+ background-color: var(--vd-color-secondary-alpha-10);
100
+ border-color: var(--vd-color-secondary);
101
+ color: var(--vd-color-secondary-dark);
102
+ }
103
+
104
+ [data-theme="dark"] .vd-alert-secondary {
105
+ color: var(--vd-color-secondary-light);
106
+ }
107
+
108
+ @media (prefers-color-scheme: dark) {
109
+ :root:not([data-theme]) .vd-alert-secondary {
110
+ color: var(--vd-color-secondary-light);
111
+ }
112
+ }
113
+
97
114
  /* Alert with Icon */
98
115
  .vd-alert-icon {
99
116
  display: flex;
@@ -222,3 +239,51 @@
222
239
  transition: none;
223
240
  }
224
241
  }
242
+
243
+ /* ==========================================================================
244
+ @vanduo-oss/vue VdAlert markup (additive; added in 1.6.1)
245
+ VdAlert renders `.vd-alert > .vd-alert-icon + .vd-alert-body + .vd-alert-dismiss`.
246
+ .vd-alert-body wraps the title + content; .vd-alert-dismiss replaces the legacy
247
+ .vd-alert-close. Scoped with :has() so legacy alert markup is untouched.
248
+ ========================================================================== */
249
+ .vd-alert:has(.vd-alert-body) {
250
+ display: flex;
251
+ align-items: flex-start;
252
+ gap: 0.75rem;
253
+ }
254
+
255
+ .vd-alert:has(.vd-alert-body) > .vd-alert-icon {
256
+ flex-shrink: 0;
257
+ }
258
+
259
+ .vd-alert-body {
260
+ flex: 1 1 auto;
261
+ min-width: 0;
262
+ }
263
+
264
+ .vd-alert-dismiss {
265
+ flex-shrink: 0;
266
+ padding: 0;
267
+ background: transparent;
268
+ border: none;
269
+ cursor: pointer;
270
+ opacity: 0.5;
271
+ color: inherit;
272
+ line-height: 1;
273
+ transition: opacity 0.15s ease;
274
+ }
275
+
276
+ .vd-alert-dismiss:hover {
277
+ opacity: 1;
278
+ }
279
+
280
+ .vd-alert-dismiss:focus-visible {
281
+ outline: 2px solid currentColor;
282
+ outline-offset: 2px;
283
+ }
284
+
285
+ @media (prefers-reduced-motion: reduce) {
286
+ .vd-alert-dismiss {
287
+ transition: none;
288
+ }
289
+ }
@@ -58,7 +58,8 @@
58
58
  }
59
59
 
60
60
  /* Avatar Image */
61
- .vd-avatar img {
61
+ .vd-avatar img,
62
+ .vd-avatar-img {
62
63
  width: 100%;
63
64
  height: 100%;
64
65
  object-fit: cover;
@@ -94,7 +94,8 @@
94
94
  color: var(--vd-color-gray-900);
95
95
  }
96
96
 
97
- .vd-badge-error {
97
+ .vd-badge-error,
98
+ .vd-badge-danger {
98
99
  background-color: var(--vd-color-error);
99
100
  color: var(--vd-color-white);
100
101
  }
@@ -527,4 +527,48 @@ a.vd-btn:hover {
527
527
  to {
528
528
  transform: rotate(360deg);
529
529
  }
530
+ }
531
+
532
+ /* ==========================================================================
533
+ @vanduo-oss/vue VdButton spinner (additive; added in 1.6.1)
534
+ VdButton renders a real `<span class="vd-btn-spinner">` while loading (the
535
+ button also gets .is-loading). Style the real element and suppress the legacy
536
+ ::after so only one spinner is shown.
537
+ ========================================================================== */
538
+ .vd-btn.is-loading:has(.vd-btn-spinner)::after {
539
+ content: none;
540
+ }
541
+
542
+ .vd-btn-spinner {
543
+ position: absolute;
544
+ top: 50%;
545
+ left: 50%;
546
+ width: 1em;
547
+ height: 1em;
548
+ margin: -0.5em 0 0 -0.5em;
549
+ border: 2px solid var(--vd-color-primary);
550
+ border-right-color: transparent;
551
+ border-radius: 50%;
552
+ animation: btn-spinner 0.6s linear infinite;
553
+ }
554
+
555
+ .vd-btn-primary .vd-btn-spinner,
556
+ .vd-btn-secondary .vd-btn-spinner,
557
+ .vd-btn-success .vd-btn-spinner,
558
+ .vd-btn-danger .vd-btn-spinner,
559
+ .vd-btn-error .vd-btn-spinner,
560
+ .vd-btn-info .vd-btn-spinner {
561
+ border-color: var(--vd-color-white);
562
+ border-right-color: transparent;
563
+ }
564
+
565
+ .vd-btn-warning .vd-btn-spinner {
566
+ border-color: var(--vd-color-black);
567
+ border-right-color: transparent;
568
+ }
569
+
570
+ @media (prefers-reduced-motion: reduce) {
571
+ .vd-btn-spinner {
572
+ animation-duration: 1.2s;
573
+ }
530
574
  }
@@ -323,3 +323,29 @@ a.vd-card:active {
323
323
  flex: 1 1 0%;
324
324
  }
325
325
  }
326
+
327
+ /* @vanduo-oss/vue VdCard :interactive (additive; added in 1.6.1) */
328
+ .vd-card-interactive {
329
+ cursor: pointer;
330
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
331
+ }
332
+
333
+ .vd-card-interactive:hover {
334
+ transform: translateY(-2px) translateZ(0);
335
+ box-shadow: var(--vd-shadow-lg);
336
+ }
337
+
338
+ .vd-card-interactive:focus-visible {
339
+ outline: 2px solid var(--vd-color-primary);
340
+ outline-offset: 2px;
341
+ }
342
+
343
+ @media (prefers-reduced-motion: reduce) {
344
+ .vd-card-interactive {
345
+ transition: none;
346
+ }
347
+
348
+ .vd-card-interactive:hover {
349
+ transform: none;
350
+ }
351
+ }
@@ -553,3 +553,26 @@
553
553
  transition: none;
554
554
  }
555
555
  }
556
+
557
+ /* ==========================================================================
558
+ @vanduo-oss/vue VdCodeSnippet <pre> (additive; added in 1.6.1)
559
+ VdCodeSnippet renders `figure.vd-code-snippet > pre.vd-code-snippet-pre > code`.
560
+ ========================================================================== */
561
+ .vd-code-snippet-pre {
562
+ margin: 0;
563
+ padding: var(--vd-code-padding-y) var(--vd-code-padding-x);
564
+ overflow-x: auto;
565
+ -webkit-overflow-scrolling: touch;
566
+ background-color: var(--vd-code-bg);
567
+ font-family: var(--vd-font-family-mono, 'JetBrains Mono', 'Fira Code', 'Consolas', monospace);
568
+ font-size: var(--vd-code-font-size);
569
+ line-height: var(--vd-code-line-height);
570
+ color: var(--vd-code-text);
571
+ }
572
+
573
+ .vd-code-snippet-pre code {
574
+ font: inherit;
575
+ color: inherit;
576
+ white-space: pre;
577
+ tab-size: 2;
578
+ }
@@ -242,7 +242,7 @@
242
242
  .vd-collection-item {
243
243
  flex-wrap: wrap;
244
244
  }
245
-
245
+
246
246
  .vd-collection-action {
247
247
  width: 100%;
248
248
  margin-left: 0;
@@ -251,3 +251,23 @@
251
251
  }
252
252
  }
253
253
 
254
+ /* ==========================================================================
255
+ @vanduo-oss/vue VdCollection additions (additive; added in 1.6.1)
256
+ VdCollection wraps items in `ul.vd-collection-list` and renders a
257
+ `.vd-collection-text-secondary` subtitle.
258
+ ========================================================================== */
259
+ .vd-collection-list {
260
+ display: flex;
261
+ flex-direction: column;
262
+ margin: 0;
263
+ padding: 0;
264
+ list-style: none;
265
+ }
266
+
267
+ .vd-collection-text-secondary {
268
+ display: block;
269
+ margin-top: 0.125rem;
270
+ font-size: var(--vd-font-size-sm);
271
+ color: var(--vd-text-secondary);
272
+ }
273
+
@@ -263,3 +263,23 @@
263
263
  padding: 0.8125rem 0.8125rem 2rem;
264
264
  }
265
265
  }
266
+
267
+ /* ==========================================================================
268
+ @vanduo-oss/vue VdFlow inline controls (additive; added in 1.6.1)
269
+ VdFlow renders a `.vd-flow-controls` bar with prev/next buttons and a
270
+ `.vd-flow-position` "n / total" label below the track.
271
+ ========================================================================== */
272
+ .vd-flow-controls {
273
+ display: flex;
274
+ align-items: center;
275
+ justify-content: center;
276
+ gap: 0.75rem;
277
+ margin-top: 0.8125rem;
278
+ }
279
+
280
+ .vd-flow-position {
281
+ min-width: 4ch;
282
+ font-size: var(--vd-font-size-sm);
283
+ color: var(--vd-text-secondary);
284
+ text-align: center;
285
+ }