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
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# OpeningHours Component
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
`OpeningHours` (`app/components/02.molecules/opening-hours/`) renders a business's weekly opening
|
|
6
|
+
hours as a `<dl>`, plus an optional "special opening times" list for bank holidays, closures etc.
|
|
7
|
+
Data is authored **per day**; the component groups consecutive identical days into ranges
|
|
8
|
+
("Monday – Saturday") itself, so a single day change never leaves a hand-written range stale.
|
|
9
|
+
|
|
10
|
+
Covers: single sessions, split sessions (restaurant lunch/dinner), closed days, 24 hours,
|
|
11
|
+
by appointment, overnight sessions (closes after midnight), per-day notes, date/date-range
|
|
12
|
+
exceptions, today highlight, schema.org JSON-LD. Not included (yet): a live "open now" status.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Props reference
|
|
17
|
+
|
|
18
|
+
> **Hyphenation rule**: write camelCase props hyphenated in templates (`:hour12`, `group-days`).
|
|
19
|
+
|
|
20
|
+
| Prop (template form) | Type | Default | Notes |
|
|
21
|
+
|---|---|---|---|
|
|
22
|
+
| `:days` | `OpeningDay[]` | (required) | One entry per day; missing days render as closed |
|
|
23
|
+
| `:exceptions` | `OpeningException[]` | `[]` | Special dates, listed under their own heading |
|
|
24
|
+
| `locale` | `string` | `"en-GB"` | Drives day names, dates and time format via `Intl` |
|
|
25
|
+
| `:hour12` | `boolean` | `false` | 12-hour am/pm times |
|
|
26
|
+
| `day-format` | `"long" \| "short"` | `"long"` | "Monday" vs "Mon" |
|
|
27
|
+
| `:group-days` | `boolean` | `true` | Collapse consecutive identical days; `false` lists all seven |
|
|
28
|
+
| `week-starts-on` | `"monday" \| "sunday"` | `"monday"` | Row order |
|
|
29
|
+
| `:highlight-today` | `boolean` | `true` | Marks today's row with `data-today` + `aria-current="date"` |
|
|
30
|
+
| `:hide-past-exceptions` | `boolean` | `true` | Drops exceptions whose end date has passed |
|
|
31
|
+
| `time-zone` | `string` | visitor's | IANA zone used to work out "today"; set to the business's zone |
|
|
32
|
+
| `heading-tag` | `"h2"`–`"h6"` | `"h3"` | Level of the exceptions heading |
|
|
33
|
+
| `exceptions-heading` | `string` | `"Special opening times"` | `""` omits the heading |
|
|
34
|
+
| `closed-label` | `string` | `"Closed"` | |
|
|
35
|
+
| `open24-hours-label` | `string` | `"Open 24 hours"` | |
|
|
36
|
+
| `by-appointment-label` | `string` | `"By appointment only"` | |
|
|
37
|
+
| `to-label` | `string` | `"to"` | Screen-reader word read in place of the visual dash |
|
|
38
|
+
| `:structured-data` | `OpeningHoursStructuredData` | `undefined` | When set, emits LocalBusiness JSON-LD via `useHead` (read once at setup) |
|
|
39
|
+
| `:style-class-passthrough` | `string \| string[]` | `[]` | Classes on the root; reactive |
|
|
40
|
+
|
|
41
|
+
All visible text is a prop or comes from `Intl`, so passing `locale` plus translated labels fully
|
|
42
|
+
localises it.
|
|
43
|
+
|
|
44
|
+
### Data shape
|
|
45
|
+
|
|
46
|
+
Importable: `import type { OpeningDay, OpeningException, OpeningSession, OpeningStatus, OpeningHoursStructuredData } from "srcdev-nuxt-components"`
|
|
47
|
+
(source: `app/types/components/opening-hours.d.ts`).
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
type OpeningWeekday = 0 | 1 | 2 | 3 | 4 | 5 | 6; // 0 = Monday, 6 = Sunday
|
|
51
|
+
type OpeningStatus = "open" | "closed" | "24-hours" | "by-appointment";
|
|
52
|
+
|
|
53
|
+
interface OpeningSession { opens: string; closes: string; label?: string } // 24h "HH:MM"
|
|
54
|
+
interface OpeningDay {
|
|
55
|
+
day: OpeningWeekday;
|
|
56
|
+
status?: OpeningStatus; // default: "open" if sessions given, else "closed"
|
|
57
|
+
sessions?: OpeningSession[];
|
|
58
|
+
note?: string;
|
|
59
|
+
}
|
|
60
|
+
interface OpeningException {
|
|
61
|
+
from: string; // "YYYY-MM-DD"
|
|
62
|
+
to?: string; // inclusive, omit for one day
|
|
63
|
+
label?: string; // "Christmas"
|
|
64
|
+
status?: OpeningStatus; // same default rule; no sessions = closed
|
|
65
|
+
sessions?: OpeningSession[];
|
|
66
|
+
note?: string;
|
|
67
|
+
}
|
|
68
|
+
interface OpeningHoursStructuredData { type?: string; name?: string; id?: string }
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Times are always authored as 24-hour strings; `hour12` only changes the display. A `closes`
|
|
72
|
+
earlier than `opens` means the session runs past midnight and is displayed as given.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Behaviour notes
|
|
77
|
+
|
|
78
|
+
- Grouping compares status, sessions and note; only **consecutive** days (in `week-starts-on`
|
|
79
|
+
order) group. No wrap-around from Sunday to Monday.
|
|
80
|
+
- Exceptions don't alter the weekly table; they are listed separately.
|
|
81
|
+
- Today's highlight and past-exception hiding run in `onMounted`, never on the server, so cached
|
|
82
|
+
HTML can't carry a stale day. Past exceptions are briefly visible before hydration.
|
|
83
|
+
- **Structured data**: emits `{ "@type": structuredData.type ?? "LocalBusiness", "@id", name,
|
|
84
|
+
openingHoursSpecification }`. If the site already has a main business JSON-LD block, either pass
|
|
85
|
+
the same `id` so search engines merge the two, or skip the prop and call the auto-imported
|
|
86
|
+
`buildOpeningHoursSpecification(days, exceptions)` util (`app/utils/opening-hours.ts`) to add
|
|
87
|
+
the hours to the existing block. Closed and by-appointment weekly days are omitted; closed
|
|
88
|
+
exceptions use `opens = closes = "00:00"` per schema.org; 24 hours uses `00:00`–`23:59`.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Usage
|
|
93
|
+
|
|
94
|
+
```vue
|
|
95
|
+
<OpeningHours :days="openingDays" :exceptions="specialDates" time-zone="Europe/London" />
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Restaurant with split sessions, 12-hour display and JSON-LD:
|
|
99
|
+
|
|
100
|
+
```vue
|
|
101
|
+
<OpeningHours
|
|
102
|
+
:days="restaurantDays"
|
|
103
|
+
:hour12="true"
|
|
104
|
+
time-zone="Europe/London"
|
|
105
|
+
:structured-data="{ type: 'Restaurant', name: 'The Anchor', id: 'https://example.com/#business' }"
|
|
106
|
+
/>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
const restaurantDays: OpeningDay[] = [
|
|
111
|
+
{ day: 1, sessions: [{ opens: "12:00", closes: "14:30", label: "Lunch" }, { opens: "18:00", closes: "22:00", label: "Dinner" }] },
|
|
112
|
+
{ day: 5, sessions: [{ opens: "18:00", closes: "01:00" }], note: "Last orders 23:30" },
|
|
113
|
+
];
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Styling: `--opening-hours-*` tokens, see `CONSUMER-STYLING.md` next to the component.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# PageHeroHighlights Component
|
|
2
2
|
|
|
3
|
+
> **Changed 2026-09-28:** styles are now in `@layer components` (they were unlayered). Every token is `--page-hero-highlights-*` with its default as a `var()` fallback, so it can be set on the component or any ancestor (previously declared on the root with generic names like `--max-width`, `--highlight-border`, so ancestor values never landed). Inner classes are prefixed (`.page-hero-highlights-header-row`, `-header-slot`, `-strip`, `-content-row`, `-content-slot`); the content-align root classes are `.content-align-start`/`.content-align-center` (were bare `.start`/`.center`); the highlight contract classes are `.page-hero-highlights-item`, `-item-title`, `-item-body` (were `.highlight`, `.title`, `.body`); PageHeroHighlightsHeader uses `.page-hero-highlights-header-start`/`-end` and `--page-hero-highlights-header-*` tokens (were `.phh-*` / `--phh-*`). Full token reference: `CONSUMER-STYLING.md` in the component folder.
|
|
4
|
+
|
|
3
5
|
## Overview
|
|
4
6
|
|
|
5
7
|
`PageHeroHighlights` is a page-level layout template that creates a "hero + highlights strip" grid. It has:
|
|
@@ -20,7 +22,7 @@ The layout uses a 4-row CSS Grid with `subgrid` — no `translate`, negative mar
|
|
|
20
22
|
| `widthConstrained` | `boolean` | `false` | When `true`, caps the central column at `--width-constrained` (default `1064px`). Gutters grow responsively to enforce the constraint. |
|
|
21
23
|
| `contentAlign` | `"start" \| "center"` | `"center"` | When `widthConstrained` is `true`: `"center"` grows gutters equally; `"start"` pins content to the left with a fixed left gutter. |
|
|
22
24
|
| `contentPanel` | `boolean` | `true` | When `true`, renders a decorative panel behind the content slot and offsets the highlights strip. Set to `false` for a flat layout with no backdrop. |
|
|
23
|
-
| `highlightTitleBaseline`| `boolean` | `false` | When `true`, fixes the highlight title row to a set height so titles align at a common baseline. Override `--
|
|
25
|
+
| `highlightTitleBaseline`| `boolean` | `false` | When `true`, fixes the highlight title row to a set height so titles align at a common baseline. Override `--page-hero-highlights-title-height` to tune. |
|
|
24
26
|
| `styleClassPassthrough` | `string \| string[]` | `[]` | Extra classes on the root element |
|
|
25
27
|
|
|
26
28
|
## Slots
|
|
@@ -102,17 +104,17 @@ Located at: `app/components/04.templates/page-hero-highlights/PageHeroHighlights
|
|
|
102
104
|
| Slot | Purpose |
|
|
103
105
|
| ------- | --------------------------------------------------------- |
|
|
104
106
|
| `start` | Title and description — always rendered, fills full width when `#end` is absent |
|
|
105
|
-
| `end` | Action buttons — `.
|
|
107
|
+
| `end` | Action buttons — `.page-hero-highlights-header-end` is only mounted when this slot is provided |
|
|
106
108
|
|
|
107
109
|
### CSS tokens
|
|
108
110
|
|
|
109
111
|
| Token | Default | Description |
|
|
110
112
|
| -------------------------- | ---------------- | ---------------------------------------------------- |
|
|
111
|
-
| `--
|
|
112
|
-
| `--
|
|
113
|
-
| `--
|
|
114
|
-
| `--
|
|
115
|
-
| `--
|
|
113
|
+
| `--page-hero-highlights-header-padding-block-mobile` | `1.6rem 3.2rem` | Block padding (start end) at mobile widths |
|
|
114
|
+
| `--page-hero-highlights-header-padding-block-tablet` | `2.4rem 4.8rem` | Block padding (start end) at ≥768px |
|
|
115
|
+
| `--page-hero-highlights-header-padding-block-desktop` | `3.2rem 6.4rem` | Block padding (start end) at ≥1024px |
|
|
116
|
+
| `--page-hero-highlights-header-gap` | `1.6rem` | Gap between `#start` and `#end` areas |
|
|
117
|
+
| `--page-hero-highlights-header-end-gap` | `0.8rem` | Gap between items within `#end` |
|
|
116
118
|
|
|
117
119
|
### Usage
|
|
118
120
|
|
|
@@ -219,40 +221,38 @@ See [component-local-style-override.md](../component-local-style-override.md) fo
|
|
|
219
221
|
/* --page-hero-highlights-gutter-desktop: 32px; */
|
|
220
222
|
|
|
221
223
|
/* Header zone */
|
|
222
|
-
/* --header-
|
|
224
|
+
/* --page-hero-highlights-header-background: darkblue; */
|
|
223
225
|
|
|
224
226
|
/* Highlights strip */
|
|
225
|
-
/* --highlights-
|
|
226
|
-
/* --
|
|
227
|
+
/* --page-hero-highlights-strip-gap: 1rem; */
|
|
228
|
+
/* --page-hero-highlights-strip-inset: 1.2rem; */
|
|
227
229
|
|
|
228
230
|
/* Highlight cards */
|
|
229
|
-
/* --
|
|
230
|
-
/* --
|
|
231
|
-
/* --
|
|
232
|
-
/* --
|
|
233
|
-
/* --
|
|
234
|
-
/* --
|
|
235
|
-
/* --
|
|
236
|
-
/* --
|
|
231
|
+
/* --page-hero-highlights-item-rows-gap: 1.2rem; */
|
|
232
|
+
/* --page-hero-highlights-title-height: 1fr; */ /* see: highlight-title-baseline prop */
|
|
233
|
+
/* --page-hero-highlights-item-padding-block-start: 1.2rem; */
|
|
234
|
+
/* --page-hero-highlights-item-padding: 1.2rem; */
|
|
235
|
+
/* --page-hero-highlights-item-background: white; */
|
|
236
|
+
/* --page-hero-highlights-item-border: 1px solid black; */
|
|
237
|
+
/* --page-hero-highlights-item-border-radius: 8px; */
|
|
238
|
+
/* --page-hero-highlights-item-colour: black; */
|
|
237
239
|
|
|
238
240
|
/* Content zone */
|
|
239
|
-
/* --content-
|
|
240
|
-
/* --content-
|
|
241
|
-
/* --content-
|
|
241
|
+
/* --page-hero-highlights-content-background: var(--slate-01); */ /* transparent */
|
|
242
|
+
/* --page-hero-highlights-content-start-gap: 1.2rem; */
|
|
243
|
+
/* --page-hero-highlights-content-end-gap: 1.2rem; */
|
|
242
244
|
|
|
243
245
|
/* Content slot decorative border */
|
|
244
|
-
/* --content-
|
|
245
|
-
/* --content-
|
|
246
|
-
/* --
|
|
247
|
-
/* --
|
|
248
|
-
/* --
|
|
249
|
-
/* --
|
|
246
|
+
/* --page-hero-highlights-content-margin-block-start: 2.4rem; */
|
|
247
|
+
/* --page-hero-highlights-content-margin: var(--page-hero-highlights-strip-inset); */
|
|
248
|
+
/* --page-hero-highlights-panel-background: var(--slate-00); */
|
|
249
|
+
/* --page-hero-highlights-panel-border: 1px solid var(--slate-06); */
|
|
250
|
+
/* --page-hero-highlights-panel-border-radius: 0.8rem; */
|
|
251
|
+
/* --page-hero-highlights-panel-outline: 1px solid var(--slate-02); */
|
|
250
252
|
|
|
251
253
|
/* When using :highlight-title-baseline="true" */
|
|
252
|
-
/*
|
|
253
|
-
/*
|
|
254
|
-
/* --highlight-padding-block-start: 0; */
|
|
255
|
-
/* } */
|
|
254
|
+
/* --page-hero-highlights-title-height-baseline: 4rem; */ /* proportional value preferred */
|
|
255
|
+
/* --page-hero-highlights-item-padding-block-start-baseline: 0; */
|
|
256
256
|
}
|
|
257
257
|
}
|
|
258
258
|
</style>
|
|
@@ -268,14 +268,14 @@ row3: highlights bottom half
|
|
|
268
268
|
row4: page content (never underflows highlights)
|
|
269
269
|
```
|
|
270
270
|
|
|
271
|
-
`.header-row` spans cols 1–3, rows 1–2 (edge-to-edge bg). `.header-slot` is placed in row 1 only.
|
|
272
|
-
`.content-row` spans cols 1–3, rows 3–4 (bg fills behind highlights; `.content-slot` is placed in row 4 only). The decorative border behind `.content-slot` is rendered via `.content-row
|
|
271
|
+
`.page-hero-highlights-header-row` spans cols 1–3, rows 1–2 (edge-to-edge bg). `.page-hero-highlights-header-slot` is placed in row 1 only.
|
|
272
|
+
`.page-hero-highlights-content-row` spans cols 1–3, rows 3–4 (bg fills behind highlights; `.page-hero-highlights-content-slot` is placed in row 4 only). The decorative border behind `.page-hero-highlights-content-slot` is rendered via `.page-hero-highlights-content-row::before` — there is no separate DOM element for it.
|
|
273
273
|
|
|
274
274
|
Grid columns are determined entirely by CSS — no `v-bind`. The `widthConstrained` and `contentAlign` props add CSS classes (`width-constrained`, `start`, `center`) which select the appropriate `grid-template-columns` rule.
|
|
275
275
|
|
|
276
|
-
## Layout pitfall: do not use `grid-template-rows: subgrid` inside `.highlights-
|
|
276
|
+
## Layout pitfall: do not use `grid-template-rows: subgrid` inside `.page-hero-highlights-strip`
|
|
277
277
|
|
|
278
|
-
The `.highlights-
|
|
278
|
+
The `.page-hero-highlights-strip` element spans rows 2–3 of the parent grid (the "straddle"). If you add an inner grid to `.page-hero-highlights-strip` (e.g. to extend `equal-widths` behaviour) and include `grid-template-rows: subgrid`, auto-placed items will only occupy row 1 of the subgrid (= parent row 2). Parent row 3 collapses to 0-height, destroying the straddle effect — `.page-hero-highlights-content-row` appears immediately below the highlights instead of overlapping it.
|
|
279
279
|
|
|
280
280
|
```css
|
|
281
281
|
/* ❌ — breaks the straddle when items are auto-placed by column flow */
|
|
@@ -20,7 +20,7 @@ no extra wrapper divs needed.
|
|
|
20
20
|
| `variant` | `"full" \| "popout" \| "content" \| "inset-content"` | `"content"` | Grid column track this element occupies when nested in another PageRow |
|
|
21
21
|
| `align` | `"start" \| "end"` | — | Bleeds one side to the viewport edge while respecting the variant boundary on the other |
|
|
22
22
|
| `id` | `string` | — | `id` attribute on the root element |
|
|
23
|
-
| `:style-class-passthrough` | `string \| string[]` | `[]` | Extra classes on the root element |
|
|
23
|
+
| `:style-class-passthrough` | `string \| string[]` | `[]` | Extra classes on the root element (reactive after mount) |
|
|
24
24
|
|
|
25
25
|
---
|
|
26
26
|
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# PendingEffect Component
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
`PendingEffect` is a decorative SVG that draws an animated dashed line around a busy button. It
|
|
6
|
+
is an internal part of `InputButton`: set `has-pending-effect` on the button and toggle
|
|
7
|
+
`is-pending`. Don't render it on its own. Its CSS depends on the host having `.pending-effect`
|
|
8
|
+
(and `position: relative`, which that rule provides), plus `.is-pending` to show and animate it.
|
|
9
|
+
|
|
10
|
+
```vue
|
|
11
|
+
<InputButton button-text="Submit" type="submit" has-pending-effect :is-pending="submitting" />
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Props reference
|
|
17
|
+
|
|
18
|
+
| Prop (template form) | Type | Default | Notes |
|
|
19
|
+
|------|------|---------|-------|
|
|
20
|
+
| `theme` | `"default" \| "success" \| "error" \| "warning"` | `"default"` | Set as `data-theme` on the SVG, so the `--theme-surface` colour defaults follow the theme. `InputButton` passes its own `theme`. |
|
|
21
|
+
| `:style-class-passthrough` | `string \| string[]` | `[]` | Extra classes on the SVG. Not forwarded by `InputButton`. |
|
|
22
|
+
|
|
23
|
+
No slots, no events.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Behaviour
|
|
28
|
+
|
|
29
|
+
- Hidden (`opacity: 0`) until the host has `.is-pending`.
|
|
30
|
+
- The host must not clip overflow: the line is drawn outside the host's edge. `InputButton`
|
|
31
|
+
sets `overflow: hidden` on buttons generally, and switches it to `visible` when
|
|
32
|
+
`.pending-effect` is present. Before 2026-09-26 it didn't, so the effect never rendered at all.
|
|
33
|
+
- Under `prefers-reduced-motion: reduce` it never shows, since the animation is the whole effect.
|
|
34
|
+
- `aria-hidden="true"` and `focusable="false"`: it is decorative. Busy state for assistive tech
|
|
35
|
+
is the host button's responsibility.
|
|
36
|
+
- The dash animation runs on the SVG's own rects. It used to run on the host button, and because
|
|
37
|
+
`stroke-dashoffset` is inherited, it also animated the stroke of any SVG icon inside the button.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Styling
|
|
42
|
+
|
|
43
|
+
Full table in `app/components/05.forms/pending-effect/CONSUMER-STYLING.md`. Public tokens:
|
|
44
|
+
`--pending-effect-line-color|line-thickness|line-length`, `--pending-effect-blur-color|blur-size`,
|
|
45
|
+
`--pending-effect-offset`, `--pending-effect-border-radius|border-radius-icon-only`,
|
|
46
|
+
`--pending-effect-animation-duration`. All read with fallbacks at the point of use, so they can
|
|
47
|
+
be set on any ancestor.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## History
|
|
52
|
+
|
|
53
|
+
**Migrated 2026-09-26** (0/5 → full compliance):
|
|
54
|
+
|
|
55
|
+
- Tokens renamed to `--pending-effect-*` (were `--pending-line-*`, `--pending-blur-*`,
|
|
56
|
+
`--pending-offset`, and the generic `--animation-speed`). They used to be declared on the host
|
|
57
|
+
button, which blocked any override set on a parent. No consumer overrode the old names.
|
|
58
|
+
- Inner classes prefixed (`.pending-effect-container|blur|line`), keyframes renamed from the
|
|
59
|
+
generic `stroke-dashoffset` to `pending-effect-dash`.
|
|
60
|
+
- Animation moved from the host button to the rects (see Behaviour).
|
|
61
|
+
- Corner radius became a public token; removed a dead base `stroke: black; stroke-width: 0.5rem`
|
|
62
|
+
that both rects always overrode.
|
|
63
|
+
- SVG is now `aria-hidden`; `styleClassPassthrough` changes after mount are picked up.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# PriceList Component
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
`PriceList` (`app/components/02.molecules/price-list/`) renders a service/menu-style price list:
|
|
6
|
+
one or more columns, each with a heading (optional icon) and a `<dl>` of description/price rows.
|
|
7
|
+
Columns stack below `48em` and sit two-up above it. Not a SaaS plan comparison, use `PricingCard`
|
|
8
|
+
for that.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Props reference
|
|
13
|
+
|
|
14
|
+
> **Hyphenation rule**: write camelCase props hyphenated in templates (`:price-list-data`).
|
|
15
|
+
|
|
16
|
+
| Prop (template form) | Type | Default | Notes |
|
|
17
|
+
|---|---|---|---|
|
|
18
|
+
| `:price-list-data` | `PriceListData[]` | (required) | One entry per column |
|
|
19
|
+
| `heading-tag` | `"h2" \| "h3" \| "h4" \| "h5" \| "h6"` | `"h2"` | Heading level for column titles; match the page outline |
|
|
20
|
+
| `from-label` | `string` | `"from"` | Text before a price whose item has `from: true`. Pass a translated string for i18n |
|
|
21
|
+
| `:style-class-passthrough` | `string \| string[]` | `[]` | Classes on the root; reactive |
|
|
22
|
+
|
|
23
|
+
### Data shape
|
|
24
|
+
|
|
25
|
+
Importable: `import type { PriceListData, PriceItem } from "srcdev-nuxt-components"`
|
|
26
|
+
(source: `app/types/components/price-list.d.ts`).
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
interface PriceItem {
|
|
30
|
+
description: string;
|
|
31
|
+
price: string; // pre-formatted, e.g. "£45"
|
|
32
|
+
from?: boolean; // prefix with fromLabel
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface PriceListData {
|
|
36
|
+
headingtext: string; // note: lower-case "t"
|
|
37
|
+
headingIcon?: string; // Iconify name, e.g. "lucide:sparkles"
|
|
38
|
+
items: PriceItem[];
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
No slots, no events.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Semantics
|
|
47
|
+
|
|
48
|
+
- Column titles are `HeroText` headings at `heading-tag`. Prices are plain `<span>`s inside `<dd>`,
|
|
49
|
+
not headings (before 2026-09-27 each price was an `<h2>`, which flooded the heading outline).
|
|
50
|
+
- Rows are `<div>`-wrapped `<dt>`/`<dd>` pairs, valid inside `<dl>`.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Styling
|
|
55
|
+
|
|
56
|
+
All tokens are `--price-list-*`; full table in `CONSUMER-STYLING.md` next to the component.
|
|
57
|
+
Common ones: `--price-list-divider-colour`, `--price-list-divider-opacity`,
|
|
58
|
+
`--price-list-price-font-size`, `--price-list-heading-margin-block-end`.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Usage
|
|
63
|
+
|
|
64
|
+
```vue
|
|
65
|
+
<PriceList :price-list-data="priceListData" :style-class-passthrough="['mbe-20']" />
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Nested under an existing `h2` section heading:
|
|
69
|
+
|
|
70
|
+
```vue
|
|
71
|
+
<PriceList :price-list-data="priceListData" heading-tag="h3" from-label="ab" />
|
|
72
|
+
```
|
|
@@ -49,7 +49,7 @@ Override the default feature list rendering. Receives no slot scope.
|
|
|
49
49
|
|
|
50
50
|
### #cta slot
|
|
51
51
|
|
|
52
|
-
Customize the CTA button. Default renders `
|
|
52
|
+
Customize the CTA button. Default renders `InputButton` with theme support.
|
|
53
53
|
|
|
54
54
|
**Slot scope:**
|
|
55
55
|
- `ctaText: string` — button label from `:cta-text` prop
|
|
@@ -60,7 +60,7 @@ Customize the CTA button. Default renders `InputButtonCore` with theme support.
|
|
|
60
60
|
```vue
|
|
61
61
|
<PricingCard plan-name="Pro" :price="99" @select="handleSelect">
|
|
62
62
|
<template #cta="{ ctaText, isDisabled, onSelect }">
|
|
63
|
-
<
|
|
63
|
+
<InputButton
|
|
64
64
|
:button-text="ctaText"
|
|
65
65
|
variant="secondary"
|
|
66
66
|
theme="custom"
|
|
@@ -127,7 +127,7 @@ All `--pricing-card-*` tokens can be overridden at global, page, or instance sco
|
|
|
127
127
|
@select="handleSelect"
|
|
128
128
|
>
|
|
129
129
|
<template #cta="{ ctaText, isDisabled, onSelect }">
|
|
130
|
-
<
|
|
130
|
+
<InputButton
|
|
131
131
|
:button-text="ctaText"
|
|
132
132
|
variant="primary"
|
|
133
133
|
:readonly="isDisabled"
|
|
@@ -6,6 +6,8 @@ type: reference
|
|
|
6
6
|
|
|
7
7
|
# ProfileSection
|
|
8
8
|
|
|
9
|
+
> **Classes renamed 2026-09-27:** `.picture` → `.profile-section-picture`, `.profile-picture` → `.profile-section-image`, `.profile-info` → `.profile-section-info`, `.profile-info-content` → `.profile-section-info-content`, `.profile-info-block` → `.profile-section-info-block`, `.profile-links` → `.profile-section-links`.
|
|
10
|
+
|
|
9
11
|
## Overview
|
|
10
12
|
|
|
11
13
|
`ProfileSection` is a molecule that renders a practitioner/author profile: a header area (eyebrow + heading), a profile picture, and a flexible set of bio/info blocks alongside optional profile links. It is landmark-aware — when `tag` is `section`, `article`, or `aside`, the root element automatically gets `aria-labelledby` wired to the heading inside the `#heroText` slot (**you must bind `headingId` yourself, and a console warning fires if you forget** — see [component-aria-landmark.md](../component-aria-landmark.md)). `tag="main"` is never auto-labelled.
|
|
@@ -14,7 +16,7 @@ type: reference
|
|
|
14
16
|
|
|
15
17
|
| Prop | Type | Default | Description |
|
|
16
18
|
|------|------|---------|-------------|
|
|
17
|
-
| `profilePicture` | `{ src
|
|
19
|
+
| `profilePicture` | `ProfilePicture` (`{ src; alt; width?; height? }`, exported from the layer types) | — | **Required.** Rendered via `NuxtImg` with `width`/`height` defaulting to `828`/`1104` (3:4, a Vercel-allowed width). |
|
|
18
20
|
| `tag` | `"div" \| "section" \| "article" \| "main"` | `"div"` | HTML element rendered as the root. |
|
|
19
21
|
| `profileInfoCount` | `number` | `3` | Number of `profile-info-N` slots to generate when none are explicitly provided. |
|
|
20
22
|
| `styleClassPassthrough` | `string \| string[]` | `[]` | Extra classes applied to the root element. |
|
|
@@ -70,7 +72,7 @@ type: reference
|
|
|
70
72
|
The `profile-info-N` slots are discovered at runtime by filtering `useSlots()` for keys matching `/^profile-info-\d+$/`. The slots are rendered in ascending numeric order.
|
|
71
73
|
|
|
72
74
|
- If you provide `#profile-info-1`, `#profile-info-2`, `#profile-info-3` — all three render in order.
|
|
73
|
-
- If you provide no `profile-info-*` slots, the component
|
|
75
|
+
- If you provide no `profile-info-*` slots, the component renders `profileInfoCount` empty blocks (they used to contain visible placeholder text, removed 2026-09-27). Slot discovery runs every render, so slots added after mount appear.
|
|
74
76
|
- Gaps are supported — you can provide `#profile-info-1` and `#profile-info-3` without `#profile-info-2`; they sort correctly.
|
|
75
77
|
|
|
76
78
|
## heroText slot prop
|
|
@@ -88,8 +90,8 @@ If you use a different heading component, bind `headingId` to whatever prop rend
|
|
|
88
90
|
## Layout
|
|
89
91
|
|
|
90
92
|
- **Mobile**: single column — picture stacked above info.
|
|
91
|
-
- **768px+**: two columns — `384px` picture column, `1fr` info column, `4rem` gap.
|
|
92
|
-
- Picture frame:
|
|
93
|
+
- **768px+**: two columns — `--profile-section-picture-width` (`384px`) picture column, `1fr` info column, `--profile-section-gap-wide` (`4rem`) gap (`--profile-section-gap`, `2rem`, below 768px).
|
|
94
|
+
- Picture frame (`.profile-section-picture`): `--profile-section-picture-aspect-ratio` (`3 / 4`), `--profile-section-picture-border-radius` (`8px`), `overflow: hidden`. Full token list: `CONSUMER-STYLING.md` in the component folder. The `NuxtImg` fills the frame with `object-fit: cover`.
|
|
93
95
|
- Profile links: `align-items: end; justify-content: flex-end` — right-aligned to the bottom of the info column.
|
|
94
96
|
|
|
95
97
|
## CSS notes
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: SamaritanPrompt
|
|
3
|
+
description: SamaritanPrompt and SamaritanPromptMixed animated text prompts — props, MessageConfig API, typewriter/word-pulse effects, pause on hover, aria-live announcements, cursor slot, CSS tokens
|
|
4
|
+
type: reference
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# SamaritanPrompt / SamaritanPromptMixed
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
Two components in `02.molecules/samaritan-prompt/` that loop through messages with animated text
|
|
12
|
+
effects, styled as a monospace line over an underline with a pulsing cursor glyph below:
|
|
13
|
+
|
|
14
|
+
- **`SamaritanPrompt`** — a list of plain strings, one effect and one set of timings for all of them.
|
|
15
|
+
- **`SamaritanPromptMixed`** — a list of `SamaritanPromptMessageConfig` objects, each able to pick its
|
|
16
|
+
own effect and override any timing. Adds an `introDelay` before each loop.
|
|
17
|
+
|
|
18
|
+
Effects:
|
|
19
|
+
|
|
20
|
+
- `typewriter` — characters typed one by one, held, deleted one by one.
|
|
21
|
+
- `word-pulse` — the whole message fades in, holds, fades out.
|
|
22
|
+
|
|
23
|
+
Both use `useCancellableTimer` for all timing, so the loop exits cleanly on unmount.
|
|
24
|
+
|
|
25
|
+
## Accessibility
|
|
26
|
+
|
|
27
|
+
- The visual content (`.samaritan-prompt__content`) and the cursor are `aria-hidden="true"`, so
|
|
28
|
+
screen readers never hear partial text.
|
|
29
|
+
- A visually hidden `aria-live="polite"` `aria-atomic="true"` span announces each full message when
|
|
30
|
+
it's fully shown (typewriter: once typed; word-pulse: once faded in) and is cleared before it
|
|
31
|
+
deletes or fades out, so a repeated message announces again.
|
|
32
|
+
- **Pause on hover** (WCAG 2.2.2): pointer over the root pauses the sequence where it is and the
|
|
33
|
+
cursor pulse; leaving resumes. The root gets `data-paused` while paused.
|
|
34
|
+
- `prefers-reduced-motion: reduce` removes the cursor pulse and the word-pulse fade transition. The
|
|
35
|
+
text sequence keeps running (it's the content).
|
|
36
|
+
|
|
37
|
+
> **Changed 2026-09-27**: `SamaritanPrompt` previously had no live region (the visible text was read
|
|
38
|
+
> character by character, if at all) and no reduced-motion handling; both now match
|
|
39
|
+
> `SamaritanPromptMixed`. Pause on hover is new on both.
|
|
40
|
+
|
|
41
|
+
## Props — SamaritanPrompt
|
|
42
|
+
|
|
43
|
+
| Prop | Type | Default | Description |
|
|
44
|
+
|------|------|---------|-------------|
|
|
45
|
+
| `messages` | `string[]` | — | Messages to cycle through. **Required.** |
|
|
46
|
+
| `effect` | `"typewriter" \| "word-pulse"` | `"typewriter"` | Effect for all messages. Changing it restarts the loop. |
|
|
47
|
+
| `typeSpeed` | `number` | `80` | ms per character typed. |
|
|
48
|
+
| `deleteSpeed` | `number` | `40` | ms per character deleted. |
|
|
49
|
+
| `holdDuration` | `number` | `2000` | ms the typed text holds before deleting. |
|
|
50
|
+
| `pauseDuration` | `number` | `500` | Typewriter: ms between messages. Word-pulse: ms before each full cycle. |
|
|
51
|
+
| `wordDuration` | `number` | `1200` | ms a word-pulse message stays fully visible. |
|
|
52
|
+
| `fadeDuration` | `number` | `400` | ms for the word-pulse fade in/out. |
|
|
53
|
+
| `hideCursorInCycle` | `boolean` | `true` | Hide the cursor while text animates, show it during pauses. |
|
|
54
|
+
| `styleClassPassthrough` | `string \| string[]` | `[]` | Extra classes on the root. Reactive. |
|
|
55
|
+
|
|
56
|
+
## Props — SamaritanPromptMixed
|
|
57
|
+
|
|
58
|
+
| Prop | Type | Default | Description |
|
|
59
|
+
|------|------|---------|-------------|
|
|
60
|
+
| `messageConfigs` | `SamaritanPromptMessageConfig[]` | — | Messages. **Required.** |
|
|
61
|
+
| `effect` | `"typewriter" \| "word-pulse"` | `"typewriter"` | Default effect. |
|
|
62
|
+
| `typeSpeed` | `number` | `80` | ms per character typed. |
|
|
63
|
+
| `deleteSpeed` | `number` | `40` | ms per character deleted. |
|
|
64
|
+
| `holdDuration` | `number` | `7000` | ms the typed text holds before deleting. |
|
|
65
|
+
| `pauseDuration` | `number` | `1000` | ms pause after each message. |
|
|
66
|
+
| `wordDuration` | `number` | `1200` | ms a word-pulse message stays fully visible. |
|
|
67
|
+
| `fadeDuration` | `number` | `400` | ms for the word-pulse fade in/out. |
|
|
68
|
+
| `introDelay` | `number` | `2000` | ms before the first message of every loop. `0` starts immediately. |
|
|
69
|
+
| `hideCursorInCycle` | `boolean` | `true` | Hide the cursor while text animates. |
|
|
70
|
+
| `styleClassPassthrough` | `string \| string[]` | `[]` | Extra classes on the root. Reactive. |
|
|
71
|
+
|
|
72
|
+
Note the different defaults for `holdDuration` and `pauseDuration` between the two components.
|
|
73
|
+
|
|
74
|
+
### SamaritanPromptMessageConfig
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
import type { SamaritanPromptMessageConfig } from "srcdev-nuxt-components";
|
|
78
|
+
|
|
79
|
+
interface SamaritanPromptMessageConfig {
|
|
80
|
+
text: string;
|
|
81
|
+
effect?: "typewriter" | "word-pulse";
|
|
82
|
+
typeSpeed?: number;
|
|
83
|
+
deleteSpeed?: number;
|
|
84
|
+
holdDuration?: number;
|
|
85
|
+
pauseDuration?: number;
|
|
86
|
+
wordDuration?: number;
|
|
87
|
+
fadeDuration?: number;
|
|
88
|
+
hideCursorInCycle?: boolean;
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Omitted fields fall back to the matching component prop. `SamaritanPromptEffect` is exported too.
|
|
93
|
+
|
|
94
|
+
> **Changed 2026-09-27**: this type was `MessageConfig`, exported from inside
|
|
95
|
+
> `SamaritanPromptMixed.vue`. It now lives in `app/types/components/samaritan-prompt.d.ts`.
|
|
96
|
+
|
|
97
|
+
## Slots
|
|
98
|
+
|
|
99
|
+
| Slot | Default | Description |
|
|
100
|
+
|------|---------|-------------|
|
|
101
|
+
| `cursor` | `▲` | Cursor glyph. Rendered inside `aria-hidden` `.samaritan-prompt__cursor`, so keep it decorative. |
|
|
102
|
+
|
|
103
|
+
## Usage
|
|
104
|
+
|
|
105
|
+
```vue
|
|
106
|
+
<SamaritanPrompt :messages="['Can you hear me?', 'Surveillance active']" />
|
|
107
|
+
|
|
108
|
+
<SamaritanPrompt effect="word-pulse" :word-duration="2000" :messages="['Stand by']" />
|
|
109
|
+
|
|
110
|
+
<SamaritanPromptMixed
|
|
111
|
+
:intro-delay="0"
|
|
112
|
+
:message-configs="[
|
|
113
|
+
{ text: 'Initialising system', effect: 'typewriter', holdDuration: 3000 },
|
|
114
|
+
{ text: 'Stand by', effect: 'word-pulse', wordDuration: 2000 },
|
|
115
|
+
]"
|
|
116
|
+
/>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Inside a `messageConfigs` object literal, keys are camelCase (`holdDuration`), not hyphenated; only
|
|
120
|
+
props on the component tag are hyphenated.
|
|
121
|
+
|
|
122
|
+
## Styling
|
|
123
|
+
|
|
124
|
+
Full token list and class hooks: `app/components/02.molecules/samaritan-prompt/CONSUMER-STYLING.md`.
|
|
125
|
+
Tokens are `--samaritan-prompt-*` (text/underline/cursor colours, font, sizes, gaps, pulse
|
|
126
|
+
duration). Defaults are white text on the assumption of a dark page; for a light or theme-switching
|
|
127
|
+
page set `--samaritan-prompt-text-colour` and `--samaritan-prompt-underline-colour` (e.g. to
|
|
128
|
+
`var(--theme-text)`).
|
|
129
|
+
|
|
130
|
+
The component brings no page layout; centre it from its parent.
|
|
131
|
+
|
|
132
|
+
> **Changed 2026-09-27**: tokens renamed from `--samaritan-*` / `color` to `--samaritan-prompt-*` /
|
|
133
|
+
> `colour`. `SamaritanPromptMixed` no longer needs (or styles) a `.samaritan-stage` ancestor.
|
|
134
|
+
|
|
135
|
+
## Notes
|
|
136
|
+
|
|
137
|
+
- `SamaritanPromptMixed` reads `messageConfigs` at the start of each loop, so prop changes land on
|
|
138
|
+
the next loop. `SamaritanPrompt` restarts only when `effect` changes.
|
|
139
|
+
- The `Mono MMM 5` font is declared with `@font-face` in each component's unscoped style from
|
|
140
|
+
`/fonts/monoMMM_5.ttf` (`font-display: swap` in `SamaritanPrompt`, `optional` in `SamaritanPromptMixed`).
|