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.
Files changed (623) hide show
  1. package/.claude/skills/component-aria-landmark.md +1 -1
  2. package/.claude/skills/component-dynamic-slots.md +0 -1
  3. package/.claude/skills/component-export-types.md +3 -3
  4. package/.claude/skills/component-inline-action-button.md +7 -7
  5. package/.claude/skills/component-local-style-override.md +134 -50
  6. package/.claude/skills/component-naming.md +107 -0
  7. package/.claude/skills/components/action-menu.md +18 -14
  8. package/.claude/skills/components/alert-content.md +110 -0
  9. package/.claude/skills/components/alert-mask-core.md +15 -1
  10. package/.claude/skills/components/alert-masked-content.md +95 -0
  11. package/.claude/skills/components/auto-grid.md +21 -13
  12. package/.claude/skills/components/canvas-switcher.md +3 -3
  13. package/.claude/skills/components/capture-qr-code.md +19 -9
  14. package/.claude/skills/components/carousel-flip.md +3 -3
  15. package/.claude/skills/components/container-glow.md +2 -2
  16. package/.claude/skills/components/content-docs.md +9 -5
  17. package/.claude/skills/components/cookie-consent-banner.md +16 -17
  18. package/.claude/skills/components/dashboard-quad-grid.md +4 -4
  19. package/.claude/skills/components/decode-qr-code.md +15 -9
  20. package/.claude/skills/components/display-avatar.md +16 -31
  21. package/.claude/skills/components/display-chip.md +15 -10
  22. package/.claude/skills/components/display-dialog.md +3 -1
  23. package/.claude/skills/components/display-pill.md +17 -75
  24. package/.claude/skills/components/display-prompt.md +11 -19
  25. package/.claude/skills/components/display-qr-code.md +5 -0
  26. package/.claude/skills/components/display-theme-switch.md +7 -6
  27. package/.claude/skills/components/display-toast.md +5 -6
  28. package/.claude/skills/components/entry-animation.md +2 -5
  29. package/.claude/skills/components/eyebrow-text.md +6 -4
  30. package/.claude/skills/components/form-field.md +79 -0
  31. package/.claude/skills/components/form-fieldset.md +75 -0
  32. package/.claude/skills/components/form-wrapper.md +71 -0
  33. package/.claude/skills/components/glass-panel.md +60 -51
  34. package/.claude/skills/components/grid-stack.md +8 -2
  35. package/.claude/skills/components/header-block.md +1 -1
  36. package/.claude/skills/components/hero-text.md +8 -6
  37. package/.claude/skills/components/input-button.md +72 -0
  38. package/.claude/skills/components/input-checkbox-radio.md +149 -0
  39. package/.claude/skills/components/input-checkbox.md +148 -0
  40. package/.claude/skills/components/input-description.md +102 -0
  41. package/.claude/skills/components/input-error.md +105 -0
  42. package/.claude/skills/components/input-label.md +119 -0
  43. package/.claude/skills/components/{input-number-core.md → input-number.md} +41 -36
  44. package/.claude/skills/components/input-radio.md +95 -0
  45. package/.claude/skills/components/input-range-core.md +4 -4
  46. package/.claude/skills/components/input-select-core.md +1 -1
  47. package/.claude/skills/components/input-text-core.md +8 -6
  48. package/.claude/skills/components/input-textarea-core.md +4 -4
  49. package/.claude/skills/components/layout-grid-by-cols.md +31 -43
  50. package/.claude/skills/components/link-text.md +2 -2
  51. package/.claude/skills/components/opening-hours.md +116 -0
  52. package/.claude/skills/components/page-hero-highlights.md +35 -35
  53. package/.claude/skills/components/page-row.md +1 -1
  54. package/.claude/skills/components/pending-effect.md +63 -0
  55. package/.claude/skills/components/price-list.md +72 -0
  56. package/.claude/skills/components/pricing-card.md +3 -3
  57. package/.claude/skills/components/profile-section.md +6 -4
  58. package/.claude/skills/components/samaritan-prompt.md +140 -0
  59. package/.claude/skills/components/scroll-reveal-frame.md +21 -20
  60. package/.claude/skills/components/scroll-reveal-image.md +31 -21
  61. package/.claude/skills/components/service-detail.md +2 -2
  62. package/.claude/skills/components/services-card-grid.md +5 -4
  63. package/.claude/skills/components/services-card.md +12 -10
  64. package/.claude/skills/components/site-navigation.md +20 -6
  65. package/.claude/skills/components/slider-gallery.md +88 -0
  66. package/.claude/skills/components/social-icons-list.md +12 -6
  67. package/.claude/skills/components/tab-navigation.md +1 -1
  68. package/.claude/skills/components/text-block.md +68 -0
  69. package/.claude/skills/components/toggle-switch-core.md +3 -3
  70. package/.claude/skills/components/triple-toggle-switch.md +85 -0
  71. package/.claude/skills/composable-zod-validation.md +1 -1
  72. package/.claude/skills/consumer-styles-structure.md +153 -0
  73. package/.claude/skills/icon-sets.md +3 -3
  74. package/.claude/skills/icon-sizing.md +66 -0
  75. package/.claude/skills/index.md +35 -16
  76. package/.claude/skills/new-app-scaffold.md +45 -7
  77. package/.claude/skills/pull-request-description.md +1 -0
  78. package/.claude/skills/storybook-add-story.md +53 -5
  79. package/.claude/skills/testing-add-playwright.md +1 -1
  80. package/.claude/skills/theming-colour-ramps.md +25 -3
  81. package/.claude/skills/theming-component-token-pattern.md +16 -16
  82. package/.claude/skills/theming-override-default.md +7 -0
  83. package/.claude/skills/theming-partial-override.md +1 -1
  84. package/.claude/skills/theming-typography-tokens.md +1 -1
  85. package/.claude/skills/vercel-node-version.md +1 -1
  86. package/.vscode/srcdev-component-action-menu.code-snippets +42 -0
  87. package/.vscode/srcdev-component-alert-content.code-snippets +36 -0
  88. package/.vscode/srcdev-component-alert-masked-content.code-snippets +35 -0
  89. package/.vscode/srcdev-component-auto-grid.code-snippets +39 -0
  90. package/.vscode/srcdev-component-capture-decode-qr-code.code-snippets +28 -0
  91. package/.vscode/srcdev-component-content-docs.code-snippets +4 -4
  92. package/.vscode/srcdev-component-cookie-consent-banner.code-snippets +33 -0
  93. package/.vscode/srcdev-component-display-avatar.code-snippets +28 -0
  94. package/.vscode/srcdev-component-display-chip.code-snippets +27 -0
  95. package/.vscode/srcdev-component-display-pill.code-snippets +38 -0
  96. package/.vscode/srcdev-component-display-prompt.code-snippets +10 -54
  97. package/.vscode/srcdev-component-display-qr-code.code-snippets +22 -0
  98. package/.vscode/srcdev-component-eyebrow-text.code-snippets +19 -0
  99. package/.vscode/srcdev-component-form-field.code-snippets +25 -0
  100. package/.vscode/srcdev-component-form-fieldset.code-snippets +36 -0
  101. package/.vscode/srcdev-component-form-wrapper.code-snippets +30 -0
  102. package/.vscode/srcdev-component-glass-panel.code-snippets +38 -0
  103. package/.vscode/srcdev-component-grid-stack.code-snippets +49 -0
  104. package/.vscode/srcdev-component-input-button.code-snippets +27 -0
  105. package/.vscode/srcdev-component-input-checkbox-radio.code-snippets +60 -0
  106. package/.vscode/srcdev-component-input-checkbox.code-snippets +48 -0
  107. package/.vscode/srcdev-component-input-description.code-snippets +44 -0
  108. package/.vscode/srcdev-component-input-error.code-snippets +30 -0
  109. package/.vscode/srcdev-component-input-label.code-snippets +39 -0
  110. package/.vscode/srcdev-component-input-number.code-snippets +11 -11
  111. package/.vscode/srcdev-component-input-radio.code-snippets +58 -0
  112. package/.vscode/srcdev-component-layout-grid-by-cols.code-snippets +46 -0
  113. package/.vscode/srcdev-component-link-text.code-snippets +30 -0
  114. package/.vscode/srcdev-component-opening-hours.code-snippets +40 -0
  115. package/.vscode/srcdev-component-page-hero-highlights.code-snippets +37 -0
  116. package/.vscode/srcdev-component-page-row.code-snippets +47 -0
  117. package/.vscode/srcdev-component-pending-effect.code-snippets +26 -0
  118. package/.vscode/srcdev-component-price-list.code-snippets +37 -0
  119. package/.vscode/srcdev-component-pricing-card.code-snippets +2 -2
  120. package/.vscode/srcdev-component-profile-section.code-snippets +36 -0
  121. package/.vscode/srcdev-component-samaritan-prompt.code-snippets +60 -0
  122. package/.vscode/srcdev-component-scroll-reveal-frame.code-snippets +36 -0
  123. package/.vscode/srcdev-component-scroll-reveal-image.code-snippets +46 -0
  124. package/.vscode/srcdev-component-services-card.code-snippets +4 -4
  125. package/.vscode/srcdev-component-services-grids.code-snippets +36 -0
  126. package/.vscode/srcdev-component-site-navigation.code-snippets +26 -18
  127. package/.vscode/srcdev-component-slider-gallery.code-snippets +9 -0
  128. package/.vscode/srcdev-component-social-icons-list.code-snippets +24 -0
  129. package/.vscode/srcdev-component-stepper-list.code-snippets +39 -0
  130. package/.vscode/srcdev-component-text-block.code-snippets +31 -0
  131. package/.vscode/srcdev-component-triple-toggle-switch.code-snippets +30 -0
  132. package/README.md +2 -2
  133. package/app/app.config.ts +10 -0
  134. package/app/assets/styles/setup/02.colours/_orange.css +11 -11
  135. package/app/assets/styles/setup/02.colours/_theme-params.css +2 -2
  136. package/app/assets/styles/setup/03.theming/_default.css +1 -22
  137. package/app/assets/styles/setup/03.theming/_theme-slots.css +1 -1
  138. package/app/assets/styles/setup/03.theming/_warning.css +8 -10
  139. package/app/assets/styles/setup/04.elements/forms/02.typography.css +0 -14
  140. package/app/assets/styles/setup/04.elements/forms/06.button-geometry.css +1 -1
  141. package/app/assets/styles/setup/index.css +1 -1
  142. package/app/components/01.atoms/alert-mask/AlertMaskCore.vue +23 -5
  143. package/app/components/01.atoms/alert-mask/CONSUMER-STYLING.md +23 -5
  144. package/app/components/01.atoms/alert-mask/stories/AlertMaskCore.stories.ts +45 -19
  145. package/app/components/01.atoms/alert-mask/tests/AlertMaskCore.spec.ts +35 -1
  146. package/app/components/01.atoms/animations/animated-svg-text/CONSUMER-STYLING.md +13 -0
  147. package/app/components/01.atoms/animations/clip-element/CONSUMER-STYLING.md +13 -0
  148. package/app/components/01.atoms/animations/clip-element/ClipElement.vue +2 -2
  149. package/app/components/01.atoms/animations/container-glow/CONSUMER-STYLING.md +26 -5
  150. package/app/components/01.atoms/animations/entry/.nuxt/app.config.mjs +21 -0
  151. package/app/components/01.atoms/animations/entry/.nuxt/components.d.ts +66 -0
  152. package/app/components/01.atoms/animations/entry/.nuxt/imports.d.ts +30 -0
  153. package/app/components/01.atoms/animations/entry/.nuxt/manifest/meta/test.json +1 -0
  154. package/app/components/01.atoms/animations/entry/.nuxt/types/app.config.d.ts +35 -0
  155. package/app/components/01.atoms/animations/entry/.nuxt/types/build.d.ts +23 -0
  156. package/app/components/01.atoms/animations/entry/.nuxt/types/builder-env.d.ts +1 -0
  157. package/app/components/01.atoms/animations/entry/.nuxt/types/components.d.ts +71 -0
  158. package/app/components/01.atoms/animations/entry/.nuxt/types/imports.d.ts +386 -0
  159. package/app/components/01.atoms/animations/entry/.nuxt/types/middleware.d.ts +11 -0
  160. package/app/components/01.atoms/animations/entry/.nuxt/types/modules.d.ts +79 -0
  161. package/app/components/01.atoms/animations/entry/.nuxt/types/nitro-layouts.d.ts +17 -0
  162. package/app/components/01.atoms/animations/entry/.nuxt/types/nitro-nuxt.d.ts +64 -0
  163. package/app/components/01.atoms/animations/entry/.nuxt/types/plugins.d.ts +29 -0
  164. package/app/components/01.atoms/animations/entry/.nuxt/types/runtime-config.d.ts +32 -0
  165. package/app/components/01.atoms/animations/entry/.nuxt/types/shared-imports.d.ts +10 -0
  166. package/app/components/01.atoms/animations/entry/.nuxt/types/vue-shim.d.ts +0 -0
  167. package/app/components/01.atoms/animations/entry/.nuxtrc +1 -0
  168. package/app/components/01.atoms/animations/entry/CONSUMER-STYLING.md +65 -0
  169. package/app/components/01.atoms/animations/entry/EntryAnimation.vue +6 -5
  170. package/app/components/01.atoms/animations/entry/node_modules/.cache/nuxt/chrome-workspace.json +1 -0
  171. package/app/components/01.atoms/animations/entry/node_modules/.cache/vite/client/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  172. package/app/components/01.atoms/animations/entry/stories/EntryAnimation.stories.ts +1 -1
  173. package/app/components/01.atoms/animations/entry/tests/EntryAnimation.spec.ts +25 -0
  174. package/app/components/01.atoms/animations/glowing-border/CONSUMER-STYLING.md +24 -5
  175. package/app/components/01.atoms/animations/marquee-scroller/CONSUMER-STYLING.md +20 -0
  176. package/app/components/01.atoms/animations/rotating-carousel-image/CONSUMER-STYLING.md +17 -0
  177. package/app/components/01.atoms/animations/scroll-reveal-frame/CONSUMER-STYLING.md +77 -0
  178. package/app/components/01.atoms/animations/scroll-reveal-frame/ScrollRevealFrame.vue +37 -78
  179. package/app/components/01.atoms/animations/scroll-reveal-frame/stories/ScrollRevealFrame.stories.ts +48 -0
  180. package/app/components/01.atoms/animations/scroll-reveal-frame/tests/ScrollRevealFrame.spec.ts +40 -33
  181. package/app/components/01.atoms/animations/scroll-reveal-frame/tests/__snapshots__/ScrollRevealFrame.spec.ts.snap +4 -4
  182. package/app/components/01.atoms/animations/scroll-reveal-image/CONSUMER-STYLING.md +74 -0
  183. package/app/components/01.atoms/animations/scroll-reveal-image/ScrollRevealImage.vue +14 -44
  184. package/app/components/01.atoms/animations/scroll-reveal-image/stories/ScrollRevealImage.stories.ts +50 -1
  185. package/app/components/01.atoms/animations/scroll-reveal-image/tests/ScrollRevealImage.spec.ts +27 -20
  186. package/app/components/01.atoms/animations/scroll-reveal-image/tests/__snapshots__/ScrollRevealImage.spec.ts.snap +4 -4
  187. package/app/components/01.atoms/animations/section-parallax/CONSUMER-STYLING.md +21 -4
  188. package/app/components/01.atoms/animations/view-timeline/CONSUMER-STYLING.md +25 -0
  189. package/app/components/01.atoms/banner-video/CONSUMER-STYLING.md +12 -5
  190. package/app/components/01.atoms/canvas-switcher/CONSUMER-STYLING.md +20 -7
  191. package/app/components/01.atoms/canvas-switcher/CanvasSwitcher.vue +12 -7
  192. package/app/components/01.atoms/card/CONSUMER-STYLING.md +47 -42
  193. package/app/components/01.atoms/card/CardCore.vue +7 -17
  194. package/app/components/01.atoms/clipped-panel/CONSUMER-STYLING.md +13 -0
  195. package/app/components/01.atoms/content-wrappers/docs-pages/CONSUMER-STYLING.md +127 -0
  196. package/app/components/01.atoms/content-wrappers/docs-pages/ContentDocs.vue +44 -77
  197. package/app/components/01.atoms/content-wrappers/docs-pages/stories/ContentDocs.stories.ts +3 -3
  198. package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/CONSUMER-STYLING.md +14 -1
  199. package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-quad-grid/stories/DashboardQuadGrid.stories.ts +2 -0
  200. package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/CONSUMER-STYLING.md +13 -0
  201. package/app/components/01.atoms/content-wrappers/layout-grid/dashboard-stats-grid/stories/DashboardStatsGrid.stories.ts +2 -0
  202. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/CONSUMER-STYLING.md +72 -0
  203. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/LayoutGridByCols.vue +26 -25
  204. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/stories/LayoutGridByCols.stories.ts +91 -107
  205. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/tests/LayoutGridByCols.spec.ts +50 -15
  206. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/tests/__snapshots__/LayoutGridByCols.spec.ts.snap +5 -5
  207. package/app/components/01.atoms/display-banner/CONSUMER-STYLING.md +13 -0
  208. package/app/components/01.atoms/display-dialog/CONSUMER-STYLING.md +82 -54
  209. package/app/components/01.atoms/display-dialog/DisplayDialog.vue +38 -45
  210. package/app/components/01.atoms/display-dialog/stories/DisplayDialog.stories.ts +25 -0
  211. package/app/components/01.atoms/display-dialog/tests/DisplayDialog.spec.ts +21 -0
  212. package/app/components/01.atoms/display-pill/CONSUMER-STYLING.md +112 -0
  213. package/app/components/01.atoms/display-pill/DisplayPill.vue +88 -50
  214. package/app/components/01.atoms/display-pill/stories/DisplayPill.stories.ts +56 -3
  215. package/app/components/01.atoms/display-pill/tests/DisplayPill.spec.ts +104 -4
  216. package/app/components/01.atoms/display-pill/tests/__snapshots__/DisplayPill.spec.ts.snap +3 -3
  217. package/app/components/01.atoms/display-tooltip/CONSUMER-STYLING.md +22 -2
  218. package/app/components/01.atoms/display-tooltip/DisplayTooltip.vue +18 -26
  219. package/app/components/01.atoms/glass-panel/CONSUMER-STYLING.md +91 -0
  220. package/app/components/01.atoms/glass-panel/GlassPanel.vue +34 -30
  221. package/app/components/01.atoms/glass-panel/stories/GlassPanel.stories.ts +121 -0
  222. package/app/components/01.atoms/glass-panel/tests/GlassPanel.spec.ts +61 -0
  223. package/app/components/01.atoms/grids/auto-grid/AutoGrid.vue +5 -10
  224. package/app/components/01.atoms/grids/auto-grid/CONSUMER-STYLING.md +76 -0
  225. package/app/components/01.atoms/grids/auto-grid/stories/AutoGrid.stories.ts +5 -4
  226. package/app/components/01.atoms/grids/auto-grid/tests/AutoGrid.spec.ts +8 -0
  227. package/app/components/01.atoms/grids/column-flow-grid/CONSUMER-STYLING.md +11 -2
  228. package/app/components/01.atoms/grids/grid-stack/CONSUMER-STYLING.md +76 -0
  229. package/app/components/01.atoms/grids/grid-stack/GridStack.vue +6 -1
  230. package/app/components/01.atoms/grids/grid-stack/stories/GridStack.stories.ts +1 -1
  231. package/app/components/01.atoms/grids/grid-stack/tests/GridStack.spec.ts +35 -0
  232. package/app/components/01.atoms/grids/masonry-grid/CONSUMER-STYLING.md +11 -2
  233. package/app/components/01.atoms/navigation/breadcrumb/Breadcrumb.vue +5 -10
  234. package/app/components/01.atoms/navigation/breadcrumb/CONSUMER-STYLING.md +15 -0
  235. package/app/components/01.atoms/navigation/skip-links/CONSUMER-STYLING.md +13 -0
  236. package/app/components/01.atoms/navigation/tabs/CONSUMER-STYLING.md +21 -0
  237. package/app/components/01.atoms/page-row/CONSUMER-STYLING.md +46 -8
  238. package/app/components/01.atoms/page-row/PageRow.vue +17 -13
  239. package/app/components/01.atoms/page-row/stories/PageRow.stories.ts +8 -0
  240. package/app/components/01.atoms/page-row/tests/PageRow.spec.ts +7 -11
  241. package/app/components/01.atoms/pop-over/CONSUMER-STYLING.md +13 -0
  242. package/app/components/01.atoms/qr-code/CONSUMER-STYLING.md +48 -0
  243. package/app/components/01.atoms/qr-code/DisplayQrCode.vue +5 -1
  244. package/app/components/01.atoms/qr-code/stories/DisplayQrCode.stories.ts +11 -3
  245. package/app/components/01.atoms/qr-code/tests/DisplayQrCode.spec.ts +15 -0
  246. package/app/components/01.atoms/text-block/CONSUMER-STYLING.md +49 -0
  247. package/app/components/01.atoms/text-block/TextBlock.vue +13 -5
  248. package/app/components/01.atoms/text-block/stories/TextBlock.stories.ts +84 -0
  249. package/app/components/01.atoms/text-block/tests/TextBlock.spec.ts +78 -0
  250. package/app/components/01.atoms/text-block/tests/__snapshots__/TextBlock.spec.ts.snap +7 -0
  251. package/app/components/01.atoms/text-blocks/eyebrow-text/CONSUMER-STYLING.md +56 -0
  252. package/app/components/01.atoms/text-blocks/eyebrow-text/EyebrowText.vue +10 -5
  253. package/app/components/01.atoms/text-blocks/eyebrow-text/tests/EyebrowText.spec.ts +11 -0
  254. package/app/components/01.atoms/text-blocks/header-block/CONSUMER-STYLING.md +16 -1
  255. package/app/components/01.atoms/text-blocks/hero-text/CONSUMER-STYLING.md +74 -0
  256. package/app/components/01.atoms/text-blocks/hero-text/HeroText.vue +14 -9
  257. package/app/components/01.atoms/text-blocks/hero-text/tests/HeroText.spec.ts +11 -0
  258. package/app/components/01.atoms/text-blocks/link-text/CONSUMER-STYLING.md +45 -0
  259. package/app/components/01.atoms/text-blocks/link-text/LinkText.vue +15 -8
  260. package/app/components/01.atoms/text-blocks/link-text/tests/LinkText.spec.ts +11 -0
  261. package/app/components/01.atoms/ui-block-decorated/CONSUMER-STYLING.md +13 -0
  262. package/app/components/02.molecules/action-menu/ActionMenu.vue +28 -30
  263. package/app/components/02.molecules/action-menu/{ActionMenuItemCore.vue → ActionMenuItem.vue} +12 -14
  264. package/app/components/02.molecules/action-menu/CONSUMER-STYLING.md +90 -76
  265. package/app/components/02.molecules/action-menu/stories/ActionMenu.stories.ts +48 -41
  266. package/app/components/02.molecules/action-menu/tests/ActionMenu.spec.ts +46 -1
  267. package/app/components/02.molecules/action-menu/tests/{ActionMenuItemCore.spec.ts → ActionMenuItem.spec.ts} +11 -5
  268. package/app/components/02.molecules/action-menu/tests/__snapshots__/ActionMenuItem.spec.ts.snap +27 -0
  269. package/app/components/02.molecules/alert-content/AlertContent.vue +17 -8
  270. package/app/components/02.molecules/alert-content/AlertContentInner.vue +57 -30
  271. package/app/components/02.molecules/alert-content/CONSUMER-STYLING.md +84 -0
  272. package/app/components/02.molecules/alert-content/stories/AlertContent.stories.ts +39 -0
  273. package/app/components/02.molecules/alert-content/tests/AlertContent.spec.ts +32 -0
  274. package/app/components/02.molecules/alert-content/tests/AlertContentInner.spec.ts +32 -0
  275. package/app/components/02.molecules/alert-masked-content/AlertMaskedContent.vue +9 -5
  276. package/app/components/02.molecules/alert-masked-content/CONSUMER-STYLING.md +73 -0
  277. package/app/components/02.molecules/alert-masked-content/stories/AlertMaskedContent.stories.ts +91 -10
  278. package/app/components/02.molecules/alert-masked-content/tests/AlertMaskedContent.spec.ts +52 -0
  279. package/app/components/02.molecules/cookie-consent-banner/CONSUMER-STYLING.md +95 -0
  280. package/app/components/02.molecules/cookie-consent-banner/CookieConsentBanner.vue +149 -0
  281. package/app/components/{01.atoms → 02.molecules}/cookie-consent-banner/stories/CookieConsentBanner.stories.ts +22 -3
  282. package/app/components/{01.atoms → 02.molecules}/cookie-consent-banner/tests/CookieConsentBanner.spec.ts +81 -4
  283. package/app/components/02.molecules/display-avatar/CONSUMER-STYLING.md +63 -0
  284. package/app/components/02.molecules/display-avatar/DisplayAvatar.vue +120 -0
  285. package/app/components/{01.atoms → 02.molecules}/display-avatar/stories/DisplayAvatar.stories.ts +56 -14
  286. package/app/components/{01.atoms → 02.molecules}/display-avatar/tests/DisplayAvatar.spec.ts +43 -11
  287. package/app/components/02.molecules/display-avatar/tests/__snapshots__/DisplayAvatar.spec.ts.snap +11 -0
  288. package/app/components/02.molecules/display-chip/CONSUMER-STYLING.md +57 -0
  289. package/app/components/02.molecules/display-chip/DisplayChip.vue +50 -83
  290. package/app/components/02.molecules/display-chip/tests/DisplayChip.spec.ts +10 -10
  291. package/app/components/02.molecules/display-chip/tests/__snapshots__/DisplayChip.spec.ts.snap +4 -4
  292. package/app/components/02.molecules/display-theme-switch/CONSUMER-STYLING.md +25 -4
  293. package/app/components/02.molecules/display-theme-switch/DisplayThemeSwitch.vue +9 -6
  294. package/app/components/02.molecules/display-theme-switch/stories/DisplayThemeSwitch.stories.ts +6 -1
  295. package/app/components/02.molecules/display-theme-switch/tests/DisplayThemeSwitch.spec.ts +10 -1
  296. package/app/components/02.molecules/display-tooltip-defined/CONSUMER-STYLING.md +11 -0
  297. package/app/components/02.molecules/expandable/accordian/CONSUMER-STYLING.md +11 -4
  298. package/app/components/02.molecules/expandable/expanding-panel/CONSUMER-STYLING.md +12 -5
  299. package/app/components/02.molecules/expandable/expanding-panel-classic/CONSUMER-STYLING.md +12 -5
  300. package/app/components/02.molecules/input-copy/CONSUMER-STYLING.md +12 -5
  301. package/app/components/02.molecules/input-copy/InputCopy.vue +12 -25
  302. package/app/components/02.molecules/input-copy/stories/InputCopy.stories.ts +1 -1
  303. package/app/components/02.molecules/input-copy/tests/InputCopy.spec.ts +1 -1
  304. package/app/components/02.molecules/navigation/deep-expanding-menu/CONSUMER-STYLING.md +13 -0
  305. package/app/components/02.molecules/navigation/deep-expanding-menu-classic/CONSUMER-STYLING.md +11 -0
  306. package/app/components/02.molecules/navigation/site-navigation/CONSUMER-STYLING.md +109 -0
  307. package/app/components/02.molecules/navigation/site-navigation/SiteNavigation.vue +37 -55
  308. package/app/components/02.molecules/navigation/site-navigation/stories/SiteNavigation.stories.ts +22 -1
  309. package/app/components/02.molecules/navigation/site-navigation/tests/SiteNavigation.spec.ts +41 -6
  310. package/app/components/02.molecules/navigation/tab-navigation/CONSUMER-STYLING.md +13 -8
  311. package/app/components/02.molecules/navigation/tab-navigation/TabNavigation.vue +18 -36
  312. package/app/components/02.molecules/navigation/tab-navigation/stories/TabNavigation.stories.ts +1 -1
  313. package/app/components/02.molecules/navigation/tab-navigation/tests/TabNavigation.spec.ts +1 -1
  314. package/app/components/02.molecules/opening-hours/CONSUMER-STYLING.md +134 -0
  315. package/app/components/02.molecules/opening-hours/OpeningHours.vue +352 -0
  316. package/app/components/02.molecules/opening-hours/stories/OpeningHours.stories.ts +127 -0
  317. package/app/components/02.molecules/opening-hours/tests/OpeningHours.spec.ts +228 -0
  318. package/app/components/02.molecules/opening-hours/tests/OpeningHours.structuredData.spec.ts +45 -0
  319. package/app/components/02.molecules/opening-hours/tests/__snapshots__/OpeningHours.spec.ts.snap +23 -0
  320. package/app/components/02.molecules/opening-hours/tests/buildOpeningHoursSpecification.spec.ts +52 -0
  321. package/app/components/02.molecules/price-list/CONSUMER-STYLING.md +106 -0
  322. package/app/components/02.molecules/price-list/PriceList.vue +48 -40
  323. package/app/components/02.molecules/price-list/stories/PriceList.stories.ts +15 -2
  324. package/app/components/02.molecules/price-list/tests/PriceList.spec.ts +39 -2
  325. package/app/components/02.molecules/price-list/tests/__snapshots__/PriceList.spec.ts.snap +4 -16
  326. package/app/components/02.molecules/pricing-card/CONSUMER-STYLING.md +23 -5
  327. package/app/components/02.molecules/pricing-card/PricingCard.vue +31 -61
  328. package/app/components/02.molecules/pricing-card/stories/PricingCard.stories.ts +2 -0
  329. package/app/components/02.molecules/pricing-card/tests/PricingCard.spec.ts +14 -1
  330. package/app/components/02.molecules/profile-section/CONSUMER-STYLING.md +53 -0
  331. package/app/components/02.molecules/profile-section/ProfileSection.vue +53 -66
  332. package/app/components/02.molecules/profile-section/tests/ProfileSection.spec.ts +4 -4
  333. package/app/components/02.molecules/profile-section/tests/__snapshots__/ProfileSection.spec.ts.snap +6 -12
  334. package/app/components/02.molecules/prompt/CONSUMER-STYLING.md +51 -0
  335. package/app/components/{01.atoms → 02.molecules}/prompt/DisplayPrompt.vue +23 -8
  336. package/app/components/{01.atoms → 02.molecules}/prompt/stories/DisplayPrompt.stories.ts +18 -1
  337. package/app/components/{01.atoms → 02.molecules}/prompt/tests/DisplayPrompt.spec.ts +37 -7
  338. package/app/components/02.molecules/qr-code/CONSUMER-STYLING.md +66 -0
  339. package/app/components/02.molecules/qr-code/CaptureQrCode.vue +31 -12
  340. package/app/components/02.molecules/qr-code/DecodeQrCode.vue +55 -19
  341. package/app/components/02.molecules/qr-code/stories/CaptureQrCode.stories.ts +56 -0
  342. package/app/components/02.molecules/qr-code/stories/DecodeQrCode.stories.ts +53 -0
  343. package/app/components/02.molecules/qr-code/tests/CaptureQrCode.spec.ts +68 -20
  344. package/app/components/02.molecules/qr-code/tests/DecodeQrCode.spec.ts +44 -8
  345. package/app/components/02.molecules/samaritan-prompt/CONSUMER-STYLING.md +118 -0
  346. package/app/components/02.molecules/samaritan-prompt/SamaritanPrompt.vue +108 -51
  347. package/app/components/02.molecules/samaritan-prompt/SamaritanPromptMixed.vue +63 -62
  348. package/app/components/02.molecules/samaritan-prompt/stories/SamaritanPrompt.stories.ts +129 -0
  349. package/app/components/02.molecules/samaritan-prompt/stories/SamaritanPromptMixed.stories.ts +124 -0
  350. package/app/components/02.molecules/samaritan-prompt/tests/SamaritanPrompt.spec.ts +66 -0
  351. package/app/components/02.molecules/samaritan-prompt/tests/SamaritanPromptMixed.spec.ts +95 -17
  352. package/app/components/02.molecules/select-menu/CONSUMER-STYLING.md +11 -2
  353. package/app/components/02.molecules/social-icons-list/CONSUMER-STYLING.md +43 -0
  354. package/app/components/02.molecules/social-icons-list/SocialIconsList.vue +15 -15
  355. package/app/components/02.molecules/social-icons-list/stories/SocialIconsList.stories.ts +6 -1
  356. package/app/components/02.molecules/social-icons-list/tests/SocialIconsList.spec.ts +22 -1
  357. package/app/components/02.molecules/social-icons-list/tests/__snapshots__/SocialIconsList.spec.ts.snap +3 -3
  358. package/app/components/02.molecules/stepper-list/CONSUMER-STYLING.md +44 -5
  359. package/app/components/02.molecules/stepper-list/StepperList.vue +23 -43
  360. package/app/components/02.molecules/stepper-list/tests/StepperList.spec.ts +9 -0
  361. package/app/components/{01.atoms → 02.molecules}/toast/CONSUMER-STYLING.md +14 -0
  362. package/app/components/{01.atoms → 02.molecules}/toast/DisplayToast.vue +1 -2
  363. package/app/components/{01.atoms → 02.molecules}/toast/DisplayToastProvider.vue +1 -2
  364. package/app/components/{01.atoms → 02.molecules}/toast/stories/DisplayToast.stories.ts +1 -1
  365. package/app/components/{01.atoms → 02.molecules}/toast/stories/DisplayToastProvider.stories.ts +1 -1
  366. package/app/components/03.organisms/image-galleries/carousel-flip/CONSUMER-STYLING.md +13 -0
  367. package/app/components/03.organisms/image-galleries/slider-gallery/CONSUMER-STYLING.md +137 -0
  368. package/app/components/03.organisms/image-galleries/slider-gallery/SliderGallery.vue +378 -343
  369. package/app/components/03.organisms/image-galleries/slider-gallery/stories/SliderGallery.stories.ts +26 -1
  370. package/app/components/03.organisms/image-galleries/slider-gallery/tests/SliderGallery.spec.ts +102 -23
  371. package/app/components/03.organisms/image-galleries/slider-gallery/tests/__snapshots__/SliderGallery.spec.ts.snap +44 -44
  372. package/app/components/03.organisms/responsive-header/CONSUMER-STYLING.md +12 -1
  373. package/app/components/03.organisms/responsive-header/ResponsiveHeader.vue +0 -4
  374. package/app/components/03.organisms/services/service-detail/CONSUMER-STYLING.md +24 -3
  375. package/app/components/03.organisms/services/service-detail/ServiceDetail.vue +3 -3
  376. package/app/components/03.organisms/services/service-detail/stories/ServiceDetail.stories.ts +13 -13
  377. package/app/components/03.organisms/services/service-detail/tests/__snapshots__/ServiceDetail.spec.ts.snap +1 -1
  378. package/app/components/03.organisms/services/service-summary/CONSUMER-STYLING.md +24 -7
  379. package/app/components/03.organisms/services/service-summary/ServiceSummary.vue +3 -3
  380. package/app/components/03.organisms/services/service-summary/stories/ServiceSummary.stories.ts +1 -1
  381. package/app/components/03.organisms/services/service-summary/tests/__snapshots__/ServiceSummary.spec.ts.snap +1 -1
  382. package/app/components/03.organisms/services/services-card/CONSUMER-STYLING.md +11 -2
  383. package/app/components/03.organisms/services/services-card/ServicesCard.vue +17 -26
  384. package/app/components/03.organisms/services/services-card/tests/ServicesCard.spec.ts +21 -0
  385. package/app/components/03.organisms/services/services-grids/CONSUMER-STYLING.md +50 -0
  386. package/app/components/03.organisms/services/services-grids/ServicesCardGrid.vue +9 -16
  387. package/app/components/03.organisms/services/services-grids/stories/ServicesCardGrid.stories.ts +6 -0
  388. package/app/components/03.organisms/services/services-grids/tests/ServicesCardGrid.spec.ts +18 -0
  389. package/app/components/03.organisms/services/services-grids/tests/__snapshots__/ServiceSummaryGrid.spec.ts.snap +3 -3
  390. package/app/components/03.organisms/services/services-grids/tests/__snapshots__/ServicesCardGrid.spec.ts.snap +3 -3
  391. package/app/components/03.organisms/site-header/CONSUMER-STYLING.md +12 -1
  392. package/app/components/04.templates/page-hero-highlights/CONSUMER-STYLING.md +103 -0
  393. package/app/components/04.templates/page-hero-highlights/PageHeroHighlights.vue +144 -193
  394. package/app/components/04.templates/page-hero-highlights/PageHeroHighlightsHeader.vue +27 -37
  395. package/app/components/04.templates/page-hero-highlights/stories/PageHeroHighlights.stories.ts +56 -60
  396. package/app/components/04.templates/page-hero-highlights/stories/PageHeroHighlightsHeader.stories.ts +2 -2
  397. package/app/components/04.templates/page-hero-highlights/tests/PageHeroHighlights.spec.ts +10 -10
  398. package/app/components/04.templates/page-hero-highlights/tests/PageHeroHighlightsHeader.spec.ts +7 -7
  399. package/app/components/04.templates/page-hero-highlights/tests/__snapshots__/PageHeroHighlights.spec.ts.snap +6 -6
  400. package/app/components/05.forms/form-errors/CONSUMER-STYLING.md +112 -0
  401. package/app/components/05.forms/form-errors/InputError.vue +101 -122
  402. package/app/components/05.forms/form-errors/stories/InputError.stories.ts +125 -0
  403. package/app/components/05.forms/form-errors/tests/InputError.spec.ts +82 -31
  404. package/app/components/05.forms/form-field/CONSUMER-STYLING.md +91 -0
  405. package/app/components/05.forms/form-field/FormField.vue +26 -35
  406. package/app/components/05.forms/form-field/stories/FormField.stories.ts +104 -0
  407. package/app/components/05.forms/form-field/tests/FormField.spec.ts +75 -0
  408. package/app/components/05.forms/form-fieldset/CONSUMER-STYLING.md +88 -0
  409. package/app/components/05.forms/form-fieldset/FormFieldset.vue +34 -28
  410. package/app/components/05.forms/form-fieldset/stories/FormFieldset.stories.ts +84 -0
  411. package/app/components/05.forms/form-fieldset/tests/FormFieldset.spec.ts +111 -0
  412. package/app/components/05.forms/form-wrapper/CONSUMER-STYLING.md +101 -0
  413. package/app/components/05.forms/form-wrapper/FormWrapper.vue +32 -15
  414. package/app/components/05.forms/form-wrapper/stories/FormWrapper.stories.ts +75 -0
  415. package/app/components/05.forms/form-wrapper/tests/FormWrapper.spec.ts +57 -0
  416. package/app/components/05.forms/input-button/CONSUMER-STYLING.md +52 -7
  417. package/app/components/05.forms/input-button/{InputButtonCore.vue → InputButton.vue} +60 -18
  418. package/app/components/05.forms/input-button/playwright/{input-button-core.playwright.ts → input-button.playwright.ts} +5 -5
  419. package/app/components/05.forms/input-button/stories/{InputButtonCore.stories.ts → InputButton.stories.ts} +8 -10
  420. package/app/components/05.forms/input-button/tests/{InputButtonCore.spec.ts → InputButton.spec.ts} +75 -19
  421. package/app/components/05.forms/input-button/tests/__snapshots__/{InputButtonCore.spec.ts.snap → InputButton.spec.ts.snap} +18 -18
  422. package/app/components/05.forms/input-checkbox/CONSUMER-STYLING.md +93 -0
  423. package/app/components/05.forms/input-checkbox/MultipleCheckboxes.vue +19 -25
  424. package/app/components/05.forms/input-checkbox/SingleCheckbox.vue +17 -43
  425. package/app/components/05.forms/input-checkbox/stories/MultipleCheckboxes.stories.ts +104 -0
  426. package/app/components/05.forms/input-checkbox/stories/SingleCheckbox.stories.ts +75 -0
  427. package/app/components/05.forms/input-checkbox/tests/MultipleCheckboxes.spec.ts +91 -53
  428. package/app/components/05.forms/input-checkbox/tests/SingleCheckbox.spec.ts +112 -0
  429. package/app/components/05.forms/input-checkbox-radio/CONSUMER-STYLING.md +115 -35
  430. package/app/components/05.forms/input-checkbox-radio/InputCheckboxRadio.vue +158 -0
  431. package/app/components/05.forms/input-checkbox-radio/InputCheckboxRadioButton.vue +102 -101
  432. package/app/components/05.forms/input-checkbox-radio/InputCheckboxRadioField.vue +100 -0
  433. package/app/components/05.forms/input-checkbox-radio/stories/{InputCheckboxRadioCore.stories.ts → InputCheckboxRadio.stories.ts} +23 -8
  434. package/app/components/05.forms/input-checkbox-radio/stories/InputCheckboxRadioButton.stories.ts +60 -16
  435. package/app/components/05.forms/input-checkbox-radio/stories/InputCheckboxRadioField.stories.ts +93 -0
  436. package/app/components/05.forms/input-checkbox-radio/tests/InputCheckboxRadio.spec.ts +174 -0
  437. package/app/components/05.forms/input-checkbox-radio/tests/InputCheckboxRadioButton.spec.ts +87 -0
  438. package/app/components/05.forms/input-checkbox-radio/tests/InputCheckboxRadioField.spec.ts +87 -0
  439. package/app/components/05.forms/input-description/CONSUMER-STYLING.md +177 -0
  440. package/app/components/05.forms/input-description/InputDescription.vue +45 -24
  441. package/app/components/05.forms/input-description/stories/InputDescription.stories.ts +160 -0
  442. package/app/components/05.forms/input-description/tests/InputDescription.spec.ts +62 -386
  443. package/app/components/05.forms/input-label/CONSUMER-STYLING.md +134 -0
  444. package/app/components/05.forms/input-label/InputLabel.vue +99 -38
  445. package/app/components/05.forms/input-label/stories/InputLabel.stories.ts +236 -0
  446. package/app/components/05.forms/input-label/tests/InputLabel.spec.ts +113 -342
  447. package/app/components/05.forms/input-number/CONSUMER-STYLING.md +16 -7
  448. package/app/components/05.forms/input-number/{InputNumberCore.vue → InputNumber.vue} +6 -6
  449. package/app/components/05.forms/input-number/{variants/InputNumberDefault.vue → InputNumberField.vue} +12 -15
  450. package/app/components/05.forms/input-number/stories/{InputNumberCore.stories.ts → InputNumber.stories.ts} +6 -6
  451. package/app/components/05.forms/input-number/{variants/stories/InputNumberDefault.stories.ts → stories/InputNumberField.stories.ts} +5 -5
  452. package/app/components/05.forms/input-number/tests/{InputNumberCore.spec.ts → InputNumber.spec.ts} +2 -2
  453. package/app/components/05.forms/input-number/{variants/tests/InputNumberDefault.spec.ts → tests/InputNumberField.spec.ts} +8 -8
  454. package/app/components/05.forms/input-radio/CONSUMER-STYLING.md +70 -0
  455. package/app/components/05.forms/input-radio/MultipleRadiobuttons.vue +19 -30
  456. package/app/components/05.forms/input-radio/stories/MultipleRadiobuttons.stories.ts +116 -0
  457. package/app/components/05.forms/input-radio/tests/MultipleRadioButtons.spec.ts +125 -74
  458. package/app/components/05.forms/input-range/CONSUMER-STYLING.md +13 -0
  459. package/app/components/05.forms/input-range/InputRangeCore.vue +1 -1
  460. package/app/components/05.forms/input-range/{variants/InputRangeDefault.vue → InputRangeDefault.vue} +7 -11
  461. package/app/components/05.forms/input-range/{variants/tests → tests}/InputRangeDefault.spec.ts +1 -1
  462. package/app/components/05.forms/input-select/CONSUMER-STYLING.md +11 -2
  463. package/app/components/05.forms/input-select/{variants/InputSelectWithLabel.vue → InputSelectWithLabel.vue} +6 -9
  464. package/app/components/05.forms/input-select/stories/InputSelectWithLabel.stories.ts +1 -1
  465. package/app/components/05.forms/input-text/CONSUMER-STYLING.md +12 -3
  466. package/app/components/05.forms/input-text/{variants/InputPasswordWithLabel.vue → InputPasswordWithLabel.vue} +3 -3
  467. package/app/components/05.forms/input-text/{variants/InputTextAsNumberWithLabel.vue → InputTextAsNumberWithLabel.vue} +12 -15
  468. package/app/components/05.forms/input-text/InputTextCore.vue +8 -11
  469. package/app/components/05.forms/input-text/{variants/InputTextWithLabel.vue → InputTextWithLabel.vue} +9 -10
  470. package/app/components/05.forms/input-text/stories/InputPasswordWithLabel.stories.ts +1 -1
  471. package/app/components/05.forms/input-text/stories/InputTextAsNumberWithLabel.stories.ts +1 -1
  472. package/app/components/05.forms/input-text/stories/InputTextWithLabel.stories.ts +1 -1
  473. package/app/components/05.forms/input-text/tests/InputPasswordWithLabel.spec.ts +2 -1
  474. package/app/components/05.forms/input-text/tests/InputTextAsNumberWithLabel.spec.ts +1 -1
  475. package/app/components/05.forms/input-text/tests/InputTextWithLabel.spec.ts +2 -1
  476. package/app/components/05.forms/input-textarea/CONSUMER-STYLING.md +11 -2
  477. package/app/components/05.forms/input-textarea/{variants/InputTextareaWithLabel.vue → InputTextareaWithLabel.vue} +3 -7
  478. package/app/components/05.forms/input-textarea/stories/InputTextareaWithLabel.stories.ts +1 -1
  479. package/app/components/05.forms/patterns/stories/ContactForm.stories.ts +9 -10
  480. package/app/components/05.forms/patterns/stories/LoginForm.stories.ts +10 -10
  481. package/app/components/05.forms/patterns/stories/MigratedFieldsForm.stories.ts +246 -101
  482. package/app/components/05.forms/pending-effect/CONSUMER-STYLING.md +92 -0
  483. package/app/components/05.forms/pending-effect/PendingEffect.vue +52 -45
  484. package/app/components/05.forms/pending-effect/stories/PendingEffect.stories.ts +132 -0
  485. package/app/components/05.forms/pending-effect/tests/PendingEffect.spec.ts +67 -0
  486. package/app/components/05.forms/toggle-switch/CONSUMER-STYLING.md +11 -2
  487. package/app/components/05.forms/toggle-switch/ToggleSwitchCore.vue +10 -29
  488. package/app/components/05.forms/toggle-switch/{variants/ToggleSwitchWithLabel.vue → ToggleSwitchWithLabel.vue} +5 -7
  489. package/app/components/05.forms/toggle-switch/{variants/ToggleSwitchWithLabelInline.vue → ToggleSwitchWithLabelInline.vue} +2 -4
  490. package/app/components/05.forms/toggle-switch/stories/ToggleSwitchWithLabel.stories.ts +1 -1
  491. package/app/components/05.forms/toggle-switch/stories/ToggleSwitchWithLabelInline.stories.ts +4 -1
  492. package/app/components/05.forms/toggle-switch/{variants/tests → tests}/ToggleSwitchWithLabel.spec.ts +26 -0
  493. package/app/components/05.forms/triple-toggle-switch/CONSUMER-STYLING.md +75 -62
  494. package/app/components/05.forms/triple-toggle-switch/TripleToggleSwitch.vue +243 -0
  495. package/app/components/05.forms/triple-toggle-switch/stories/TripleToggleSwitch.stories.ts +104 -0
  496. package/app/components/05.forms/triple-toggle-switch/tests/TripleToggleSwitch.spec.ts +138 -0
  497. package/app/composables/tests/useCancellableTimer.spec.ts +48 -0
  498. package/app/composables/tests/useMaxChildWidth.spec.ts +67 -0
  499. package/app/composables/useCancellableTimer.ts +27 -7
  500. package/app/composables/useMaxChildWidth.ts +4 -6
  501. package/app/types/app-config.d.ts +10 -0
  502. package/app/types/components/cookie-consent-banner.d.ts +3 -0
  503. package/app/types/components/index.ts +6 -1
  504. package/app/types/components/opening-hours.d.ts +48 -0
  505. package/app/types/components/price-list.d.ts +11 -0
  506. package/app/types/components/profile-section.d.ts +6 -0
  507. package/app/types/components/samaritan-prompt.d.ts +13 -0
  508. package/app/types/components/services-card.d.ts +9 -0
  509. package/app/types/components/slider-gallery.d.ts +2 -0
  510. package/app/types/components/social-icons-list.d.ts +2 -0
  511. package/app/types/forms/types.forms.d.ts +3 -0
  512. package/app/types/forms/types.zodFormControl.d.ts +0 -3
  513. package/app/utils/opening-hours.ts +44 -0
  514. package/nuxt.config.ts +5 -1
  515. package/package.json +2 -2
  516. package/ramps.config.mjs +1 -1
  517. package/.claude/commands/create-commit-message.md +0 -13
  518. package/.claude/commands/create-release-notes.md +0 -34
  519. package/.claude/commands/migrate-component.md +0 -169
  520. package/.claude/commands/run-commit.md +0 -13
  521. package/.claude/component-ledger/artifact-url.txt +0 -1
  522. package/.claude/component-ledger/audit.json +0 -1
  523. package/.claude/component-ledger/build.mjs +0 -164
  524. package/.claude/component-ledger/output.html +0 -569
  525. package/.claude/component-ledger/template.html +0 -569
  526. package/.claude/hooks/check-component-update.sh +0 -95
  527. package/.claude/hooks/refresh-component-ledger.sh +0 -32
  528. package/.claude/settings.json +0 -134
  529. package/.claude/settings.local.json +0 -38
  530. package/.claude/skills/components/alert-content-inner.md +0 -60
  531. package/.claude/skills/components/navigation-horizontal.md +0 -99
  532. package/.claude/skills/components/samaritan-prompt-mixed.md +0 -139
  533. package/app/components/01.atoms/content-wrappers/content-columns-2/ContentColumns2.vue +0 -51
  534. package/app/components/01.atoms/content-wrappers/content-columns-2/stories/ContentColumns2.stories.ts +0 -110
  535. package/app/components/01.atoms/content-wrappers/content-columns-2/tests/ContentColumns2.spec.ts +0 -105
  536. package/app/components/01.atoms/content-wrappers/content-columns-2/tests/__snapshots__/ContentColumns2.spec.ts.snap +0 -14
  537. package/app/components/01.atoms/content-wrappers/content-width/ContentWidth.vue +0 -88
  538. package/app/components/01.atoms/content-wrappers/content-width/stories/ContentWidth.stories.ts +0 -362
  539. package/app/components/01.atoms/content-wrappers/content-width/tests/ContentWidth.spec.ts +0 -132
  540. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/tests/__snapshots__/LayoutGrid.spec.ts.snap +0 -36
  541. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/LayoutGridByWidth.vue +0 -70
  542. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/stories/LayoutGridByWidth.stories.ts +0 -220
  543. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/tests/LayoutGridByWidth.spec.ts +0 -174
  544. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/tests/__snapshots__/LayoutGrid.spec.ts.snap +0 -36
  545. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/tests/__snapshots__/LayoutGridByCols.spec.ts.snap +0 -36
  546. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/tests/__snapshots__/LayoutGridByWidth.spec.ts.snap +0 -36
  547. package/app/components/01.atoms/cookie-consent-banner/CookieConsentBanner.vue +0 -148
  548. package/app/components/01.atoms/display-avatar/DisplayAvatar.vue +0 -130
  549. package/app/components/01.atoms/display-avatar/tests/__snapshots__/DisplayAvatar.spec.ts.snap +0 -11
  550. package/app/components/02.molecules/action-menu/tests/__snapshots__/ActionMenuItemCore.spec.ts.snap +0 -27
  551. package/app/components/02.molecules/navigation/navigation-horizontal/NavigationHorizontal.vue +0 -162
  552. package/app/components/02.molecules/navigation/navigation-horizontal/stories/NavigationHorizontal.stories.ts +0 -373
  553. package/app/components/02.molecules/navigation/navigation-horizontal/tests/NavigationHorizontal.spec.ts +0 -152
  554. package/app/components/02.molecules/navigation/navigation-horizontal/tests/__snapshots__/NavigationHorizontal.spec.ts.snap +0 -17
  555. package/app/components/02.molecules/qr-code/stories/QrCode.stories.ts +0 -101
  556. package/app/components/03.organisms/colour-finder/ColourFinder.vue +0 -1519
  557. package/app/components/05.forms/input-checkbox-radio/InputCheckboxRadioCore.vue +0 -202
  558. package/app/components/05.forms/input-checkbox-radio/InputCheckboxRadioWithLabel.vue +0 -105
  559. package/app/components/05.forms/input-checkbox-radio/tests/InputCheckboxRadioCore.spec.ts +0 -320
  560. package/app/components/05.forms/triple-toggle-switch/TripleToggleSwitchCore.vue +0 -314
  561. package/app/components/05.forms/triple-toggle-switch/stories/TripleToggleSwitchCore.stories.ts +0 -63
  562. package/.vscode/{srcdev-component-dialog.code-snippets → srcdev-component-display-dialog.code-snippets} +0 -0
  563. package/app/components/{01.atoms → 02.molecules}/toast/tests/DisplayToast.spec.ts +1 -1
  564. /package/app/components/{01.atoms → 02.molecules}/toast/tests/DisplayToastProvider.spec.ts +0 -0
  565. /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
  566. /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
  567. /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
  568. /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
  569. /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
  570. /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
  571. /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
  572. /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
  573. /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
  574. /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
  575. /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
  576. /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
  577. /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
  578. /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
  579. /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
  580. /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
  581. /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
  582. /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
  583. /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
  584. /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
  585. /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
  586. /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
  587. /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
  588. /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
  589. /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
  590. /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
  591. /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
  592. /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
  593. /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
  594. /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
  595. /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
  596. /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
  597. /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
  598. /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
  599. /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
  600. /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
  601. /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
  602. /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
  603. /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
  604. /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
  605. /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
  606. /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
  607. /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
  608. /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
  609. /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
  610. /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
  611. /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
  612. /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
  613. /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
  614. /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
  615. /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
  616. /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
  617. /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
  618. /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
  619. /package/app/components/05.forms/input-range/{variants/stories → stories}/InputRangeDefault.stories.ts +0 -0
  620. /package/app/components/05.forms/input-select/{variants/tests → tests}/InputSelectWithLabel.spec.ts +0 -0
  621. /package/app/components/05.forms/input-textarea/{variants/tests → tests}/InputTextareaWithLabel.spec.ts +0 -0
  622. /package/app/components/05.forms/toggle-switch/{variants/tests → tests}/ToggleSwitchWithLabelInline.spec.ts +0 -0
  623. /package/app/types/components/{navigation-horizontal.d.ts → nav-item.d.ts} +0 -0
@@ -0,0 +1,149 @@
1
+ # InputCheckboxRadio Component
2
+
3
+ > **Renamed 2026-09-27**: `InputCheckboxRadioCore` → `InputCheckboxRadio`,
4
+ > `InputCheckboxRadioWithLabel` → `InputCheckboxRadioField`; `InputCheckboxRadioButton` kept its
5
+ > name. Root classes: `.input-checkbox-radio-wrapper` → `.input-checkbox-radio`,
6
+ > `.input-checkbox-radio-with-label` → `.input-checkbox-radio-field`,
7
+ > `.input-checkbox-radio-options-button` → `.input-checkbox-radio-button` (full list in
8
+ > CONSUMER-STYLING.md). Tokens unchanged.
9
+
10
+ ## Overview
11
+
12
+ The single checkbox or radio control that every checkbox and radio in `05.forms` is built from.
13
+ Consumers normally use the group components instead:
14
+
15
+ - `MultipleCheckboxes` / `SingleCheckbox` (`input-checkbox.md`)
16
+ - `MultipleRadiobuttons` (`input-radio.md`)
17
+
18
+ Use these three directly only for a custom group or layout:
19
+
20
+ | Component | Renders | Used by |
21
+ |---|---|---|
22
+ | `InputCheckboxRadio` | The visual square/circle stacked over a hidden native `<input>`. No label. | The other two |
23
+ | `InputCheckboxRadioField` | `<label>` with the control and a text label | `SingleCheckbox`, non-button `MultipleCheckboxes`/`MultipleRadiobuttons` |
24
+ | `InputCheckboxRadioButton` | `<label>` drawn as a button/pill: control, centred label, decorator icon | `is-button` mode of the group components |
25
+
26
+ ```vue
27
+ <InputCheckboxRadioField v-model="state.rememberMe" type="checkbox" name="rememberMe" label="Remember me" />
28
+
29
+ <InputCheckboxRadioButton
30
+ v-for="option in options"
31
+ :id="`service-${option.value}`"
32
+ :key="option.value"
33
+ v-model="state.services"
34
+ type="checkbox"
35
+ name="services"
36
+ :label="option.label"
37
+ :true-value="option.value"
38
+ :multiple-options="true"
39
+ :is-pill="true"
40
+ />
41
+ ```
42
+
43
+ ---
44
+
45
+ ## InputCheckboxRadio (the control)
46
+
47
+ > **Hyphenation rule**: write camelCase props hyphenated: `:true-value`, `:false-value`, `:multiple-options`, `:field-has-error`, `:aria-describedby`, `:display-as-disc`, `:is-button`, `:input-variant`, `:style-class-passthrough`.
48
+
49
+ | Prop | Type | Default | Notes |
50
+ |---|---|---|---|
51
+ | `type` | `"checkbox" \| "radio"` | required | Can change at runtime: the input is keyed on it, so it's recreated with the right v-model handling. |
52
+ | `id` | `string` | required | Native input id; pair it with a `label[for]`. |
53
+ | `name` | `string` | required | Share one `name` across a radio group. |
54
+ | `:true-value` / `:false-value` | `string \| number \| boolean` | `true` / `false` | Checked / unchecked value. `trueValue` is also the native `value`. |
55
+ | `:multiple-options` | `boolean` | `false` | Part of a checkbox group (array model). Also drops native `required` (a group can't require every box). |
56
+ | `:required` | `boolean` | `false` | Native `required` (unless `multiple-options`). |
57
+ | `:field-has-error` | `boolean` | `false` | `aria-invalid="true"` on the input, `data-invalid` on the root. |
58
+ | `:aria-describedby` | `string` | `""` | On the input, omitted when empty. |
59
+ | `theme` | `FormUiTheme` | `"default"` | `data-theme`. |
60
+ | `:input-variant` | `InputUiVariant` | `"normal"` | `data-input-variant`; `underlined` squares off a checkbox. |
61
+ | `:is-button` | `boolean` | `false` | Set by `InputCheckboxRadioButton`: no focus outline of its own, enables `display-as-disc`. |
62
+ | `:display-as-disc` | `boolean` | `false` | Rounds a checkbox, button mode only. |
63
+ | `:style-class-passthrough` | `string \| string[]` | `[]` | On the root, reacts to changes. |
64
+
65
+ `v-model` (**required**): a single value, or an array for a checkbox group (the control toggles its
66
+ `trueValue` in and out of the array).
67
+
68
+ Slot: `checkedIcon` replaces the default icon (`material-symbols:check-small`, or
69
+ `material-symbols:circle` for radios) shown when checked.
70
+
71
+ ---
72
+
73
+ ## Variants
74
+
75
+ ### InputCheckboxRadioField
76
+
77
+ Same props as the control minus `id`, `isButton`; plus `label?: string` (`""`). Generates its own
78
+ id with `useId()` and links the `<label for>` to it. Slots: `checkedIcon` (forwarded),
79
+ `labelContent` (replaces the `label` text, e.g. a label containing a terms link). Root
80
+ `<label class="input-checkbox-radio-field">` with `data-invalid`.
81
+
82
+ ### InputCheckboxRadioButton
83
+
84
+ Same props as the control minus `isButton` (always on), plus:
85
+
86
+ | Prop | Type | Default | Notes |
87
+ |---|---|---|---|
88
+ | `id` | `string` | required | Used for both the input and `label[for]`. |
89
+ | `label` | `string` | `""` | Replaced by the `labelContent` slot when given. |
90
+ | `:options-layout` | `OptionsLayout` | `"equal-widths"` | `data-options-layout`; `inline` stops the label wrapping. |
91
+ | `direction` | `"row" \| "row-reverse"` | `"row"` | `data-direction`; `row-reverse` puts the control on the right. Reacts to changes. |
92
+ | `:is-pill` | `boolean` | `false` | `data-pill`, fully rounded. |
93
+ | `:item-icon` | `string` | `"material-symbols:add-2"` | Decorator icon name. The `itemIcon` slot replaces it entirely. |
94
+
95
+ Slots: `checkedIcon`, `labelContent`, `itemIcon`.
96
+
97
+ ---
98
+
99
+ ## Accessibility
100
+
101
+ - A real native `<input type="checkbox|radio">` does the work: native checked state, keyboard
102
+ (Space; arrow keys within a same-`name` radio group), form validation. It's visually hidden with
103
+ `opacity: 0` and sized to the visible box, so it's still what gets clicked and focused.
104
+ - No `aria-checked` on the input: it's a native checkbox/radio, and ARIA in HTML forbids
105
+ `aria-checked` there (the native state is what's announced).
106
+ - Focus: the control draws an outline on `:has(input:focus-visible)`; the button draws its own
107
+ background and outline change instead.
108
+ - The Field and Button are `<label>` elements, so the whole row is clickable and labels the input.
109
+ The decorator icon is `aria-hidden`.
110
+ - Transitions are off under `prefers-reduced-motion: reduce`.
111
+ - No hardcoded copy; the icon names are props or slots.
112
+
113
+ ---
114
+
115
+ ## Styling
116
+
117
+ Full detail in `app/components/05.forms/input-checkbox-radio/CONSUMER-STYLING.md`. Tokens:
118
+ `--input-checkbox-*` (control colours, label colour/padding, transition duration) and
119
+ `--input-checkbox-button-*` (button colours, radius, pill radius, gap, paddings); shared geometry
120
+ `--input-checked-element-size`, `--input-checked-icon-size`, `--input-checked-icon-gap`,
121
+ `--input-checkbox-decorator-icon-size`. Hooks: `data-type`, `data-input-variant`, `data-theme`,
122
+ `data-button`, `data-display-as-disc`, `data-invalid`, `data-pill`, `data-direction`,
123
+ `data-options-layout`.
124
+
125
+ ---
126
+
127
+ ## History
128
+
129
+ **Migrated 2026-09-27** (3/5 → full compliance):
130
+
131
+ - Renamed (see top). Every state class became a data attribute (`.error`, `.button`, `.checkbox`,
132
+ `.inline` etc. collided with common consumer CSS).
133
+ - A runtime `type` switch left the checkbox v-model handler attached to the input, so a radio kept
134
+ toggling values in the old array; the input is now keyed on `type`.
135
+ - Removed `aria-checked` from the native input (and the `isChecked` computed that only fed it) and
136
+ the `is-button` input class, which nothing styled.
137
+ - `direction` on the button was copied into a plain `ref` at setup, so changing it did nothing; now
138
+ `data-direction`.
139
+ - The decorator icon and the button's checked icon were sized with `width`/`height` (ignored,
140
+ pitfall #24); now `font-size`, so they change size for the first time.
141
+ - The Field no longer takes `id` or `optionsLayout` (its id is always generated; the layout class
142
+ set a variable nothing read); the group components stopped passing them, so the id no longer
143
+ falls through onto the `<label>`. Removed its non-existent `body-normal*` utility classes.
144
+ `label` is optional on both Field and Button.
145
+ - The button forwards `inputVariant` (the group components already passed it, but it fell through
146
+ as an attribute). New `itemIcon` prop.
147
+ - Button radius, gap, paddings and the Field label colour became tokens; label colour default moved
148
+ from `--colour-text-default` to `--theme-text`. Removed an undeclared `--_box-shadow` and an
149
+ invalid unitless `min-height`.
@@ -0,0 +1,148 @@
1
+ # MultipleCheckboxes / SingleCheckbox Components
2
+
3
+ ## Overview
4
+
5
+ The `input-checkbox` folder holds two ready-to-use checkbox fields. Each renders a `FormFieldset`
6
+ (with `<legend>`), an optional description, the checkbox control(s), and an `InputError` message,
7
+ with `aria-describedby` wired up via `useAriaDescribedById`.
8
+
9
+ - **MultipleCheckboxes**: a group of checkboxes built from a data list (`v-model:field-data`).
10
+ The model is an array of the checked items' values. Each option renders as either a pill/button
11
+ (`InputCheckboxRadioButton`, `:is-button="true"`) or a plain labelled checkbox
12
+ (`InputCheckboxRadioField`, the default).
13
+ - **SingleCheckbox**: one labelled checkbox (e.g. "I agree to the terms"). The model toggles
14
+ between `trueValue` and `falseValue`.
15
+
16
+ For a group where only one option can be chosen, use `MultipleRadiobuttons` (`input-radio`)
17
+ instead.
18
+
19
+ ---
20
+
21
+ ## MultipleCheckboxes
22
+
23
+ > **Hyphenation rule**: always write camelCase props hyphenated in templates: `:field-has-error`, `:is-button`, `:options-layout`.
24
+
25
+ | Prop (template form) | Type | Default | Notes |
26
+ |---|---|---|---|
27
+ | `name` | `string` | (required) | Shared `name` on every checkbox; also used to build each checkbox `id` (`${name}-${item.value}`) and the error/description ids. |
28
+ | `legend` | `string` | (required) | Fieldset `<legend>` text. |
29
+ | `:error-message` | `string \| object` | (required) | Shown by `InputError` when `fieldHasError` is true. Pass `""` when there's no error. An array renders as a list. |
30
+ | `:field-has-error` | `boolean` | `false` | Shows the error, sets `aria-invalid` on the fieldset and points each checkbox's `aria-describedby` at the error. |
31
+ | `:required` | `boolean` | `false` | No ARIA output: `aria-required` isn't valid on a checkbox group (`role="group"`), so it was dropped from the fieldset 2026-09-26. Signal "required" in the legend text instead (e.g. "Interests (required)"). Native `required` is deliberately **not** put on the individual checkboxes, since that would force every box to be ticked. Validate "at least N selected" in the consuming app. |
32
+ | `:is-button` | `boolean` | `false` | Pill/button presentation (`InputCheckboxRadioButton`) instead of labelled checkboxes. |
33
+ | `:is-pill` | `boolean` | `false` | With `is-button`, fully rounded pills. |
34
+ | `:options-layout` | `OptionsLayout` | `"equal-widths"` | `"equal-widths"` (auto-fit grid, columns sized to the longest label), `"inline"` (wrapping row) or `"block"` (column). Rendered as `data-options-layout` on the items container (was a bare class until 2026-09-27). |
35
+ | `:direction` | `"row" \| "row-reverse"` | `"row"` | Button presentation only: icon/label order. |
36
+ | `:display-as-disc` | `boolean` | `false` | Round checkbox symbol. |
37
+ | `:theme` | `FormUiTheme` | `"default"` | Forwarded to each control. |
38
+ | `:input-variant` | `InputUiVariant` | `"normal"` | Forwarded to each control and the error message. |
39
+ | `:style-class-passthrough` | `string \| string[]` | `[]` | Classes on the root `<fieldset>`. Read once at mount. |
40
+ | `data-testid` | `string` | `"multiple-checkboxes"` | On the root `<fieldset>`. |
41
+ | `label` | `string` | `""` | **Ignored.** Kept only so existing call sites that pass it don't break; it has never rendered. Use `legend` or the description slots. |
42
+
43
+ ### v-models
44
+
45
+ - `v-model`: `(string | number | boolean)[]`, **required**. Bind an array (start with `[]`); checked values are added and removed from it.
46
+ - `v-model:field-data`: `IFormMultipleOptions` (`{ data: IOptionsConfig[]; total; skip; limit }`), **required**. Each `data` item's `value` is the checkbox value and `label` its text.
47
+
48
+ ### Slots
49
+
50
+ | Slot | Notes |
51
+ |---|---|
52
+ | `descriptionText` / `descriptionHtml` | Description under the legend (via `InputDescription`). |
53
+ | `checkedIcon` | Replaces the checked-state icon in every control. |
54
+ | `itemIcon` | Button presentation only: the trailing decorator icon (default `material-symbols:add-2`). |
55
+
56
+ ### Example
57
+
58
+ ```vue
59
+ <MultipleCheckboxes
60
+ v-model="state.services"
61
+ v-model:field-data="servicesData"
62
+ name="services"
63
+ legend="Services of interest"
64
+ :error-message="errors.services"
65
+ :field-has-error="!!errors.services"
66
+ options-layout="inline"
67
+ :is-button="true"
68
+ />
69
+ ```
70
+
71
+ ---
72
+
73
+ ## SingleCheckbox
74
+
75
+ | Prop (template form) | Type | Default | Notes |
76
+ |---|---|---|---|
77
+ | `name` | `string` | (required) | Checkbox `name`; also used for the error/description ids. |
78
+ | `legend` | `string` | (required) | Fieldset `<legend>` text. |
79
+ | `label` | `string` | `""` | Text next to the checkbox. Replaced by the `labelContent` slot when given. |
80
+ | `:error-message` | `string \| object` | (required) | Pass `""` when there's no error. |
81
+ | `:field-has-error` | `boolean` | `false` | Shows the error, sets `aria-invalid` on the fieldset and the checkbox's `aria-describedby`. |
82
+ | `:required` | `boolean` | `false` | Native `required` on the checkbox. (The fieldset no longer gets `aria-required`, see above.) |
83
+ | `:true-value` / `:false-value` | `string \| number \| boolean` | `true` / `false` | Model values for checked/unchecked. |
84
+ | `:options-layout` | `OptionsLayout` | `"equal-widths"` | Rendered as `data-options-layout` on the items container. |
85
+ | `:theme` | `FormUiTheme` | `"default"` | |
86
+ | `:input-variant` | `InputUiVariant` | `"normal"` | |
87
+ | `:style-class-passthrough` | `string \| string[]` | `[]` | Classes on the root `<fieldset>`. Read once at mount. |
88
+ | `data-testid` | `string` | `"single-checkbox"` | On the root `<fieldset>`. |
89
+
90
+ ### v-model
91
+
92
+ - `v-model`: `string | number | boolean`, **required**. Toggles between `trueValue` and `falseValue`. Works with `@update:model-value` for save-on-change settings toggles.
93
+
94
+ ### Slots
95
+
96
+ `descriptionText` / `descriptionHtml`, `checkedIcon`, and `labelContent` (rich label, e.g. a
97
+ terms link).
98
+
99
+ ### Example
100
+
101
+ ```vue
102
+ <SingleCheckbox
103
+ v-model="state.terms"
104
+ name="terms"
105
+ legend="Terms and conditions"
106
+ label="I agree to the terms"
107
+ :required="true"
108
+ :error-message="errors.terms"
109
+ :field-has-error="!!errors.terms"
110
+ />
111
+ ```
112
+
113
+ ---
114
+
115
+ ## CSS token API
116
+
117
+ See [CONSUMER-STYLING.md](../../../app/components/05.forms/input-checkbox/CONSUMER-STYLING.md).
118
+ These components own only the items-container spacing (`--multiple-checkboxes-gap`,
119
+ `--multiple-checkboxes-margin-block-start`, `--single-checkbox-gap`,
120
+ `--single-checkbox-margin-block-start`, `--single-checkbox-column-min-width`). The checkbox
121
+ controls' own colours are the `--input-checkbox-*` tokens in `input-checkbox-radio`.
122
+
123
+ ---
124
+
125
+ ## Migration notes (2026-09-25)
126
+
127
+ Brought to full compliance. Behaviour changes a consumer could notice:
128
+
129
+ - **MultipleCheckboxes no longer puts native `required` on every checkbox.** Previously each box
130
+ got `required`, so a form without `novalidate` would refuse to submit until every option was
131
+ ticked. `InputCheckboxRadioField`/`InputCheckboxRadioButton` now forward `multipleOptions`
132
+ to `InputCheckboxRadio` (they declared it but dropped it), and `MultipleCheckboxes` passes
133
+ `true`.
134
+ - **SingleCheckbox `styleClassPassthrough` now lands on the root `<fieldset>`**, matching
135
+ `MultipleCheckboxes`. It was being applied to the error message.
136
+ - **SingleCheckbox default `data-testid` is now `"single-checkbox"`** (was a copy-paste
137
+ `"multiple-radio-buttons"`).
138
+ - Removed never-used props: `placeholder`, `multipleOptions`, `equalCols` (MultipleCheckboxes);
139
+ `multipleOptions`, `equalCols` (SingleCheckbox). MultipleCheckboxes' `label` became optional
140
+ and stays ignored.
141
+ - Removed SingleCheckbox's dead `watchEffect` that tried to add `mbs-12` to the error message (it
142
+ never reached the DOM, since `InputError` reads its classes once at mount).
143
+ - Both `v-model`s (and `v-model:field-data`) are now `defineModel({ required: true })`.
144
+ - Items-container spacing is now overridable via the public tokens above (defaults unchanged).
145
+
146
+ Fixed 2026-09-26 (FormFieldset migration): the shared `FormFieldset` used to hardcode
147
+ `role="radiogroup"`, so screen readers announced checkbox groups as radio groups. It now defaults
148
+ to the native fieldset `group` role; only `MultipleRadiobuttons` opts into `radiogroup`.
@@ -0,0 +1,102 @@
1
+ # InputDescription Component
2
+
3
+ ## Overview
4
+
5
+ `InputDescription` renders a form field's help text. Every `*Field` wrapper in `05.forms`
6
+ (`InputTextWithLabel`, `InputNumberField`, `InputSelectWithLabel`, `InputTextareaWithLabel`,
7
+ `InputRangeDefault`, `InputTextAsNumberWithLabel`, `SingleCheckbox`, `MultipleCheckboxes`,
8
+ `MultipleRadiobuttons`) already renders one and forwards its own `descriptionText` /
9
+ `descriptionHtml` slots into it, so consumers normally just pass those slots to the wrapper:
10
+
11
+ ```vue
12
+ <InputTextWithLabel v-model="email" name="email" label="Email" :field-has-error :error-message>
13
+ <template #descriptionText>We'll only use this for your booking confirmation</template>
14
+ </InputTextWithLabel>
15
+ ```
16
+
17
+ Use `InputDescription` directly only when building a custom field wrapper.
18
+
19
+ With neither slot provided it renders nothing (no empty element, no dangling id).
20
+
21
+ ---
22
+
23
+ ## Props reference
24
+
25
+ > **Hyphenation rule**: write camelCase props hyphenated in templates: `:description-id`, `:field-has-error`, `:input-variant`, `:style-class-passthrough`.
26
+
27
+ | Prop (template form) | Type | Default | Notes |
28
+ |------|------|---------|-------|
29
+ | `:description-id` | `string` | `""` | Rendered as the root `id`, omitted when empty. Must match the id in the control's `aria-describedby`; wrappers get it from `useAriaDescribedById(...).descriptionId`, which only adds it to `aria-describedby` when a description slot is present. |
30
+ | `:field-has-error` | `boolean` | `false` | Rendered as `data-invalid`. Styling hook only. |
31
+ | `:input-variant` | `"normal" \| "outlined" \| "underlined"` | `"normal"` | Rendered as `data-input-variant`. Styling hook only. |
32
+ | `:style-class-passthrough` | `string \| string[]` | `[]` | Extra classes on the root, reacts to prop changes. |
33
+
34
+ ## Slots
35
+
36
+ | Slot | Rendered in | Notes |
37
+ |------|-------------|-------|
38
+ | `descriptionHtml` | `<div class="input-description-html">` | Rich markup (lists, links). Rendered first. |
39
+ | `descriptionText` | `<p class="input-description-text">` | Plain text only (it's inside a `<p>`, so no block elements). |
40
+
41
+ **Forwarding slots from a wrapper**: only forward a slot when your own consumer provided it,
42
+ otherwise `InputDescription` sees an (empty) slot and renders an empty element:
43
+
44
+ ```vue
45
+ <InputDescription :description-id :input-variant :field-has-error>
46
+ <template v-if="slots.descriptionHtml" #descriptionHtml><slot name="descriptionHtml"></slot></template>
47
+ <template v-if="slots.descriptionText" #descriptionText><slot name="descriptionText"></slot></template>
48
+ </InputDescription>
49
+ ```
50
+
51
+ ---
52
+
53
+ ## Accessibility
54
+
55
+ - It's a plain description, not a live region: link it with `aria-describedby` on the control
56
+ (`useAriaDescribedById` does this in every wrapper).
57
+ - `InputTextWithLabel`, `InputSelectWithLabel` and `InputTextareaWithLabel` render it **after**
58
+ the control for the `outlined` variant and before it otherwise; both positions carry the same id.
59
+
60
+ ---
61
+
62
+ ## Styling
63
+
64
+ Full token table in `app/components/05.forms/input-description/CONSUMER-STYLING.md`. Public
65
+ tokens: `--input-description-color`, `--input-description-font-size`,
66
+ `--input-description-line-height`, `--input-description-slot-margin-block-start|end`,
67
+ `--input-description-slot-margin-inline`; panel tokens on the root (matching `FormFieldset`):
68
+ `--input-description-background-color`, `--input-description-margin-block|inline`,
69
+ `--input-description-padding-block|inline`, `--input-description-border`,
70
+ `--input-description-border-radius`, `--input-description-outline|outline-offset`. For a callout
71
+ look, zero the slot margins and space it with the root margins (example in CONSUMER-STYLING.md). Hooks:
72
+ `data-input-variant`, `data-invalid`.
73
+
74
+
75
+ ---
76
+
77
+ ## History
78
+
79
+ **Migrated 2026-09-26** (1/5 → full compliance):
80
+
81
+ - Wrappers forwarded both description slots unconditionally, so every field rendered an empty
82
+ description element (with its id) even when no description was given. Each wrapper now forwards
83
+ a slot only when its own consumer supplied it.
84
+ - `InputTextWithLabel` and `InputSelectWithLabel` rendered the description **twice** for the
85
+ `outlined` variant (before and after the control); the first copy now has
86
+ `v-if="inputVariant !== 'outlined'"`, matching `InputTextareaWithLabel`.
87
+ - The outlined-variant copies had no `description-id`, so the control's `aria-describedby`
88
+ pointed at an id that didn't exist. They now pass it.
89
+ - Removed props that were never read: `id` (a leftover from a commented-out id computation) and
90
+ `theme`. Wrappers also stopped passing `name`, which wasn't a prop and fell through as an
91
+ invalid `name` attribute on the `<div>`.
92
+ - `inputVariant` and `fieldHasError` (previously accepted but unused) now render as
93
+ `data-input-variant` / `data-invalid` styling hooks.
94
+ - Colour read `--form-description-color`, which was never declared anywhere; replaced by
95
+ `--input-description-color` (defaults to `inherit`, same visual result). Font size, line height
96
+ and margins promoted to public tokens with the old values as defaults.
97
+ - Added root panel tokens (background, margin, padding, border, radius, outline) matching
98
+ `FormFieldset`. Removed `InputLabel`'s `.input-label + .input-description { margin-block-end: 0.2rem }`
99
+ rule, which overrode the root margin token (no visual change by default: the slot's `0.8rem`
100
+ bottom margin collapsed through and won anyway).
101
+ - An empty `descriptionId` no longer renders `id=""`. `styleClassPassthrough` now reacts to prop
102
+ changes.
@@ -0,0 +1,105 @@
1
+ # InputError Component
2
+
3
+ ## Overview
4
+
5
+ `InputError` renders the red error message strip under a form control. Every `*Field` wrapper in
6
+ `05.forms` (`InputTextWithLabel`, `InputNumberField`, `InputSelectWithLabel`, `InputTextareaWithLabel`,
7
+ `InputRangeDefault`, `ToggleSwitchWithLabel`, `SingleCheckbox`, `MultipleCheckboxes`,
8
+ `MultipleRadiobuttons`, `InputTextAsNumberWithLabel`) already renders one, so consumers rarely use
9
+ it directly. Use it yourself only when building a custom field wrapper.
10
+
11
+ It is designed to sit in **grid row 2** of the wrapper, directly under the control in row 1: it is
12
+ translated up by the control's border width + radius so an attached error tucks under the
13
+ control's bottom edge. It opens with a `grid-template-rows: 0fr → 1fr` + opacity transition.
14
+
15
+ Its root carries `data-theme="error"`, so the red `--theme-*` ramp applies inside it regardless of
16
+ the surrounding theme.
17
+
18
+ ---
19
+
20
+ ## Props reference
21
+
22
+ > **Hyphenation rule**: write camelCase props hyphenated in templates: `:error-message`, `:show-error`, `:is-detached`, `:input-variant`, `:style-class-passthrough`.
23
+
24
+ | Prop (template form) | Type | Default | Notes |
25
+ |------|------|---------|-------|
26
+ | `:id` | `string` | (required) | Must match an id in the control's `aria-describedby` while in error. Wrappers get it from `useAriaDescribedById(...).errorId`, which only adds it to `aria-describedby` when `fieldHasError` is true. |
27
+ | `:error-message` | `string \| string[] \| object` | (required) | A string renders as one message; an array renders as a `<ul>` list. |
28
+ | `:show-error` | `boolean` | (required) | Opens the strip. Rendered as `data-visible`; when `false` the root gets `aria-hidden="true"`. |
29
+ | `:is-detached` | `boolean` | (required) | `true`: sits below the control with a `2rem` gap, fully rounded. `false`: tucked under the control's bottom edge. Rendered as `data-detached`. |
30
+ | `:input-variant` | `"normal" \| "outlined" \| "underlined"` | `"normal"` | Match the control's variant. Rendered as `data-input-variant`. `underlined` drops the rounded corners and (when attached) the outline. |
31
+ | `icon` | `string` | `"radix-icons:circle-backslash"` | Iconify name for the decorative icon (`aria-hidden`). |
32
+ | `data-testid` | `string` | `"inputError"` | |
33
+ | `:style-class-passthrough` | `string \| string[]` | `[]` | Extra classes on the root, reacts to prop changes. |
34
+
35
+ No slots.
36
+
37
+ ---
38
+
39
+ ## Usage (inside a custom field wrapper)
40
+
41
+ ```vue
42
+ <template>
43
+ <div class="my-field">
44
+ <input :id :aria-describedby :aria-invalid="fieldHasError" />
45
+ <InputError :id="errorId" :error-message :show-error="fieldHasError" :is-detached="false" :input-variant />
46
+ </div>
47
+ </template>
48
+
49
+ <script setup lang="ts">
50
+ const { id, errorId, ariaDescribedby } = useAriaDescribedById(props.name, toRef(props, "fieldHasError"), useSlots());
51
+ </script>
52
+
53
+ <style>
54
+ .my-field {
55
+ display: grid;
56
+ grid-template-rows: auto auto;
57
+ }
58
+ </style>
59
+ ```
60
+
61
+ ---
62
+
63
+ ## Accessibility
64
+
65
+ - The message is exposed through the control's `aria-describedby`, not a live region, so it's
66
+ read when the control is focused. Moving focus to the first invalid field on submit is the
67
+ form's job (see `FormWrapper` / pattern forms).
68
+ - Hidden errors are `aria-hidden="true"`; the icon is always `aria-hidden`.
69
+ - The open/close transition is disabled under `prefers-reduced-motion: reduce`.
70
+
71
+ ---
72
+
73
+ ## Styling
74
+
75
+ Full token table in `app/components/05.forms/form-errors/CONSUMER-STYLING.md`. Public tokens:
76
+ `--input-error-text-color`, `--input-error-icon-color`, `--input-error-icon-size`,
77
+ `--input-error-background-color`, `--input-error-border-color`, `--input-error-outline-color`,
78
+ `--input-error-border-radius`, `--input-error-font-family|size|weight`,
79
+ `--input-error-padding-inline`, `--input-error-padding-block-start|end`, `--input-error-list-gap`,
80
+ `--input-error-detached-offset`, `--input-error-margin-block-start`,
81
+ `--input-error-transition-duration`.
82
+
83
+ Set them on an ancestor, not the global `--theme-error-*` tokens: the root's `data-theme="error"`
84
+ re-declares those on the element itself, so ancestor overrides of them never land.
85
+
86
+ ---
87
+
88
+ ## History
89
+
90
+ **Migrated 2026-09-26** (1/5 → full compliance):
91
+
92
+ - State moved from bare classes (`.show`, `.detached`, `.normal`/`.outlined`/`.underlined`) to
93
+ `data-visible`, `data-detached`, `data-input-variant`; inner elements renamed from generic
94
+ `.inner`/`.inner-content`/`.inner-icon`/`.icon`/`.message`/`.message-*` to
95
+ `.input-error-message-*`. It renders inline in the consumer's DOM, so those names collided with
96
+ consumer CSS (pitfall #16).
97
+ - Removed the unused `compact` prop (declared, never read, never passed).
98
+ - Added the `icon` prop.
99
+ - Removed dead CSS: detached-state border colours (including a hardcoded `--red-08` bottom border)
100
+ only applied while hidden at `opacity: 0` and were overridden by the visible-state border, and a
101
+ top-level `.underlined` outline rule that the visible state always overrode.
102
+ - Hardcoded `white` on the icon and list items replaced by the text-colour token (same default).
103
+ Hardcoded font size/weight, padding, list gap and detached gap promoted to public tokens.
104
+ - `aria-hidden` now omitted when visible (was `"false"`); icon marked `aria-hidden`;
105
+ `prefers-reduced-motion` respected; `styleClassPassthrough` now reacts to prop changes.
@@ -0,0 +1,119 @@
1
+ # InputLabel Component
2
+
3
+ ## Overview
4
+
5
+ `InputLabel` renders a form field's `<label>`. Every labelled wrapper in `05.forms`
6
+ (`InputTextWithLabel`, `InputTextAsNumberWithLabel`, `InputNumberField`, `InputSelectWithLabel`,
7
+ `InputTextareaWithLabel`, `InputRangeDefault`, `ToggleSwitchWithLabel`,
8
+ `ToggleSwitchWithLabelInline`) already renders one from its `label` prop, so consumers normally
9
+ never use it directly.
10
+
11
+ Use `InputLabel` directly only when building a custom field wrapper:
12
+
13
+ ```vue
14
+ <InputLabel :id="inputId" :input-variant :field-has-error>
15
+ <template #textLabel>{{ label }}</template>
16
+ </InputLabel>
17
+ ```
18
+
19
+ ---
20
+
21
+ ## Props reference
22
+
23
+ > **Hyphenation rule**: write camelCase props hyphenated in templates: `:required-text`, `:optional-icon`, `:field-has-error`, `:input-variant`, `:style-class-passthrough`.
24
+
25
+ | Prop (template form) | Type | Default | Notes |
26
+ |------|------|---------|-------|
27
+ | `:id` | `string` | required | The **control's** id, rendered as the label's `for`. The label itself gets no id. Must match the id actually on the `<input>`/`<select>`/`<textarea>` (e.g. `ToggleSwitchCore` prefixes its input id with `toggle-switch-`, so its wrappers pass `toggleSwitchId`). |
28
+ | `:required` | `boolean` | `false` | Whether the field is required. Only decides which fields the indicator marks; it doesn't set `required` on the control. Wrappers forward their own `required`. |
29
+ | `:indicator` | `"none" \| "required" \| "optional"` | `undefined` → app.config → `"none"` | Which fields get a marker. |
30
+ | `:required-text` | `string` | `undefined` → app.config → `"*"` | Required marker text. |
31
+ | `:optional-text` | `string` | `undefined` → app.config → `"(optional)"` | Optional marker text (translatable). |
32
+ | `:required-icon` | `string` | `undefined` → app.config → none | Iconify name that replaces the required text. |
33
+ | `:optional-icon` | `string` | `undefined` → app.config → none | Iconify name that replaces the visible optional text (the text stays as `.sr-only`). |
34
+ | `:field-has-error` | `boolean` | `false` | Rendered as `data-invalid`. Styling hook only. |
35
+ | `:input-variant` | `"normal" \| "outlined" \| "underlined"` | `"normal"` | Rendered as `data-input-variant`. Styling hook only. |
36
+ | `:style-class-passthrough` | `string \| string[]` | `[]` | Extra classes on the `<label>`, reacts to prop changes. |
37
+
38
+ ## Slots
39
+
40
+ | Slot | Notes |
41
+ |------|-------|
42
+ | `htmlLabel` | Rich markup (e.g. a required marker). Rendered first. Phrasing content only: it's inside a `<label>`, so no interactive elements. |
43
+ | `textLabel` | Plain label text. |
44
+
45
+ Both render directly inside the `<label>`, no wrapper elements. Don't hardcode a required
46
+ asterisk in a slot: use the indicator below.
47
+
48
+ ---
49
+
50
+ ## Required / optional indicator
51
+
52
+ Resolution for every indicator prop: **explicit prop → `app.config` `srcdev.inputLabel.*` → fallback**.
53
+ Consumers normally set it once site-wide and never touch the props:
54
+
55
+ ```ts
56
+ // consumer app.config.ts
57
+ export default defineAppConfig({
58
+ srcdev: { inputLabel: { indicator: "required", requiredIcon: "mdi:asterisk" } },
59
+ });
60
+ ```
61
+
62
+ - `"required"` mode: a marker on fields with `required`; `"optional"` mode: a marker on fields
63
+ without it; `"none"`: nothing (default, so existing sites are unchanged).
64
+ - `InputTextWithLabel`, `InputTextAsNumberWithLabel`, `InputNumberField`, `InputSelectWithLabel`,
65
+ `InputTextareaWithLabel` and `InputRangeDefault` forward `:required`.
66
+ `ToggleSwitchWithLabel`/`ToggleSwitchWithLabelInline` pass `indicator="none"`: a switch always
67
+ has a value, so neither marker means anything there.
68
+ - The wrappers don't expose the indicator props per field; use `app.config`.
69
+ - Text props are the i18n hook: pass translated `optionalText`/`requiredText` (or set them in
70
+ `app.config`).
71
+
72
+ ---
73
+
74
+ ## Accessibility
75
+
76
+ - The `for`/`id` pairing is the accessible name for the control. If the ids don't match, the
77
+ control has no name and clicking the label does nothing; check this whenever the control
78
+ component derives its own id from the one you pass it.
79
+ - The required marker is `aria-hidden`: the control's own `required` attribute is what screen
80
+ readers announce, so the control must actually carry it. The optional marker is announced, and
81
+ keeps its text as `.sr-only` when an icon replaces it.
82
+
83
+ ---
84
+
85
+ ## Styling
86
+
87
+ Full token table in `app/components/05.forms/input-label/CONSUMER-STYLING.md`. Public tokens:
88
+ `--input-label-color` (defaults to `inherit`),
89
+ `--input-label-font-size`, `--input-label-font-weight`, `--input-label-line-height`,
90
+ `--input-label-margin-block`, `--input-label-margin-inline`; indicator:
91
+ `--input-label-indicator-color[-required|-optional]`, `--input-label-indicator-font-size[-required|-optional]`,
92
+ `--input-label-indicator-font-weight`, `--input-label-indicator-gap`, `--input-label-indicator-icon-size`.
93
+ Hooks: `data-input-variant`, `data-invalid`, `.input-label-indicator[data-indicator]`.
94
+
95
+ ---
96
+
97
+ ## History
98
+
99
+ **Migrated 2026-09-26** (1/5 → full compliance):
100
+
101
+ - Removed props that were never read: `name` and `theme`. Wrappers stopped passing them.
102
+ - Wrappers also passed a non-prop `:for`, which fell through and overrode the `for` built from
103
+ `id`. For the text/number/select/textarea/range wrappers it was the same value (dropped). For
104
+ `ToggleSwitchWithLabel`/`ToggleSwitchWithLabelInline` it was the only thing pointing the label
105
+ at the real input (`toggle-switch-<id>`); they now pass `:id="toggleSwitchId"` explicitly.
106
+ - `inputVariant` moved from a bare class (`.normal`/`.underlined`, whose rules were duplicates of
107
+ the base rule) to `data-input-variant`. `fieldHasError` (accepted but unused) now renders
108
+ `data-invalid`.
109
+ - Colour, font size, font weight, line height and margins are public tokens with the old values
110
+ as defaults. The colour used to read `--form-label-color`, never declared in this library;
111
+ replaced by `--input-label-color` (defaults to `inherit`, same visual result).
112
+ - Removed the unused `--field-label-*`, `--field-description-*`, `--field-error-*` and
113
+ `--input-line-height` globals from `04.elements/forms/02.typography.css`, left over from before
114
+ the per-component token pattern.
115
+ - `styleClassPassthrough` now reacts to prop changes.
116
+
117
+ **2026-09-27**: added the required/optional indicator (`required`, `indicator`, `requiredText`,
118
+ `optionalText`, `requiredIcon`, `optionalIcon`, all app.config-backed under `srcdev.inputLabel`),
119
+ with wrappers forwarding `:required`.