@vanduo-oss/framework 1.6.0 → 1.7.1

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,6 +8,30 @@ 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.7.1] - 2026-07-05
12
+
13
+ ### Fixed
14
+ - **Button danger alias** — `.vd-btn-danger`, `.vd-btn-outline-danger`, and
15
+ `.vd-btn-ghost-danger` now share the same rules as the existing `-error`
16
+ variants, matching badges, alerts, and chips after the unified status vocabulary
17
+ migration.
18
+
19
+ ## [1.7.0] - 2026-06-29
20
+
21
+ Additive minor backing the `@vanduo-oss/vue` 0.3.0 release. Adds CSS for new
22
+ components plus alias classes the Vue components render, so the framework
23
+ stylesheet (which `@vanduo-oss/vue` ships as its CSS) styles every class. No
24
+ vanilla class names changed; every rule is additive and container-level rules
25
+ that could collide with legacy base styles are gated with `:has()`.
26
+
27
+ ### Added
28
+ - **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`.)
29
+ - **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`.
30
+ - **Accordion component** — new `css/components/accordion.css` (`.vd-accordion`, `-item`, `-header`, `-icon`, `-panel`), wired into `css/vanduo.css`. Previously no accordion CSS existed.
31
+ - **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.
32
+ - **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).
33
+ - **Utilities** — `.vd-muted` and `.vd-visually-hidden` (`css/core/helpers.css`).
34
+
11
35
  ## [1.6.0] - 2026-06-27
12
36
 
13
37
  Additive release. Adds the Popover and Search primitives and an optional
package/README.md CHANGED
@@ -1,201 +1,49 @@
1
- # Vanduo Framework v1.6.0
1
+ <div align="center">
2
+ <img src="vanduo-oss-animated.svg" alt="vanduo-oss/framework" width="220"/>
3
+ </div>
2
4
 
3
- <p align="center">
4
- <img src="vanduo-banner.svg" alt="Vanduo Framework Banner" width="100%">
5
- </p>
5
+ # @vanduo-oss/framework
6
6
 
7
- <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>
11
- </p>
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)
12
10
 
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.
11
+ > The zero-build **Vanilla** engine of the Vanduo design system.
14
12
 
15
- [Browse Docs](https://vanduo.dev/#docs)
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).
16
14
 
17
- ## Highlights
15
+ ## Install
18
16
 
19
- - Zero runtime dependencies
20
- - 48+ 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.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
46
-
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.
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.
49
-
50
- ## Previous: 1.4.6
51
-
52
- - **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`.
53
- - **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.
54
- - **Smaller package** — the build ships only the icon weights the bundle actually uses into `dist/icons/`, instead of all six.
55
- - **TypeScript types** — a hand-written `dist/vanduo.d.ts` for the `Vanduo` runtime, exposed via the `types` field.
56
- - **In-repo changelog** — a new [CHANGELOG.md](CHANGELOG.md) (Keep a Changelog), now validated by `check:versions`.
57
- - **Version-consistency now covers prose** — `pnpm check:versions` validates README, `SECURITY.md`, `llms.txt`, and `CHANGELOG.md`, not just the dist banners.
58
- - **Lint guard** — raw `innerHTML` assignment is now flagged by ESLint outside the sanitization helpers.
59
- - **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.
60
-
61
- ## Previous: 1.4.5
62
-
63
- - **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.
64
- - **Background-clip audit** — Playwright `@audit` harness at `tests/audit/background-clip-audit.spec.ts` for regression checks.
65
- - Normative API: [openspec/specs/draggable/spec.md](openspec/specs/draggable/spec.md).
66
-
67
- ## Quick Start
68
-
69
- ### CDN
70
-
71
- ```html
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>
74
- <script>
75
- Vanduo.init();
76
- </script>
77
- ```
78
-
79
- > **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`.
80
-
81
- ### Local Dist Files
82
-
83
- ```html
84
- <link rel="stylesheet" href="dist/vanduo.min.css">
85
- <script src="dist/vanduo.min.js"></script>
86
- <script>
87
- Vanduo.init();
88
- </script>
89
- ```
90
-
91
- ### Package Install
92
-
93
- ```bash
17
+ ```sh
94
18
  pnpm add @vanduo-oss/framework
95
19
  ```
96
20
 
97
21
  ```js
98
- import '@vanduo-oss/framework/css';
99
- import { Vanduo } from '@vanduo-oss/framework';
22
+ import "@vanduo-oss/framework/css";
23
+ import { Vanduo } from "@vanduo-oss/framework";
100
24
 
101
25
  Vanduo.init();
102
26
  ```
103
27
 
104
- ## Runtime API
105
-
106
- ```js
107
- Vanduo.init(root);
108
- Vanduo.initComponents(root);
109
- Vanduo.reinit('lazyLoad', root);
110
- Vanduo.destroy(root);
111
- Vanduo.destroyAll();
112
- Vanduo.getComponent('docSearch');
113
- ```
114
-
115
- - Omit `root` to target the full document.
116
- - Pass an `Element` to initialize or destroy only a subtree.
117
- - Canonical component registry names use `lowerCamelCase`.
118
- - `LazyLoad` remains available as a compatibility alias for `lazyLoad` in `1.4.x`.
119
-
120
- ## Token API
121
-
122
- Vanduo `1.4.1` treats `--vd-*` as the only shipped custom-property namespace:
123
-
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).
128
- - Colors: `--vd-color-*`
129
- - Backgrounds: `--vd-bg-*`
130
- - Text: `--vd-text-*`
131
- - Borders: `--vd-border-*`
132
- - Shadows: `--vd-shadow-*`
133
- - Components/effects: `--vd-btn-*`, `--vd-card-*`, `--vd-morph-*`, and related internals
134
-
135
- Legacy unprefixed token aliases were removed in `1.4.1`; update custom themes and overrides to use the `--vd-*` equivalents.
136
-
137
- ```css
138
- .cta {
139
- color: var(--vd-text-inverse);
140
- background: var(--vd-color-primary);
141
- border-color: var(--vd-border-color);
142
- }
143
- ```
144
-
145
- More detail lives in [TOKENS.md](TOKENS.md).
146
-
147
- ## CSS Bundle Notes
148
-
149
- - `css/vanduo.css` remains the main framework entrypoint in `1.4.1`.
150
- - The main bundle still includes framework-wide form defaults for native inputs and textareas.
151
- - New component styling should prefer `.vd-*` hooks over new raw element selectors.
152
-
153
- ## Project Structure
154
-
155
- ```text
156
- framework/
157
- ├── css/ # Foundation, utilities, effects, components
158
- ├── js/ # Runtime, lifecycle, components
159
- ├── dist/ # Built artifacts
160
- ├── tests/ # Playwright fixtures and specs
161
- ├── scripts/ # Build, verification, and inventory scripts
162
- ├── openspec/ # Spec-driven change proposals and component specs
163
- └── docs/*.md # Release and architecture notes
164
- ```
165
-
166
- ## Development
28
+ ## Quick start (no build)
167
29
 
168
- ```bash
169
- corepack enable
170
- pnpm install
171
- pnpm run lint
172
- pnpm run build
173
- pnpm run check:versions
174
- pnpm test
175
- pnpm run stats:css
30
+ ```html
31
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/vanduo-oss/framework@v1.7.1/dist/vanduo.min.css">
32
+ <script src="https://cdn.jsdelivr.net/gh/vanduo-oss/framework@v1.7.1/dist/vanduo.min.js"></script>
33
+ <script>
34
+ Vanduo.init();
35
+ </script>
176
36
  ```
177
37
 
178
- 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)).
179
-
180
- ## Release Notes
181
-
182
- - Changelog: [CHANGELOG.md](CHANGELOG.md)
183
- - Architecture notes: [ARCHITECTURE.md](ARCHITECTURE.md)
184
- - Token model: [TOKENS.md](TOKENS.md)
185
- - Theme Switcher spec: [openspec/specs/theme-switcher/spec.md](openspec/specs/theme-switcher/spec.md)
186
- - Draggable spec: [openspec/specs/draggable/spec.md](openspec/specs/draggable/spec.md)
187
- - Changelog policy: [openspec/specs/changelog/spec.md](openspec/specs/changelog/spec.md)
188
- - QA strategy: [QA-Automation-Strategy.md](QA-Automation-Strategy.md)
189
- - Contributor workflow: [CONTRIBUTING.md](CONTRIBUTING.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/).
190
39
 
191
- ## Ecosystem
40
+ ## Documentation
192
41
 
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.
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)
197
46
 
198
47
  ## License
199
48
 
200
- MIT - see [LICENSE](LICENSE).
201
- 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.1/dist/vanduo.min.css">
19
+ <script src="https://cdn.jsdelivr.net/gh/vanduo-oss/framework@v1.7.1/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
  }
@@ -165,20 +165,23 @@
165
165
  transform: translateY(1px);
166
166
  }
167
167
 
168
- /* Button Variants - Error */
169
- .vd-btn-error {
168
+ /* Button Variants - Danger (unified) / Error (alias) */
169
+ .vd-btn-error,
170
+ .vd-btn-danger {
170
171
  background-color: var(--vd-color-error);
171
172
  border-color: var(--vd-color-error);
172
173
  color: var(--vd-color-white);
173
174
  }
174
175
 
175
- .vd-btn-error:hover:not(:disabled):not(.disabled):not(.is-disabled) {
176
+ .vd-btn-error:hover:not(:disabled):not(.disabled):not(.is-disabled),
177
+ .vd-btn-danger:hover:not(:disabled):not(.disabled):not(.is-disabled) {
176
178
  background-color: var(--vd-color-error-dark);
177
179
  border-color: var(--vd-color-error-dark);
178
180
  color: var(--vd-color-white);
179
181
  }
180
182
 
181
- .vd-btn-error:active:not(:disabled):not(.disabled):not(.is-disabled) {
183
+ .vd-btn-error:active:not(:disabled):not(.disabled):not(.is-disabled),
184
+ .vd-btn-danger:active:not(:disabled):not(.disabled):not(.is-disabled) {
182
185
  background-color: var(--vd-color-error-dark);
183
186
  border-color: var(--vd-color-error-dark);
184
187
  transform: translateY(1px);
@@ -264,13 +267,15 @@
264
267
  color: var(--vd-color-black);
265
268
  }
266
269
 
267
- .vd-btn-outline-error {
270
+ .vd-btn-outline-error,
271
+ .vd-btn-outline-danger {
268
272
  background-color: transparent;
269
273
  border-color: var(--vd-color-error);
270
274
  color: var(--vd-color-error);
271
275
  }
272
276
 
273
- .vd-btn-outline-error:hover:not(:disabled):not(.disabled):not(.is-disabled) {
277
+ .vd-btn-outline-error:hover:not(:disabled):not(.disabled):not(.is-disabled),
278
+ .vd-btn-outline-danger:hover:not(:disabled):not(.disabled):not(.is-disabled) {
274
279
  background-color: var(--vd-color-error);
275
280
  border-color: var(--vd-color-error);
276
281
  color: var(--vd-color-white);
@@ -370,18 +375,21 @@
370
375
  color: var(--vd-color-warning-active);
371
376
  }
372
377
 
373
- .vd-btn-ghost-error {
378
+ .vd-btn-ghost-error,
379
+ .vd-btn-ghost-danger {
374
380
  background-color: transparent;
375
381
  border-color: transparent;
376
382
  color: var(--vd-color-error);
377
383
  }
378
384
 
379
- .vd-btn-ghost-error:hover:not(:disabled):not(.disabled):not(.is-disabled) {
385
+ .vd-btn-ghost-error:hover:not(:disabled):not(.disabled):not(.is-disabled),
386
+ .vd-btn-ghost-danger:hover:not(:disabled):not(.disabled):not(.is-disabled) {
380
387
  background-color: var(--vd-color-error-alpha-10);
381
388
  color: var(--vd-color-error-dark);
382
389
  }
383
390
 
384
- .vd-btn-ghost-error:active:not(:disabled):not(.disabled):not(.is-disabled) {
391
+ .vd-btn-ghost-error:active:not(:disabled):not(.disabled):not(.is-disabled),
392
+ .vd-btn-ghost-danger:active:not(:disabled):not(.disabled):not(.is-disabled) {
385
393
  background-color: var(--vd-color-error-alpha-20);
386
394
  color: var(--vd-color-error-active);
387
395
  }
@@ -513,6 +521,7 @@ a.vd-btn:hover {
513
521
  .vd-btn-secondary.is-loading::after,
514
522
  .vd-btn-success.is-loading::after,
515
523
  .vd-btn-error.is-loading::after,
524
+ .vd-btn-danger.is-loading::after,
516
525
  .vd-btn-info.is-loading::after {
517
526
  border-color: var(--vd-color-white);
518
527
  border-right-color: transparent;
@@ -527,4 +536,48 @@ a.vd-btn:hover {
527
536
  to {
528
537
  transform: rotate(360deg);
529
538
  }
539
+ }
540
+
541
+ /* ==========================================================================
542
+ @vanduo-oss/vue VdButton spinner (additive; added in 1.6.1)
543
+ VdButton renders a real `<span class="vd-btn-spinner">` while loading (the
544
+ button also gets .is-loading). Style the real element and suppress the legacy
545
+ ::after so only one spinner is shown.
546
+ ========================================================================== */
547
+ .vd-btn.is-loading:has(.vd-btn-spinner)::after {
548
+ content: none;
549
+ }
550
+
551
+ .vd-btn-spinner {
552
+ position: absolute;
553
+ top: 50%;
554
+ left: 50%;
555
+ width: 1em;
556
+ height: 1em;
557
+ margin: -0.5em 0 0 -0.5em;
558
+ border: 2px solid var(--vd-color-primary);
559
+ border-right-color: transparent;
560
+ border-radius: 50%;
561
+ animation: btn-spinner 0.6s linear infinite;
562
+ }
563
+
564
+ .vd-btn-primary .vd-btn-spinner,
565
+ .vd-btn-secondary .vd-btn-spinner,
566
+ .vd-btn-success .vd-btn-spinner,
567
+ .vd-btn-danger .vd-btn-spinner,
568
+ .vd-btn-error .vd-btn-spinner,
569
+ .vd-btn-info .vd-btn-spinner {
570
+ border-color: var(--vd-color-white);
571
+ border-right-color: transparent;
572
+ }
573
+
574
+ .vd-btn-warning .vd-btn-spinner {
575
+ border-color: var(--vd-color-black);
576
+ border-right-color: transparent;
577
+ }
578
+
579
+ @media (prefers-reduced-motion: reduce) {
580
+ .vd-btn-spinner {
581
+ animation-duration: 1.2s;
582
+ }
530
583
  }
@@ -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
+ }