srcdev-nuxt-components 9.4.11 → 9.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/component-aria-landmark.md +1 -1
- package/.claude/skills/component-dynamic-slots.md +0 -1
- package/.claude/skills/component-export-types.md +3 -3
- package/.claude/skills/component-inline-action-button.md +7 -7
- package/.claude/skills/component-local-style-override.md +134 -50
- package/.claude/skills/component-naming.md +107 -0
- package/.claude/skills/components/action-menu.md +18 -14
- package/.claude/skills/components/alert-content.md +110 -0
- package/.claude/skills/components/alert-mask-core.md +15 -1
- package/.claude/skills/components/alert-masked-content.md +95 -0
- package/.claude/skills/components/auto-grid.md +21 -13
- package/.claude/skills/components/canvas-switcher.md +3 -3
- package/.claude/skills/components/capture-qr-code.md +19 -9
- package/.claude/skills/components/carousel-flip.md +3 -3
- package/.claude/skills/components/container-glow.md +2 -2
- package/.claude/skills/components/content-docs.md +9 -5
- package/.claude/skills/components/cookie-consent-banner.md +16 -17
- package/.claude/skills/components/dashboard-quad-grid.md +4 -4
- package/.claude/skills/components/decode-qr-code.md +15 -9
- package/.claude/skills/components/display-avatar.md +16 -31
- package/.claude/skills/components/display-chip.md +15 -10
- package/.claude/skills/components/display-dialog.md +3 -1
- package/.claude/skills/components/display-pill.md +17 -75
- package/.claude/skills/components/display-prompt.md +11 -19
- package/.claude/skills/components/display-qr-code.md +5 -0
- package/.claude/skills/components/display-theme-switch.md +7 -6
- package/.claude/skills/components/display-toast.md +5 -6
- package/.claude/skills/components/entry-animation.md +2 -5
- package/.claude/skills/components/eyebrow-text.md +6 -4
- package/.claude/skills/components/form-field.md +79 -0
- package/.claude/skills/components/form-fieldset.md +75 -0
- package/.claude/skills/components/form-wrapper.md +71 -0
- package/.claude/skills/components/glass-panel.md +60 -51
- package/.claude/skills/components/grid-stack.md +8 -2
- package/.claude/skills/components/header-block.md +1 -1
- package/.claude/skills/components/hero-text.md +8 -6
- package/.claude/skills/components/input-button.md +72 -0
- package/.claude/skills/components/input-checkbox-radio.md +149 -0
- package/.claude/skills/components/input-checkbox.md +148 -0
- package/.claude/skills/components/input-description.md +102 -0
- package/.claude/skills/components/input-error.md +105 -0
- package/.claude/skills/components/input-label.md +119 -0
- package/.claude/skills/components/{input-number-core.md → input-number.md} +41 -36
- package/.claude/skills/components/input-radio.md +95 -0
- package/.claude/skills/components/input-range-core.md +4 -4
- package/.claude/skills/components/input-select-core.md +1 -1
- package/.claude/skills/components/input-text-core.md +8 -6
- package/.claude/skills/components/input-textarea-core.md +4 -4
- package/.claude/skills/components/layout-grid-by-cols.md +31 -43
- package/.claude/skills/components/link-text.md +2 -2
- package/.claude/skills/components/opening-hours.md +116 -0
- package/.claude/skills/components/page-hero-highlights.md +35 -35
- package/.claude/skills/components/page-row.md +1 -1
- package/.claude/skills/components/pending-effect.md +63 -0
- package/.claude/skills/components/price-list.md +72 -0
- package/.claude/skills/components/pricing-card.md +3 -3
- package/.claude/skills/components/profile-section.md +6 -4
- package/.claude/skills/components/samaritan-prompt.md +140 -0
- package/.claude/skills/components/scroll-reveal-frame.md +21 -20
- package/.claude/skills/components/scroll-reveal-image.md +31 -21
- package/.claude/skills/components/service-detail.md +2 -2
- package/.claude/skills/components/services-card-grid.md +5 -4
- package/.claude/skills/components/services-card.md +12 -10
- package/.claude/skills/components/site-navigation.md +20 -6
- package/.claude/skills/components/slider-gallery.md +88 -0
- package/.claude/skills/components/social-icons-list.md +12 -6
- package/.claude/skills/components/tab-navigation.md +1 -1
- package/.claude/skills/components/text-block.md +68 -0
- package/.claude/skills/components/toggle-switch-core.md +3 -3
- package/.claude/skills/components/triple-toggle-switch.md +85 -0
- package/.claude/skills/composable-zod-validation.md +1 -1
- package/.claude/skills/consumer-styles-structure.md +153 -0
- package/.claude/skills/icon-sets.md +3 -3
- package/.claude/skills/icon-sizing.md +66 -0
- package/.claude/skills/index.md +35 -16
- package/.claude/skills/new-app-scaffold.md +45 -7
- package/.claude/skills/pull-request-description.md +1 -0
- package/.claude/skills/storybook-add-story.md +53 -5
- package/.claude/skills/testing-add-playwright.md +1 -1
- package/.claude/skills/theming-colour-ramps.md +25 -3
- package/.claude/skills/theming-component-token-pattern.md +16 -16
- package/.claude/skills/theming-override-default.md +7 -0
- package/.claude/skills/theming-partial-override.md +1 -1
- package/.claude/skills/theming-typography-tokens.md +1 -1
- package/.claude/skills/vercel-node-version.md +1 -1
- package/.vscode/srcdev-component-action-menu.code-snippets +42 -0
- package/.vscode/srcdev-component-alert-content.code-snippets +36 -0
- package/.vscode/srcdev-component-alert-masked-content.code-snippets +35 -0
- package/.vscode/srcdev-component-auto-grid.code-snippets +39 -0
- package/.vscode/srcdev-component-capture-decode-qr-code.code-snippets +28 -0
- package/.vscode/srcdev-component-content-docs.code-snippets +4 -4
- package/.vscode/srcdev-component-cookie-consent-banner.code-snippets +33 -0
- package/.vscode/srcdev-component-display-avatar.code-snippets +28 -0
- package/.vscode/srcdev-component-display-chip.code-snippets +27 -0
- package/.vscode/srcdev-component-display-pill.code-snippets +38 -0
- package/.vscode/srcdev-component-display-prompt.code-snippets +10 -54
- package/.vscode/srcdev-component-display-qr-code.code-snippets +22 -0
- package/.vscode/srcdev-component-eyebrow-text.code-snippets +19 -0
- package/.vscode/srcdev-component-form-field.code-snippets +25 -0
- package/.vscode/srcdev-component-form-fieldset.code-snippets +36 -0
- package/.vscode/srcdev-component-form-wrapper.code-snippets +30 -0
- package/.vscode/srcdev-component-glass-panel.code-snippets +38 -0
- package/.vscode/srcdev-component-grid-stack.code-snippets +49 -0
- package/.vscode/srcdev-component-input-button.code-snippets +27 -0
- package/.vscode/srcdev-component-input-checkbox-radio.code-snippets +60 -0
- package/.vscode/srcdev-component-input-checkbox.code-snippets +48 -0
- package/.vscode/srcdev-component-input-description.code-snippets +44 -0
- package/.vscode/srcdev-component-input-error.code-snippets +30 -0
- package/.vscode/srcdev-component-input-label.code-snippets +39 -0
- package/.vscode/srcdev-component-input-number.code-snippets +11 -11
- package/.vscode/srcdev-component-input-radio.code-snippets +58 -0
- package/.vscode/srcdev-component-layout-grid-by-cols.code-snippets +46 -0
- package/.vscode/srcdev-component-link-text.code-snippets +30 -0
- package/.vscode/srcdev-component-opening-hours.code-snippets +40 -0
- package/.vscode/srcdev-component-page-hero-highlights.code-snippets +37 -0
- package/.vscode/srcdev-component-page-row.code-snippets +47 -0
- package/.vscode/srcdev-component-pending-effect.code-snippets +26 -0
- package/.vscode/srcdev-component-price-list.code-snippets +37 -0
- package/.vscode/srcdev-component-pricing-card.code-snippets +2 -2
- package/.vscode/srcdev-component-profile-section.code-snippets +36 -0
- package/.vscode/srcdev-component-samaritan-prompt.code-snippets +60 -0
- package/.vscode/srcdev-component-scroll-reveal-frame.code-snippets +36 -0
- package/.vscode/srcdev-component-scroll-reveal-image.code-snippets +46 -0
- package/.vscode/srcdev-component-services-card.code-snippets +4 -4
- package/.vscode/srcdev-component-services-grids.code-snippets +36 -0
- package/.vscode/srcdev-component-site-navigation.code-snippets +26 -18
- package/.vscode/srcdev-component-slider-gallery.code-snippets +9 -0
- package/.vscode/srcdev-component-social-icons-list.code-snippets +24 -0
- package/.vscode/srcdev-component-stepper-list.code-snippets +39 -0
- package/.vscode/srcdev-component-text-block.code-snippets +31 -0
- package/.vscode/srcdev-component-triple-toggle-switch.code-snippets +30 -0
- package/README.md +2 -2
- package/app/app.config.ts +10 -0
- package/app/assets/styles/setup/02.colours/_orange.css +11 -11
- package/app/assets/styles/setup/02.colours/_theme-params.css +2 -2
- package/app/assets/styles/setup/03.theming/_default.css +1 -22
- package/app/assets/styles/setup/03.theming/_theme-slots.css +1 -1
- package/app/assets/styles/setup/03.theming/_warning.css +8 -10
- package/app/assets/styles/setup/04.elements/forms/02.typography.css +0 -14
- package/app/assets/styles/setup/04.elements/forms/06.button-geometry.css +1 -1
- package/app/assets/styles/setup/index.css +1 -1
- package/app/components/01.atoms/alert-mask/AlertMaskCore.vue +23 -5
- package/app/components/01.atoms/alert-mask/CONSUMER-STYLING.md +23 -5
- package/app/components/01.atoms/alert-mask/stories/AlertMaskCore.stories.ts +45 -19
- package/app/components/01.atoms/alert-mask/tests/AlertMaskCore.spec.ts +35 -1
- package/app/components/01.atoms/animations/animated-svg-text/CONSUMER-STYLING.md +13 -0
- package/app/components/01.atoms/animations/clip-element/CONSUMER-STYLING.md +13 -0
- package/app/components/01.atoms/animations/clip-element/ClipElement.vue +2 -2
- package/app/components/01.atoms/animations/container-glow/CONSUMER-STYLING.md +26 -5
- package/app/components/01.atoms/animations/entry/.nuxt/app.config.mjs +21 -0
- package/app/components/01.atoms/animations/entry/.nuxt/components.d.ts +66 -0
- package/app/components/01.atoms/animations/entry/.nuxt/imports.d.ts +30 -0
- package/app/components/01.atoms/animations/entry/.nuxt/manifest/meta/test.json +1 -0
- package/app/components/01.atoms/animations/entry/.nuxt/types/app.config.d.ts +35 -0
- package/app/components/01.atoms/animations/entry/.nuxt/types/build.d.ts +23 -0
- package/app/components/01.atoms/animations/entry/.nuxt/types/builder-env.d.ts +1 -0
- package/app/components/01.atoms/animations/entry/.nuxt/types/components.d.ts +71 -0
- package/app/components/01.atoms/animations/entry/.nuxt/types/imports.d.ts +386 -0
- package/app/components/01.atoms/animations/entry/.nuxt/types/middleware.d.ts +11 -0
- package/app/components/01.atoms/animations/entry/.nuxt/types/modules.d.ts +79 -0
- package/app/components/01.atoms/animations/entry/.nuxt/types/nitro-layouts.d.ts +17 -0
- package/app/components/01.atoms/animations/entry/.nuxt/types/nitro-nuxt.d.ts +64 -0
- package/app/components/01.atoms/animations/entry/.nuxt/types/plugins.d.ts +29 -0
- package/app/components/01.atoms/animations/entry/.nuxt/types/runtime-config.d.ts +32 -0
- package/app/components/01.atoms/animations/entry/.nuxt/types/shared-imports.d.ts +10 -0
- package/app/components/01.atoms/animations/entry/.nuxt/types/vue-shim.d.ts +0 -0
- package/app/components/01.atoms/animations/entry/.nuxtrc +1 -0
- package/app/components/01.atoms/animations/entry/CONSUMER-STYLING.md +65 -0
- package/app/components/01.atoms/animations/entry/EntryAnimation.vue +6 -5
- package/app/components/01.atoms/animations/entry/node_modules/.cache/nuxt/chrome-workspace.json +1 -0
- package/app/components/01.atoms/animations/entry/node_modules/.cache/vite/client/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
- package/app/components/01.atoms/animations/entry/stories/EntryAnimation.stories.ts +1 -1
- package/app/components/01.atoms/animations/entry/tests/EntryAnimation.spec.ts +25 -0
- package/app/components/01.atoms/animations/glowing-border/CONSUMER-STYLING.md +24 -5
- package/app/components/01.atoms/animations/marquee-scroller/CONSUMER-STYLING.md +20 -0
- package/app/components/01.atoms/animations/rotating-carousel-image/CONSUMER-STYLING.md +17 -0
- package/app/components/01.atoms/animations/scroll-reveal-frame/CONSUMER-STYLING.md +77 -0
- package/app/components/01.atoms/animations/scroll-reveal-frame/ScrollRevealFrame.vue +37 -78
- package/app/components/01.atoms/animations/scroll-reveal-frame/stories/ScrollRevealFrame.stories.ts +48 -0
- package/app/components/01.atoms/animations/scroll-reveal-frame/tests/ScrollRevealFrame.spec.ts +40 -33
- package/app/components/01.atoms/animations/scroll-reveal-frame/tests/__snapshots__/ScrollRevealFrame.spec.ts.snap +4 -4
- package/app/components/01.atoms/animations/scroll-reveal-image/CONSUMER-STYLING.md +74 -0
- package/app/components/01.atoms/animations/scroll-reveal-image/ScrollRevealImage.vue +14 -44
- package/app/components/01.atoms/animations/scroll-reveal-image/stories/ScrollRevealImage.stories.ts +50 -1
- package/app/components/01.atoms/animations/scroll-reveal-image/tests/ScrollRevealImage.spec.ts +27 -20
- package/app/components/01.atoms/animations/scroll-reveal-image/tests/__snapshots__/ScrollRevealImage.spec.ts.snap +4 -4
- package/app/components/01.atoms/animations/section-parallax/CONSUMER-STYLING.md +21 -4
- package/app/components/01.atoms/animations/view-timeline/CONSUMER-STYLING.md +25 -0
- package/app/components/01.atoms/banner-video/CONSUMER-STYLING.md +12 -5
- package/app/components/01.atoms/canvas-switcher/CONSUMER-STYLING.md +20 -7
- package/app/components/01.atoms/canvas-switcher/CanvasSwitcher.vue +12 -7
- package/app/components/01.atoms/card/CONSUMER-STYLING.md +47 -42
- package/app/components/01.atoms/card/CardCore.vue +7 -17
- package/app/components/01.atoms/clipped-panel/CONSUMER-STYLING.md +13 -0
- package/app/components/01.atoms/content-wrappers/docs-pages/CONSUMER-STYLING.md +127 -0
- package/app/components/01.atoms/content-wrappers/docs-pages/ContentDocs.vue +44 -77
- package/app/components/01.atoms/content-wrappers/docs-pages/stories/ContentDocs.stories.ts +3 -3
- package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/CONSUMER-STYLING.md +14 -1
- package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/stories/DashboardQuadGrid.stories.ts +2 -0
- package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/CONSUMER-STYLING.md +13 -0
- package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/stories/DashboardStatsGrid.stories.ts +2 -0
- package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/CONSUMER-STYLING.md +72 -0
- package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/LayoutGridByCols.vue +26 -25
- package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/stories/LayoutGridByCols.stories.ts +91 -107
- package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/tests/LayoutGridByCols.spec.ts +50 -15
- package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/tests/__snapshots__/LayoutGridByCols.spec.ts.snap +5 -5
- package/app/components/01.atoms/display-banner/CONSUMER-STYLING.md +13 -0
- package/app/components/01.atoms/display-dialog/CONSUMER-STYLING.md +82 -54
- package/app/components/01.atoms/display-dialog/DisplayDialog.vue +38 -45
- package/app/components/01.atoms/display-dialog/stories/DisplayDialog.stories.ts +25 -0
- package/app/components/01.atoms/display-dialog/tests/DisplayDialog.spec.ts +21 -0
- package/app/components/01.atoms/display-pill/CONSUMER-STYLING.md +112 -0
- package/app/components/01.atoms/display-pill/DisplayPill.vue +88 -50
- package/app/components/01.atoms/display-pill/stories/DisplayPill.stories.ts +56 -3
- package/app/components/01.atoms/display-pill/tests/DisplayPill.spec.ts +104 -4
- package/app/components/01.atoms/display-pill/tests/__snapshots__/DisplayPill.spec.ts.snap +3 -3
- package/app/components/01.atoms/display-tooltip/CONSUMER-STYLING.md +22 -2
- package/app/components/01.atoms/display-tooltip/DisplayTooltip.vue +18 -26
- package/app/components/01.atoms/glass-panel/CONSUMER-STYLING.md +91 -0
- package/app/components/01.atoms/glass-panel/GlassPanel.vue +34 -30
- package/app/components/01.atoms/glass-panel/stories/GlassPanel.stories.ts +121 -0
- package/app/components/01.atoms/glass-panel/tests/GlassPanel.spec.ts +61 -0
- package/app/components/01.atoms/grids/auto-grid/AutoGrid.vue +5 -10
- package/app/components/01.atoms/grids/auto-grid/CONSUMER-STYLING.md +76 -0
- package/app/components/01.atoms/grids/auto-grid/stories/AutoGrid.stories.ts +5 -4
- package/app/components/01.atoms/grids/auto-grid/tests/AutoGrid.spec.ts +8 -0
- package/app/components/01.atoms/grids/column-flow-grid/CONSUMER-STYLING.md +11 -2
- package/app/components/01.atoms/grids/grid-stack/CONSUMER-STYLING.md +76 -0
- package/app/components/01.atoms/grids/grid-stack/GridStack.vue +6 -1
- package/app/components/01.atoms/grids/grid-stack/stories/GridStack.stories.ts +1 -1
- package/app/components/01.atoms/grids/grid-stack/tests/GridStack.spec.ts +35 -0
- package/app/components/01.atoms/grids/masonry-grid/CONSUMER-STYLING.md +11 -2
- package/app/components/01.atoms/navigation/breadcrumb/Breadcrumb.vue +5 -10
- package/app/components/01.atoms/navigation/breadcrumb/CONSUMER-STYLING.md +15 -0
- package/app/components/01.atoms/navigation/skip-links/CONSUMER-STYLING.md +13 -0
- package/app/components/01.atoms/navigation/tabs/CONSUMER-STYLING.md +21 -0
- package/app/components/01.atoms/page-row/CONSUMER-STYLING.md +46 -8
- package/app/components/01.atoms/page-row/PageRow.vue +17 -13
- package/app/components/01.atoms/page-row/stories/PageRow.stories.ts +8 -0
- package/app/components/01.atoms/page-row/tests/PageRow.spec.ts +7 -11
- package/app/components/01.atoms/pop-over/CONSUMER-STYLING.md +13 -0
- package/app/components/01.atoms/qr-code/CONSUMER-STYLING.md +48 -0
- package/app/components/01.atoms/qr-code/DisplayQrCode.vue +5 -1
- package/app/components/01.atoms/qr-code/stories/DisplayQrCode.stories.ts +11 -3
- package/app/components/01.atoms/qr-code/tests/DisplayQrCode.spec.ts +15 -0
- package/app/components/01.atoms/text-block/CONSUMER-STYLING.md +49 -0
- package/app/components/01.atoms/text-block/TextBlock.vue +13 -5
- package/app/components/01.atoms/text-block/stories/TextBlock.stories.ts +84 -0
- package/app/components/01.atoms/text-block/tests/TextBlock.spec.ts +78 -0
- package/app/components/01.atoms/text-block/tests/__snapshots__/TextBlock.spec.ts.snap +7 -0
- package/app/components/01.atoms/text-blocks/eyebrow-text/CONSUMER-STYLING.md +56 -0
- package/app/components/01.atoms/text-blocks/eyebrow-text/EyebrowText.vue +10 -5
- package/app/components/01.atoms/text-blocks/eyebrow-text/tests/EyebrowText.spec.ts +11 -0
- package/app/components/01.atoms/text-blocks/header-block/CONSUMER-STYLING.md +16 -1
- package/app/components/01.atoms/text-blocks/hero-text/CONSUMER-STYLING.md +74 -0
- package/app/components/01.atoms/text-blocks/hero-text/HeroText.vue +14 -9
- package/app/components/01.atoms/text-blocks/hero-text/tests/HeroText.spec.ts +11 -0
- package/app/components/01.atoms/text-blocks/link-text/CONSUMER-STYLING.md +45 -0
- package/app/components/01.atoms/text-blocks/link-text/LinkText.vue +15 -8
- package/app/components/01.atoms/text-blocks/link-text/tests/LinkText.spec.ts +11 -0
- package/app/components/01.atoms/ui-block-decorated/CONSUMER-STYLING.md +13 -0
- package/app/components/02.molecules/action-menu/ActionMenu.vue +28 -30
- package/app/components/02.molecules/action-menu/{ActionMenuItemCore.vue → ActionMenuItem.vue} +12 -14
- package/app/components/02.molecules/action-menu/CONSUMER-STYLING.md +90 -76
- package/app/components/02.molecules/action-menu/stories/ActionMenu.stories.ts +48 -41
- package/app/components/02.molecules/action-menu/tests/ActionMenu.spec.ts +46 -1
- package/app/components/02.molecules/action-menu/tests/{ActionMenuItemCore.spec.ts → ActionMenuItem.spec.ts} +11 -5
- package/app/components/02.molecules/action-menu/tests/__snapshots__/ActionMenuItem.spec.ts.snap +27 -0
- package/app/components/02.molecules/alert-content/AlertContent.vue +17 -8
- package/app/components/02.molecules/alert-content/AlertContentInner.vue +57 -30
- package/app/components/02.molecules/alert-content/CONSUMER-STYLING.md +84 -0
- package/app/components/02.molecules/alert-content/stories/AlertContent.stories.ts +39 -0
- package/app/components/02.molecules/alert-content/tests/AlertContent.spec.ts +32 -0
- package/app/components/02.molecules/alert-content/tests/AlertContentInner.spec.ts +32 -0
- package/app/components/02.molecules/alert-masked-content/AlertMaskedContent.vue +9 -5
- package/app/components/02.molecules/alert-masked-content/CONSUMER-STYLING.md +73 -0
- package/app/components/02.molecules/alert-masked-content/stories/AlertMaskedContent.stories.ts +91 -10
- package/app/components/02.molecules/alert-masked-content/tests/AlertMaskedContent.spec.ts +52 -0
- package/app/components/02.molecules/cookie-consent-banner/CONSUMER-STYLING.md +95 -0
- package/app/components/02.molecules/cookie-consent-banner/CookieConsentBanner.vue +149 -0
- package/app/components/{01.atoms → 02.molecules}/cookie-consent-banner/stories/CookieConsentBanner.stories.ts +22 -3
- package/app/components/{01.atoms → 02.molecules}/cookie-consent-banner/tests/CookieConsentBanner.spec.ts +81 -4
- package/app/components/02.molecules/display-avatar/CONSUMER-STYLING.md +63 -0
- package/app/components/02.molecules/display-avatar/DisplayAvatar.vue +120 -0
- package/app/components/{01.atoms → 02.molecules}/display-avatar/stories/DisplayAvatar.stories.ts +56 -14
- package/app/components/{01.atoms → 02.molecules}/display-avatar/tests/DisplayAvatar.spec.ts +43 -11
- package/app/components/02.molecules/display-avatar/tests/__snapshots__/DisplayAvatar.spec.ts.snap +11 -0
- package/app/components/02.molecules/display-chip/CONSUMER-STYLING.md +57 -0
- package/app/components/02.molecules/display-chip/DisplayChip.vue +50 -83
- package/app/components/02.molecules/display-chip/tests/DisplayChip.spec.ts +10 -10
- package/app/components/02.molecules/display-chip/tests/__snapshots__/DisplayChip.spec.ts.snap +4 -4
- package/app/components/02.molecules/display-theme-switch/CONSUMER-STYLING.md +25 -4
- package/app/components/02.molecules/display-theme-switch/DisplayThemeSwitch.vue +9 -6
- package/app/components/02.molecules/display-theme-switch/stories/DisplayThemeSwitch.stories.ts +6 -1
- package/app/components/02.molecules/display-theme-switch/tests/DisplayThemeSwitch.spec.ts +10 -1
- package/app/components/02.molecules/display-tooltip-defined/CONSUMER-STYLING.md +11 -0
- package/app/components/02.molecules/expandable/accordian/CONSUMER-STYLING.md +11 -4
- package/app/components/02.molecules/expandable/expanding-panel/CONSUMER-STYLING.md +12 -5
- package/app/components/02.molecules/expandable/expanding-panel-classic/CONSUMER-STYLING.md +12 -5
- package/app/components/02.molecules/input-copy/CONSUMER-STYLING.md +12 -5
- package/app/components/02.molecules/input-copy/InputCopy.vue +12 -25
- package/app/components/02.molecules/input-copy/stories/InputCopy.stories.ts +1 -1
- package/app/components/02.molecules/input-copy/tests/InputCopy.spec.ts +1 -1
- package/app/components/02.molecules/navigation/deep-expanding-menu/CONSUMER-STYLING.md +13 -0
- package/app/components/02.molecules/navigation/deep-expanding-menu-classic/CONSUMER-STYLING.md +11 -0
- package/app/components/02.molecules/navigation/site-navigation/CONSUMER-STYLING.md +109 -0
- package/app/components/02.molecules/navigation/site-navigation/SiteNavigation.vue +37 -55
- package/app/components/02.molecules/navigation/site-navigation/stories/SiteNavigation.stories.ts +22 -1
- package/app/components/02.molecules/navigation/site-navigation/tests/SiteNavigation.spec.ts +41 -6
- package/app/components/02.molecules/navigation/tab-navigation/CONSUMER-STYLING.md +13 -8
- package/app/components/02.molecules/navigation/tab-navigation/TabNavigation.vue +18 -36
- package/app/components/02.molecules/navigation/tab-navigation/stories/TabNavigation.stories.ts +1 -1
- package/app/components/02.molecules/navigation/tab-navigation/tests/TabNavigation.spec.ts +1 -1
- package/app/components/02.molecules/opening-hours/CONSUMER-STYLING.md +134 -0
- package/app/components/02.molecules/opening-hours/OpeningHours.vue +352 -0
- package/app/components/02.molecules/opening-hours/stories/OpeningHours.stories.ts +127 -0
- package/app/components/02.molecules/opening-hours/tests/OpeningHours.spec.ts +228 -0
- package/app/components/02.molecules/opening-hours/tests/OpeningHours.structuredData.spec.ts +45 -0
- package/app/components/02.molecules/opening-hours/tests/__snapshots__/OpeningHours.spec.ts.snap +23 -0
- package/app/components/02.molecules/opening-hours/tests/buildOpeningHoursSpecification.spec.ts +52 -0
- package/app/components/02.molecules/price-list/CONSUMER-STYLING.md +106 -0
- package/app/components/02.molecules/price-list/PriceList.vue +48 -40
- package/app/components/02.molecules/price-list/stories/PriceList.stories.ts +15 -2
- package/app/components/02.molecules/price-list/tests/PriceList.spec.ts +39 -2
- package/app/components/02.molecules/price-list/tests/__snapshots__/PriceList.spec.ts.snap +4 -16
- package/app/components/02.molecules/pricing-card/CONSUMER-STYLING.md +23 -5
- package/app/components/02.molecules/pricing-card/PricingCard.vue +31 -61
- package/app/components/02.molecules/pricing-card/stories/PricingCard.stories.ts +2 -0
- package/app/components/02.molecules/pricing-card/tests/PricingCard.spec.ts +14 -1
- package/app/components/02.molecules/profile-section/CONSUMER-STYLING.md +53 -0
- package/app/components/02.molecules/profile-section/ProfileSection.vue +53 -66
- package/app/components/02.molecules/profile-section/tests/ProfileSection.spec.ts +4 -4
- package/app/components/02.molecules/profile-section/tests/__snapshots__/ProfileSection.spec.ts.snap +6 -12
- package/app/components/02.molecules/prompt/CONSUMER-STYLING.md +51 -0
- package/app/components/{01.atoms → 02.molecules}/prompt/DisplayPrompt.vue +23 -8
- package/app/components/{01.atoms → 02.molecules}/prompt/stories/DisplayPrompt.stories.ts +18 -1
- package/app/components/{01.atoms → 02.molecules}/prompt/tests/DisplayPrompt.spec.ts +37 -7
- package/app/components/02.molecules/qr-code/CONSUMER-STYLING.md +66 -0
- package/app/components/02.molecules/qr-code/CaptureQrCode.vue +31 -12
- package/app/components/02.molecules/qr-code/DecodeQrCode.vue +55 -19
- package/app/components/02.molecules/qr-code/stories/CaptureQrCode.stories.ts +56 -0
- package/app/components/02.molecules/qr-code/stories/DecodeQrCode.stories.ts +53 -0
- package/app/components/02.molecules/qr-code/tests/CaptureQrCode.spec.ts +68 -20
- package/app/components/02.molecules/qr-code/tests/DecodeQrCode.spec.ts +44 -8
- package/app/components/02.molecules/samaritan-prompt/CONSUMER-STYLING.md +118 -0
- package/app/components/02.molecules/samaritan-prompt/SamaritanPrompt.vue +108 -51
- package/app/components/02.molecules/samaritan-prompt/SamaritanPromptMixed.vue +63 -62
- package/app/components/02.molecules/samaritan-prompt/stories/SamaritanPrompt.stories.ts +129 -0
- package/app/components/02.molecules/samaritan-prompt/stories/SamaritanPromptMixed.stories.ts +124 -0
- package/app/components/02.molecules/samaritan-prompt/tests/SamaritanPrompt.spec.ts +66 -0
- package/app/components/02.molecules/samaritan-prompt/tests/SamaritanPromptMixed.spec.ts +95 -17
- package/app/components/02.molecules/select-menu/CONSUMER-STYLING.md +11 -2
- package/app/components/02.molecules/social-icons-list/CONSUMER-STYLING.md +43 -0
- package/app/components/02.molecules/social-icons-list/SocialIconsList.vue +15 -15
- package/app/components/02.molecules/social-icons-list/stories/SocialIconsList.stories.ts +6 -1
- package/app/components/02.molecules/social-icons-list/tests/SocialIconsList.spec.ts +22 -1
- package/app/components/02.molecules/social-icons-list/tests/__snapshots__/SocialIconsList.spec.ts.snap +3 -3
- package/app/components/02.molecules/stepper-list/CONSUMER-STYLING.md +44 -5
- package/app/components/02.molecules/stepper-list/StepperList.vue +23 -43
- package/app/components/02.molecules/stepper-list/tests/StepperList.spec.ts +9 -0
- package/app/components/{01.atoms → 02.molecules}/toast/CONSUMER-STYLING.md +14 -0
- package/app/components/{01.atoms → 02.molecules}/toast/DisplayToast.vue +1 -2
- package/app/components/{01.atoms → 02.molecules}/toast/DisplayToastProvider.vue +1 -2
- package/app/components/{01.atoms → 02.molecules}/toast/stories/DisplayToast.stories.ts +1 -1
- package/app/components/{01.atoms → 02.molecules}/toast/stories/DisplayToastProvider.stories.ts +1 -1
- package/app/components/03.organisms/image-galleries/carousel-flip/CONSUMER-STYLING.md +13 -0
- package/app/components/03.organisms/image-galleries/slider-gallery/CONSUMER-STYLING.md +137 -0
- package/app/components/03.organisms/image-galleries/slider-gallery/SliderGallery.vue +378 -343
- package/app/components/03.organisms/image-galleries/slider-gallery/stories/SliderGallery.stories.ts +26 -1
- package/app/components/03.organisms/image-galleries/slider-gallery/tests/SliderGallery.spec.ts +102 -23
- package/app/components/03.organisms/image-galleries/slider-gallery/tests/__snapshots__/SliderGallery.spec.ts.snap +44 -44
- package/app/components/03.organisms/responsive-header/CONSUMER-STYLING.md +12 -1
- package/app/components/03.organisms/responsive-header/ResponsiveHeader.vue +0 -4
- package/app/components/03.organisms/services/service-detail/CONSUMER-STYLING.md +24 -3
- package/app/components/03.organisms/services/service-detail/ServiceDetail.vue +3 -3
- package/app/components/03.organisms/services/service-detail/stories/ServiceDetail.stories.ts +13 -13
- package/app/components/03.organisms/services/service-detail/tests/__snapshots__/ServiceDetail.spec.ts.snap +1 -1
- package/app/components/03.organisms/services/service-summary/CONSUMER-STYLING.md +24 -7
- package/app/components/03.organisms/services/service-summary/ServiceSummary.vue +3 -3
- package/app/components/03.organisms/services/service-summary/stories/ServiceSummary.stories.ts +1 -1
- package/app/components/03.organisms/services/service-summary/tests/__snapshots__/ServiceSummary.spec.ts.snap +1 -1
- package/app/components/03.organisms/services/services-card/CONSUMER-STYLING.md +11 -2
- package/app/components/03.organisms/services/services-card/ServicesCard.vue +17 -26
- package/app/components/03.organisms/services/services-card/tests/ServicesCard.spec.ts +21 -0
- package/app/components/03.organisms/services/services-grids/CONSUMER-STYLING.md +50 -0
- package/app/components/03.organisms/services/services-grids/ServicesCardGrid.vue +9 -16
- package/app/components/03.organisms/services/services-grids/stories/ServicesCardGrid.stories.ts +6 -0
- package/app/components/03.organisms/services/services-grids/tests/ServicesCardGrid.spec.ts +18 -0
- package/app/components/03.organisms/services/services-grids/tests/__snapshots__/ServiceSummaryGrid.spec.ts.snap +3 -3
- package/app/components/03.organisms/services/services-grids/tests/__snapshots__/ServicesCardGrid.spec.ts.snap +3 -3
- package/app/components/03.organisms/site-header/CONSUMER-STYLING.md +12 -1
- package/app/components/04.templates/page-hero-highlights/CONSUMER-STYLING.md +103 -0
- package/app/components/04.templates/page-hero-highlights/PageHeroHighlights.vue +144 -193
- package/app/components/04.templates/page-hero-highlights/PageHeroHighlightsHeader.vue +27 -37
- package/app/components/04.templates/page-hero-highlights/stories/PageHeroHighlights.stories.ts +56 -60
- package/app/components/04.templates/page-hero-highlights/stories/PageHeroHighlightsHeader.stories.ts +2 -2
- package/app/components/04.templates/page-hero-highlights/tests/PageHeroHighlights.spec.ts +10 -10
- package/app/components/04.templates/page-hero-highlights/tests/PageHeroHighlightsHeader.spec.ts +7 -7
- package/app/components/04.templates/page-hero-highlights/tests/__snapshots__/PageHeroHighlights.spec.ts.snap +6 -6
- package/app/components/05.forms/form-errors/CONSUMER-STYLING.md +112 -0
- package/app/components/05.forms/form-errors/InputError.vue +101 -122
- package/app/components/05.forms/form-errors/stories/InputError.stories.ts +125 -0
- package/app/components/05.forms/form-errors/tests/InputError.spec.ts +82 -31
- package/app/components/05.forms/form-field/CONSUMER-STYLING.md +91 -0
- package/app/components/05.forms/form-field/FormField.vue +26 -35
- package/app/components/05.forms/form-field/stories/FormField.stories.ts +104 -0
- package/app/components/05.forms/form-field/tests/FormField.spec.ts +75 -0
- package/app/components/05.forms/form-fieldset/CONSUMER-STYLING.md +88 -0
- package/app/components/05.forms/form-fieldset/FormFieldset.vue +34 -28
- package/app/components/05.forms/form-fieldset/stories/FormFieldset.stories.ts +84 -0
- package/app/components/05.forms/form-fieldset/tests/FormFieldset.spec.ts +111 -0
- package/app/components/05.forms/form-wrapper/CONSUMER-STYLING.md +101 -0
- package/app/components/05.forms/form-wrapper/FormWrapper.vue +32 -15
- package/app/components/05.forms/form-wrapper/stories/FormWrapper.stories.ts +75 -0
- package/app/components/05.forms/form-wrapper/tests/FormWrapper.spec.ts +57 -0
- package/app/components/05.forms/input-button/CONSUMER-STYLING.md +52 -7
- package/app/components/05.forms/input-button/{InputButtonCore.vue → InputButton.vue} +60 -18
- package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts → input-button.playwright.ts} +5 -5
- package/app/components/05.forms/input-button/stories/{InputButtonCore.stories.ts → InputButton.stories.ts} +8 -10
- package/app/components/05.forms/input-button/tests/{InputButtonCore.spec.ts → InputButton.spec.ts} +75 -19
- package/app/components/05.forms/input-button/tests/__snapshots__/{InputButtonCore.spec.ts.snap → InputButton.spec.ts.snap} +18 -18
- package/app/components/05.forms/input-checkbox/CONSUMER-STYLING.md +93 -0
- package/app/components/05.forms/input-checkbox/MultipleCheckboxes.vue +19 -25
- package/app/components/05.forms/input-checkbox/SingleCheckbox.vue +17 -43
- package/app/components/05.forms/input-checkbox/stories/MultipleCheckboxes.stories.ts +104 -0
- package/app/components/05.forms/input-checkbox/stories/SingleCheckbox.stories.ts +75 -0
- package/app/components/05.forms/input-checkbox/tests/MultipleCheckboxes.spec.ts +91 -53
- package/app/components/05.forms/input-checkbox/tests/SingleCheckbox.spec.ts +112 -0
- package/app/components/05.forms/input-checkbox-radio/CONSUMER-STYLING.md +115 -35
- package/app/components/05.forms/input-checkbox-radio/InputCheckboxRadio.vue +158 -0
- package/app/components/05.forms/input-checkbox-radio/InputCheckboxRadioButton.vue +102 -101
- package/app/components/05.forms/input-checkbox-radio/InputCheckboxRadioField.vue +100 -0
- package/app/components/05.forms/input-checkbox-radio/stories/{InputCheckboxRadioCore.stories.ts → InputCheckboxRadio.stories.ts} +23 -8
- package/app/components/05.forms/input-checkbox-radio/stories/InputCheckboxRadioButton.stories.ts +60 -16
- package/app/components/05.forms/input-checkbox-radio/stories/InputCheckboxRadioField.stories.ts +93 -0
- package/app/components/05.forms/input-checkbox-radio/tests/InputCheckboxRadio.spec.ts +174 -0
- package/app/components/05.forms/input-checkbox-radio/tests/InputCheckboxRadioButton.spec.ts +87 -0
- package/app/components/05.forms/input-checkbox-radio/tests/InputCheckboxRadioField.spec.ts +87 -0
- package/app/components/05.forms/input-description/CONSUMER-STYLING.md +177 -0
- package/app/components/05.forms/input-description/InputDescription.vue +45 -24
- package/app/components/05.forms/input-description/stories/InputDescription.stories.ts +160 -0
- package/app/components/05.forms/input-description/tests/InputDescription.spec.ts +62 -386
- package/app/components/05.forms/input-label/CONSUMER-STYLING.md +134 -0
- package/app/components/05.forms/input-label/InputLabel.vue +99 -38
- package/app/components/05.forms/input-label/stories/InputLabel.stories.ts +236 -0
- package/app/components/05.forms/input-label/tests/InputLabel.spec.ts +113 -342
- package/app/components/05.forms/input-number/CONSUMER-STYLING.md +16 -7
- package/app/components/05.forms/input-number/{InputNumberCore.vue → InputNumber.vue} +6 -6
- package/app/components/05.forms/input-number/{variants/InputNumberDefault.vue → InputNumberField.vue} +12 -15
- package/app/components/05.forms/input-number/stories/{InputNumberCore.stories.ts → InputNumber.stories.ts} +6 -6
- package/app/components/05.forms/input-number/{variants/stories/InputNumberDefault.stories.ts → stories/InputNumberField.stories.ts} +5 -5
- package/app/components/05.forms/input-number/tests/{InputNumberCore.spec.ts → InputNumber.spec.ts} +2 -2
- package/app/components/05.forms/input-number/{variants/tests/InputNumberDefault.spec.ts → tests/InputNumberField.spec.ts} +8 -8
- package/app/components/05.forms/input-radio/CONSUMER-STYLING.md +70 -0
- package/app/components/05.forms/input-radio/MultipleRadiobuttons.vue +19 -30
- package/app/components/05.forms/input-radio/stories/MultipleRadiobuttons.stories.ts +116 -0
- package/app/components/05.forms/input-radio/tests/MultipleRadioButtons.spec.ts +125 -74
- package/app/components/05.forms/input-range/CONSUMER-STYLING.md +13 -0
- package/app/components/05.forms/input-range/InputRangeCore.vue +1 -1
- package/app/components/05.forms/input-range/{variants/InputRangeDefault.vue → InputRangeDefault.vue} +7 -11
- package/app/components/05.forms/input-range/{variants/tests → tests}/InputRangeDefault.spec.ts +1 -1
- package/app/components/05.forms/input-select/CONSUMER-STYLING.md +11 -2
- package/app/components/05.forms/input-select/{variants/InputSelectWithLabel.vue → InputSelectWithLabel.vue} +6 -9
- package/app/components/05.forms/input-select/stories/InputSelectWithLabel.stories.ts +1 -1
- package/app/components/05.forms/input-text/CONSUMER-STYLING.md +12 -3
- package/app/components/05.forms/input-text/{variants/InputPasswordWithLabel.vue → InputPasswordWithLabel.vue} +3 -3
- package/app/components/05.forms/input-text/{variants/InputTextAsNumberWithLabel.vue → InputTextAsNumberWithLabel.vue} +12 -15
- package/app/components/05.forms/input-text/InputTextCore.vue +8 -11
- package/app/components/05.forms/input-text/{variants/InputTextWithLabel.vue → InputTextWithLabel.vue} +9 -10
- package/app/components/05.forms/input-text/stories/InputPasswordWithLabel.stories.ts +1 -1
- package/app/components/05.forms/input-text/stories/InputTextAsNumberWithLabel.stories.ts +1 -1
- package/app/components/05.forms/input-text/stories/InputTextWithLabel.stories.ts +1 -1
- package/app/components/05.forms/input-text/tests/InputPasswordWithLabel.spec.ts +2 -1
- package/app/components/05.forms/input-text/tests/InputTextAsNumberWithLabel.spec.ts +1 -1
- package/app/components/05.forms/input-text/tests/InputTextWithLabel.spec.ts +2 -1
- package/app/components/05.forms/input-textarea/CONSUMER-STYLING.md +11 -2
- package/app/components/05.forms/input-textarea/{variants/InputTextareaWithLabel.vue → InputTextareaWithLabel.vue} +3 -7
- package/app/components/05.forms/input-textarea/stories/InputTextareaWithLabel.stories.ts +1 -1
- package/app/components/05.forms/patterns/stories/ContactForm.stories.ts +9 -10
- package/app/components/05.forms/patterns/stories/LoginForm.stories.ts +10 -10
- package/app/components/05.forms/patterns/stories/MigratedFieldsForm.stories.ts +246 -101
- package/app/components/05.forms/pending-effect/CONSUMER-STYLING.md +92 -0
- package/app/components/05.forms/pending-effect/PendingEffect.vue +52 -45
- package/app/components/05.forms/pending-effect/stories/PendingEffect.stories.ts +132 -0
- package/app/components/05.forms/pending-effect/tests/PendingEffect.spec.ts +67 -0
- package/app/components/05.forms/toggle-switch/CONSUMER-STYLING.md +11 -2
- package/app/components/05.forms/toggle-switch/ToggleSwitchCore.vue +10 -29
- package/app/components/05.forms/toggle-switch/{variants/ToggleSwitchWithLabel.vue → ToggleSwitchWithLabel.vue} +5 -7
- package/app/components/05.forms/toggle-switch/{variants/ToggleSwitchWithLabelInline.vue → ToggleSwitchWithLabelInline.vue} +2 -4
- package/app/components/05.forms/toggle-switch/stories/ToggleSwitchWithLabel.stories.ts +1 -1
- package/app/components/05.forms/toggle-switch/stories/ToggleSwitchWithLabelInline.stories.ts +4 -1
- package/app/components/05.forms/toggle-switch/{variants/tests → tests}/ToggleSwitchWithLabel.spec.ts +26 -0
- package/app/components/05.forms/triple-toggle-switch/CONSUMER-STYLING.md +75 -62
- package/app/components/05.forms/triple-toggle-switch/TripleToggleSwitch.vue +243 -0
- package/app/components/05.forms/triple-toggle-switch/stories/TripleToggleSwitch.stories.ts +104 -0
- package/app/components/05.forms/triple-toggle-switch/tests/TripleToggleSwitch.spec.ts +138 -0
- package/app/composables/tests/useCancellableTimer.spec.ts +48 -0
- package/app/composables/tests/useMaxChildWidth.spec.ts +67 -0
- package/app/composables/useCancellableTimer.ts +27 -7
- package/app/composables/useMaxChildWidth.ts +4 -6
- package/app/types/app-config.d.ts +10 -0
- package/app/types/components/cookie-consent-banner.d.ts +3 -0
- package/app/types/components/index.ts +6 -1
- package/app/types/components/opening-hours.d.ts +48 -0
- package/app/types/components/price-list.d.ts +11 -0
- package/app/types/components/profile-section.d.ts +6 -0
- package/app/types/components/samaritan-prompt.d.ts +13 -0
- package/app/types/components/services-card.d.ts +9 -0
- package/app/types/components/slider-gallery.d.ts +2 -0
- package/app/types/components/social-icons-list.d.ts +2 -0
- package/app/types/forms/types.forms.d.ts +3 -0
- package/app/types/forms/types.zodFormControl.d.ts +0 -3
- package/app/utils/opening-hours.ts +44 -0
- package/nuxt.config.ts +5 -1
- package/package.json +2 -2
- package/ramps.config.mjs +1 -1
- package/.claude/commands/create-commit-message.md +0 -13
- package/.claude/commands/create-release-notes.md +0 -34
- package/.claude/commands/migrate-component.md +0 -169
- package/.claude/commands/run-commit.md +0 -13
- package/.claude/component-ledger/artifact-url.txt +0 -1
- package/.claude/component-ledger/audit.json +0 -1
- package/.claude/component-ledger/build.mjs +0 -164
- package/.claude/component-ledger/output.html +0 -569
- package/.claude/component-ledger/template.html +0 -569
- package/.claude/hooks/check-component-update.sh +0 -95
- package/.claude/hooks/refresh-component-ledger.sh +0 -32
- package/.claude/settings.json +0 -134
- package/.claude/settings.local.json +0 -38
- package/.claude/skills/components/alert-content-inner.md +0 -60
- package/.claude/skills/components/navigation-horizontal.md +0 -99
- package/.claude/skills/components/samaritan-prompt-mixed.md +0 -139
- package/app/components/01.atoms/content-wrappers/content-columns-2/ContentColumns2.vue +0 -51
- package/app/components/01.atoms/content-wrappers/content-columns-2/stories/ContentColumns2.stories.ts +0 -110
- package/app/components/01.atoms/content-wrappers/content-columns-2/tests/ContentColumns2.spec.ts +0 -105
- package/app/components/01.atoms/content-wrappers/content-columns-2/tests/__snapshots__/ContentColumns2.spec.ts.snap +0 -14
- package/app/components/01.atoms/content-wrappers/content-width/ContentWidth.vue +0 -88
- package/app/components/01.atoms/content-wrappers/content-width/stories/ContentWidth.stories.ts +0 -362
- package/app/components/01.atoms/content-wrappers/content-width/tests/ContentWidth.spec.ts +0 -132
- package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/tests/__snapshots__/LayoutGrid.spec.ts.snap +0 -36
- package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/LayoutGridByWidth.vue +0 -70
- package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/stories/LayoutGridByWidth.stories.ts +0 -220
- package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/tests/LayoutGridByWidth.spec.ts +0 -174
- package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/tests/__snapshots__/LayoutGrid.spec.ts.snap +0 -36
- package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/tests/__snapshots__/LayoutGridByCols.spec.ts.snap +0 -36
- package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/tests/__snapshots__/LayoutGridByWidth.spec.ts.snap +0 -36
- package/app/components/01.atoms/cookie-consent-banner/CookieConsentBanner.vue +0 -148
- package/app/components/01.atoms/display-avatar/DisplayAvatar.vue +0 -130
- package/app/components/01.atoms/display-avatar/tests/__snapshots__/DisplayAvatar.spec.ts.snap +0 -11
- package/app/components/02.molecules/action-menu/tests/__snapshots__/ActionMenuItemCore.spec.ts.snap +0 -27
- package/app/components/02.molecules/navigation/navigation-horizontal/NavigationHorizontal.vue +0 -162
- package/app/components/02.molecules/navigation/navigation-horizontal/stories/NavigationHorizontal.stories.ts +0 -373
- package/app/components/02.molecules/navigation/navigation-horizontal/tests/NavigationHorizontal.spec.ts +0 -152
- package/app/components/02.molecules/navigation/navigation-horizontal/tests/__snapshots__/NavigationHorizontal.spec.ts.snap +0 -17
- package/app/components/02.molecules/qr-code/stories/QrCode.stories.ts +0 -101
- package/app/components/03.organisms/colour-finder/ColourFinder.vue +0 -1519
- package/app/components/05.forms/input-checkbox-radio/InputCheckboxRadioCore.vue +0 -202
- package/app/components/05.forms/input-checkbox-radio/InputCheckboxRadioWithLabel.vue +0 -105
- package/app/components/05.forms/input-checkbox-radio/tests/InputCheckboxRadioCore.spec.ts +0 -320
- package/app/components/05.forms/triple-toggle-switch/TripleToggleSwitchCore.vue +0 -314
- package/app/components/05.forms/triple-toggle-switch/stories/TripleToggleSwitchCore.stories.ts +0 -63
- package/.vscode/{srcdev-component-dialog.code-snippets → srcdev-component-display-dialog.code-snippets} +0 -0
- package/app/components/{01.atoms → 02.molecules}/toast/tests/DisplayToast.spec.ts +1 -1
- /package/app/components/{01.atoms → 02.molecules}/toast/tests/DisplayToastProvider.spec.ts +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-icons-secondary-chromium-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-icons-secondary-firefox-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-icons-secondary-webkit-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-icons-tertiary-chromium-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-icons-tertiary-firefox-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-icons-tertiary-webkit-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-primary-pending-chromium-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-primary-pending-firefox-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-primary-pending-webkit-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-secondary-pill-chromium-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-secondary-pill-firefox-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-secondary-pill-webkit-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-tertiary-readonly-chromium-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-tertiary-readonly-firefox-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/combo-tertiary-readonly-webkit-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-chromium-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-firefox-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-default-chromium-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-default-firefox-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-default-webkit-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-error-chromium-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-error-firefox-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-error-webkit-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-success-chromium-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-success-firefox-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-success-webkit-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-warning-chromium-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-warning-firefox-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-theme-warning-webkit-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-variant-primary-chromium-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-variant-primary-firefox-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-variant-primary-webkit-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-variant-secondary-chromium-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-variant-secondary-firefox-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-variant-secondary-webkit-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-variant-tertiary-chromium-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-variant-tertiary-firefox-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-variant-tertiary-webkit-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/default-webkit-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/nuxt-icon-only-component-chromium-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/nuxt-icon-only-component-firefox-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/nuxt-icon-only-component-webkit-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/state-pending-chromium-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/state-pending-firefox-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/state-pending-webkit-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/state-pill-chromium-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/state-pill-firefox-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/state-pill-webkit-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/state-readonly-chromium-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/state-readonly-firefox-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/state-readonly-webkit-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/with-both-nuxt-icon-components-chromium-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/with-both-nuxt-icon-components-firefox-darwin.png +0 -0
- /package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts-snapshots → input-button.playwright.ts-snapshots}/with-both-nuxt-icon-components-webkit-darwin.png +0 -0
- /package/app/components/05.forms/input-range/{variants/stories → stories}/InputRangeDefault.stories.ts +0 -0
- /package/app/components/05.forms/input-select/{variants/tests → tests}/InputSelectWithLabel.spec.ts +0 -0
- /package/app/components/05.forms/input-textarea/{variants/tests → tests}/InputTextareaWithLabel.spec.ts +0 -0
- /package/app/components/05.forms/toggle-switch/{variants/tests → tests}/ToggleSwitchWithLabelInline.spec.ts +0 -0
- /package/app/types/components/{navigation-horizontal.d.ts → nav-item.d.ts} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ScrollRevealFrame
|
|
3
|
-
description: ScrollRevealFrame generic parallax clipping frame — props, slot API, CSS tokens, browser support, when to use vs ScrollRevealImage
|
|
3
|
+
description: ScrollRevealFrame generic parallax clipping frame — props, slot API, public CSS tokens (prop or CSS), browser support, when to use vs ScrollRevealImage
|
|
4
4
|
type: reference
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -14,26 +14,28 @@ Use `ScrollRevealFrame` when the content inside the frame is **anything other th
|
|
|
14
14
|
|
|
15
15
|
## How it works
|
|
16
16
|
|
|
17
|
-
- The `<figure>` root is a fixed-height clipping window (`overflow: hidden`) that registers a named `view-timeline`.
|
|
18
|
-
- The inner `.reveal-content` wrapper is taller than the frame by
|
|
17
|
+
- The `<figure class="scroll-reveal-frame">` root is a fixed-height clipping window (`overflow: hidden`) that registers a named `view-timeline`.
|
|
18
|
+
- The inner `.scroll-reveal-frame-content` wrapper is taller than the frame by the parallax offset and animates `translateY` as the frame scrolls through the viewport.
|
|
19
19
|
- Slot content fills that wrapper — anything inside pans as a unit.
|
|
20
20
|
|
|
21
21
|
Browser support (as of 2026): Chrome 115+, Edge 115+, Firefox 114+, Safari 17.2+. Older browsers fall back to a static cropped view.
|
|
22
22
|
|
|
23
23
|
## Props
|
|
24
24
|
|
|
25
|
+
The three sizing props have **no default**. When passed, each writes its public token inline on the root (so it wins over any CSS). When omitted, the token comes from CSS, falling back to the default shown.
|
|
26
|
+
|
|
25
27
|
| Prop | Type | Default | Description |
|
|
26
28
|
|------|------|---------|-------------|
|
|
27
|
-
| `frameHeight` | `string` | `
|
|
28
|
-
| `parallaxOffset` | `string` | `
|
|
29
|
-
| `radius` | `string` | `
|
|
29
|
+
| `frameHeight` | `string` | unset (CSS `540px`) | Height of the visible clipping frame. Any CSS length unit. Writes `--scroll-reveal-frame-height`. |
|
|
30
|
+
| `parallaxOffset` | `string` | unset (CSS `36rem`) | Distance the content travels vertically across the full scroll range. Writes `--scroll-reveal-frame-parallax-offset`. |
|
|
31
|
+
| `radius` | `string` | unset (CSS `0px`) | `border-radius` of the clipping frame. Writes `--scroll-reveal-frame-radius`. |
|
|
30
32
|
| `styleClassPassthrough` | `string \| string[]` | `[]` | Extra classes applied to the root `<figure>`. |
|
|
31
33
|
|
|
32
34
|
## Slots
|
|
33
35
|
|
|
34
36
|
| Slot | Description |
|
|
35
37
|
|------|-------------|
|
|
36
|
-
| `default` | Content to pan. It fills a `div.reveal-content` that is taller than the frame by
|
|
38
|
+
| `default` | Content to pan. It fills a `div.scroll-reveal-frame-content` that is taller than the frame by the parallax offset. |
|
|
37
39
|
|
|
38
40
|
## Basic usage — single image
|
|
39
41
|
|
|
@@ -91,29 +93,27 @@ Wrap each `<img>` / `<NuxtImg>` in a `<div>` cell — `object-fit` on an `<img>`
|
|
|
91
93
|
|
|
92
94
|
## Responsive frame height
|
|
93
95
|
|
|
94
|
-
|
|
96
|
+
Don't pass the prop; set the public token from CSS on an element you own:
|
|
95
97
|
|
|
96
98
|
```css
|
|
97
99
|
.my-page {
|
|
98
|
-
|
|
99
|
-
--_frame-height: 320px;
|
|
100
|
+
--scroll-reveal-frame-height: 320px;
|
|
100
101
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
102
|
+
@media (width >= 768px) {
|
|
103
|
+
--scroll-reveal-frame-height: 540px;
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
106
|
```
|
|
107
107
|
|
|
108
108
|
## CSS custom properties
|
|
109
109
|
|
|
110
|
-
|
|
110
|
+
Full detail in `CONSUMER-STYLING.md` next to the component.
|
|
111
111
|
|
|
112
|
-
| Property | Default | Set by prop |
|
|
112
|
+
| Property | Default | Set by prop (when passed) |
|
|
113
113
|
|----------|---------|-------------|
|
|
114
|
-
| `--
|
|
115
|
-
| `--
|
|
116
|
-
| `--
|
|
114
|
+
| `--scroll-reveal-frame-height` | `540px` | `frameHeight` |
|
|
115
|
+
| `--scroll-reveal-frame-parallax-offset` | `36rem` | `parallaxOffset` |
|
|
116
|
+
| `--scroll-reveal-frame-radius` | `0px` | `radius` |
|
|
117
117
|
|
|
118
118
|
## Choosing parallaxOffset
|
|
119
119
|
|
|
@@ -131,6 +131,7 @@ Values below `20rem` tend to look static at normal scroll speeds.
|
|
|
131
131
|
## Notes
|
|
132
132
|
|
|
133
133
|
- `overflow: hidden` is on the root `<figure>` — content that needs to escape (dropdowns, tooltips) must be portalled outside.
|
|
134
|
-
- The named `view-timeline` (`--reveal-frame-timeline`) is scoped to the component. Multiple `ScrollRevealFrame` instances on the same page are independent.
|
|
135
|
-
- Reduced-motion: the animation is disabled and the content
|
|
134
|
+
- The named `view-timeline` (`--scroll-reveal-frame-timeline`) is scoped to the component. Multiple `ScrollRevealFrame` instances on the same page are independent.
|
|
135
|
+
- Reduced-motion: the animation is disabled and the content is sized to the frame (a static crop) via `@media (prefers-reduced-motion: reduce)`. Same for browsers without `animation-timeline`.
|
|
136
136
|
- Do not put `ScrollRevealFrame` inside a container with `overflow: hidden` or `overflow: clip` — this breaks the `view-timeline` scroll detection.
|
|
137
|
+
- 2026-09-27 migration: the private `--_frame-height`/`--_parallax-offset`/`--_radius` tokens became public `--scroll-reveal-frame-*` tokens, and the props lost their defaults. Before, the props always wrote the private tokens inline, so the CSS override this doc used to recommend could never apply. Classes renamed `.reveal-frame` → `.scroll-reveal-frame`, `.reveal-content` → `.scroll-reveal-frame-content`; keyframes `reveal-pan` → `scroll-reveal-frame-pan` (generic global names, collision-prone). `ScrollRevealImage`'s image class became `.scroll-reveal-image`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ScrollRevealImage
|
|
3
|
-
description: ScrollRevealImage single-image parallax reveal — props, focalX
|
|
3
|
+
description: ScrollRevealImage single-image parallax reveal — props, focalX and focal-y crop tokens, CSS tokens (prop or CSS), browser support, when to use vs ScrollRevealFrame
|
|
4
4
|
type: reference
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -20,10 +20,10 @@ For arbitrary slot content — a grid of images, video, markup — use `ScrollRe
|
|
|
20
20
|
| `alt` | `string` | `""` | Alt text for the image. |
|
|
21
21
|
| `imgWidth` | `number` | `1920` | Intrinsic width of the source image — required for NuxtImg optimisation. |
|
|
22
22
|
| `imgHeight` | `number` | `1080` | Intrinsic height of the source image — required for NuxtImg optimisation. |
|
|
23
|
-
| `frameHeight` | `string` | `
|
|
24
|
-
| `parallaxOffset` | `string` | `
|
|
25
|
-
| `focalX` | `string` | `
|
|
26
|
-
| `radius` | `string` | `
|
|
23
|
+
| `frameHeight` | `string` | unset (CSS default `540px`) | Height of the visible clipping frame. Any CSS length unit. Leave unset to control it from CSS via `--scroll-reveal-frame-height`. |
|
|
24
|
+
| `parallaxOffset` | `string` | unset (CSS default `36rem`) | Distance the image travels vertically across the full scroll range. Leave unset to control it via `--scroll-reveal-frame-parallax-offset`. |
|
|
25
|
+
| `focalX` | `string` | unset (CSS default `50%`) | Horizontal focal point, CSS `object-position` x value. Controls which horizontal slice stays in view. Leave unset to control it via `--scroll-reveal-image-focal-x`. |
|
|
26
|
+
| `radius` | `string` | unset (CSS default `0px`) | `border-radius` of the clipping frame. Leave unset to control it via `--scroll-reveal-frame-radius`. |
|
|
27
27
|
| `loading` | `"lazy" \| "eager"` | `"lazy"` | Image loading strategy. Use `"eager"` if this is the LCP image (e.g. partially in view on load). |
|
|
28
28
|
| `styleClassPassthrough` | `string \| string[]` | `[]` | Extra classes applied to the root `<figure>`. |
|
|
29
29
|
|
|
@@ -102,7 +102,7 @@ The vertical position of the image is driven by the scroll animation (`translate
|
|
|
102
102
|
| `"75%"` | Right of centre — useful for a subject offset to the right |
|
|
103
103
|
| `"100%"` or `"right"` | Right edge |
|
|
104
104
|
|
|
105
|
-
Internally, `focalX` sets `object-position: <
|
|
105
|
+
Internally, `focalX` sets `--scroll-reveal-image-focal-x`, used as `object-position: <focal-x> <focal-y>` on the `<img>`. The Y comes from `--scroll-reveal-image-focal-y` (default `0%`, so the animation starts at the image top); raise it if the top of the image is empty or the subject sits low. With no animation (reduced motion or no support), Y is `--scroll-reveal-image-focal-y-static` (default `50%`).
|
|
106
106
|
|
|
107
107
|
## imgWidth / imgHeight
|
|
108
108
|
|
|
@@ -122,34 +122,43 @@ Common pairs:
|
|
|
122
122
|
|
|
123
123
|
## Responsive frame height
|
|
124
124
|
|
|
125
|
-
|
|
125
|
+
Don't pass `frame-height`, and set the frame's public token from CSS on an ancestor you own (a prop,
|
|
126
|
+
when passed, is written inline and always wins):
|
|
126
127
|
|
|
127
128
|
```css
|
|
128
129
|
.my-page {
|
|
129
|
-
|
|
130
|
-
--_frame-height: 320px;
|
|
130
|
+
--scroll-reveal-frame-height: 320px;
|
|
131
131
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
132
|
+
@media (width >= 768px) {
|
|
133
|
+
--scroll-reveal-frame-height: 480px;
|
|
134
|
+
}
|
|
135
135
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
136
|
+
@media (width >= 1024px) {
|
|
137
|
+
--scroll-reveal-frame-height: 540px;
|
|
139
138
|
}
|
|
140
139
|
}
|
|
141
140
|
```
|
|
142
141
|
|
|
142
|
+
> **Changed 2026-09-27**: this section used to recommend overriding `--_frame-height` on
|
|
143
|
+
> `.reveal-frame`. That never worked, because this component always passed a default `frameHeight`
|
|
144
|
+
> down and the frame always wrote it inline. The frame-sizing props now default to unset.
|
|
145
|
+
|
|
143
146
|
## CSS custom properties
|
|
144
147
|
|
|
145
|
-
|
|
148
|
+
Frame tokens come from `ScrollRevealFrame` (see its `CONSUMER-STYLING.md`); each prop writes its
|
|
149
|
+
token inline only when passed.
|
|
146
150
|
|
|
147
151
|
| Property | Default | Set by prop |
|
|
148
152
|
| -------- | ------- | ----------- |
|
|
149
|
-
| `--
|
|
150
|
-
| `--
|
|
151
|
-
| `--
|
|
152
|
-
| `--
|
|
153
|
+
| `--scroll-reveal-frame-height` | `540px` | `frameHeight` |
|
|
154
|
+
| `--scroll-reveal-frame-parallax-offset` | `36rem` | `parallaxOffset` |
|
|
155
|
+
| `--scroll-reveal-frame-radius` | `0px` | `radius` |
|
|
156
|
+
| `--scroll-reveal-image-focal-x` | `50%` | `focalX` |
|
|
157
|
+
| `--scroll-reveal-image-focal-y` | `0%` | none (CSS only) |
|
|
158
|
+
| `--scroll-reveal-image-focal-y-static` | `50%` | none (CSS only) |
|
|
159
|
+
|
|
160
|
+
Classes: root `.scroll-reveal-frame`, wrapper `.scroll-reveal-frame-content`, image
|
|
161
|
+
`.scroll-reveal-image` (renamed 2026-09-27 from `.reveal-frame`/`.reveal-content`/`.reveal-image`).
|
|
153
162
|
|
|
154
163
|
## Choosing parallaxOffset
|
|
155
164
|
|
|
@@ -160,5 +169,6 @@ See `scroll-reveal-frame.md` for the full guide. For portrait images the default
|
|
|
160
169
|
- The root `<figure>` has `margin: 0` set in the component — browser default `<figure>` margins are neutralised at source.
|
|
161
170
|
- `decoding="async"` is always set on the `<img>`. Use `:loading="'eager'"` if this component is the LCP image (e.g. a hero partially in view on load) — the default `"lazy"` is correct for below-fold usage.
|
|
162
171
|
- Do not place inside a container with `overflow: hidden` or `overflow: clip` — breaks the `view-timeline` scroll detection inherited from `ScrollRevealFrame`.
|
|
163
|
-
- Reduced-motion: animation is disabled and the image falls back to a static crop
|
|
172
|
+
- Reduced-motion: animation is disabled and the image falls back to a static crop at `object-position: <focal-x> <focal-y-static>` (default `50% 50%`).
|
|
173
|
+
- 2026-09-27 migration: `focalX` lost its `"50%"` default and now writes the public `--scroll-reveal-image-focal-x` only when passed (it was a private `--_focal-x`, always inline, so CSS could never change it). New `--scroll-reveal-image-focal-y`/`-focal-y-static` tokens replace the hardcoded vertical crop. Added CONSUMER-STYLING.md, snippet and a `CssTokens` story.
|
|
164
174
|
- Storybook: the `"none"` image provider is active (`nuxt.config.ts`), so `src` paths pass through unchanged. Always provide explicit `img-width` and `img-height` props to avoid the `w=1536` fallback in deployed Storybook.
|
|
@@ -111,7 +111,7 @@ are delegated to the consumer, matching `ServiceSummary`'s slot-based routing pa
|
|
|
111
111
|
:related-services="relatedServices"
|
|
112
112
|
>
|
|
113
113
|
<template #book-cta>
|
|
114
|
-
<
|
|
114
|
+
<InputButton tag="a" href="/contact" button-text="Book now" variant="primary" />
|
|
115
115
|
</template>
|
|
116
116
|
<template #sidebar-note>
|
|
117
117
|
A patch test is required at least 48 hours before any colour treatment.
|
|
@@ -120,7 +120,7 @@ are delegated to the consumer, matching `ServiceSummary`'s slot-based routing pa
|
|
|
120
120
|
<NuxtLink :to="`/services/${related.slug}`">{{ related.title }} — {{ related.price }}</NuxtLink>
|
|
121
121
|
</template>
|
|
122
122
|
<template #final-cta>
|
|
123
|
-
<
|
|
123
|
+
<InputButton tag="a" href="/contact" button-text="Book now" variant="secondary" />
|
|
124
124
|
</template>
|
|
125
125
|
</ServiceDetail>
|
|
126
126
|
```
|
|
@@ -10,13 +10,14 @@
|
|
|
10
10
|
| ----------------------- | --------------------------------- | -------------------------------- | -------- |
|
|
11
11
|
| `servicesData` | `Service[]` | — | **yes** |
|
|
12
12
|
| `tag` | `"div" \| "section" \| "main"` | `"div"` | no |
|
|
13
|
-
| `eyebrowConfig` | `
|
|
14
|
-
| `heroConfig` | `
|
|
13
|
+
| `eyebrowConfig` | `ServicesCardEyebrowConfig` | `{}` | no |
|
|
14
|
+
| `heroConfig` | `ServicesCardHeroConfig` | `{}` | no |
|
|
15
15
|
| `hrefBase` | `string` | `"/services/"` | no |
|
|
16
16
|
| `buttonTextPrefix` | `string` | `"Enquire about"` | no |
|
|
17
|
+
| `buttonIcon` | `string` | `"mdi:arrow-right"` | no |
|
|
17
18
|
| `styleClassPassthrough` | `string \| string[]` | `[]` | no |
|
|
18
19
|
|
|
19
|
-
Both config props are passed through to every `ServicesCard` in the grid unchanged. See [services-card.md](./services-card.md) for the full `
|
|
20
|
+
Both config props are passed through to every `ServicesCard` in the grid unchanged. See [services-card.md](./services-card.md) for the full key reference. The types are exported as `ServicesCardEyebrowConfig` / `ServicesCardHeroConfig` from `srcdev-nuxt-components` (were inline and not importable before 2026-09-28).
|
|
20
21
|
|
|
21
22
|
### Button link and text
|
|
22
23
|
|
|
@@ -104,6 +105,6 @@ if (servicesData.value.length === 0) {
|
|
|
104
105
|
|
|
105
106
|
- Component is auto-imported in Nuxt — no import needed.
|
|
106
107
|
- The `Service` type is imported from `~/types/types.services`.
|
|
107
|
-
- Uses `repeat(auto-fit, minmax(var(--services-card-grid-column-min-width, 250px), 1fr))` — columns grow to fill available space and wrap when below the minimum width.
|
|
108
|
+
- Uses `repeat(auto-fit, minmax(min(var(--services-card-grid-column-min-width, 250px), 100%), 1fr))` (the `min(…, 100%)` stops a single column overflowing containers narrower than the minimum, fixed 2026-09-28) — columns grow to fill available space and wrap when below the minimum width.
|
|
108
109
|
- The `#actions` slot template is passed down into each `ServicesCard`; `serviceData` is the scoped prop for the current iteration item.
|
|
109
110
|
- Data fetching is the page's responsibility — pass an empty array as fallback while loading (`servicesData ?? []`).
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
| `tag` | `"div" \| "section" \| "article"` | `"div"` | no |
|
|
13
13
|
| `href` | `string` | `undefined` | no |
|
|
14
14
|
| `external` | `boolean` | `false` | no |
|
|
15
|
-
| `eyebrowConfig` | `
|
|
16
|
-
| `heroConfig` | `
|
|
15
|
+
| `eyebrowConfig` | `ServicesCardEyebrowConfig` | `{}` | no |
|
|
16
|
+
| `heroConfig` | `ServicesCardHeroConfig` | `{}` | no |
|
|
17
17
|
| `durationText` | `string` | `undefined` | no |
|
|
18
18
|
| `priceText` | `string` | `undefined` | no |
|
|
19
19
|
| `styleClassPassthrough` | `string \| string[]` | `[]` | no |
|
|
@@ -24,7 +24,7 @@ A row below the description shows duration (left) and price (right), separated b
|
|
|
24
24
|
|
|
25
25
|
### Whole-card clickable (`href`)
|
|
26
26
|
|
|
27
|
-
When `href` is set **and no `actions` slot content is provided**, the root element switches from `tag` to a link (`NuxtLink` for an internal href starting with `/`, a plain `a` otherwise) and the whole card becomes clickable — matching `
|
|
27
|
+
When `href` is set **and no `actions` slot content is provided**, the root element switches from `tag` to a link (`NuxtLink` for an internal href starting with `/`, a plain `a` otherwise) and the whole card becomes clickable — matching `InputButton`'s link-resolution pattern. `external` forces a plain `a` tag even for an internal-looking href (e.g. a Nitro server route like `/api/auth/github`).
|
|
28
28
|
|
|
29
29
|
If an `actions` slot is provided, the card stays as a static `tag` element (no href rendered) even when `href` is set — this avoids nesting another interactive element (e.g. a button/link in `actions`) inside the card's own anchor, which would be invalid HTML. Use the `href` mode for a plain "whole card links out" card with no separate CTA, and the `actions`-slot mode (see Basic usage below) when the card needs its own button/link.
|
|
30
30
|
|
|
@@ -32,6 +32,8 @@ If an `actions` slot is provided, the card stays as a static `tag` element (no h
|
|
|
32
32
|
|
|
33
33
|
### EyebrowConfig
|
|
34
34
|
|
|
35
|
+
Exported as `ServicesCardEyebrowConfig` (and `ServicesCardHeroConfig` below) from `srcdev-nuxt-components` since 2026-09-28.
|
|
36
|
+
|
|
35
37
|
| Key | Type | Default |
|
|
36
38
|
| ---------- | ---------------------------------- | --------- |
|
|
37
39
|
| `tag` | `"p" \| "div" \| "span"` | `"div"` |
|
|
@@ -71,7 +73,7 @@ scaffold a style block using `styleClassPassthrough` instead — see
|
|
|
71
73
|
```vue
|
|
72
74
|
<ServicesCard :service-data="service">
|
|
73
75
|
<template #actions="{ serviceData }">
|
|
74
|
-
<
|
|
76
|
+
<InputButton
|
|
75
77
|
variant="secondary"
|
|
76
78
|
:button-text="`More about ${serviceData.title}`"
|
|
77
79
|
:href="`/services/${serviceData.slug}`"
|
|
@@ -79,7 +81,7 @@ scaffold a style block using `styleClassPassthrough` instead — see
|
|
|
79
81
|
<template #right>
|
|
80
82
|
<Icon name="mdi:arrow-right" class="icon" />
|
|
81
83
|
</template>
|
|
82
|
-
</
|
|
84
|
+
</InputButton>
|
|
83
85
|
</template>
|
|
84
86
|
</ServicesCard>
|
|
85
87
|
```
|
|
@@ -93,7 +95,7 @@ scaffold a style block using `styleClassPassthrough` instead — see
|
|
|
93
95
|
:hero-config="{ tag: 'h3', fontSize: 'title' }"
|
|
94
96
|
>
|
|
95
97
|
<template #actions="{ serviceData }">
|
|
96
|
-
<
|
|
98
|
+
<InputButton variant="secondary" :button-text="`Enquire`" :href="`/services/${serviceData.slug}`" />
|
|
97
99
|
</template>
|
|
98
100
|
</ServicesCard>
|
|
99
101
|
```
|
|
@@ -111,7 +113,7 @@ scaffold a style block using `styleClassPassthrough` instead — see
|
|
|
111
113
|
<span>From {{ serviceData.price }}</span>
|
|
112
114
|
</template>
|
|
113
115
|
<template #actions="{ serviceData }">
|
|
114
|
-
<
|
|
116
|
+
<InputButton variant="secondary" :button-text="`Enquire`" :href="`/services/${serviceData.slug}`" />
|
|
115
117
|
</template>
|
|
116
118
|
</ServicesCard>
|
|
117
119
|
```
|
|
@@ -126,7 +128,7 @@ scaffold a style block using `styleClassPassthrough` instead — see
|
|
|
126
128
|
:hero-config="{ tag: 'h2', fontSize: 'heading' }"
|
|
127
129
|
>
|
|
128
130
|
<template #actions="{ serviceData }">
|
|
129
|
-
<
|
|
131
|
+
<InputButton
|
|
130
132
|
variant="secondary"
|
|
131
133
|
:button-text="`Enquire about ${serviceData.title}`"
|
|
132
134
|
:href="`/services/${serviceData.slug}`"
|
|
@@ -135,7 +137,7 @@ scaffold a style block using `styleClassPassthrough` instead — see
|
|
|
135
137
|
<template #right>
|
|
136
138
|
<Icon name="mdi:arrow-right" class="icon" />
|
|
137
139
|
</template>
|
|
138
|
-
</
|
|
140
|
+
</InputButton>
|
|
139
141
|
</template>
|
|
140
142
|
</ServicesCard>
|
|
141
143
|
</template>
|
|
@@ -172,5 +174,5 @@ No `actions` slot — the entire card renders as an anchor (`NuxtLink` for the i
|
|
|
172
174
|
- Root markup is two rows (`grid-template-rows: auto 1fr`): `.image-wrapper`, then a `.details-wrapper` (`display: flex; flex-direction: column`) holding the eyebrow, title, description, and a `.footer` wrapper. Description length is controlled by `--description-line-clamp` (default effectively unclamped) rather than a fixed-height grid row.
|
|
173
175
|
- `.footer` groups the meta row and the `actions` slot and gets `margin-block-start: auto`, pinning them to the bottom of the card. Combined with the root's `1fr` details row, this means when `ServicesCardGrid`'s default `align-items: stretch` makes a card taller than its own content (to match a taller sibling in the same row), the extra height goes to `.footer`'s top margin rather than leaving whitespace below the actions slot — so the meta row and actions/button line up across a row of cards regardless of each card's description length. This does the visual job of CSS subgrid without needing a subgrid chain across `ServicesCard`/`ServicesCardGrid` (which would also break whenever cards in a row don't all render the same optional rows — `.meta` and `actions` are both conditional).
|
|
174
176
|
- Image has a `3/4` aspect ratio with a subtle scale-on-hover effect.
|
|
175
|
-
- `.services-card`, `.image-wrapper`, `.details-wrapper`, and `.footer` all set `min-inline-size: 0`. Without it, an unbreakable child — most commonly a long `actions` slot button label, since `
|
|
177
|
+
- `.services-card`, `.image-wrapper`, `.details-wrapper`, and `.footer` all set `min-inline-size: 0`. Without it, an unbreakable child — most commonly a long `actions` slot button label, since `InputButton`'s `.button-text` is `white-space: nowrap` with no ellipsis — forces its content's min-content width up through the flex/grid chain and widens that one card's grid column in `ServicesCardGrid` wider than its siblings (the image just rides along on the widened column; it isn't the actual cause). If you see one card/column wider than the rest with cut-off content, check for a long unbreakable string in a slot before assuming it's an image sizing issue.
|
|
176
178
|
- Usually consumed via `ServicesCardGrid` rather than directly.
|
|
@@ -17,6 +17,8 @@ Both the horizontal list and the panel include animated active/hover indicator d
|
|
|
17
17
|
| `navItemData` | `NavItemData` | — (required) | Navigation items — see type below |
|
|
18
18
|
| `navAlign` | `"left" \| "center" \| "right"` | `"left"` | Alignment of the horizontal nav list |
|
|
19
19
|
| `ariaLabel` | `string` | `"Site navigation"` | aria-label on the root `<nav>` landmark — override for localisation |
|
|
20
|
+
| `openMenuLabel` | `string` | `"Open navigation menu"` | Burger button text (screen-reader) while closed — override for localisation |
|
|
21
|
+
| `closeMenuLabel` | `string` | `"Close navigation menu"` | Burger button text (screen-reader) while open — override for localisation |
|
|
20
22
|
| `styleClassPassthrough` | `string \| string[]` | `[]` | Extra classes applied to the root `<nav>` |
|
|
21
23
|
|
|
22
24
|
## NavItemData type
|
|
@@ -24,7 +26,7 @@ Both the horizontal list and the panel include animated active/hover indicator d
|
|
|
24
26
|
**Within the layer:**
|
|
25
27
|
|
|
26
28
|
```ts
|
|
27
|
-
import type { NavItemData } from "~/types/components/
|
|
29
|
+
import type { NavItemData } from "~/types/components/nav-item.d";
|
|
28
30
|
```
|
|
29
31
|
|
|
30
32
|
**In a consuming app:**
|
|
@@ -70,6 +72,8 @@ Set these tokens on a parent element (e.g. your `<header>`) to theme the navigat
|
|
|
70
72
|
.your-header {
|
|
71
73
|
/* ── Decorators ────────────────────────────────────── */
|
|
72
74
|
--site-nav-decorator-indicator-color: var(--rose-05); /* underline bar */
|
|
75
|
+
--site-nav-decorator-hovered-bg: transparent; /* hover pill behind a link */
|
|
76
|
+
--site-nav-decorator-active-bg: transparent; /* active pill behind a link */
|
|
73
77
|
|
|
74
78
|
/* ── Horizontal nav links ──────────────────────────── */
|
|
75
79
|
--site-nav-link-color: var(--warm-01);
|
|
@@ -102,30 +106,40 @@ Set these tokens on a parent element (e.g. your `<header>`) to theme the navigat
|
|
|
102
106
|
--site-nav-burger-gap: 5px;
|
|
103
107
|
--site-nav-burger-transition: 300ms ease;
|
|
104
108
|
|
|
105
|
-
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
The backdrop is teleported to `<body>`, so its tokens only land when set on `:root`/`html`/`body`,
|
|
113
|
+
not on your header:
|
|
114
|
+
|
|
115
|
+
```css
|
|
116
|
+
:where(html) {
|
|
106
117
|
--site-nav-backdrop-bg: oklch(0% 0 0 / 55%);
|
|
107
118
|
--site-nav-backdrop-blur: 3px;
|
|
108
119
|
--site-nav-backdrop-duration: 350ms;
|
|
120
|
+
--site-nav-backdrop-z-index: 10; /* keep your header above this */
|
|
109
121
|
}
|
|
110
122
|
```
|
|
111
123
|
|
|
124
|
+
Full reference: `app/components/02.molecules/navigation/site-navigation/CONSUMER-STYLING.md`.
|
|
125
|
+
|
|
112
126
|
## Behaviour notes
|
|
113
127
|
|
|
114
128
|
- **Collapse detection**: `ResizeObserver` fires on every container resize. The list's `scrollWidth` is cached whenever the list is in the DOM; that cached value is compared against the container's `clientWidth` to set `isCollapsed`.
|
|
115
129
|
- **isLoaded state**: The component uses `useState("site-nav-loaded")` — a Nuxt shared state — to gate visibility until the first measurement is complete, preventing a flash of the wrong nav state on load. The nav renders `opacity: 0` until `is-loaded` is applied.
|
|
116
130
|
- **Teleport**: The backdrop overlay is teleported to `<body>` via `<Teleport>` and is only mounted when `isCollapsed && isLoaded`.
|
|
117
|
-
- **Panel inert**: The
|
|
131
|
+
- **Panel inert**: The panel div (id `site-nav-panel-{useId}`, unique per instance) receives `:inert="!isMenuOpen ? true : undefined"` — it is inert (keyboard/pointer-inaccessible) when closed.
|
|
118
132
|
- **Decorator init**: `initNavDecorators()` and `initPanelDecorators()` inject `<li>` elements with CSS-driven indicator `<div>`s. They query `[data-nav-item]` / `[data-panel-nav-item]` to find links, and look for `router-link-active` to set the initial active position.
|
|
119
133
|
|
|
120
134
|
## Accessibility
|
|
121
135
|
|
|
122
|
-
- Root `<nav>` has `aria-label
|
|
123
|
-
- Burger button
|
|
136
|
+
- Root `<nav>` has `aria-label` from the `ariaLabel` prop (default `"Site navigation"`).
|
|
137
|
+
- Burger button text comes from `openMenuLabel`/`closeMenuLabel`, with `aria-expanded` (string `"true"/"false"`) and `aria-controls` pointing at the panel's per-instance id (was a fixed `site-nav-panel`, which collided when two navs were on one page; fixed 2026-09-27).
|
|
124
138
|
- Backdrop and indicator `<li>` elements are `aria-hidden="true"`.
|
|
125
139
|
- Panel div is `inert` when closed.
|
|
126
140
|
|
|
127
141
|
## Related files
|
|
128
142
|
|
|
129
|
-
- Type: `app/types/components/
|
|
143
|
+
- Type: `app/types/components/nav-item.d.ts`
|
|
130
144
|
- Tests: `app/components/02.molecules/navigation/site-navigation/tests/SiteNavigation.spec.ts`
|
|
131
145
|
- Story: `app/components/02.molecules/navigation/site-navigation/stories/SiteNavigation.stories.ts`
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# SliderGallery
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
`SliderGallery` (`03.organisms/image-galleries/slider-gallery`) is a full-screen image carousel:
|
|
6
|
+
a large slide with staggered text, a thumbnail strip that animates into place, prev/next arrows, a
|
|
7
|
+
progress bar, and optional auto-advance. It's `position: absolute; inset: 0` at `100svh × 100vw`,
|
|
8
|
+
so place it inside a positioned container sized for it (usually a full-viewport hero).
|
|
9
|
+
|
|
10
|
+
> **Changed 2026-09-28:** every inner class is now `slider-gallery-*` (was bare `.list`, `.item`,
|
|
11
|
+
> `.content`, `.title`, `.thumbnail`, `.arrows`, `.time` and so on, which collided with consumer CSS
|
|
12
|
+
> since the component renders inline). State classes are `.is-next`/`.is-prev`/`.is-prepended`/`.is-loaded`.
|
|
13
|
+
> The arrows lost their fixed `id="prev"`/`id="next"`. The dead "See more" `<button>` is now a link,
|
|
14
|
+
> rendered only for slides with an `href`. Auto-advance pauses on hover/focus and is off under
|
|
15
|
+
> reduced motion. Keyframes are prefixed `slider-gallery-*`.
|
|
16
|
+
|
|
17
|
+
## Props
|
|
18
|
+
|
|
19
|
+
| Prop | Type | Default | Notes |
|
|
20
|
+
|---|---|---|---|
|
|
21
|
+
| `v-model:gallery-data` | `IGalleryData[]` | required | Slides (see type below) |
|
|
22
|
+
| `autoRun` | `boolean` | `true` | Auto-advance. Paused while hovered or focused; never runs under `prefers-reduced-motion: reduce` |
|
|
23
|
+
| `autoRunInterval` | `number` | `7000` | ms between auto-advances |
|
|
24
|
+
| `animationDuration` | `number` | `3000` | ms a transition locks the controls (also drives the progress bar) |
|
|
25
|
+
| `ariaLabel` | `string` | `"Image gallery"` | Carousel region label |
|
|
26
|
+
| `loadingText` | `string` | `"Loading gallery..."` | Loading-state copy |
|
|
27
|
+
| `seeMoreText` | `string` | `"SEE MORE"` | Link text for slides with an `href` |
|
|
28
|
+
| `prevAriaLabel` / `nextAriaLabel` | `string` | `"Previous image"` / `"Next image"` | Arrow button labels |
|
|
29
|
+
| `prevIcon` / `nextIcon` | `string` | `ic:outline-keyboard-arrow-left/right` | Arrow icons |
|
|
30
|
+
| `textScrim` | `boolean` | `true` | Fades in a gradient behind the active slide's text (slides with no stylist, title, category, description or href get none): dark behind `textBrightness: "light"` slides, light behind `"dark"` ones. Adds `.has-text-scrim` to the root. Styled by `--slider-gallery-text-light-scrim` / `--slider-gallery-text-dark-scrim` |
|
|
31
|
+
| `styleClassPassthrough` | `string \| string[]` | `[]` | Classes on the root. Reactive |
|
|
32
|
+
|
|
33
|
+
All copy props are there for localisation: pass translated strings.
|
|
34
|
+
|
|
35
|
+
## IGalleryData
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import type { IGalleryData } from "srcdev-nuxt-components";
|
|
39
|
+
|
|
40
|
+
interface IGalleryData {
|
|
41
|
+
src: string;
|
|
42
|
+
alt: string;
|
|
43
|
+
stylist?: string; // small caps line above the title
|
|
44
|
+
title?: string;
|
|
45
|
+
category?: string; // second large line
|
|
46
|
+
description?: string;
|
|
47
|
+
thumbnail?: { title: string; description: string };
|
|
48
|
+
textBrightness: "light" | "dark"; // text colour over this image
|
|
49
|
+
href?: string; // renders a see-more link; omitted = no link
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Accessibility
|
|
54
|
+
|
|
55
|
+
- Root is `role="region"` + `aria-roledescription="carousel"` + `aria-label`.
|
|
56
|
+
- Arrow buttons have labels; ArrowLeft/ArrowRight work while focus is inside the gallery.
|
|
57
|
+
- The thumbnail strip is decorative duplicate content: `aria-hidden`, thumbnail images have empty `alt`.
|
|
58
|
+
- Loading block is `role="status"`; the progress bar is `aria-hidden`.
|
|
59
|
+
- Auto-advance meets WCAG 2.2.2 via pause-on-hover/focus, and is disabled under reduced motion (animations also collapse to near-instant there).
|
|
60
|
+
|
|
61
|
+
## Usage
|
|
62
|
+
|
|
63
|
+
```vue
|
|
64
|
+
<script setup lang="ts">
|
|
65
|
+
import type { IGalleryData } from "srcdev-nuxt-components";
|
|
66
|
+
const slides = ref<IGalleryData[]>([
|
|
67
|
+
{ src: "/images/work-1.jpg", alt: "Balayage on long curls", title: "Balayage", textBrightness: "light", href: "/work/balayage" },
|
|
68
|
+
]);
|
|
69
|
+
</script>
|
|
70
|
+
|
|
71
|
+
<template>
|
|
72
|
+
<div class="hero" style="position: relative; height: 100svh;">
|
|
73
|
+
<SliderGallery v-model:gallery-data="slides" aria-label="Recent work" />
|
|
74
|
+
</div>
|
|
75
|
+
</template>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Styling
|
|
79
|
+
|
|
80
|
+
Public tokens (`--slider-gallery-*`) cover height, z-index, accent (spinner and progress), text
|
|
81
|
+
colours, thumbnail size/border/radius/overlay, arrow row position (base, tablet, desktop), arrow size, colours, border, outline (resting, hover and focus) and CTA colours. Full reference:
|
|
82
|
+
`app/components/03.organisms/image-galleries/slider-gallery/CONSUMER-STYLING.md`.
|
|
83
|
+
|
|
84
|
+
## Notes
|
|
85
|
+
|
|
86
|
+
- Navigation moves real DOM nodes (append/prepend) rather than re-rendering, so don't key other
|
|
87
|
+
logic off the rendered order of `.slider-gallery-item`.
|
|
88
|
+
- `z-index` defaults to `9999` (`--slider-gallery-z-index`) because it's a full-screen takeover.
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
|------|------|---------|-------|
|
|
13
13
|
| `items` | `ISocialIcon[]` | — | **Required.** Array of social network items. |
|
|
14
14
|
| `label` | `string` | `"Social media profiles"` | `aria-label` applied to the `<ul>` element. |
|
|
15
|
+
| `linkLabelTemplate` | `string` | `"{network} profile (opens in a new tab)"` | `aria-label` for each link; `{network}` is replaced with the item's `networkName`. |
|
|
15
16
|
| `styleClassPassthrough` | `string \| string[]` | `[]` | Extra CSS classes applied to the root `<ul>`. |
|
|
16
17
|
|
|
17
18
|
---
|
|
@@ -20,7 +21,8 @@
|
|
|
20
21
|
|
|
21
22
|
```ts
|
|
22
23
|
interface ISocialIcon {
|
|
23
|
-
networkName: string; //
|
|
24
|
+
networkName: string; // Fills {network} in the list's linkLabelTemplate
|
|
25
|
+
label?: string; // Optional per-item aria-label, overrides the template
|
|
24
26
|
iconName: string; // Iconify icon name, e.g. "logos:instagram-icon"
|
|
25
27
|
baseHref: string; // Base URL including trailing slash, e.g. "https://www.instagram.com/"
|
|
26
28
|
profileId: string; // Profile identifier appended to baseHref
|
|
@@ -84,8 +86,12 @@ import type { ISocialIcon } from "srcdev-nuxt-components";
|
|
|
84
86
|
|
|
85
87
|
| Property | Default | Notes |
|
|
86
88
|
|----------|---------|-------|
|
|
87
|
-
| `--
|
|
88
|
-
| `--
|
|
89
|
+
| `--social-icons-list-icon-size` | `2.4rem` | Icon size (applied as `font-size`) |
|
|
90
|
+
| `--social-icons-list-gap` | `1.2rem` | Gap between icons in the flex row |
|
|
91
|
+
| `--social-icons-list-hover-scale` | `1.15` | Hover/focus scale (none under reduced motion) |
|
|
92
|
+
| `--social-icons-list-hover-opacity` | `0.85` | Hover/focus opacity |
|
|
93
|
+
|
|
94
|
+
> Renamed 2026-09-28 from `--theme-social-icon-size` / `--theme-social-icon-gap`. Full reference: `CONSUMER-STYLING.md` in the component folder.
|
|
89
95
|
|
|
90
96
|
> **Note:** Iconify's `logos:*` styles are injected outside any CSS `@layer`, which means they override layered component styles. Icon sizing is applied via an inline `style` attribute on the `<Icon>` element so it takes precedence.
|
|
91
97
|
|
|
@@ -108,8 +114,8 @@ Offer this scaffold when placing the component in a consuming page or section. T
|
|
|
108
114
|
─────────────────────────────────────────────────────────────────── */
|
|
109
115
|
.my-page-or-section {
|
|
110
116
|
.social-icons-list {
|
|
111
|
-
/* --
|
|
112
|
-
/* --
|
|
117
|
+
/* --social-icons-list-icon-size: 3.2rem; */
|
|
118
|
+
/* --social-icons-list-gap: 1.6rem; */
|
|
113
119
|
/* margin-block-start: 1.6rem; */
|
|
114
120
|
|
|
115
121
|
.social-icon-link {
|
|
@@ -130,6 +136,6 @@ need to target a specific instance. See `component-local-style-override.md` for
|
|
|
130
136
|
## Notes
|
|
131
137
|
|
|
132
138
|
- All links open in a new tab with `rel="noopener noreferrer"`.
|
|
133
|
-
- Each link
|
|
139
|
+
- Each link's `aria-label` comes from `linkLabelTemplate` (default `"{network} profile (opens in a new tab)"`, `{network}` = `networkName`), or the item's own `label`. Pass a translated template for other languages. The icon is `aria-hidden`.
|
|
134
140
|
- The `logos:*` Iconify collection requires `@iconify-json/logos` to be installed in the consumer app. Without it, icons will fall back to a CDN fetch (causing FOUC). See [icon-sets.md](../icon-sets.md).
|
|
135
141
|
- Auto-imported in Nuxt — no manual import needed.
|
|
@@ -245,7 +245,7 @@ SSR and the very first client paint always render the **full, uncollapsed** `<ul
|
|
|
245
245
|
swap is what shrinks the header and shifts everything below it.
|
|
246
246
|
|
|
247
247
|
Confirmed via `PerformanceObserver({type: "layout-shift"})` plus DOM `MutationObserver` tracing in a
|
|
248
|
-
consuming app
|
|
248
|
+
consuming app: the class mutation on `.tab-navigation` (adding
|
|
249
249
|
`is-loaded is-animated`) lines up exactly with `.main-content`'s bounding-rect top moving by the
|
|
250
250
|
header's full height delta, at a variable point (roughly 100ms–800ms after first paint depending on
|
|
251
251
|
hydration timing) after first paint.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: TextBlock
|
|
3
|
+
description: TextBlock vertical-rhythm text wrapper — tag prop, fluid block padding tokens, heading-id slot prop for section/article aria-labelledby, styleClassPassthrough
|
|
4
|
+
type: reference
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# TextBlock
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
`TextBlock` wraps a block of text (typically a page lead: `EyebrowText` + `HeroText`/`HeaderBlock`
|
|
12
|
+
+ intro copy) and gives it consistent fluid vertical padding. It has no layout of its own; put it
|
|
13
|
+
inside a `PageRow` for horizontal placement.
|
|
14
|
+
|
|
15
|
+
## Props
|
|
16
|
+
|
|
17
|
+
| Prop | Type | Default | Description |
|
|
18
|
+
|------|------|---------|-------------|
|
|
19
|
+
| `tag` | `"div" \| "section" \| "article" \| "main"` | `"div"` | Root element. `section`/`article` get `aria-labelledby` (see below); `main` deliberately does not. |
|
|
20
|
+
| `styleClassPassthrough` | `string \| string[]` | `[]` | Extra classes on the root. Reactive: changing the prop swaps the classes. |
|
|
21
|
+
|
|
22
|
+
## Slots
|
|
23
|
+
|
|
24
|
+
| Slot | Slot props | Description |
|
|
25
|
+
|------|-----------|-------------|
|
|
26
|
+
| `default` | `{ headingId: string }` | Content. Bind `headingId` to your heading's `id` when `tag` is `section`/`article`. |
|
|
27
|
+
|
|
28
|
+
## Basic usage
|
|
29
|
+
|
|
30
|
+
```vue
|
|
31
|
+
<PageRow tag="div" variant="content">
|
|
32
|
+
<TextBlock :style-class-passthrough="['page-lead']">
|
|
33
|
+
<EyebrowText text-content="Pricing" font-size="large" />
|
|
34
|
+
<HeroText … />
|
|
35
|
+
</TextBlock>
|
|
36
|
+
</PageRow>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## As a labelled landmark
|
|
40
|
+
|
|
41
|
+
With `tag="section"` or `tag="article"`, the root gets `aria-labelledby` from `useAriaLabelledById`.
|
|
42
|
+
Bind the `heading-id` slot prop to a real heading, or the landmark has no accessible name (a
|
|
43
|
+
dev-mode `console.warn` flags this):
|
|
44
|
+
|
|
45
|
+
```vue
|
|
46
|
+
<TextBlock tag="section" v-slot="{ headingId }">
|
|
47
|
+
<HeaderBlock :id="headingId" :tag-level="2" :class-level="2">Our services</HeaderBlock>
|
|
48
|
+
<p>…</p>
|
|
49
|
+
</TextBlock>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## CSS tokens
|
|
53
|
+
|
|
54
|
+
| Token | Default |
|
|
55
|
+
|-------|---------|
|
|
56
|
+
| `--text-block-padding-block-start` | `var(--fluid-space-48-96)` |
|
|
57
|
+
| `--text-block-padding-block-end` | `var(--fluid-space-48-96)` |
|
|
58
|
+
|
|
59
|
+
See [CONSUMER-STYLING.md](../../../app/components/01.atoms/text-block/CONSUMER-STYLING.md).
|
|
60
|
+
|
|
61
|
+
## History
|
|
62
|
+
|
|
63
|
+
- **Migrated 2026-09-25** (0/5 → 5/5): padding moved from hardcoded `--fluid-space-48-96` to the two
|
|
64
|
+
public tokens above (same defaults, no visual change); `section`/`article` now get
|
|
65
|
+
`aria-labelledby` plus the `heading-id` slot prop (previously an unnamed landmark);
|
|
66
|
+
`styleClassPassthrough` is now reactive to prop changes. Some consumer apps
|
|
67
|
+
redeclare `.text-block { padding-block-*: var(--fluid-space-48-96) }` in their
|
|
68
|
+
own pages; that duplicates the default and can be deleted.
|