srcdev-nuxt-components 9.6.2 → 9.6.3

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 (44) hide show
  1. package/.claude/rules/consumer/consumer-overrides.md +17 -0
  2. package/.claude/rules/consumer/css-comment-slash.md +13 -0
  3. package/.claude/rules/consumer/css-native-nesting.md +13 -0
  4. package/.claude/rules/consumer/css-no-deep.md +13 -0
  5. package/.claude/rules/consumer/css-rem-base.md +11 -0
  6. package/.claude/rules/consumer/css-surface-text-pairing.md +13 -0
  7. package/.claude/rules/consumer/css-webkit-support.md +15 -0
  8. package/.claude/rules/consumer/explicit-vue-imports.md +11 -0
  9. package/.claude/rules/consumer/nuxt-img-dimensions.md +12 -0
  10. package/.claude/rules/consumer/srcdev-skills-location.md +9 -0
  11. package/.claude/rules/consumer/story-args.md +12 -0
  12. package/.claude/rules/consumer/story-register-components.md +12 -0
  13. package/.claude/rules/consumer/vue-auto-imports.md +14 -0
  14. package/.claude/rules/consumer/vue-no-self-closing.md +11 -0
  15. package/.claude/rules/consumer/vue-prop-hyphenation.md +11 -0
  16. package/.claude/rules/consumer/vue-props-pattern.md +13 -0
  17. package/.claude/rules/consumer/vue-slots-no-computed.md +14 -0
  18. package/.claude/rules/consumer/vue-video-source.md +12 -0
  19. package/.claude/skills/component-compliance-checklist.md +23 -1
  20. package/.claude/skills/component-naming.md +1 -1
  21. package/.claude/skills/components/pricing-card.md +68 -84
  22. package/.claude/skills/index.md +9 -3
  23. package/.claude/skills/new-app-scaffold.md +4 -2
  24. package/.claude/skills/setup-postinstall.md +5 -4
  25. package/.claude/skills/storybook-add-story.md +36 -0
  26. package/.claude/skills/theming-component-token-pattern.md +46 -0
  27. package/.claude/skills/theming-partial-override.md +1 -1
  28. package/.vscode/srcdev-component-pricing-card.code-snippets +46 -84
  29. package/README.md +5 -5
  30. package/app/components/01.atoms/animations/scroll-reveal-frame/stories/ScrollRevealFrame.stories.ts +2 -0
  31. package/app/components/01.atoms/animations/scroll-reveal-image/stories/ScrollRevealImage.stories.ts +2 -0
  32. package/app/components/01.atoms/animations/section-parallax/stories/SectionParallax.stories.ts +4 -0
  33. package/app/components/01.atoms/animations/view-timeline/stories/WipeAwayVertical.stories.ts +2 -0
  34. package/app/components/02.molecules/cookie-consent-banner/stories/CookieConsentBanner.stories.ts +2 -0
  35. package/app/components/02.molecules/input-copy/stories/InputCopy.stories.ts +0 -1
  36. package/app/components/02.molecules/pricing-card/CONSUMER-STYLING.md +96 -149
  37. package/app/components/02.molecules/pricing-card/PricingCard.vue +84 -44
  38. package/app/components/02.molecules/pricing-card/stories/PricingCard.stories.ts +241 -104
  39. package/app/components/02.molecules/pricing-card/tests/PricingCard.spec.ts +149 -123
  40. package/app/components/02.molecules/toast/stories/DisplayToast.stories.ts +4 -0
  41. package/app/components/02.molecules/toast/stories/DisplayToastProvider.stories.ts +4 -0
  42. package/app/components/05.forms/toggle-switch/ToggleSwitchWithLabel.vue +1 -1
  43. package/app/composables/useAriaDescribedById.ts +1 -1
  44. package/package.json +2 -1
@@ -287,6 +287,29 @@ prop and try to pass it. Make it unmistakable:
287
287
 
288
288
  `PriceList.stories.ts` and `GoogleReviews.stories.ts` (line-clamp controls) follow this.
289
289
 
290
+ ## Docs page
291
+
292
+ `.storybook/preview.ts` sets `tags: ["autodocs"]` globally (2026-10-14), so every story file gets a
293
+ generated Docs page and the meta doesn't need the tag. Before that, only two files opted in, and
294
+ the earlier nightly `@nuxtjs/storybook` didn't render Docs pages at all, so a lot of existing
295
+ `docs.description` text had never been visible. Check the page whenever you add or change a story
296
+ (compliance checklist item 6c):
297
+
298
+ - `parameters.docs.description.component` in the meta: what the component is for and its main
299
+ props, slots and events. `docs.description.story` on a story: what that story shows.
300
+ - The Docs page renders every story inline in one document. Overlays (`position: fixed`), dialogs,
301
+ toasts, fullscreen canvases and scroll-driven effects break or overlap there. Render them in
302
+ their own iframe instead:
303
+
304
+ ```ts
305
+ parameters: {
306
+ docs: { story: { inline: false, height: "480px" } },
307
+ },
308
+ ```
309
+
310
+ - Opt a file out with `tags: ["!autodocs"]` only when it isn't a component reference (tooling, or
311
+ a file with its own attached `.mdx` page, like `ColourRamps.stories.ts` with `SetupGuide.mdx`).
312
+
290
313
  ## Link to the stories of components that use this one
291
314
 
292
315
  When the component you're working on is a building block of other components (it's rendered
@@ -362,6 +385,19 @@ story: "See the [CookieConsentBanner](?path=/story/molecules-cookieconsentbanner
362
385
  controls that make sense (hide irrelevant ones with `Story.argTypes = { x: { table: { disable: true } } }`),
363
386
  or, for a fixed showcase (comparisons, all-themes grids, composition examples), add
364
387
  `controls: { disable: true }` to that story's `parameters`.
388
+ - **Sidebar order** comes from the `storySort` function in `.storybook/preview.ts`: top-level
389
+ groups in tier order, everything below them alphabetical, entries within one component in file
390
+ order with Docs first. Storybook doesn't run that function from the compiled file. It extracts
391
+ the function's source and `eval`s it as plain JavaScript, so any TypeScript inside it
392
+ (annotations, `as` casts) or a reference to something outside its body fails the whole preview
393
+ build with `SyntaxError: Unexpected token ':'` (found 2026-10-15). It stays annotation-free
394
+ under a `// @ts-expect-error`. Check an edit without starting Storybook:
395
+
396
+ ```bash
397
+ node --input-type=module -e 'import { getStorySortParameter } from "storybook/internal/csf-tools"; import fs from "node:fs"; console.log(typeof getStorySortParameter(fs.readFileSync(".storybook/preview.ts", "utf8")));'
398
+ ```
399
+
400
+ `function` means it parses; a syntax error is the same one Storybook would hit.
365
401
 
366
402
  ## Scroll/animation-driven effects need surrounding chrome, not just the bare component
367
403
 
@@ -42,6 +42,52 @@ overrides (2026-08-25):
42
42
  Tier 1 is the one deliberate exception. Everything else gets a real component-prefixed name with
43
43
  an inline fallback, even if that fallback happens to be a Tier 1 or Tier 2 token underneath.
44
44
 
45
+ ## Public vs private tokens
46
+
47
+ Rule: `.claude/rules/css-public-private-tokens.md`.
48
+
49
+ The public/private decision is about **consumer relevance, not reuse
50
+ count**. A value a consumer could plausibly want to customise — colours, spacing, sizes, radii,
51
+ durations, and any per-state variant of these (a hover outline width, a focus border colour) — is
52
+ a **public token**, consumed directly at its point of use: `border-radius: var(--component-name-border-radius, 0.5rem)`.
53
+ This holds even when it's only used once — single-use is not a reason to demote a genuinely
54
+ consumer-facing value to private. Per-state variants get their own public token that falls back
55
+ to the resting one, rather than being derived privately: `--component-name-outline-width-hover`
56
+ falling back to `--component-name-outline-width`, not a private var with no override hook.
57
+
58
+ A value with **no plausible consumer relevance** — genuine internal implementation detail, e.g.
59
+ something composed from a `v-bind()` JS value, or an intermediate that exists purely to avoid
60
+ repeating a computation — is a **private token**, always prefixed `--_x`. Prefix it even when
61
+ it's used only once: the underscore is a grep-able, at-a-glance "this is not public API" signal,
62
+ and that signal shouldn't depend on how many places the value happens to appear.
63
+
64
+ ```css
65
+ /* ✅ Single-use, consumer-facing — still a public token, consumed directly */
66
+ .component-name {
67
+ border-radius: var(--component-name-border-radius, 0.5rem);
68
+ transition: all var(--component-name-transition-duration, 300ms) ease;
69
+ }
70
+
71
+ /* ✅ Resting/hover pair — both public, hover falls back to resting; --_ only wraps the
72
+ genuinely-shared intermediate so the fallback chain isn't repeated */
73
+ .component-name {
74
+ --_border-colour: var(--component-name-border-colour, transparent);
75
+ border-color: var(--_border-colour);
76
+
77
+ &:hover {
78
+ border-color: var(--component-name-border-colour-hover, var(--_border-colour));
79
+ }
80
+ }
81
+
82
+ /* ✅ Private — internal only, no consumer would ever want to override this directly */
83
+ .component-name {
84
+ --_computed-offset: calc(v-bind(dynamicWidth) * 0.5px);
85
+ }
86
+ ```
87
+
88
+ CLAUDE.md pitfall #20 is the concrete case (`ServicesCard`'s private layer wrapped public tokens with
89
+ no composition or state-swap behind them: pure pass-through duplication, not genuine privacy).
90
+
45
91
  ## Naming convention
46
92
 
47
93
  `--{component-kebab-name}-{variant-if-any}-{property}[-state]`
@@ -47,7 +47,7 @@ affects buttons, inputs, prompts, and toasts simultaneously:
47
47
  | `--theme-border-focus` | `--colour-theme-4` / `3` | Focused border |
48
48
  | `--theme-ring` | `--colour-theme-1` / `9` | Focus ring (outline) |
49
49
  | `--theme-on-surface` | `--colour-theme-0` | Text/icon on filled/inverted surface (fixed light value in both modes — pair this with any dark-in-light-mode surface, not `--theme-text`) |
50
- | `--theme-text` | `--colour-theme-9` / `2` | Text on page, outline element text (assumes a *light* surface — don't pair with `--theme-surface-hover`/`-inverted`, see pitfall #13 in `Claude.md`) |
50
+ | `--theme-text` | `--colour-theme-9` / `2` | Text on page, outline element text (assumes a *light* surface — don't pair with `--theme-surface-hover`/`-inverted`, see pitfall #13 in `CLAUDE.md`) |
51
51
  | `--theme-text-inverted` | `--colour-theme-0` / `7` | Text on `--theme-surface-inverted` (fixed to a light value in light mode as of 2026-08-03 — was `--colour-theme-9`, identical to the surface it sits on) |
52
52
 
53
53
  Input-specific tokens:
@@ -4,97 +4,65 @@
4
4
  "scope": "vue,html",
5
5
  "body": [
6
6
  "<PricingCard",
7
- " planName=\"$1Single Site\"",
7
+ " plan-name=\"$1Single Site\"",
8
8
  " :price=\"$2199\"",
9
- " billingPeriod=\"$3one-time\"",
10
- " description=\"$4Perfect for freelancers and solo practitioners.\"",
11
- " :features=\"[",
12
- " '$5Feature 1',",
13
- " '$6Feature 2',",
14
- " '$7Feature 3',",
15
- " ]\"",
16
- " @select=\"$8handleSelect\"",
9
+ " currency-symbol=\"$3£\"",
10
+ " billing-period=\"$4one-time\"",
11
+ " description=\"$5Perfect for freelancers and solo practitioners.\"",
12
+ " :features=\"['$6Feature 1', '$7Feature 2', '$8Feature 3']\"",
13
+ " @select=\"$9handleSelect\"",
17
14
  "/>"
18
15
  ]
19
16
  },
20
17
  "SRCDEV PricingCard Highlighted": {
21
- "description": "PricingCard with 'Most Popular' highlight and custom button",
18
+ "description": "PricingCard with 'Most Popular' highlight",
22
19
  "scope": "vue,html",
23
20
  "body": [
24
21
  "<PricingCard",
25
- " planName=\"$1Agency\"",
22
+ " plan-name=\"$1Agency\"",
26
23
  " :price=\"$2499\"",
27
- " billingPeriod=\"$3one-time\"",
24
+ " billing-period=\"$3one-time\"",
28
25
  " description=\"$4Best for growing teams.\"",
29
- " :is-highlighted=\"true\"",
30
- " :features=\"[",
31
- " '$5Feature 1',",
32
- " '$6Feature 2',",
33
- " '$7Feature 3',",
34
- " ]\"",
35
- " @select=\"$8handleSelect\"",
36
- ">",
37
- " <template #cta=\"{ ctaText, isDisabled, onSelect }\">",
38
- " <InputButton",
39
- " :button-text=\"ctaText\"",
40
- " variant=\"$9primary\"",
41
- " :readonly=\"isDisabled\"",
42
- " @click=\"onSelect\"",
43
- " />",
44
- " </template>",
45
- "</PricingCard>"
26
+ " is-highlighted",
27
+ " badge-text=\"$5Most Popular\"",
28
+ " :features=\"['$6Feature 1', '$7Feature 2', '$8Feature 3']\"",
29
+ " @select=\"$9handleSelect\"",
30
+ "/>"
46
31
  ]
47
32
  },
48
33
  "SRCDEV PricingCard Grid": {
49
- "description": "Three-card pricing comparison grid",
34
+ "description": "Pricing comparison grid from a plans array",
50
35
  "scope": "vue,html",
51
36
  "body": [
52
- "<div class=\"pricing-cards-grid\">",
53
- " <PricingCard",
54
- " planName=\"Single Site\"",
55
- " :price=\"$1199\"",
56
- " billingPeriod=\"one-time\"",
57
- " description=\"$2For freelancers.\"",
58
- " :features=\"['$3Feature 1', '$4Feature 2']\"",
59
- " @select=\"handleSelect\"",
60
- " />",
61
- " <PricingCard",
62
- " planName=\"Agency\"",
63
- " :price=\"$5499\"",
64
- " billingPeriod=\"one-time\"",
65
- " description=\"$6For growing teams.\"",
66
- " :is-highlighted=\"true\"",
67
- " :features=\"['$7Feature 1', '$8Feature 2', '$9Feature 3']\"",
68
- " @select=\"handleSelect\"",
69
- " />",
37
+ "<div class=\"$1pricing-grid\">",
70
38
  " <PricingCard",
71
- " planName=\"Unlimited\"",
72
- " :price=\"$10999\"",
73
- " billingPeriod=\"one-time\"",
74
- " description=\"$11Enterprise plan.\"",
75
- " :features=\"['$12Feature 1', '$13Feature 2', '$14Feature 3', '$15Feature 4']\"",
76
- " @select=\"handleSelect\"",
39
+ " v-for=\"plan in $2plans\"",
40
+ " :key=\"plan.id\"",
41
+ " :plan-name=\"plan.name\"",
42
+ " :price=\"plan.price\"",
43
+ " :description=\"plan.description\"",
44
+ " :features=\"plan.features\"",
45
+ " :is-highlighted=\"plan.id === '$3pro'\"",
46
+ " heading-tag=\"$4h2\"",
47
+ " @select=\"$5handleSelect\"",
77
48
  " />",
78
49
  "</div>"
79
50
  ]
80
51
  },
81
52
  "SRCDEV PricingCard Custom Button": {
82
- "description": "PricingCard with custom button variant via #cta slot",
53
+ "description": "PricingCard with custom button via #cta slot",
83
54
  "scope": "vue,html",
84
55
  "body": [
85
56
  "<PricingCard",
86
- " planName=\"$1Premium\"",
57
+ " plan-name=\"$1Premium\"",
87
58
  " :price=\"$2799\"",
88
- " billingPeriod=\"$3one-time\"",
89
- " description=\"$4All features included.\"",
90
- " :features=\"['$5Feature 1', '$6Feature 2']\"",
91
- " @select=\"$7handleSelect\"",
59
+ " :features=\"['$3Feature 1', '$4Feature 2']\"",
60
+ " @select=\"$5handleSelect\"",
92
61
  ">",
93
62
  " <template #cta=\"{ ctaText, isDisabled, onSelect }\">",
94
63
  " <InputButton",
95
64
  " :button-text=\"ctaText\"",
96
- " variant=\"$8secondary\"",
97
- " theme=\"$9default\"",
65
+ " variant=\"$6secondary\"",
98
66
  " :readonly=\"isDisabled\"",
99
67
  " @click=\"onSelect\"",
100
68
  " />",
@@ -107,17 +75,12 @@
107
75
  "scope": "vue,html",
108
76
  "body": [
109
77
  "<PricingCard",
110
- " planName=\"$1Annual\"",
78
+ " plan-name=\"$1Annual\"",
111
79
  " :price=\"$249\"",
112
- " billingPeriod=\"$3per year\"",
113
- " description=\"$4Early adopter pricing on the annual plan.\"",
114
- " ribbonText=\"$5EARLYBIRD50 · 50% off\"",
115
- " :features=\"[",
116
- " '$6Feature 1',",
117
- " '$7Feature 2',",
118
- " '$8Feature 3',",
119
- " ]\"",
120
- " @select=\"$9handleSelect\"",
80
+ " billing-period=\"$3per year\"",
81
+ " ribbon-text=\"$4EARLYBIRD50 · 50% off\"",
82
+ " :features=\"['$5Feature 1', '$6Feature 2']\"",
83
+ " @select=\"$7handleSelect\"",
121
84
  "/>"
122
85
  ]
123
86
  },
@@ -127,21 +90,20 @@
127
90
  "body": [
128
91
  ".$1pricing-page {",
129
92
  " .pricing-card {",
130
- " --pricing-card-border-radius: $2;",
131
- " --pricing-card-padding: $3;",
132
- " --pricing-card-gap: $4;",
133
- " --pricing-card-shadow: $5;",
93
+ " --pricing-card-background: $2;",
94
+ " --pricing-card-border-radius: $3;",
95
+ " --pricing-card-padding: $4;",
96
+ " --pricing-card-gap: $5;",
134
97
  " --pricing-card-name-color: $6;",
135
- " --pricing-card-amount-color: $7;",
136
- " --pricing-card-cta-bg: $8;",
137
- " --pricing-card-cta-bg-hover: $9;",
138
- " --pricing-card-ribbon-bg: $10;",
139
- " --pricing-card-ribbon-text: $11;",
98
+ " --pricing-card-description-line-clamp: $7;",
99
+ " --pricing-card-feature-icon-color: $8;",
100
+ " --pricing-card-ribbon-bg: $9;",
101
+ " --input-button-primary-surface: $10;",
140
102
  "",
141
103
  " &.is-highlighted {",
142
- " --pricing-card-highlight-border: $12;",
143
- " --pricing-card-highlight-shadow: $13;",
144
- " --pricing-card-highlight-scale: $14;",
104
+ " --pricing-card-highlight-border: $11;",
105
+ " --pricing-card-highlight-scale: $12;",
106
+ " --pricing-card-badge-bg: $13;",
145
107
  " }",
146
108
  " }",
147
109
  "}"
package/README.md CHANGED
@@ -25,12 +25,12 @@ defineNuxtConfig({
25
25
 
26
26
  ## Claude Code Skills
27
27
 
28
- This package ships Claude Code skills — reference docs for components and development tasks — in the `.claude/` directory.
28
+ This package ships Claude Code skills (reference docs for components and development tasks) and a curated set of Claude Code rules (short constraints for working with the layer: CSS nesting, overrides, props, NuxtImg, Storybook args) in the `.claude/` directory.
29
29
 
30
30
  To make them available in your project, add this script to your `package.json`:
31
31
 
32
32
  ```json
33
- "setup:claude": "cp -r node_modules/srcdev-nuxt-components/.claude/skills .claude/skills/srcdev-nuxt-components"
33
+ "setup:claude": "rm -rf .claude/skills/srcdev-nuxt-components .claude/rules/srcdev-nuxt-components && mkdir -p .claude/skills/srcdev-nuxt-components .claude/rules/srcdev-nuxt-components && cp -r node_modules/srcdev-nuxt-components/.claude/skills/. .claude/skills/srcdev-nuxt-components && cp -r node_modules/srcdev-nuxt-components/.claude/rules/consumer/. .claude/rules/srcdev-nuxt-components"
34
34
  ```
35
35
 
36
36
  Then run it after install:
@@ -39,7 +39,7 @@ Then run it after install:
39
39
  npm run setup:claude
40
40
  ```
41
41
 
42
- Skills are copied into `.claude/skills/srcdev-nuxt-components/` so they never conflict with or overwrite skills your own project defines. Re-running the script after a package update is safe.
42
+ Skills are copied into `.claude/skills/srcdev-nuxt-components/` and rules into `.claude/rules/srcdev-nuxt-components/`, so they never conflict with or overwrite your own project's. Re-running the script after a package update is safe: it replaces only those two `srcdev-nuxt-components` folders, so skills and rules dropped or renamed upstream are removed too, and your own skills and rules are never touched.
43
43
 
44
44
  ### Automate with postinstall (recommended)
45
45
 
@@ -47,7 +47,7 @@ To ensure skills are always up to date, VSCode snippets are installed, and `nuxt
47
47
 
48
48
  ```json
49
49
  "scripts": {
50
- "setup:claude": "mkdir -p .claude/skills/srcdev-nuxt-components && cp -r node_modules/srcdev-nuxt-components/.claude/skills/. .claude/skills/srcdev-nuxt-components",
50
+ "setup:claude": "rm -rf .claude/skills/srcdev-nuxt-components .claude/rules/srcdev-nuxt-components && mkdir -p .claude/skills/srcdev-nuxt-components .claude/rules/srcdev-nuxt-components && cp -r node_modules/srcdev-nuxt-components/.claude/skills/. .claude/skills/srcdev-nuxt-components && cp -r node_modules/srcdev-nuxt-components/.claude/rules/consumer/. .claude/rules/srcdev-nuxt-components",
51
51
  "postinstall": "node node_modules/srcdev-nuxt-components/scripts/copy-snippets.mjs && nuxt prepare && npm run setup:claude"
52
52
  }
53
53
  ```
@@ -56,7 +56,7 @@ To ensure skills are always up to date, VSCode snippets are installed, and `nuxt
56
56
 
57
57
  1. `copy-snippets.mjs` — copies VSCode snippets (`.code-snippets` files) from the layer to your `.vscode/` folder
58
58
  2. `nuxt prepare` — generates Nuxt type declarations
59
- 3. `setup:claude` — copies skills into `.claude/skills/srcdev-nuxt-components/`
59
+ 3. `setup:claude` — copies skills into `.claude/skills/srcdev-nuxt-components/` and rules into `.claude/rules/srcdev-nuxt-components/`
60
60
 
61
61
  > **Note**: The snippet copy must run from your consumer app's postinstall, not the layer's. npm doesn't invoke postinstall hooks for dependencies, so each consumer app is responsible for copying snippets into its own `.vscode/` folder. Don't set `SRCDEV_STANDALONE` in a consumer app: that flag is only for running this layer on its own (it enables dev-only modules and the ramp watcher).
62
62
 
@@ -25,7 +25,9 @@ const meta: Meta<typeof ScrollRevealFrame> = {
25
25
  },
26
26
  },
27
27
  parameters: {
28
+ // Own iframe on the Docs page: the effect depends on page scroll.
28
29
  docs: {
30
+ story: { inline: false, height: "600px" },
29
31
  description: {
30
32
  component:
31
33
  "Generic clipping frame that pans any slot content vertically as it scrolls through the viewport — driven entirely by CSS Scroll-driven Animations. No scroll listeners, no JS. Use this when you need the parallax reveal with arbitrary content (grids, video, etc.). For a single NuxtImg with optimisation and focal-point control, use ScrollRevealImage instead.",
@@ -50,7 +50,9 @@ const meta: Meta<typeof ScrollRevealImage> = {
50
50
  },
51
51
  },
52
52
  parameters: {
53
+ // Own iframe on the Docs page: the effect depends on page scroll.
53
54
  docs: {
55
+ story: { inline: false, height: "600px" },
54
56
  description: {
55
57
  component:
56
58
  "Single-image parallax reveal built on ScrollRevealFrame. Adds NuxtImg optimisation (src, alt, intrinsic dimensions) and a horizontal focal-point prop (focalX). For arbitrary slot content — grids, video, etc. — use ScrollRevealFrame directly.",
@@ -45,6 +45,10 @@ export default {
45
45
  showOverlay: true,
46
46
  overlayText: "A quiet moment.",
47
47
  },
48
+ parameters: {
49
+ // Own iframe on the Docs page: the effect depends on page scroll and vh heights.
50
+ docs: { story: { inline: false, height: "600px" } },
51
+ },
48
52
  } as Meta<StoryArgs>;
49
53
 
50
54
  const Template: StoryFn<StoryArgs> = (args) => ({
@@ -20,7 +20,9 @@ const meta: Meta<typeof WipeAwayVertical> = {
20
20
  styleClassPassthrough: { table: { disable: true } },
21
21
  },
22
22
  parameters: {
23
+ // Own iframe on the Docs page: the effect depends on page scroll and vh heights.
23
24
  docs: {
25
+ story: { inline: false, height: "600px" },
24
26
  description: {
25
27
  component:
26
28
  "Scroll-driven vertical wipe effect: each sticky panel wipes away to reveal the next as its paired scrolling section crosses the viewport. Pure CSS — a single-column grid overlays `.sticky-items-container` across all `.scrolling-section` rows via `animation-timeline: view()`, so there's no scroll listener or JS measurement involved. Consumers supply `stickyItem-{n}` slots for each of `itemCount` panels, and `scrollingItem-{n}` slots for only the first `itemCount - 1` — the last panel has nothing left to reveal, so it has no wipe animation or scrolling section of its own, just a small built-in trailing buffer to release cleanly. The sticky panel's own visible height is `--wipe-away-vertical-height` (default `100vh`) — leave the root's own `height` unset (`auto`) so it sizes itself from its children. Browsers without `animation-timeline: view()` support (via `@supports not (...)`) just get the sticky items stacked in normal document flow instead.",
@@ -40,7 +40,9 @@ export default {
40
40
  styleClassPassthrough: [],
41
41
  },
42
42
  parameters: {
43
+ // Own iframe on the Docs page: the banner is fixed to the viewport.
43
44
  docs: {
45
+ story: { inline: false, height: "400px" },
44
46
  description: {
45
47
  // Drives itself from the real useCookieConsent()/useCookie() state, so
46
48
  // once accepted/rejected in this browser it stays hidden across story
@@ -4,7 +4,6 @@ import InputCopy from "../InputCopy.vue";
4
4
  const meta: Meta<typeof InputCopy> = {
5
5
  title: "Molecules/Input Copy",
6
6
  component: InputCopy,
7
- tags: ["autodocs"],
8
7
  argTypes: {
9
8
  value: { control: "text" },
10
9
  id: {