srcdev-nuxt-components 9.4.8 → 9.4.10
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/.claude/commands/migrate-component.md +20 -6
- package/.claude/component-ledger/audit.json +1 -1
- package/.claude/component-ledger/build.mjs +26 -0
- package/.claude/component-ledger/output.html +8 -3
- package/.claude/component-ledger/template.html +7 -2
- package/.claude/skills/component-dynamic-slots.md +1 -1
- package/.claude/skills/components/alert-mask-core.md +84 -0
- package/.claude/skills/components/canvas-switcher.md +1 -1
- package/.claude/skills/components/carousel-flip.md +112 -168
- package/.claude/skills/components/container-glow.md +123 -0
- package/.claude/skills/components/dashboard-quad-grid.md +98 -0
- package/.claude/skills/components/dashboard-stats-grid.md +103 -0
- package/.claude/skills/components/display-theme-switch.md +60 -0
- package/.claude/skills/components/glowing-border.md +66 -0
- package/.claude/skills/components/input-range-core.md +142 -0
- package/.claude/skills/components/section-parallax.md +32 -10
- package/.claude/skills/components/ui-block-decorated.md +56 -0
- package/.claude/skills/components/wipe-away-vertical.md +98 -0
- package/.claude/skills/icon-sets.md +1 -1
- package/.claude/skills/index.md +10 -1
- package/.vscode/css-custom-data.json +38 -0
- package/.vscode/settings.json +3 -0
- package/.vscode/srcdev-component-alert-mask-core.code-snippets +31 -0
- package/.vscode/srcdev-component-carousel-flip.code-snippets +41 -0
- package/.vscode/srcdev-component-container-glow.code-snippets +33 -0
- package/.vscode/srcdev-component-dashboard-quad-grid.code-snippets +36 -0
- package/.vscode/srcdev-component-dashboard-stats-grid.code-snippets +35 -0
- package/.vscode/srcdev-component-display-theme-switch.code-snippets +27 -0
- package/.vscode/srcdev-component-glowing-border.code-snippets +23 -0
- package/.vscode/srcdev-component-input-range.code-snippets +85 -0
- package/.vscode/srcdev-component-section-parallax.code-snippets +27 -0
- package/.vscode/srcdev-component-ui-block-decorated.code-snippets +24 -0
- package/.vscode/srcdev-component-wipe-away-vertical.code-snippets +25 -0
- package/README.md +18 -37
- package/app/components/{alert-mask → 01.atoms/alert-mask}/AlertMaskCore.vue +16 -17
- package/app/components/01.atoms/alert-mask/CONSUMER-STYLING.md +46 -0
- package/app/components/01.atoms/alert-mask/stories/AlertMaskCore.stories.ts +79 -0
- package/app/components/{alert-mask → 01.atoms/alert-mask}/tests/AlertMaskCore.spec.ts +10 -10
- package/app/components/01.atoms/animations/container-glow/CONSUMER-STYLING.md +86 -0
- package/app/components/01.atoms/animations/container-glow/ContainerGlow.vue +299 -0
- package/app/components/01.atoms/animations/container-glow/stories/ContainerGlow.stories.ts +175 -0
- package/app/components/01.atoms/animations/container-glow/tests/ContainerGlow.spec.ts +131 -0
- package/app/components/01.atoms/animations/container-glow/tests/__snapshots__/ContainerGlow.spec.ts.snap +14 -0
- package/app/components/01.atoms/animations/glowing-border/CONSUMER-STYLING.md +61 -0
- package/app/components/01.atoms/animations/glowing-border/GlowingBorder.vue +132 -0
- package/app/components/01.atoms/animations/glowing-border/stories/GlowingBorder.stories.ts +165 -0
- package/app/components/01.atoms/animations/glowing-border/tests/GlowingBorder.spec.ts +94 -0
- package/app/components/01.atoms/animations/glowing-border/tests/__snapshots__/GlowingBorder.spec.ts.snap +3 -0
- package/app/components/01.atoms/animations/section-parallax/CONSUMER-STYLING.md +44 -0
- package/app/components/{parallax → 01.atoms/animations/section-parallax}/SectionParallax.vue +11 -10
- package/app/components/01.atoms/animations/section-parallax/stories/SectionParallax.stories.ts +98 -0
- package/app/components/01.atoms/animations/section-parallax/tests/SectionParallax.spec.ts +102 -0
- package/app/components/01.atoms/animations/section-parallax/tests/__snapshots__/SectionParallax.spec.ts.snap +9 -0
- package/app/components/01.atoms/animations/view-timeline/CONSUMER-STYLING.md +70 -0
- package/app/components/01.atoms/animations/view-timeline/WipeAwayVertical.vue +181 -0
- package/app/components/01.atoms/animations/view-timeline/stories/WipeAwayVertical.stories.ts +269 -0
- package/app/components/01.atoms/animations/view-timeline/tests/WipeAwayVertical.spec.ts +127 -0
- package/app/components/01.atoms/canvas-switcher/CONSUMER-STYLING.md +1 -1
- package/app/components/01.atoms/canvas-switcher/stories/CanvasSwitcher.stories.ts +1 -1
- package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/CONSUMER-STYLING.md +42 -0
- package/app/components/{layout-grids/LayoutGridA.vue → 01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/DashboardQuadGrid.vue} +23 -13
- package/app/components/{layout-grids/stories/LayoutGridA.stories.ts → 01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/stories/DashboardQuadGrid.stories.ts} +151 -23
- package/app/components/{layout-grids/tests/LayoutGridA.spec.ts → 01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/tests/DashboardQuadGrid.spec.ts} +25 -25
- package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/CONSUMER-STYLING.md +41 -0
- package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/DashboardStatsGrid.vue +133 -0
- package/app/components/{layout-grids/stories/LayoutGridB.stories.ts → 01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/stories/DashboardStatsGrid.stories.ts} +24 -24
- package/app/components/{layout-grids/tests/LayoutGridB.spec.ts → 01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/tests/DashboardStatsGrid.spec.ts} +23 -23
- package/app/components/01.atoms/navigation/skip-links/SkipLinks.vue +7 -1
- package/app/components/01.atoms/ui-block-decorated/CONSUMER-STYLING.md +39 -0
- package/app/components/01.atoms/ui-block-decorated/UiBlockDecorated.vue +141 -0
- package/app/components/01.atoms/ui-block-decorated/stories/UiBlockDecorated.stories.ts +148 -0
- package/app/components/01.atoms/ui-block-decorated/tests/UiBlockDecorated.spec.ts +80 -0
- package/app/components/01.atoms/ui-block-decorated/tests/__snapshots__/UiBlockDecorated.spec.ts.snap +3 -0
- package/app/components/02.molecules/alert-masked-content/tests/AlertMaskedContent.spec.ts +6 -6
- package/app/components/02.molecules/display-theme-switch/CONSUMER-STYLING.md +34 -0
- package/app/components/02.molecules/display-theme-switch/DisplayThemeSwitch.vue +102 -0
- package/app/components/02.molecules/display-theme-switch/stories/DisplayThemeSwitch.stories.ts +115 -0
- package/app/components/02.molecules/display-theme-switch/tests/DisplayThemeSwitch.spec.ts +86 -0
- package/app/components/03.organisms/image-galleries/carousel-flip/CONSUMER-STYLING.md +46 -0
- package/app/components/{carousels → 03.organisms/image-galleries/carousel-flip}/CarouselFlip.vue +63 -42
- package/app/components/{carousels → 03.organisms/image-galleries/carousel-flip}/stories/CarouselFlip.stories.ts +96 -11
- package/app/components/{carousels → 03.organisms/image-galleries/carousel-flip}/tests/CarouselFlip.spec.ts +80 -0
- package/app/components/05.forms/form-field/FormField.vue +1 -1
- package/app/components/05.forms/form-wrapper/FormWrapper.vue +1 -1
- package/app/components/05.forms/input-range/CONSUMER-STYLING.md +45 -0
- package/app/components/05.forms/input-range/InputRangeCore.vue +79 -143
- package/app/components/05.forms/input-range/stories/InputRangeCore.stories.ts +126 -0
- package/app/components/05.forms/input-range/tests/InputRangeCore.spec.ts +124 -0
- package/app/components/05.forms/input-range/variants/InputRangeDefault.vue +9 -32
- package/app/components/05.forms/input-range/variants/stories/InputRangeDefault.stories.ts +108 -0
- package/app/components/05.forms/input-range/variants/tests/InputRangeDefault.spec.ts +140 -0
- package/app/components/05.forms/patterns/stories/MigratedFieldsForm.stories.ts +135 -0
- package/app/components/05.forms/triple-toggle-switch/CONSUMER-STYLING.md +16 -2
- package/app/components/05.forms/triple-toggle-switch/TripleToggleSwitchCore.vue +6 -4
- package/app/types/components/container-glow.d.ts +8 -0
- package/app/types/components/index.ts +1 -1
- package/package.json +3 -2
- package/app/components/05.forms/input-range-fancy/InputRangeFancyCore.vue +0 -426
- package/app/components/05.forms/input-range-fancy/InputRangeFancyWithLabel.vue +0 -94
- package/app/components/carousels/CarouselBasic.vue +0 -317
- package/app/components/carousels/CarouselInfinite.vue +0 -358
- package/app/components/container-glow/ContainerGlowCore.vue +0 -296
- package/app/components/container-glow/stories/ContainerGlowCore.stories.ts +0 -337
- package/app/components/display-theme-switch/DisplayThemeSwitch.vue +0 -189
- package/app/components/display-theme-switch/stories/DisplayThemeSwitch.stories.ts +0 -154
- package/app/components/glowing-border/GlowingBorder.vue +0 -142
- package/app/components/glowing-border/stories/GlowingBorder.stories.ts +0 -141
- package/app/components/layout-grids/LayoutGridB.vue +0 -134
- package/app/components/test-storybook/TestStorybook.vue +0 -49
- package/app/components/test-storybook/stories/TestStorybook.stories.ts +0 -28
- package/app/components/ui-block-decorated/UiBlockDecorated.vue +0 -167
- package/app/components/view-timeline/WipeAwayVertical.vue +0 -180
- package/app/types/components/carousel-basic.d.ts +0 -19
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# DashboardQuadGrid Component
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
`DashboardQuadGrid` (renamed from `LayoutGridA`) is a fixed 4-panel dashboard layout. Unlike
|
|
6
|
+
`LayoutGridByCols`/`LayoutGridByWidth`, it does not take a column-count prop — it has four
|
|
7
|
+
**named** slots (`slot1`–`slot4`) with a fixed responsive arrangement that changes shape (not
|
|
8
|
+
just column count) across breakpoints, designed for dashboard-style layouts (one primary panel
|
|
9
|
+
plus three supporting panels).
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Slot pattern
|
|
14
|
+
|
|
15
|
+
Exactly four fixed slot names — `slot1`, `slot2`, `slot3`, `slot4`. Not dynamic; each is a named
|
|
16
|
+
slot with a specific position in the layout at each breakpoint.
|
|
17
|
+
|
|
18
|
+
```vue
|
|
19
|
+
<DashboardQuadGrid>
|
|
20
|
+
<template #slot1><ArticleCard /></template>
|
|
21
|
+
<template #slot2><StatsPanel /></template>
|
|
22
|
+
<template #slot3><QuickActions /></template>
|
|
23
|
+
<template #slot4><ActivityFeed /></template>
|
|
24
|
+
</DashboardQuadGrid>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Props reference
|
|
30
|
+
|
|
31
|
+
| Prop (template form) | Type | Default | Notes |
|
|
32
|
+
|------|------|---------|-------|
|
|
33
|
+
| `:style-class-passthrough` | `string \| string[]` | `[]` | Extra CSS classes on the root element. |
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Responsive behaviour
|
|
38
|
+
|
|
39
|
+
Uses **CSS container queries** (`container-type: inline-size`) on the wrapper — responds to its
|
|
40
|
+
own container width, not the viewport.
|
|
41
|
+
|
|
42
|
+
- **Below 768px**: all four slots stack vertically in order (slot1 → slot2 → slot3 → slot4).
|
|
43
|
+
- **768px–1059px**: 2-column, 3-row grid. `slot1` and `slot2` each span the full width (rows 1
|
|
44
|
+
and 2); `slot3`/`slot4` sit side by side in row 3.
|
|
45
|
+
- **≥1060px**: 3-column, 2-row grid. `slot1` spans vertically down the left column; `slot2` spans
|
|
46
|
+
horizontally across the top-right; `slot3`/`slot4` sit in the bottom-right.
|
|
47
|
+
|
|
48
|
+
This shape is structural — there is no prop to reconfigure it. If you need an arbitrary
|
|
49
|
+
column count instead, use `LayoutGridByCols`/`LayoutGridByWidth`.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## CSS token API
|
|
54
|
+
|
|
55
|
+
See [CONSUMER-STYLING.md](../../app/components/01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/CONSUMER-STYLING.md).
|
|
56
|
+
|
|
57
|
+
| Token | Default | Controls |
|
|
58
|
+
|---|---|---|
|
|
59
|
+
| `--dashboard-quad-grid-gap` | `2rem` | Gap between the four slot panels |
|
|
60
|
+
| `--dashboard-quad-grid-padding` | `2rem` | Padding inside each slot panel |
|
|
61
|
+
| `--dashboard-quad-grid-outline-width` | `0.1rem` | Slot panel outline width |
|
|
62
|
+
| `--dashboard-quad-grid-outline-colour` | `light-dark(black, white)` | Slot panel outline colour |
|
|
63
|
+
| `--dashboard-quad-grid-outline-offset` | `0` | Slot panel outline offset |
|
|
64
|
+
| `--dashboard-quad-grid-border-width` | `0` | Slot panel border width (off by default — the panel edge is drawn by the outline) |
|
|
65
|
+
| `--dashboard-quad-grid-border-colour` | `light-dark(black, white)` | Slot panel border colour, only visible once `--dashboard-quad-grid-border-width` is set |
|
|
66
|
+
| `--dashboard-quad-grid-border-radius` | `0.5rem` | Slot panel corner radius |
|
|
67
|
+
| `--dashboard-quad-grid-rule-width` | `0.1rem` | Width of the grid gap rule line (CSS Gap Decorations, limited browser support) |
|
|
68
|
+
| `--dashboard-quad-grid-rule-colour` | `transparent` | Colour of the grid gap rule line, invisible by default |
|
|
69
|
+
| `--dashboard-quad-grid-rule-inset` | `0` | Inset of the grid gap rule line from the panel edges |
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Local style override scaffold
|
|
74
|
+
|
|
75
|
+
```vue
|
|
76
|
+
<DashboardQuadGrid :style-class-passthrough="['my-grid']">
|
|
77
|
+
...
|
|
78
|
+
</DashboardQuadGrid>
|
|
79
|
+
|
|
80
|
+
<style>
|
|
81
|
+
.dashboard-quad-grid-wrapper {
|
|
82
|
+
&.my-grid {
|
|
83
|
+
--dashboard-quad-grid-gap: 1.6rem;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
</style>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Notes
|
|
92
|
+
|
|
93
|
+
- Auto-imported in Nuxt — no manual import needed.
|
|
94
|
+
- Renamed from `LayoutGridA` during the 2026-09-21 compliance migration; previously lived
|
|
95
|
+
unplaced at `app/components/layout-grids/LayoutGridA.vue` with options-style props and no
|
|
96
|
+
public CSS tokens (its geometry values were hardcoded px literals).
|
|
97
|
+
- For a generic, arbitrary-column-count grid, use `LayoutGridByCols`/`LayoutGridByWidth` instead
|
|
98
|
+
— this component's 4-slot shape is fixed and specifically dashboard-oriented.
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# DashboardStatsGrid Component
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
`DashboardStatsGrid` (renamed from `LayoutGridB`) is a dashboard layout combining a multi-panel
|
|
6
|
+
top row (a cluster of small stat/summary panels plus two static side panels) with a strip of
|
|
7
|
+
panels in the bottom row. Item counts in the two dynamic clusters are prop-driven; the two static
|
|
8
|
+
top-row slots and overall shape are fixed.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Slot pattern
|
|
13
|
+
|
|
14
|
+
- `top-row-slot1-{n}-content` — dynamic, `n` from `1` to `topRowSlot1ItemCount`
|
|
15
|
+
- `top-row-slot-2` — static
|
|
16
|
+
- `top-row-slot-3` — static
|
|
17
|
+
- `bottom-row-{n}-content` — dynamic, `n` from `1` to `bottomRowItemCount`
|
|
18
|
+
|
|
19
|
+
```vue
|
|
20
|
+
<DashboardStatsGrid :top-row-slot1-item-count="3" :bottom-row-item-count="2">
|
|
21
|
+
<template #top-row-slot1-1-content><StatCard label="Uptime" value="98.5%" /></template>
|
|
22
|
+
<template #top-row-slot1-2-content><StatCard label="Users" value="1,247" /></template>
|
|
23
|
+
<template #top-row-slot1-3-content><StatCard label="Latency" value="342ms" /></template>
|
|
24
|
+
|
|
25
|
+
<template #top-row-slot-2><FeaturedPanel /></template>
|
|
26
|
+
<template #top-row-slot-3><InfoPanel /></template>
|
|
27
|
+
|
|
28
|
+
<template #bottom-row-1-content><FeaturePanel /></template>
|
|
29
|
+
<template #bottom-row-2-content><FeaturePanel /></template>
|
|
30
|
+
</DashboardStatsGrid>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Props reference
|
|
36
|
+
|
|
37
|
+
| Prop (template form) | Type | Default | Notes |
|
|
38
|
+
|------|------|---------|-------|
|
|
39
|
+
| `:top-row-slot1-item-count` | `number` | `6` | Number of dynamic panels rendered in the top-row cluster (`top-row-slot1-{n}-content`). |
|
|
40
|
+
| `:bottom-row-item-count` | `number` | `4` | Number of dynamic panels rendered in the bottom row (`bottom-row-{n}-content`). |
|
|
41
|
+
| `:style-class-passthrough` | `string \| string[]` | `[]` | Extra CSS classes on the root element. |
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Responsive behaviour
|
|
46
|
+
|
|
47
|
+
Uses **CSS container queries** (`container-type: inline-size`) — responds to its own container
|
|
48
|
+
width, not the viewport.
|
|
49
|
+
|
|
50
|
+
- **Top row, below 1024px**: `slot1` cluster, `slot2`, `slot3` stack vertically.
|
|
51
|
+
- **Top row, ≥1024px**: two-column layout — `slot1` cluster + `slot3` on the left
|
|
52
|
+
(`minmax(46rem, 33%)` on the right for `slot2`), with `slot2` spanning both rows on the right.
|
|
53
|
+
- **`slot1` cluster, below 680px**: 2 columns.
|
|
54
|
+
- **`slot1` cluster, ≥680px**: 3 columns.
|
|
55
|
+
- **Bottom row**: always a fixed 2-column grid regardless of container width.
|
|
56
|
+
|
|
57
|
+
This shape is structural — there is no prop to reconfigure it.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## CSS token API
|
|
62
|
+
|
|
63
|
+
See [CONSUMER-STYLING.md](../../app/components/01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/CONSUMER-STYLING.md).
|
|
64
|
+
|
|
65
|
+
| Token | Default | Controls |
|
|
66
|
+
|---|---|---|
|
|
67
|
+
| `--dashboard-stats-grid-gap` | `1.2rem` | Gap between panels, in every row |
|
|
68
|
+
| `--dashboard-stats-grid-panel-padding` | `1.2rem` | Padding inside each panel |
|
|
69
|
+
| `--dashboard-stats-grid-border-width` | `0.1rem` | Panel border width |
|
|
70
|
+
| `--dashboard-stats-grid-border-colour` | `light-dark(hsl(0, 29%, 3%), hsl(0, 0%, 92%))` | Panel border colour |
|
|
71
|
+
| `--dashboard-stats-grid-border-radius` | `1.2rem` | Panel corner radius |
|
|
72
|
+
| `--dashboard-stats-grid-rule-width` | `0.1rem` | Width of the grid gap rule line (CSS Gap Decorations, limited browser support) |
|
|
73
|
+
| `--dashboard-stats-grid-rule-colour` | `transparent` | Colour of the grid gap rule line, invisible by default |
|
|
74
|
+
| `--dashboard-stats-grid-rule-inset` | `0` | Inset of the grid gap rule line from the panel edges |
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Local style override scaffold
|
|
79
|
+
|
|
80
|
+
```vue
|
|
81
|
+
<DashboardStatsGrid :style-class-passthrough="['my-grid']">
|
|
82
|
+
...
|
|
83
|
+
</DashboardStatsGrid>
|
|
84
|
+
|
|
85
|
+
<style>
|
|
86
|
+
.dashboard-stats-grid {
|
|
87
|
+
&.my-grid {
|
|
88
|
+
--dashboard-stats-grid-gap: 1.6rem;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
</style>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Notes
|
|
97
|
+
|
|
98
|
+
- Auto-imported in Nuxt — no manual import needed.
|
|
99
|
+
- Renamed from `LayoutGridB` during the 2026-09-21 compliance migration; previously lived
|
|
100
|
+
unplaced at `app/components/layout-grids/LayoutGridB.vue` with options-style props. Its old
|
|
101
|
+
`--_color` custom property was dead code (declared, never consumed) and was removed rather than
|
|
102
|
+
promoted; `--_gap`/`--_border-color` had no public fallback and are now
|
|
103
|
+
`--dashboard-stats-grid-gap`/`--dashboard-stats-grid-border-colour`.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: DisplayThemeSwitch
|
|
3
|
+
description: DisplayThemeSwitch system/light/dark theme picker wired to useSettingsStore, wraps TripleToggleSwitchCore
|
|
4
|
+
type: reference
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# DisplayThemeSwitch
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
`DisplayThemeSwitch` is a system/light/dark colour-scheme picker. It's a thin wrapper around
|
|
12
|
+
`TripleToggleSwitchCore` (`app/components/05.forms/triple-toggle-switch/`), wired to
|
|
13
|
+
`useSettingsStore` (`app/stores/useSettingsStore.ts`) so selecting an option updates the app's
|
|
14
|
+
`colourScheme` state and applies the matching class (`system`/`light`/`dark`) to
|
|
15
|
+
`<html>`. Renders inside `<ClientOnly>` since the store's persisted value isn't known until
|
|
16
|
+
hydration.
|
|
17
|
+
|
|
18
|
+
## Props
|
|
19
|
+
|
|
20
|
+
| Prop | Type | Default | Description |
|
|
21
|
+
|------|------|---------|-------------|
|
|
22
|
+
| `styleClassPassthrough` | `string \| string[]` | `[]` | Extra classes on the root. Pass `"small"` for compact sizing. |
|
|
23
|
+
| `systemLabel` | `string` | `"System"` | Accessible label for the system option. |
|
|
24
|
+
| `lightLabel` | `string` | `"Light"` | Accessible label for the light option. |
|
|
25
|
+
| `darkLabel` | `string` | `"Dark"` | Accessible label for the dark option. |
|
|
26
|
+
| `systemIcon` | `string` | `"material-symbols:night-sight-auto-sharp"` | Icon name for the system option. |
|
|
27
|
+
| `lightIcon` | `string` | `"radix-icons:sun"` | Icon name for the light option. |
|
|
28
|
+
| `darkIcon` | `string` | `"radix-icons:moon"` | Icon name for the dark option. |
|
|
29
|
+
|
|
30
|
+
## Basic usage
|
|
31
|
+
|
|
32
|
+
```vue
|
|
33
|
+
<DisplayThemeSwitch />
|
|
34
|
+
|
|
35
|
+
<!-- Compact, for a header/nav slot -->
|
|
36
|
+
<DisplayThemeSwitch style-class-passthrough="small" />
|
|
37
|
+
|
|
38
|
+
<!-- Translated labels -->
|
|
39
|
+
<DisplayThemeSwitch system-label="Automatique" light-label="Clair" dark-label="Sombre" />
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Styling
|
|
43
|
+
|
|
44
|
+
No `--display-theme-switch-*` tokens of its own — every visual aspect (colour, marker gradient,
|
|
45
|
+
sizing) is delegated to `TripleToggleSwitchCore`'s public `--triple-toggle-switch-*` tokens. See
|
|
46
|
+
CONSUMER-STYLING.md here and `TripleToggleSwitchCore`'s own CONSUMER-STYLING.md.
|
|
47
|
+
|
|
48
|
+
## Notes
|
|
49
|
+
|
|
50
|
+
- 2026-09-20 migration: moved from `app/components/display-theme-switch/` (unplaced) into
|
|
51
|
+
`02.molecules/`. Added `systemLabel`/`lightLabel`/`darkLabel`/`systemIcon`/`lightIcon`/`darkIcon`
|
|
52
|
+
props — the three option labels/icons were previously hardcoded English strings with no override
|
|
53
|
+
hook. Removed a large block of dead/duplicate CSS in this component's own `<style>` that either
|
|
54
|
+
no-op-duplicated `TripleToggleSwitchCore`'s own default styling (same selectors, same values) or
|
|
55
|
+
actively bypassed its public `--triple-toggle-switch-*` tokens with hardcoded literals (a
|
|
56
|
+
consumer setting e.g. `--triple-toggle-switch-surface` globally would have been silently
|
|
57
|
+
overridden back). Only the genuine `small`-variant sizing override remains, now driving
|
|
58
|
+
`TripleToggleSwitchCore`'s own public sizing tokens (`--triple-toggle-switch-gap`/`-padding`/
|
|
59
|
+
`-option-padding`/`-icon-size`, added in the same migration) instead of reaching into its
|
|
60
|
+
private `--_form-*`/`--_scheme-icon-font-size` locals directly.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: GlowingBorder
|
|
3
|
+
description: GlowingBorder decorative wrapper with an animated conic-gradient glow border in 5 colour variants
|
|
4
|
+
type: reference
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# GlowingBorder
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
`GlowingBorder` wraps its default slot content in a rotating conic-gradient border effect, built
|
|
12
|
+
with `@property`-registered custom properties so the hue rotation animates smoothly. It renders as
|
|
13
|
+
a configurable root element via the `tag` prop.
|
|
14
|
+
|
|
15
|
+
## Props
|
|
16
|
+
|
|
17
|
+
| Prop | Type | Default | Description |
|
|
18
|
+
|------|------|---------|-------------|
|
|
19
|
+
| `tag` | `"div" \| "p" \| "span" \| "section" \| "article" \| "aside" \| "header" \| "footer" \| "main" \| "nav" \| "ul" \| "ol"` | `"div"` | Root element tag. |
|
|
20
|
+
| `variant` | `"subtle" \| "vivid" \| "silver" \| "steel" \| "green"` | `"subtle"` | Glow colour variant. |
|
|
21
|
+
| `styleClassPassthrough` | `string \| string[]` | `[]` | Extra classes applied to the root element. |
|
|
22
|
+
|
|
23
|
+
## Slots
|
|
24
|
+
|
|
25
|
+
| Slot | Description |
|
|
26
|
+
|---|---|
|
|
27
|
+
| `default` | Content rendered inside the glowing border. |
|
|
28
|
+
|
|
29
|
+
## Basic usage
|
|
30
|
+
|
|
31
|
+
```vue
|
|
32
|
+
<GlowingBorder variant="vivid">
|
|
33
|
+
<p>Content wrapped in a glowing border</p>
|
|
34
|
+
</GlowingBorder>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Styling
|
|
38
|
+
|
|
39
|
+
Border width, radius, surface colour, animation duration, and every variant's 5 gradient colour
|
|
40
|
+
stops are public CSS custom properties — see `CONSUMER-STYLING.md` for the full token table.
|
|
41
|
+
|
|
42
|
+
```vue
|
|
43
|
+
<GlowingBorder
|
|
44
|
+
variant="steel"
|
|
45
|
+
style="--glowing-border-width: 2px; --glowing-border-animation-duration: 6s;"
|
|
46
|
+
>
|
|
47
|
+
<p>Slower, thinner steel glow</p>
|
|
48
|
+
</GlowingBorder>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Motion
|
|
52
|
+
|
|
53
|
+
The glow animation stops automatically under `prefers-reduced-motion: reduce`.
|
|
54
|
+
|
|
55
|
+
## Notes
|
|
56
|
+
|
|
57
|
+
- 2026-09-20 migration: moved from `app/components/glowing-border/` (unplaced) into
|
|
58
|
+
`01.atoms/animations/glowing-border/`; converted from options-style `defineProps({...})` to
|
|
59
|
+
`interface Props` + `withDefaults`; promoted border width/radius/surface/animation-duration and
|
|
60
|
+
every variant's 5 colour stops (previously hardcoded or unprefixed `--border-width`/`--surface`)
|
|
61
|
+
to public `--glowing-border-*` tokens; renamed internal composition custom properties
|
|
62
|
+
(`--clr-1..5`, `--glow-deg`, `--gradient-glow`) to private `--_clr-1..5`/`--_glow-deg`/
|
|
63
|
+
`--_gradient-glow`; added a `prefers-reduced-motion` guard. No behaviour change beyond the new
|
|
64
|
+
override surface.
|
|
65
|
+
- 2026-09-20: added `green` variant (vibrant, saturated greens: `#00ff87`, `#39ff14`, `#00c853`,
|
|
66
|
+
`#64dd17`, `#00e676`), each stop overridable via `--glowing-border-green-color-{1-5}`.
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# InputRangeCore Component
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
`InputRangeCore` is the low-level native `<input type="range">` primitive for the `05.forms`
|
|
6
|
+
range-slider family. It renders a single native range input with left/right button slots (for
|
|
7
|
+
step-down/step-up controls), an optional `markers` slot for custom tick marks overlaid on the
|
|
8
|
+
track, and an optional `datalist` slot for native tick-mark snapping. It has no label,
|
|
9
|
+
description, or error-message rendering of its own — that's composed by the `InputRangeDefault`
|
|
10
|
+
variant below.
|
|
11
|
+
|
|
12
|
+
Most consumers should reach for **InputRangeDefault** rather than `InputRangeCore` directly.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Props reference
|
|
17
|
+
|
|
18
|
+
> **Hyphenation rule**: Vue's ESLint config enforces `vue/attribute-hyphenation`. Always write camelCase prop names hyphenated in templates: `:field-has-error`, `:style-class-passthrough`, `:aria-describedby`.
|
|
19
|
+
|
|
20
|
+
| Prop (template form) | Type | Default | Notes |
|
|
21
|
+
|------|------|---------|-------|
|
|
22
|
+
| `:id` | `string` | (required) | Applied to the native input. |
|
|
23
|
+
| `:name` | `string` | (required) | Applied to the native input, and used to derive the `list` id when the `datalist` slot is used (`${name}-datalist`). |
|
|
24
|
+
| `:min` | `number` | (required) | Native `min`. |
|
|
25
|
+
| `:max` | `number` | (required) | Native `max`. |
|
|
26
|
+
| `:step` | `number` | `1` | Native `step`. |
|
|
27
|
+
| `:required` | `boolean` | `false` | Native `required`. |
|
|
28
|
+
| `:placeholder` | `string` | `""` | Declared but not rendered — range inputs have no placeholder concept. Kept for prop-shape consistency with sibling `05.forms` components. |
|
|
29
|
+
| `:theme` | `FormUiTheme` | `"default"` | Sets `data-theme` on the wrapper. |
|
|
30
|
+
| `:weight` | `FormWeight` | `"normal"` | Adds an `input-range--{weight}` class to the input. **No CSS in the library currently styles this class — it's a no-op today**, kept for prop-shape consistency with sibling components. |
|
|
31
|
+
| `:field-has-error` | `boolean` | `false` | Declared, but doesn't drive any visible state inside `InputRangeCore` itself — `InputRangeDefault` handles the actual error styling (`data-invalid`/`.error` class) on its own wrapper. |
|
|
32
|
+
| `:style-class-passthrough` | `string \| string[]` | `[]` | Extra CSS classes applied to the input element. |
|
|
33
|
+
| `:aria-describedby` | `string` | `""` | Forwarded to the native input. |
|
|
34
|
+
|
|
35
|
+
### v-model
|
|
36
|
+
|
|
37
|
+
`v-model` — `number`, **required** (`defineModel<number>({ required: true })`). Bound directly to
|
|
38
|
+
the native range input. Required rather than defaulted deliberately — a real `<input type="range">`
|
|
39
|
+
always has a concrete value (there's no meaningful "empty" range slider), so a default here would
|
|
40
|
+
be an artificial value rather than reflecting actual native behaviour. This also satisfies
|
|
41
|
+
`vue/require-default-prop`, which otherwise flags any `defineModel()` without a default — see
|
|
42
|
+
`project_ledger_eslint_issues_column` in memory for why that's the correct fix (not a rule
|
|
43
|
+
disable, not a fake default).
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Slots
|
|
48
|
+
|
|
49
|
+
| Slot | Notes |
|
|
50
|
+
|------|-------|
|
|
51
|
+
| `left` | Rendered before the track (e.g. a step-down button). |
|
|
52
|
+
| `right` | Rendered after the track (e.g. a step-up button). |
|
|
53
|
+
| `markers` | Rendered as an overlay on top of the track (`grid-area: element-stack`, same cell as the input). Adds a `has-markers` class to the input, which shrinks its visible track to a thin `0.2rem` strip and hides the native thumb, so your marker content becomes the primary visual. Expected shape: a `.input-range-markers` wrapper containing `.marker` elements (each optionally containing a `.marker-icon`) — see the component's own scoped CSS for the classes it pre-styles. |
|
|
54
|
+
| `datalist` | Rendered after the input. Must contain a real `<datalist>` element whose `id` matches `${name}-datalist` for the browser to link it via the input's `list` attribute — the component computes that id string for the `list` attribute itself, but does not set the `id` on your slotted `<datalist>` for you. |
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## CSS token API
|
|
59
|
+
|
|
60
|
+
See [CONSUMER-STYLING.md](../../app/components/05.forms/input-range/CONSUMER-STYLING.md) for the
|
|
61
|
+
full table with defaults.
|
|
62
|
+
|
|
63
|
+
**Common tokens:**
|
|
64
|
+
- `--input-range-accent-colour` — native `accent-color` (track/thumb tint), falls back to `--theme-accent`
|
|
65
|
+
- `--input-range-marker-background-colour` / `-outline-colour` — marker dot styling
|
|
66
|
+
- `--input-range-marker-icon-colour` — falls back to `--input-range-accent-colour`
|
|
67
|
+
|
|
68
|
+
Thumb/track height and the button-slot's button size come from the shared global geometry token
|
|
69
|
+
`--input-range-button-size` (declared in `03.generic-input-geometry.css`, not owned by this
|
|
70
|
+
component), matching the convention `theming-form-geometry-tokens.md` documents for the rest of
|
|
71
|
+
`05.forms`.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Fixed 2026-09-21: dead `accent-color` token
|
|
76
|
+
|
|
77
|
+
`accent-color` previously read `--theme-form-range-accent-color`, a custom property that was never
|
|
78
|
+
declared anywhere in the codebase, with no fallback. Per the CSS spec, an undefined `var()` with
|
|
79
|
+
no fallback makes the whole declaration invalid at computed-value time — so `accent-color` was
|
|
80
|
+
silently falling back to the browser's native default (an OS-dependent blue) instead of the
|
|
81
|
+
intended theme colour, in every place it was used (the input itself, its `.has-markers` state, and
|
|
82
|
+
the marker icon colour). This is the same bug class found in `CarouselFlip`'s edge-preview tokens
|
|
83
|
+
around the same time — check any component reaching for a `--theme-*`-prefixed custom property for
|
|
84
|
+
a real declaration of that name before trusting it renders correctly.
|
|
85
|
+
|
|
86
|
+
Also removed: a broken `::-webkit-slider-thumb` rule (`background-color: 0.1rem solid green` is
|
|
87
|
+
invalid CSS and was silently dropped; `accent-color`/`color` don't apply to that pseudo-element at
|
|
88
|
+
all) and ~60 lines of dead commented-out alternative thumb/track styling — none of it had any
|
|
89
|
+
visible effect, since `appearance: none` (required for custom thumb/track styling to take effect)
|
|
90
|
+
was itself commented out.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Variants
|
|
95
|
+
|
|
96
|
+
### InputRangeDefault
|
|
97
|
+
|
|
98
|
+
`InputRangeDefault` (`variants/InputRangeDefault.vue`) composes `InputRangeCore` with `InputLabel`,
|
|
99
|
+
`InputDescription`, and `InputError`, plus optional step-down/step-up buttons (`InputButtonCore`)
|
|
100
|
+
wired into the `left`/`right` slots.
|
|
101
|
+
|
|
102
|
+
**Additional props over InputRangeCore:**
|
|
103
|
+
|
|
104
|
+
| Prop (template form) | Type | Default | Notes |
|
|
105
|
+
|------|------|---------|-------|
|
|
106
|
+
| `:label` | `string` | (required) | Rendered via `InputLabel`. |
|
|
107
|
+
| `:error-message` | `object \| string` | (required) | Rendered via `InputError` when `field-has-error` is true. |
|
|
108
|
+
| `:step-down-label` | `string` | `"Step down"` | `button-text` on the step-down `InputButtonCore` — override for localisation. |
|
|
109
|
+
| `:step-up-label` | `string` | `"Step up"` | `button-text` on the step-up `InputButtonCore` — override for localisation. |
|
|
110
|
+
|
|
111
|
+
**Slots**: `descriptionHtml`, `descriptionText` (both forwarded to `InputDescription`), plus
|
|
112
|
+
`left`/`right`/`markers`/`datalist` (forwarded straight through to the underlying
|
|
113
|
+
`InputRangeCore` — the step-down/step-up buttons only render when you use the `left`/`right`
|
|
114
|
+
slots yourself, since the button icon content itself is consumer-supplied via `#iconOnly`).
|
|
115
|
+
|
|
116
|
+
```vue
|
|
117
|
+
<InputRangeDefault
|
|
118
|
+
name="priceRange"
|
|
119
|
+
label="Price range"
|
|
120
|
+
v-model="price"
|
|
121
|
+
:min="0"
|
|
122
|
+
:max="500"
|
|
123
|
+
:step="10"
|
|
124
|
+
error-message="Please choose a value within the allowed range"
|
|
125
|
+
:field-has-error="hasError"
|
|
126
|
+
>
|
|
127
|
+
<template #left><Icon name="mdi:minus" /></template>
|
|
128
|
+
<template #right><Icon name="mdi:plus" /></template>
|
|
129
|
+
</InputRangeDefault>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
`v-model` is `number`, **required** — same as `InputRangeCore` above.
|
|
133
|
+
|
|
134
|
+
**Fixed 2026-09-21**: removed a dead `deepCssClassPassthrough` prop (declared, never consumed
|
|
135
|
+
anywhere in the component or referenced elsewhere in the codebase) and a dead `<style>` block
|
|
136
|
+
targeting `.input-range-label`/`.label-description` — classes that nothing in this component (or
|
|
137
|
+
`InputLabel`/`InputDescription`) actually renders, so the block had no effect. Also removed two
|
|
138
|
+
dead commented-out lines (`// const id = useId();`, a duplicate no-op `FormUiTheme` computed), and
|
|
139
|
+
(same day, follow-up pass) a `const props = withDefaults(...)` in both `InputRangeCore` and
|
|
140
|
+
`InputRangeDefault` that had become entirely unused once the dead `FormUiTheme` computed was
|
|
141
|
+
removed — the template's `:id`/`:name`/etc. shorthand bindings resolve straight from `defineProps`
|
|
142
|
+
automatically in `<script setup>`, no destructuring or `props.` reference needed.
|
|
@@ -52,20 +52,37 @@ type: reference
|
|
|
52
52
|
## How it works
|
|
53
53
|
|
|
54
54
|
The component sets:
|
|
55
|
+
|
|
55
56
|
- `background-image: url(...)` via `v-bind`
|
|
56
|
-
- `background-position: center`
|
|
57
|
-
- `background-size:
|
|
58
|
-
- `min-height:
|
|
59
|
-
- `background-color: light-dark(var(--slate-01), var(--slate-08))` (visible if image fails to load)
|
|
57
|
+
- `background-position: var(--section-parallax-background-position, center)`
|
|
58
|
+
- `background-size: var(--section-parallax-background-size, cover)`
|
|
59
|
+
- `min-height: var(--section-parallax-min-height, 100svh)`
|
|
60
|
+
- `background-color: var(--section-parallax-background-colour, light-dark(var(--slate-01), var(--slate-08)))` (visible if image fails to load)
|
|
61
|
+
|
|
62
|
+
Inside `@media (hover: hover) and (pointer: fine) { @supports (background-attachment: fixed) { ... } }`:
|
|
60
63
|
|
|
61
|
-
Inside `@supports (background-attachment: fixed)`:
|
|
62
64
|
- `background-attachment: fixed` — pins the image to the viewport
|
|
63
|
-
- `
|
|
64
|
-
|
|
65
|
+
- `min-height: var(--section-parallax-min-height-fixed, 120vh)` — ensures enough scroll travel to see the parallax motion
|
|
66
|
+
|
|
67
|
+
Under `@media (prefers-reduced-motion: reduce)`, the parallax is disabled regardless of hover/
|
|
68
|
+
`@supports` support: `background-attachment` reverts to `scroll` and height reverts to
|
|
69
|
+
`--section-parallax-min-height`.
|
|
65
70
|
|
|
66
|
-
##
|
|
71
|
+
## Styling
|
|
72
|
+
|
|
73
|
+
Height, background position/size/colour are all public CSS custom properties — see
|
|
74
|
+
`CONSUMER-STYLING.md` for the full token table.
|
|
75
|
+
|
|
76
|
+
```vue
|
|
77
|
+
<SectionParallax
|
|
78
|
+
background-image="/images/candle-and-stones.jpg"
|
|
79
|
+
style="--section-parallax-min-height: 60vh; --section-parallax-min-height-fixed: 70vh;"
|
|
80
|
+
>
|
|
81
|
+
<p>Shorter atmospheric break</p>
|
|
82
|
+
</SectionParallax>
|
|
83
|
+
```
|
|
67
84
|
|
|
68
|
-
|
|
85
|
+
Alternatively, override `min-height` with a consuming-page style:
|
|
69
86
|
|
|
70
87
|
```css
|
|
71
88
|
.my-page {
|
|
@@ -98,5 +115,10 @@ Override `min-height` with a consuming-page style:
|
|
|
98
115
|
## Notes
|
|
99
116
|
|
|
100
117
|
- The `@supports` guard means the parallax activates only when the browser supports `background-attachment: fixed`. No JS is involved.
|
|
101
|
-
- Slot content is only rendered when the `default` slot is provided (`v-if="slots.default"`).
|
|
102
118
|
- The component has no built-in overlay or gradient — add one via the slot or a `::before` pseudo-element in your consuming-page styles.
|
|
119
|
+
- 2026-09-20 migration: moved from `app/components/parallax/` (unplaced) into
|
|
120
|
+
`01.atoms/animations/section-parallax/`; props pattern was already `interface Props` +
|
|
121
|
+
`withDefaults` (no change needed); promoted min-height/background-position/background-size/
|
|
122
|
+
background-colour (previously hardcoded) to public `--section-parallax-*` tokens; added a
|
|
123
|
+
`prefers-reduced-motion: reduce` guard that disables the fixed-attachment parallax. No behaviour
|
|
124
|
+
change beyond the new override surface and the reduced-motion opt-out.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: UiBlockDecorated
|
|
3
|
+
description: UiBlockDecorated plain block wrapper with independent border/shadow/inner-shadow strength levels — props, CSS tokens
|
|
4
|
+
type: reference
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# UiBlockDecorated
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
`UiBlockDecorated` renders its slot content in a plain block element (configurable `tag`) with
|
|
12
|
+
three independent, optional decorations: a border, a drop shadow, and an inset ("inner") shadow.
|
|
13
|
+
Each decoration has its own 0-based "strength" prop that selects a level from a built-in scale;
|
|
14
|
+
`0` (the default) applies no class for that decoration, so all three are opt-in and combinable.
|
|
15
|
+
|
|
16
|
+
## Props
|
|
17
|
+
|
|
18
|
+
| Prop | Type | Default | Description |
|
|
19
|
+
|------|------|---------|-------------|
|
|
20
|
+
| `tag` | `"div" \| "p" \| "span" \| "section" \| "article" \| "aside" \| "header" \| "footer" \| "main" \| "nav" \| "ul" \| "ol"` | `"div"` | Root element tag. |
|
|
21
|
+
| `borderStrength` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6` | `0` | Border strength level; `0` = no border. |
|
|
22
|
+
| `shadowStrength` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6` | `0` | Drop shadow strength level; `0` = no shadow. |
|
|
23
|
+
| `innerShadowStrength` | `0 \| 1 \| 2 \| 3 \| 4` | `0` | Inset shadow strength level; `0` = no inner shadow. |
|
|
24
|
+
| `styleClassPassthrough` | `string \| string[]` | `[]` | Extra classes applied to the root element. |
|
|
25
|
+
|
|
26
|
+
## Basic usage
|
|
27
|
+
|
|
28
|
+
```vue
|
|
29
|
+
<UiBlockDecorated :shadow-strength="3">
|
|
30
|
+
<p>Block content</p>
|
|
31
|
+
</UiBlockDecorated>
|
|
32
|
+
|
|
33
|
+
<UiBlockDecorated tag="section" :border-strength="2" :inner-shadow-strength="1">
|
|
34
|
+
<p>Block content</p>
|
|
35
|
+
</UiBlockDecorated>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## CSS custom properties
|
|
39
|
+
|
|
40
|
+
Each strength level has its own public token — see CONSUMER-STYLING.md for the full table. In
|
|
41
|
+
short: `--ui-block-decorated-border-1` .. `-6`, `--ui-block-decorated-shadow-1` .. `-6`,
|
|
42
|
+
`--ui-block-decorated-inner-shadow-1` .. `-4`, and `--ui-block-decorated-inner-shadow-highlight`
|
|
43
|
+
(layered on top of every inner shadow level).
|
|
44
|
+
|
|
45
|
+
## Notes
|
|
46
|
+
|
|
47
|
+
- 2026-09-16 migration: previously used options-style `defineProps` and referenced six families of
|
|
48
|
+
global tokens (`--border-1`..`-6`, `--shadow-1`..`-6`, `--inner-shadow-1`..`-4`,
|
|
49
|
+
`--inner-shadow-highlight`) that were never declared anywhere in the codebase — every border,
|
|
50
|
+
shadow and inner shadow rendered as nothing. Fixed by giving each strength level its own
|
|
51
|
+
component-scoped public token (`--ui-block-decorated-*`) with a real fallback value baked in, so
|
|
52
|
+
the decorations work out of the box and are still fully overridable.
|
|
53
|
+
- The applied classes were also renamed from bare `.border-1`/`.shadow-1`/`.inner-shadow-1` to
|
|
54
|
+
`.ui-block-decorated-border-1` etc. — the un-prefixed names risked colliding with a consumer
|
|
55
|
+
app's own utility classes, since this component renders inline in the consumer's DOM (not
|
|
56
|
+
teleported/portaled).
|