srcdev-nuxt-components 9.4.9 → 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.
Files changed (112) hide show
  1. package/.claude/commands/migrate-component.md +20 -6
  2. package/.claude/component-ledger/audit.json +1 -1
  3. package/.claude/component-ledger/build.mjs +26 -0
  4. package/.claude/component-ledger/output.html +8 -3
  5. package/.claude/component-ledger/template.html +7 -2
  6. package/.claude/skills/component-dynamic-slots.md +1 -1
  7. package/.claude/skills/components/alert-mask-core.md +84 -0
  8. package/.claude/skills/components/canvas-switcher.md +1 -1
  9. package/.claude/skills/components/carousel-flip.md +112 -168
  10. package/.claude/skills/components/container-glow.md +123 -0
  11. package/.claude/skills/components/dashboard-quad-grid.md +98 -0
  12. package/.claude/skills/components/dashboard-stats-grid.md +103 -0
  13. package/.claude/skills/components/display-theme-switch.md +60 -0
  14. package/.claude/skills/components/glowing-border.md +66 -0
  15. package/.claude/skills/components/input-range-core.md +142 -0
  16. package/.claude/skills/components/section-parallax.md +32 -10
  17. package/.claude/skills/components/ui-block-decorated.md +56 -0
  18. package/.claude/skills/components/wipe-away-vertical.md +98 -0
  19. package/.claude/skills/icon-sets.md +1 -1
  20. package/.claude/skills/index.md +10 -1
  21. package/.vscode/css-custom-data.json +38 -0
  22. package/.vscode/settings.json +3 -0
  23. package/.vscode/srcdev-component-alert-mask-core.code-snippets +31 -0
  24. package/.vscode/srcdev-component-carousel-flip.code-snippets +41 -0
  25. package/.vscode/srcdev-component-container-glow.code-snippets +33 -0
  26. package/.vscode/srcdev-component-dashboard-quad-grid.code-snippets +36 -0
  27. package/.vscode/srcdev-component-dashboard-stats-grid.code-snippets +35 -0
  28. package/.vscode/srcdev-component-display-theme-switch.code-snippets +27 -0
  29. package/.vscode/srcdev-component-glowing-border.code-snippets +23 -0
  30. package/.vscode/srcdev-component-input-range.code-snippets +85 -0
  31. package/.vscode/srcdev-component-section-parallax.code-snippets +27 -0
  32. package/.vscode/srcdev-component-ui-block-decorated.code-snippets +24 -0
  33. package/.vscode/srcdev-component-wipe-away-vertical.code-snippets +25 -0
  34. package/README.md +18 -37
  35. package/app/components/{alert-mask → 01.atoms/alert-mask}/AlertMaskCore.vue +16 -17
  36. package/app/components/01.atoms/alert-mask/CONSUMER-STYLING.md +46 -0
  37. package/app/components/01.atoms/alert-mask/stories/AlertMaskCore.stories.ts +79 -0
  38. package/app/components/{alert-mask → 01.atoms/alert-mask}/tests/AlertMaskCore.spec.ts +10 -10
  39. package/app/components/01.atoms/animations/container-glow/CONSUMER-STYLING.md +86 -0
  40. package/app/components/01.atoms/animations/container-glow/ContainerGlow.vue +299 -0
  41. package/app/components/01.atoms/animations/container-glow/stories/ContainerGlow.stories.ts +175 -0
  42. package/app/components/01.atoms/animations/container-glow/tests/ContainerGlow.spec.ts +131 -0
  43. package/app/components/01.atoms/animations/container-glow/tests/__snapshots__/ContainerGlow.spec.ts.snap +14 -0
  44. package/app/components/01.atoms/animations/glowing-border/CONSUMER-STYLING.md +61 -0
  45. package/app/components/01.atoms/animations/glowing-border/GlowingBorder.vue +132 -0
  46. package/app/components/01.atoms/animations/glowing-border/stories/GlowingBorder.stories.ts +165 -0
  47. package/app/components/01.atoms/animations/glowing-border/tests/GlowingBorder.spec.ts +94 -0
  48. package/app/components/01.atoms/animations/glowing-border/tests/__snapshots__/GlowingBorder.spec.ts.snap +3 -0
  49. package/app/components/01.atoms/animations/section-parallax/CONSUMER-STYLING.md +44 -0
  50. package/app/components/{parallax → 01.atoms/animations/section-parallax}/SectionParallax.vue +11 -10
  51. package/app/components/01.atoms/animations/section-parallax/stories/SectionParallax.stories.ts +98 -0
  52. package/app/components/01.atoms/animations/section-parallax/tests/SectionParallax.spec.ts +102 -0
  53. package/app/components/01.atoms/animations/section-parallax/tests/__snapshots__/SectionParallax.spec.ts.snap +9 -0
  54. package/app/components/01.atoms/animations/view-timeline/CONSUMER-STYLING.md +70 -0
  55. package/app/components/01.atoms/animations/view-timeline/WipeAwayVertical.vue +181 -0
  56. package/app/components/01.atoms/animations/view-timeline/stories/WipeAwayVertical.stories.ts +269 -0
  57. package/app/components/01.atoms/animations/view-timeline/tests/WipeAwayVertical.spec.ts +127 -0
  58. package/app/components/01.atoms/canvas-switcher/CONSUMER-STYLING.md +1 -1
  59. package/app/components/01.atoms/canvas-switcher/stories/CanvasSwitcher.stories.ts +1 -1
  60. package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/CONSUMER-STYLING.md +42 -0
  61. package/app/components/{layout-grids/LayoutGridA.vue → 01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/DashboardQuadGrid.vue} +23 -13
  62. package/app/components/{layout-grids/stories/LayoutGridA.stories.ts → 01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/stories/DashboardQuadGrid.stories.ts} +151 -23
  63. package/app/components/{layout-grids/tests/LayoutGridA.spec.ts → 01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/tests/DashboardQuadGrid.spec.ts} +25 -25
  64. package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/CONSUMER-STYLING.md +41 -0
  65. package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/DashboardStatsGrid.vue +133 -0
  66. package/app/components/{layout-grids/stories/LayoutGridB.stories.ts → 01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/stories/DashboardStatsGrid.stories.ts} +24 -24
  67. package/app/components/{layout-grids/tests/LayoutGridB.spec.ts → 01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/tests/DashboardStatsGrid.spec.ts} +23 -23
  68. package/app/components/01.atoms/ui-block-decorated/CONSUMER-STYLING.md +39 -0
  69. package/app/components/01.atoms/ui-block-decorated/UiBlockDecorated.vue +141 -0
  70. package/app/components/01.atoms/ui-block-decorated/stories/UiBlockDecorated.stories.ts +148 -0
  71. package/app/components/01.atoms/ui-block-decorated/tests/UiBlockDecorated.spec.ts +80 -0
  72. package/app/components/01.atoms/ui-block-decorated/tests/__snapshots__/UiBlockDecorated.spec.ts.snap +3 -0
  73. package/app/components/02.molecules/alert-masked-content/tests/AlertMaskedContent.spec.ts +6 -6
  74. package/app/components/02.molecules/display-theme-switch/CONSUMER-STYLING.md +34 -0
  75. package/app/components/02.molecules/display-theme-switch/DisplayThemeSwitch.vue +102 -0
  76. package/app/components/02.molecules/display-theme-switch/stories/DisplayThemeSwitch.stories.ts +115 -0
  77. package/app/components/02.molecules/display-theme-switch/tests/DisplayThemeSwitch.spec.ts +86 -0
  78. package/app/components/03.organisms/image-galleries/carousel-flip/CONSUMER-STYLING.md +46 -0
  79. package/app/components/{carousels → 03.organisms/image-galleries/carousel-flip}/CarouselFlip.vue +63 -42
  80. package/app/components/{carousels → 03.organisms/image-galleries/carousel-flip}/stories/CarouselFlip.stories.ts +96 -11
  81. package/app/components/{carousels → 03.organisms/image-galleries/carousel-flip}/tests/CarouselFlip.spec.ts +80 -0
  82. package/app/components/05.forms/form-field/FormField.vue +1 -1
  83. package/app/components/05.forms/form-wrapper/FormWrapper.vue +1 -1
  84. package/app/components/05.forms/input-range/CONSUMER-STYLING.md +45 -0
  85. package/app/components/05.forms/input-range/InputRangeCore.vue +79 -143
  86. package/app/components/05.forms/input-range/stories/InputRangeCore.stories.ts +126 -0
  87. package/app/components/05.forms/input-range/tests/InputRangeCore.spec.ts +124 -0
  88. package/app/components/05.forms/input-range/variants/InputRangeDefault.vue +9 -32
  89. package/app/components/05.forms/input-range/variants/stories/InputRangeDefault.stories.ts +108 -0
  90. package/app/components/05.forms/input-range/variants/tests/InputRangeDefault.spec.ts +140 -0
  91. package/app/components/05.forms/patterns/stories/MigratedFieldsForm.stories.ts +135 -0
  92. package/app/components/05.forms/triple-toggle-switch/CONSUMER-STYLING.md +16 -2
  93. package/app/components/05.forms/triple-toggle-switch/TripleToggleSwitchCore.vue +6 -4
  94. package/app/types/components/container-glow.d.ts +8 -0
  95. package/app/types/components/index.ts +1 -1
  96. package/package.json +3 -2
  97. package/app/components/05.forms/input-range-fancy/InputRangeFancyCore.vue +0 -426
  98. package/app/components/05.forms/input-range-fancy/InputRangeFancyWithLabel.vue +0 -94
  99. package/app/components/carousels/CarouselBasic.vue +0 -317
  100. package/app/components/carousels/CarouselInfinite.vue +0 -358
  101. package/app/components/container-glow/ContainerGlowCore.vue +0 -296
  102. package/app/components/container-glow/stories/ContainerGlowCore.stories.ts +0 -337
  103. package/app/components/display-theme-switch/DisplayThemeSwitch.vue +0 -189
  104. package/app/components/display-theme-switch/stories/DisplayThemeSwitch.stories.ts +0 -154
  105. package/app/components/glowing-border/GlowingBorder.vue +0 -142
  106. package/app/components/glowing-border/stories/GlowingBorder.stories.ts +0 -141
  107. package/app/components/layout-grids/LayoutGridB.vue +0 -134
  108. package/app/components/test-storybook/TestStorybook.vue +0 -49
  109. package/app/components/test-storybook/stories/TestStorybook.stories.ts +0 -28
  110. package/app/components/ui-block-decorated/UiBlockDecorated.vue +0 -167
  111. package/app/components/view-timeline/WipeAwayVertical.vue +0 -180
  112. package/app/types/components/carousel-basic.d.ts +0 -19
@@ -0,0 +1,98 @@
1
+ ---
2
+ name: WipeAwayVertical
3
+ description: WipeAwayVertical scroll-driven vertical wipe-away effect — props, dynamic slot API, CSS grid overlay mechanics, CSS tokens
4
+ type: reference
5
+ ---
6
+
7
+ # WipeAwayVertical
8
+
9
+ ## Overview
10
+
11
+ `WipeAwayVertical` is a scroll-driven "wipe away" effect: a stack of sticky panels, each of
12
+ which wipes away (via a `clip-path` animation) to reveal the panel underneath as the user
13
+ scrolls past its paired tracking section. Pure CSS — built on `animation-timeline: view()`, a
14
+ single-column CSS grid overlay, and no JavaScript scroll listeners or measurement at all.
15
+
16
+ ## How it works
17
+
18
+ - The root is a single-column CSS grid. `.sticky-items-container` spans every row as an overlay
19
+ (`grid-row: 1 / -1`), holding `itemCount` `.sticky-item` panels stacked with descending
20
+ `z-index` (item 0 on top).
21
+ - Each real `.scrolling-section` gets its own explicit grid row and acts as a scroll tracker —
22
+ its entry into the viewport drives the wipe-out animation of its paired sticky item via a
23
+ named `view-timeline`. Only `itemCount - 1` sections are rendered: the **last** sticky item
24
+ has nothing left to reveal, so it has no wipe animation (`animation-timeline: none`) and no
25
+ scrolling section of its own.
26
+ - A `.leading-buffer` (fixed `100vh`) renders before the first scrolling section, so section 0
27
+ isn't already partway through its `entry` timeline range at page load, whatever content
28
+ precedes the component.
29
+ - A `.trailing-buffer`, sized by `--wipe-away-vertical-trailing-buffer` (default `20vh`), renders
30
+ after the last real scrolling section — just enough room for the sticky container to release
31
+ cleanly once the final panel is fully revealed.
32
+ - `.sticky-items-container` is sized by `--wipe-away-vertical-height` (default `100vh`) and
33
+ centers itself with `top: calc((100vh - var(--wipe-away-vertical-height, 100vh)) / 2)` — a
34
+ plain `calc()`, deliberately **not** a `transform: translateY()`. `position: sticky`'s
35
+ stick/release threshold is computed from the element's *untransformed* layout position, so a
36
+ transform-based visual shift releases the sticky panel early by the transformed amount,
37
+ leaving a gap after the last panel. `.scrolling-section`'s `view-timeline-inset` uses the same
38
+ `calc()` so the entry/exit range lines up with the same visual offset. (An earlier version
39
+ used `top: 50%` — also wrong, since a percentage `top` on `position: sticky` resolves against
40
+ the containing block's height, not the viewport, and this component's containing block is
41
+ deliberately many viewport-heights tall.)
42
+ - Where `@supports not (animation-timeline: view())`, the grid/sticky/animation machinery is
43
+ dropped entirely: the root becomes `display: block`, the leading/trailing buffers and
44
+ scrolling sections are hidden, and the sticky items render as plain stacked panels in normal
45
+ document flow. No JS fallback, no opacity crossfade — just a flat, static stack.
46
+
47
+ ## Props
48
+
49
+ | Prop | Type | Default | Description |
50
+ |------|------|---------|-------------|
51
+ | `tag` | `"div" \| "section" \| "main" \| "article" \| "aside"` | `"div"` | Root element tag. |
52
+ | `itemCount` | `number` | — (required) | Number of sticky panels. Drives the sticky-item slot loop, `itemCount - 1` scrolling sections, per-item `z-index`, and `view-timeline` naming. |
53
+ | `styleClassPassthrough` | `string \| string[]` | `[]` | Extra classes applied to the root element. |
54
+
55
+ ## Slots
56
+
57
+ Dynamic named slots:
58
+
59
+ | Slot | Description |
60
+ |------|-------------|
61
+ | `stickyItem-{n}` | Content for sticky panel `n`, indexed `0` to `itemCount - 1`. |
62
+ | `scrollingItem-{n}` | Content (or an empty spacer) for scroll-tracking section `n`, indexed `0` to `itemCount - 2` only — the last panel has no scrolling section of its own. Typically an empty `100vh`-tall `div`; its height determines how much scroll distance that panel's wipe covers. |
63
+
64
+ ## Basic usage
65
+
66
+ ```vue
67
+ <WipeAwayVertical :item-count="3">
68
+ <template #stickyItem-0><PanelOne /></template>
69
+ <template #stickyItem-1><PanelTwo /></template>
70
+ <template #stickyItem-2><PanelThree /></template>
71
+
72
+ <template #scrollingItem-0><div style="height: 100vh;"></div></template>
73
+ <template #scrollingItem-1><div style="height: 100vh;"></div></template>
74
+ </WipeAwayVertical>
75
+ ```
76
+
77
+ Leave the root's own `height` unset — it's a grid that sizes itself from its children (leading
78
+ buffer + scrolling sections + trailing buffer). Setting an explicit height undersizes the root
79
+ relative to its real content and releases the sticky panel mid-wipe.
80
+
81
+ ## CSS custom properties
82
+
83
+ | Property | Default | Applies to |
84
+ |----------|---------|------------|
85
+ | `--wipe-away-vertical-height` | `100vh` | `.sticky-items-container` height (the visible sticky panel stack) |
86
+ | `--wipe-away-vertical-border-radius` | `0.5rem` | `.sticky-item` corner radius |
87
+ | `--wipe-away-vertical-animation-duration` | `1s` | `wipe-out` keyframe duration (view-timeline-supporting browsers) |
88
+ | `--wipe-away-vertical-trailing-buffer` | `20vh` | height of the release cushion after the last real scrolling section |
89
+
90
+ ## Notes
91
+
92
+ - Uses indexed dynamic slots (not the library's default named-dynamic-slot pattern) because
93
+ `itemCount` also drives non-slot logic: per-item `z-index`, grid rows, and the
94
+ `view-timeline-name`/`animation-timeline` CSS variable naming, not just the slot loop itself.
95
+ - Reduced motion: the wipe animation is disabled under `prefers-reduced-motion: reduce`
96
+ (`animation: none; clip-path: none;`) — all panels render fully visible with no clip.
97
+ - No hardcoded consumer-facing text — this is a purely structural/animation wrapper around
98
+ consumer-supplied slot content.
@@ -21,7 +21,7 @@ The layer's `modules/icon-sets.ts` runs at dev/build time and logs an info messa
21
21
  | `bi` | `@iconify-json/bi` | NavigationItems (overflow caret) |
22
22
  | `bitcoin-icons` | `@iconify-json/bitcoin-icons` | Display components |
23
23
  | `gravity-ui` | `@iconify-json/gravity-ui` | NavigationItems (burger/ellipsis overflow) |
24
- | `ic` | `@iconify-json/ic` | CarouselBasic, CarouselFlip, CarouselInfinite, SliderGallery, CanvasSwitcher |
24
+ | `ic` | `@iconify-json/ic` | CarouselFlip, SliderGallery, CanvasSwitcher |
25
25
  | `lucide` | `@iconify-json/lucide` | ColourFinder, TreatmentConsultant |
26
26
  | `material-symbols` | `@iconify-json/material-symbols` | form components |
27
27
  | `mdi` | `@iconify-json/mdi` | NavigationHorizontal, form components, ServicesCard |
@@ -63,6 +63,7 @@ Each skill is a single markdown file named `<area>-<task>.md`.
63
63
  ├── composable-analytics.md — useAnalytics: provider-agnostic trackEvent/page-view tracking (google-analytics only implemented), consent-gated, single call site for setup + firing events
64
64
  └── components/
65
65
  ├── alert-content-inner.md — AlertContentInner: shared icon/body/dismiss molecule under AlertContent + AlertMaskedContent; app.config icon map (alertContent.icons + dismissIcon) covers all consumers
66
+ ├── alert-mask-core.md — AlertMaskCore: SVG border/background mask sized to slotted content via ResizeObserver, config-prop-driven geometry/colour (no CSS token API)
66
67
  ├── animated-svg-text.md — AnimatedSvgText: inline SVG stroke-draw-then-fill animation, text slot, CSS token API
67
68
  ├── accordian-core.md — AccordianCore indexed dynamic slots (accordian-{n}-summary/icon/content), exclusive-open grouping
68
69
  ├── eyebrow-text.md — EyebrowText props, usage patterns, styling
@@ -92,6 +93,7 @@ Each skill is a single markdown file named `<area>-<task>.md`.
92
93
  ├── grid-stack.md — GridStack: CSS Grid z-axis stacking, slot API, z-order rules, sizing, video+overlay and image+text patterns
93
94
  ├── scroll-reveal-frame.md — ScrollRevealFrame: generic parallax clipping frame, slot API, image grid pattern, CSS tokens, browser support
94
95
  ├── scroll-reveal-image.md — ScrollRevealImage: single-image parallax reveal, focalX, imgWidth/imgHeight, responsive frame height
96
+ ├── wipe-away-vertical.md — WipeAwayVertical: scroll-driven vertical wipe-away effect, pure-CSS grid overlay (no JS), indexed dynamic slots, sticky-centering-via-calc gotcha, CSS tokens
95
97
  ├── marquee-scroller.md — MarqueeScroller: infinite logo/badge scroller, per-item dynamic slots (marqueeData id), hover/focus/keyboard pause, reduced-motion, CSS tokens
96
98
  ├── rotating-carousel-image.md — RotatingCarouselImage: 3D rotating image carousel, scroll-parallax tilt, focus/keyboard/hover pause, reduced-motion, CSS tokens
97
99
  ├── site-navigation.md — SiteNavigation: responsive nav with auto-collapse, burger menu, decorator indicators, CSS token API
@@ -102,6 +104,7 @@ Each skill is a single markdown file named `<area>-<task>.md`.
102
104
  ├── decode-qr-code.md — DecodeQrCode: file picker + drag-and-drop image decoder, shared results list, CSS override points
103
105
  ├── auto-grid.md — AutoGrid: auto-fit responsive grid, $slots iteration, --auto-grid-min-col-size/gap tokens, semantic tag + aria
104
106
  ├── display-avatar.md — DisplayAvatar: circular avatar with image/initials fallback, size variants, chip badge, icon slot, styleClassPassthrough
107
+ ├── display-theme-switch.md — DisplayThemeSwitch: system/light/dark picker wrapping TripleToggleSwitchCore, wired to useSettingsStore, labels/icons props, small sizing variant
105
108
  ├── card-core.md — CardCore: generic card container, dynamic named slots as rows, 4 variants, blurred backdrop layer, full CSS token API
106
109
  ├── action-menu.md — ActionMenu + ActionMenuItemCore: ellipsis trigger + anchored popover menu, indexed item-{n} slots, link/button items, full CSS token API
107
110
  ├── display-dialog.md — DisplayDialog: native <dialog> overlay, 5 variants (dialog/modal/confirm/alert/fullscreen), useDialogControls integration, CSS token API
@@ -123,9 +126,15 @@ Each skill is a single markdown file named `<area>-<task>.md`.
123
126
  ├── display-tooltip-defined.md — DisplayTooltipDefined: structured title/body/action tooltip content with close button, composes DisplayTooltip
124
127
  ├── pop-over.md — PopOver: generic anchor-positioned disclosure panel, consumer-supplied trigger/content slots, placement prop, CSS token API
125
128
  ├── input-text-core.md — InputTextCore: native text/date/number input primitive, min/max pass-through (date-picker range), CSS token API; Variants section covers InputTextWithLabel/InputPasswordWithLabel/InputTextAsNumberWithLabel
129
+ ├── input-range-core.md — InputRangeCore: native range-slider primitive, markers/datalist slots, dead --theme-form-range-accent-color token fixed, CSS token API; Variants section covers InputRangeDefault
126
130
  ├── entry-animation.md — EntryAnimation: scroll-driven entry animation wrapper (slide-in/zoom-reveal/exit-blur utility classes), skipAnimation for above-the-fold loop items, reduced-motion handled at the CSS layer
127
131
  ├── column-flow-grid.md — ColumnFlowGrid (renamed from MasonryGrid): CSS multi-column text-flow layout, named dynamic slots (no count/data prop), itemMinWidth/gap/unit sizing, CSS token API; not a true masonry, see "which one do I want?"
128
- └── masonry-grid.md — MasonryGrid: real measured-height masonry (greedy shortest-column packing, animated resize) absorbed from the now-retired MasonryGridOrdered; named dynamic slots, fixedWidth/justify, CSS token API
132
+ ├── masonry-grid.md — MasonryGrid: real measured-height masonry (greedy shortest-column packing, animated resize) absorbed from the now-retired MasonryGridOrdered; named dynamic slots, fixedWidth/justify, CSS token API
133
+ ├── glowing-border.md — GlowingBorder: animated conic-gradient glow border, 5 colour variants, tag prop, full CSS token API for width/radius/surface/duration/per-variant colour stops, reduced-motion guard
134
+ ├── section-parallax.md — SectionParallax: CSS fixed-background parallax section, iOS Safari limitation, when to use vs ScrollRevealImage, CSS token API, reduced-motion guard
135
+ ├── container-glow.md — ContainerGlow (renamed from ContainerGlowCore): pointer-proximity glow-border cards, named dynamic slots (one card per slot), config-prop-driven layout/interaction, full CSS token API for static visuals, reduced-motion guard
136
+ ├── dashboard-quad-grid.md — DashboardQuadGrid (renamed from LayoutGridA): fixed 4-slot dashboard grid, container-query breakpoints, CSS token API
137
+ └── dashboard-stats-grid.md — DashboardStatsGrid (renamed from LayoutGridB): top-row panel cluster + bottom-row panel strip dashboard grid, topRowSlot1ItemCount/bottomRowItemCount, CSS token API
129
138
  ```
130
139
 
131
140
  ## Skill file template
@@ -0,0 +1,38 @@
1
+ {
2
+ "version": 1.1,
3
+ "properties": [
4
+ {
5
+ "name": "rule",
6
+ "status": "experimental",
7
+ "description": "CSS Gap Decorations: shorthand for row-rule/column-rule width, style, and colour — draws lines in the gaps between grid/flex items. Limited browser support as of 2026.",
8
+ "references": [
9
+ {
10
+ "name": "MDN Reference",
11
+ "url": "https://developer.mozilla.org/en-US/docs/Web/CSS/rule"
12
+ }
13
+ ]
14
+ },
15
+ {
16
+ "name": "rule-break",
17
+ "status": "experimental",
18
+ "description": "CSS Gap Decorations: controls whether gap rule lines break at grid item intersections (e.g. \"intersection\", \"spanning-item\"). Limited browser support as of 2026.",
19
+ "references": [
20
+ {
21
+ "name": "MDN Reference",
22
+ "url": "https://developer.mozilla.org/en-US/docs/Web/CSS/rule-break"
23
+ }
24
+ ]
25
+ },
26
+ {
27
+ "name": "rule-inset",
28
+ "status": "experimental",
29
+ "description": "CSS Gap Decorations: insets gap rule lines from the edges of the items they run between. Limited browser support as of 2026.",
30
+ "references": [
31
+ {
32
+ "name": "MDN Reference",
33
+ "url": "https://developer.mozilla.org/en-US/docs/Web/CSS/rule-inset"
34
+ }
35
+ ]
36
+ }
37
+ ]
38
+ }
@@ -36,6 +36,9 @@
36
36
  "editor.trimAutoWhitespace": "explicit"
37
37
  }
38
38
  },
39
+ // Recognises CSS properties too new for VS Code's built-in CSS language service (e.g. Gap Decorations' rule/rule-break/rule-inset)
40
+ "css.customData": [".vscode/css-custom-data.json"],
41
+
39
42
  // More info: https://open-props.style/#getting-started
40
43
  "cssvar.files": ["assets/styles/main.css"],
41
44
  "cssvar.ignore": [],
@@ -0,0 +1,31 @@
1
+ {
2
+ "SRCDEV AlertMaskCore Basic": {
3
+ "description": "AlertMaskCore — SVG border/background mask sized to slotted content",
4
+ "scope": "vue,html",
5
+ "body": [
6
+ "<AlertMaskCore>",
7
+ " $0",
8
+ "</AlertMaskCore>"
9
+ ]
10
+ },
11
+ "SRCDEV AlertMaskCore Custom Config": {
12
+ "description": "AlertMaskCore with custom colour/geometry config",
13
+ "scope": "vue,html",
14
+ "body": [
15
+ "<AlertMaskCore",
16
+ " :config=\"{",
17
+ " borderColour: '$1var(--theme-accent)',",
18
+ " backgroundColour: '$2rgba(0, 0, 0, 0.3)',",
19
+ " radiusLeft: $38,",
20
+ " radiusRight: $44,",
21
+ " borderLeft: $56,",
22
+ " borderTop: $61,",
23
+ " borderRight: $71,",
24
+ " borderBottom: $81,",
25
+ " }\"",
26
+ ">",
27
+ " $0",
28
+ "</AlertMaskCore>"
29
+ ]
30
+ }
31
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "SRCDEV CarouselFlip Basic": {
3
+ "description": "CarouselFlip with looped item slots",
4
+ "scope": "vue,html",
5
+ "body": [
6
+ "<CarouselFlip :carousel-data-ids=\"$1items.map((item) => item.id)\">",
7
+ " <template v-for=\"$2item in $1items\" :key=\"$2item.id\" #[$2item.id]>",
8
+ " $3",
9
+ " </template>",
10
+ "</CarouselFlip>"
11
+ ]
12
+ },
13
+ "SRCDEV CarouselFlip Overlay Controls": {
14
+ "description": "CarouselFlip with markers floating over the item track",
15
+ "scope": "vue,html",
16
+ "body": [
17
+ "<CarouselFlip",
18
+ " :carousel-data-ids=\"$1items.map((item) => item.id)\"",
19
+ " button-layout=\"overlay\"",
20
+ " :use-flip-animation=\"true\"",
21
+ ">",
22
+ " <template v-for=\"$2item in $1items\" :key=\"$2item.id\" #[$2item.id]>",
23
+ " $3",
24
+ " </template>",
25
+ "</CarouselFlip>"
26
+ ]
27
+ },
28
+ "SRCDEV CarouselFlip CSS Override": {
29
+ "description": "CSS override scaffold for CarouselFlip tokens",
30
+ "scope": "css",
31
+ "body": [
32
+ ".$1my-page {",
33
+ " .carousel-flip {",
34
+ " --carousel-flip-gap: $2;",
35
+ " --carousel-flip-marker-active-colour: $3;",
36
+ " --carousel-flip-button-background-colour: $4;",
37
+ " }",
38
+ "}"
39
+ ]
40
+ }
41
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "SRCDEV ContainerGlow Basic": {
3
+ "description": "ContainerGlow — pointer-proximity glow-border card(s), one card per named slot",
4
+ "scope": "vue,html",
5
+ "body": [
6
+ "<ContainerGlow>",
7
+ " <template #${1:one}>",
8
+ " $0",
9
+ " </template>",
10
+ "</ContainerGlow>"
11
+ ]
12
+ },
13
+ "SRCDEV ContainerGlow With Config": {
14
+ "description": "ContainerGlow with custom proximity/spread/blur/gap/vertical config",
15
+ "scope": "vue,html",
16
+ "body": [
17
+ "<ContainerGlow",
18
+ " :config=\"{",
19
+ " proximity: ${1:40},",
20
+ " spread: ${2:80},",
21
+ " blur: ${3:20},",
22
+ " gap: ${4:32},",
23
+ " vertical: ${5:false},",
24
+ " inactiveOpacity: ${6:0},",
25
+ " }\"",
26
+ ">",
27
+ " <template #${7:one}>",
28
+ " $0",
29
+ " </template>",
30
+ "</ContainerGlow>"
31
+ ]
32
+ }
33
+ }
@@ -0,0 +1,36 @@
1
+ {
2
+ "SRCDEV DashboardQuadGrid Basic": {
3
+ "description": "DashboardQuadGrid with all four fixed slots",
4
+ "scope": "vue,html",
5
+ "body": [
6
+ "<DashboardQuadGrid>",
7
+ " <template #slot1>",
8
+ " $1",
9
+ " </template>",
10
+ " <template #slot2>",
11
+ " $2",
12
+ " </template>",
13
+ " <template #slot3>",
14
+ " $3",
15
+ " </template>",
16
+ " <template #slot4>",
17
+ " $4",
18
+ " </template>",
19
+ "</DashboardQuadGrid>"
20
+ ]
21
+ },
22
+ "SRCDEV DashboardQuadGrid CSS Override": {
23
+ "description": "CSS override scaffold for DashboardQuadGrid tokens",
24
+ "scope": "css",
25
+ "body": [
26
+ ".$1my-page {",
27
+ " .dashboard-quad-grid-wrapper {",
28
+ " --dashboard-quad-grid-gap: $2;",
29
+ " --dashboard-quad-grid-outline-colour: $3;",
30
+ " --dashboard-quad-grid-border-width: $4;",
31
+ " --dashboard-quad-grid-border-colour: $5;",
32
+ " }",
33
+ "}"
34
+ ]
35
+ }
36
+ }
@@ -0,0 +1,35 @@
1
+ {
2
+ "SRCDEV DashboardStatsGrid Basic": {
3
+ "description": "DashboardStatsGrid with looped top-row cluster, both static top-row slots, and looped bottom row",
4
+ "scope": "vue,html",
5
+ "body": [
6
+ "<DashboardStatsGrid :top-row-slot1-item-count=\"$1items.length\" :bottom-row-item-count=\"$2features.length\">",
7
+ " <template v-for=\"($3item, $4index) in $1items\" :key=\"$3item.id\" #[`top-row-slot1-\\${$4index + 1}-content`]>",
8
+ " $5",
9
+ " </template>",
10
+ " <template #top-row-slot-2>",
11
+ " $6",
12
+ " </template>",
13
+ " <template #top-row-slot-3>",
14
+ " $7",
15
+ " </template>",
16
+ " <template v-for=\"($8feature, $9findex) in $2features\" :key=\"$8feature.id\" #[`bottom-row-\\${$9findex + 1}-content`]>",
17
+ " $10",
18
+ " </template>",
19
+ "</DashboardStatsGrid>"
20
+ ]
21
+ },
22
+ "SRCDEV DashboardStatsGrid CSS Override": {
23
+ "description": "CSS override scaffold for DashboardStatsGrid tokens",
24
+ "scope": "css",
25
+ "body": [
26
+ ".$1my-page {",
27
+ " .dashboard-stats-grid {",
28
+ " --dashboard-stats-grid-gap: $2;",
29
+ " --dashboard-stats-grid-border-colour: $3;",
30
+ " --dashboard-stats-grid-rule-colour: $4;",
31
+ " }",
32
+ "}"
33
+ ]
34
+ }
35
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "SRCDEV DisplayThemeSwitch Basic": {
3
+ "description": "DisplayThemeSwitch — system/light/dark theme picker",
4
+ "scope": "vue,html",
5
+ "body": [
6
+ "<DisplayThemeSwitch />"
7
+ ]
8
+ },
9
+ "SRCDEV DisplayThemeSwitch Small": {
10
+ "description": "DisplayThemeSwitch compact size, for a header/nav slot",
11
+ "scope": "vue,html",
12
+ "body": [
13
+ "<DisplayThemeSwitch style-class-passthrough=\"small\" />"
14
+ ]
15
+ },
16
+ "SRCDEV DisplayThemeSwitch Custom Labels": {
17
+ "description": "DisplayThemeSwitch with translated/custom option labels",
18
+ "scope": "vue,html",
19
+ "body": [
20
+ "<DisplayThemeSwitch",
21
+ " system-label=\"$1System\"",
22
+ " light-label=\"$2Light\"",
23
+ " dark-label=\"$3Dark\"",
24
+ "/>"
25
+ ]
26
+ }
27
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "SRCDEV GlowingBorder Basic": {
3
+ "description": "GlowingBorder — animated conic-gradient glow border",
4
+ "scope": "vue,html",
5
+ "body": [
6
+ "<GlowingBorder variant=\"${1|subtle,vivid,silver,steel,green|}\">",
7
+ " $0",
8
+ "</GlowingBorder>"
9
+ ]
10
+ },
11
+ "SRCDEV GlowingBorder Custom Tokens": {
12
+ "description": "GlowingBorder with custom width/radius/animation-duration CSS tokens",
13
+ "scope": "vue,html",
14
+ "body": [
15
+ "<GlowingBorder",
16
+ " variant=\"${1|subtle,vivid,silver,steel,green|}\"",
17
+ " style=\"--glowing-border-width: ${2:3px}; --glowing-border-radius: ${3:30px}; --glowing-border-animation-duration: ${4:10s};\"",
18
+ ">",
19
+ " $0",
20
+ "</GlowingBorder>"
21
+ ]
22
+ }
23
+ }
@@ -0,0 +1,85 @@
1
+ {
2
+ "SRCDEV InputRangeCore Basic": {
3
+ "description": "Basic InputRangeCore native range input (no label/error wrapper)",
4
+ "scope": "vue,html",
5
+ "body": [
6
+ "<InputRangeCore",
7
+ " id=\"$1fieldId\"",
8
+ " name=\"$2fieldName\"",
9
+ " v-model=\"$3fieldValue\"",
10
+ " :min=\"$40\"",
11
+ " :max=\"$5100\"",
12
+ " :step=\"$61\"",
13
+ "/>"
14
+ ]
15
+ },
16
+ "SRCDEV InputRangeCore With Markers": {
17
+ "description": "InputRangeCore with custom tick-mark markers overlaid on the track",
18
+ "scope": "vue,html",
19
+ "body": [
20
+ "<InputRangeCore",
21
+ " id=\"$1fieldId\"",
22
+ " name=\"$2fieldName\"",
23
+ " v-model=\"$3fieldValue\"",
24
+ " :min=\"$40\"",
25
+ " :max=\"$52\"",
26
+ " :step=\"$61\"",
27
+ ">",
28
+ " <template #markers>",
29
+ " <div class=\"input-range-markers\">",
30
+ " <div class=\"marker\"><span class=\"marker-icon\">$7\\ud83d\\ude00</span></div>",
31
+ " <div class=\"marker\"><span class=\"marker-icon\">$8\\ud83d\\ude10</span></div>",
32
+ " <div class=\"marker\"><span class=\"marker-icon\">$9\\ud83d\\ude1e</span></div>",
33
+ " </div>",
34
+ " </template>",
35
+ "</InputRangeCore>"
36
+ ]
37
+ },
38
+ "SRCDEV InputRangeDefault Basic": {
39
+ "description": "InputRangeDefault: labelled range slider with error/description support",
40
+ "scope": "vue,html",
41
+ "body": [
42
+ "<InputRangeDefault",
43
+ " v-model=\"$1fieldValue\"",
44
+ " name=\"$2fieldName\"",
45
+ " label=\"$3Field label\"",
46
+ " :min=\"$40\"",
47
+ " :max=\"$5100\"",
48
+ " :step=\"$61\"",
49
+ " :error-message=\"$7errors.fieldName\"",
50
+ " :field-has-error=\"!!$7errors.fieldName\"",
51
+ "/>"
52
+ ]
53
+ },
54
+ "SRCDEV InputRangeDefault With Step Buttons": {
55
+ "description": "InputRangeDefault with step-down/step-up buttons wired into the left/right slots",
56
+ "scope": "vue,html",
57
+ "body": [
58
+ "<InputRangeDefault",
59
+ " v-model=\"$1fieldValue\"",
60
+ " name=\"$2fieldName\"",
61
+ " label=\"$3Field label\"",
62
+ " :min=\"$40\"",
63
+ " :max=\"$5100\"",
64
+ " :step=\"$61\"",
65
+ " :error-message=\"$7errors.fieldName\"",
66
+ " :field-has-error=\"!!$7errors.fieldName\"",
67
+ ">",
68
+ " <template #left>\\u2212</template>",
69
+ " <template #right>+</template>",
70
+ "</InputRangeDefault>"
71
+ ]
72
+ },
73
+ "SRCDEV InputRange CSS Override": {
74
+ "description": "CSS override scaffold for InputRangeCore tokens",
75
+ "scope": "css",
76
+ "body": [
77
+ ".$1my-page {",
78
+ " .input-range-wrapper {",
79
+ " --input-range-accent-colour: $2;",
80
+ " --input-range-marker-background-colour: $3;",
81
+ " }",
82
+ "}"
83
+ ]
84
+ }
85
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "SRCDEV SectionParallax Basic": {
3
+ "description": "SectionParallax — fixed-background parallax section",
4
+ "scope": "vue,html",
5
+ "body": [
6
+ "<SectionParallax",
7
+ " tag=\"${1|section,div,article,aside|}\"",
8
+ " background-image=\"${2:/images/example.jpg}\"",
9
+ ">",
10
+ " $0",
11
+ "</SectionParallax>"
12
+ ]
13
+ },
14
+ "SRCDEV SectionParallax Custom Height": {
15
+ "description": "SectionParallax with custom min-height CSS tokens",
16
+ "scope": "vue,html",
17
+ "body": [
18
+ "<SectionParallax",
19
+ " tag=\"${1|section,div,article,aside|}\"",
20
+ " background-image=\"${2:/images/example.jpg}\"",
21
+ " style=\"--section-parallax-min-height: ${3:60vh}; --section-parallax-min-height-fixed: ${4:70vh};\"",
22
+ ">",
23
+ " $0",
24
+ "</SectionParallax>"
25
+ ]
26
+ }
27
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "SRCDEV UiBlockDecorated Basic": {
3
+ "description": "UiBlockDecorated — plain block with border/shadow/inner-shadow strength props",
4
+ "scope": "vue,html",
5
+ "body": [
6
+ "<UiBlockDecorated :shadow-strength=\"$1{1|1,2,3,4,5,6|}\">",
7
+ " $0",
8
+ "</UiBlockDecorated>"
9
+ ]
10
+ },
11
+ "SRCDEV UiBlockDecorated Combined": {
12
+ "description": "UiBlockDecorated with border, shadow and inner-shadow combined",
13
+ "scope": "vue,html",
14
+ "body": [
15
+ "<UiBlockDecorated",
16
+ " :border-strength=\"$1{1|1,2,3,4,5,6|}\"",
17
+ " :shadow-strength=\"$2{2|1,2,3,4,5,6|}\"",
18
+ " :inner-shadow-strength=\"$3{1|1,2,3,4|}\"",
19
+ ">",
20
+ " $0",
21
+ "</UiBlockDecorated>"
22
+ ]
23
+ }
24
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "SRCDEV WipeAwayVertical Basic": {
3
+ "description": "WipeAwayVertical — scroll-driven vertical wipe-away effect with sticky/scrolling section pairs",
4
+ "scope": "vue,html",
5
+ "body": [
6
+ "<WipeAwayVertical :item-count=\"$13\">",
7
+ " <template #stickyItem-0>$2</template>",
8
+ " <template #stickyItem-1>$3</template>",
9
+ " <template #stickyItem-2>$4</template>",
10
+ "",
11
+ " <template #scrollingItem-0><div style=\"height: 100vh;\"></div></template>",
12
+ " <template #scrollingItem-1><div style=\"height: 100vh;\"></div></template>",
13
+ "</WipeAwayVertical>$0"
14
+ ]
15
+ },
16
+ "SRCDEV WipeAwayVertical With Passthrough": {
17
+ "description": "WipeAwayVertical with styleClassPassthrough for a custom wrapper class",
18
+ "scope": "vue,html",
19
+ "body": [
20
+ "<WipeAwayVertical :item-count=\"$12\" style-class-passthrough=\"$2my-wipe-wrapper\">",
21
+ " $0",
22
+ "</WipeAwayVertical>"
23
+ ]
24
+ }
25
+ }