srcdev-nuxt-components 9.1.49 → 9.1.51

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 (220) hide show
  1. package/.claude/settings.json +2 -4
  2. package/.claude/settings.local.json +22 -2
  3. package/.claude/skills/components/card-core.md +205 -0
  4. package/.claude/skills/components/display-dialog.md +128 -0
  5. package/.claude/skills/components/page-hero-highlights.md +1 -1
  6. package/.claude/skills/components/page-row.md +157 -0
  7. package/.claude/skills/components/services-card-grid.md +4 -4
  8. package/.claude/skills/components/services-section-grid.md +4 -4
  9. package/.claude/skills/components/tab-navigation.md +222 -0
  10. package/.claude/skills/composable-dialog-controls.md +55 -43
  11. package/.claude/skills/index.md +5 -2
  12. package/app/components/01.atoms/card/CONSUMER-STYLING.md +175 -0
  13. package/app/components/01.atoms/card/CardCore.vue +48 -21
  14. package/app/components/01.atoms/display-dialog/CONSUMER-STYLING.md +163 -0
  15. package/app/components/01.atoms/display-dialog/DisplayDialog.vue +277 -0
  16. package/app/components/01.atoms/display-dialog/stories/DisplayDialog.stories.ts +177 -0
  17. package/app/components/01.atoms/display-dialog/tests/DisplayDialog.spec.ts +264 -0
  18. package/app/components/01.atoms/display-dialog/tests/__snapshots__/DisplayDialog.spec.ts.snap +18 -0
  19. package/app/components/01.atoms/page-row/CONSUMER-STYLING.md +90 -0
  20. package/app/components/01.atoms/page-row/PageRow.vue +115 -0
  21. package/app/components/01.atoms/page-row/stories/PageRow.stories.ts +311 -0
  22. package/app/components/01.atoms/page-row/tests/PageRow.spec.ts +191 -0
  23. package/app/components/02.molecules/navigation/tab-navigation/CONSUMER-STYLING.md +145 -0
  24. package/app/components/02.molecules/navigation/tab-navigation/TabNavigation.vue +20 -9
  25. package/app/components/02.molecules/navigation/tab-navigation/tests/__snapshots__/TabNavigation.spec.ts.snap +12 -6
  26. package/app/components/{forms/ui → 05.forms/form-field}/FormField.vue +12 -19
  27. package/app/components/{forms/ui → 05.forms/form-wrapper}/FormWrapper.vue +6 -6
  28. package/app/components/{forms → 05.forms}/input-button/InputButtonCore.vue +2 -0
  29. package/app/components/{forms → 05.forms}/input-button/stories/InputButtonCore.stories.ts +1 -1
  30. package/app/components/{forms → 05.forms}/input-text/InputTextCore.vue +73 -73
  31. package/app/components/{forms → 05.forms}/input-text/variants/InputTextAsNumberWithLabel.vue +29 -29
  32. package/app/components/carousels/CarouselBasic.vue +99 -99
  33. package/app/components/carousels/CarouselInfinite.vue +150 -150
  34. package/app/components/deep-expanding-menu/DeepExpandingMenu.vue +111 -111
  35. package/app/components/responsive-header/ResponsiveHeader.vue +250 -282
  36. package/app/components/test-storybook/TestStorybook.vue +16 -16
  37. package/app/composables/tests/useDialogControls.spec.ts +34 -64
  38. package/app/composables/useDialogControls.ts +19 -33
  39. package/app/composables/useFormControl.ts +0 -2
  40. package/app/layouts/default.vue +9 -7
  41. package/app/pages/auto-grid.vue +37 -20
  42. package/app/pages/banner-video.vue +2 -2
  43. package/app/pages/forms/examples/buttons/index.vue +189 -215
  44. package/app/pages/forms/examples/material/text-fields.vue +2 -2
  45. package/app/pages/grid-stack.vue +10 -10
  46. package/app/pages/index.vue +20 -20
  47. package/app/pages/samaritan.vue +4 -4
  48. package/app/pages/typography/hero-text.vue +6 -6
  49. package/app/pages/typography/index.vue +4 -4
  50. package/app/pages/typography/page-body.vue +4 -4
  51. package/app/pages/typography/page-heading.vue +4 -4
  52. package/app/pages/typography/page-link.vue +4 -4
  53. package/app/pages/ui/accordian.vue +4 -4
  54. package/app/pages/ui/anchor-scroll-tab-navigation.vue +77 -66
  55. package/app/pages/ui/anchor-scroll.vue +94 -70
  56. package/app/pages/ui/animated-svg-text.vue +4 -4
  57. package/app/pages/ui/block-decorators.vue +11 -11
  58. package/app/pages/ui/card-core.vue +9 -9
  59. package/app/pages/ui/carousel-basic.vue +4 -4
  60. package/app/pages/ui/carousel-flip.vue +2 -2
  61. package/app/pages/ui/carousel-infinite.vue +4 -4
  62. package/app/pages/ui/clipped-panels.vue +10 -10
  63. package/app/pages/ui/contact-section.vue +4 -4
  64. package/app/pages/ui/container-glow.vue +2 -3
  65. package/app/pages/ui/deep-expanding-menu.vue +138 -0
  66. package/app/pages/ui/display-avatar.vue +2 -2
  67. package/app/pages/ui/display-banner.vue +2 -2
  68. package/app/pages/ui/display-chip.vue +32 -25
  69. package/app/pages/ui/display-details.vue +6 -10
  70. package/app/pages/ui/display-dialog.vue +96 -131
  71. package/app/pages/ui/display-pill.vue +27 -33
  72. package/app/pages/ui/display-prompt.vue +4 -4
  73. package/app/pages/ui/display-toast.vue +2 -2
  74. package/app/pages/ui/expanding-panel.vue +12 -16
  75. package/app/pages/ui/glowing-border.vue +12 -12
  76. package/app/pages/ui/layout-grid-a.vue +6 -6
  77. package/app/pages/ui/layout-grid-b.vue +4 -4
  78. package/app/pages/ui/magnetic-navigation.vue +6 -6
  79. package/app/pages/ui/marquee-scroller.vue +2 -2
  80. package/app/pages/ui/mask-element.vue +2 -2
  81. package/app/pages/ui/masonry-columns.vue +4 -4
  82. package/app/pages/ui/masonry-grid-ordered-experiment.vue +4 -4
  83. package/app/pages/ui/masonry-grid-ordered.vue +4 -4
  84. package/app/pages/ui/masonry-grid-sorted.vue +4 -4
  85. package/app/pages/ui/masonry-grid.vue +4 -4
  86. package/app/pages/ui/navigation/navigation-horizontal.vue +12 -12
  87. package/app/pages/ui/navigation/tab-navigation.vue +493 -0
  88. package/app/pages/ui/page-row.vue +127 -0
  89. package/app/pages/ui/price-list.vue +4 -4
  90. package/app/pages/ui/profile-section.vue +4 -4
  91. package/app/pages/ui/qr-code/[componentName].vue +6 -6
  92. package/app/pages/ui/rotating-carousel.vue +16 -16
  93. package/app/pages/ui/scroll-reveal-image.vue +20 -20
  94. package/app/pages/ui/section-parallax.vue +7 -7
  95. package/app/pages/ui/services/colour-finder.vue +4 -4
  96. package/app/pages/ui/services/services-cards.vue +4 -4
  97. package/app/pages/ui/services/services-section/[slug].vue +4 -4
  98. package/app/pages/ui/services/services-sections-compact.vue +6 -6
  99. package/app/pages/ui/settings.vue +10 -10
  100. package/app/pages/ui/simple-grid.vue +2 -2
  101. package/app/pages/ui/slider-gallery.vue +5 -5
  102. package/app/pages/ui/tabs-y.vue +2 -3
  103. package/app/pages/ui/tabs.vue +6 -9
  104. package/app/pages/ui/tooltips.vue +9 -9
  105. package/app/pages/ui/wipe-away-vertical.vue +14 -14
  106. package/package.json +1 -1
  107. package/.claude/skills/components/layout-row.md +0 -239
  108. package/app/components/display-dialog/DisplayDialogCore.vue +0 -276
  109. package/app/components/display-dialog/variants/DisplayDialogConfirm.vue +0 -47
  110. package/app/components/display-dialog/variants/DisplayDialogScrollableContent.vue +0 -51
  111. package/app/components/forms/c12/utils.ts +0 -14
  112. package/app/components/layout-row/LayoutRow.vue +0 -171
  113. package/app/components/layout-row/stories/LayoutRow.stories.ts +0 -528
  114. package/app/pages/ui/layout-row.vue +0 -139
  115. /package/app/components/{forms → 05.forms}/form-errors/InputError.vue +0 -0
  116. /package/app/components/{forms → 05.forms}/form-errors/tests/InputError.spec.ts +0 -0
  117. /package/app/components/{forms → 05.forms}/form-fieldset/FormFieldset.vue +0 -0
  118. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts +0 -0
  119. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-icons-secondary-chromium-darwin.png +0 -0
  120. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-icons-secondary-firefox-darwin.png +0 -0
  121. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-icons-secondary-webkit-darwin.png +0 -0
  122. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-icons-tertiary-chromium-darwin.png +0 -0
  123. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-icons-tertiary-firefox-darwin.png +0 -0
  124. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-icons-tertiary-webkit-darwin.png +0 -0
  125. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-primary-pending-chromium-darwin.png +0 -0
  126. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-primary-pending-firefox-darwin.png +0 -0
  127. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-primary-pending-webkit-darwin.png +0 -0
  128. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-secondary-pill-chromium-darwin.png +0 -0
  129. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-secondary-pill-firefox-darwin.png +0 -0
  130. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-secondary-pill-webkit-darwin.png +0 -0
  131. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-tertiary-readonly-chromium-darwin.png +0 -0
  132. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-tertiary-readonly-firefox-darwin.png +0 -0
  133. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/combo-tertiary-readonly-webkit-darwin.png +0 -0
  134. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/default-chromium-darwin.png +0 -0
  135. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/default-firefox-darwin.png +0 -0
  136. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/default-theme-default-chromium-darwin.png +0 -0
  137. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/default-theme-default-firefox-darwin.png +0 -0
  138. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/default-theme-default-webkit-darwin.png +0 -0
  139. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/default-theme-error-chromium-darwin.png +0 -0
  140. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/default-theme-error-firefox-darwin.png +0 -0
  141. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/default-theme-error-webkit-darwin.png +0 -0
  142. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/default-theme-success-chromium-darwin.png +0 -0
  143. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/default-theme-success-firefox-darwin.png +0 -0
  144. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/default-theme-success-webkit-darwin.png +0 -0
  145. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/default-theme-warning-chromium-darwin.png +0 -0
  146. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/default-theme-warning-firefox-darwin.png +0 -0
  147. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/default-theme-warning-webkit-darwin.png +0 -0
  148. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/default-variant-primary-chromium-darwin.png +0 -0
  149. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/default-variant-primary-firefox-darwin.png +0 -0
  150. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/default-variant-primary-webkit-darwin.png +0 -0
  151. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/default-variant-secondary-chromium-darwin.png +0 -0
  152. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/default-variant-secondary-firefox-darwin.png +0 -0
  153. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/default-variant-secondary-webkit-darwin.png +0 -0
  154. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/default-variant-tertiary-chromium-darwin.png +0 -0
  155. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/default-variant-tertiary-firefox-darwin.png +0 -0
  156. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/default-variant-tertiary-webkit-darwin.png +0 -0
  157. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/default-webkit-darwin.png +0 -0
  158. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/nuxt-icon-only-component-chromium-darwin.png +0 -0
  159. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/nuxt-icon-only-component-firefox-darwin.png +0 -0
  160. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/nuxt-icon-only-component-webkit-darwin.png +0 -0
  161. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/state-pending-chromium-darwin.png +0 -0
  162. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/state-pending-firefox-darwin.png +0 -0
  163. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/state-pending-webkit-darwin.png +0 -0
  164. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/state-pill-chromium-darwin.png +0 -0
  165. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/state-pill-firefox-darwin.png +0 -0
  166. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/state-pill-webkit-darwin.png +0 -0
  167. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/state-readonly-chromium-darwin.png +0 -0
  168. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/state-readonly-firefox-darwin.png +0 -0
  169. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/state-readonly-webkit-darwin.png +0 -0
  170. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/with-both-nuxt-icon-components-chromium-darwin.png +0 -0
  171. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/with-both-nuxt-icon-components-firefox-darwin.png +0 -0
  172. /package/app/components/{forms → 05.forms}/input-button/playwright/input-button-core.playwright.ts-snapshots/with-both-nuxt-icon-components-webkit-darwin.png +0 -0
  173. /package/app/components/{forms → 05.forms}/input-button/tests/InputButtonCore.spec.ts +0 -0
  174. /package/app/components/{forms → 05.forms}/input-button/tests/__snapshots__/InputButtonCore.spec.ts.snap +0 -0
  175. /package/app/components/{forms → 05.forms}/input-checkbox/MultipleCheckboxes.vue +0 -0
  176. /package/app/components/{forms → 05.forms}/input-checkbox/SingleCheckbox.vue +0 -0
  177. /package/app/components/{forms → 05.forms}/input-checkbox/tests/MultipleCheckboxes.spec.ts +0 -0
  178. /package/app/components/{forms → 05.forms}/input-checkbox/tests/data/tags.json +0 -0
  179. /package/app/components/{forms → 05.forms}/input-checkbox-radio/InputCheckboxRadioButton.vue +0 -0
  180. /package/app/components/{forms → 05.forms}/input-checkbox-radio/InputCheckboxRadioCore.vue +0 -0
  181. /package/app/components/{forms → 05.forms}/input-checkbox-radio/InputCheckboxRadioWithLabel.vue +0 -0
  182. /package/app/components/{forms → 05.forms}/input-checkbox-radio/tests/InputCheckboxRadioCore.spec.ts +0 -0
  183. /package/app/components/{forms → 05.forms}/input-copy/InputCopyCore.vue +0 -0
  184. /package/app/components/{forms → 05.forms}/input-copy/stories/InputCopyCore.stories.ts +0 -0
  185. /package/app/components/{forms → 05.forms}/input-copy/tests/InputCopyCore.spec.ts +0 -0
  186. /package/app/components/{forms → 05.forms}/input-copy/tests/__snapshots__/InputCopyCore.spec.ts.snap +0 -0
  187. /package/app/components/{forms → 05.forms}/input-description/InputDescription.vue +0 -0
  188. /package/app/components/{forms → 05.forms}/input-description/tests/InputDescription.spec.ts +0 -0
  189. /package/app/components/{forms → 05.forms}/input-label/InputLabel.vue +0 -0
  190. /package/app/components/{forms → 05.forms}/input-label/tests/InputLabel.spec.ts +0 -0
  191. /package/app/components/{forms → 05.forms}/input-number/InputNumberCore.vue +0 -0
  192. /package/app/components/{forms → 05.forms}/input-number/variants/InputNumberDefault.vue +0 -0
  193. /package/app/components/{forms → 05.forms}/input-radio/MultipleRadiobuttons.vue +0 -0
  194. /package/app/components/{forms → 05.forms}/input-radio/tests/MultipleRadioButtons.spec.ts +0 -0
  195. /package/app/components/{forms → 05.forms}/input-radio/tests/data/tags.json +0 -0
  196. /package/app/components/{forms → 05.forms}/input-range/InputRangeCore.vue +0 -0
  197. /package/app/components/{forms → 05.forms}/input-range/variants/InputRangeDefault.vue +0 -0
  198. /package/app/components/{forms → 05.forms}/input-range-fancy/InputRangeFancyCore.vue +0 -0
  199. /package/app/components/{forms → 05.forms}/input-range-fancy/InputRangeFancyWithLabel.vue +0 -0
  200. /package/app/components/{forms → 05.forms}/input-select/InputSelectCore.vue +0 -0
  201. /package/app/components/{forms → 05.forms}/input-select/variants/InputSelectWithLabel.vue +0 -0
  202. /package/app/components/{forms → 05.forms}/input-text/stories/InputPasswordWithLabel.stories.ts +0 -0
  203. /package/app/components/{forms → 05.forms}/input-text/stories/InputTextAsNumberWithLabel.stories.ts +0 -0
  204. /package/app/components/{forms → 05.forms}/input-text/stories/InputTextCore.stories.ts +0 -0
  205. /package/app/components/{forms → 05.forms}/input-text/stories/InputTextWithLabel.stories.ts +0 -0
  206. /package/app/components/{forms → 05.forms}/input-text/variants/InputPasswordWithLabel.vue +0 -0
  207. /package/app/components/{forms → 05.forms}/input-text/variants/InputTextWithLabel.vue +0 -0
  208. /package/app/components/{forms → 05.forms}/input-textarea/InputTextareaCore.vue +0 -0
  209. /package/app/components/{forms → 05.forms}/input-textarea/stories/InputTextareaCore.stories.ts +0 -0
  210. /package/app/components/{forms → 05.forms}/input-textarea/stories/InputTextareaWithLabel.stories.ts +0 -0
  211. /package/app/components/{forms → 05.forms}/input-textarea/variants/InputTextareaWithLabel.vue +0 -0
  212. /package/app/components/{forms → 05.forms}/pending-effect/PendingEffect.vue +0 -0
  213. /package/app/components/{forms → 05.forms}/toggle-switch/ToggleSwitchCore.vue +0 -0
  214. /package/app/components/{forms → 05.forms}/toggle-switch/stories/ToggleSwitchCore.stories.ts +0 -0
  215. /package/app/components/{forms → 05.forms}/toggle-switch/stories/ToggleSwitchWithLabel.stories.ts +0 -0
  216. /package/app/components/{forms → 05.forms}/toggle-switch/stories/ToggleSwitchWithLabelInline.stories.ts +0 -0
  217. /package/app/components/{forms → 05.forms}/toggle-switch/variants/ToggleSwitchWithLabel.vue +0 -0
  218. /package/app/components/{forms → 05.forms}/toggle-switch/variants/ToggleSwitchWithLabelInline.vue +0 -0
  219. /package/app/components/{forms → 05.forms}/triple-toggle-switch/TripleToggleSwitchCore.vue +0 -0
  220. /package/app/{components/forms/c12/prop-validators/index.ts → utils/prop-validators.ts} +0 -0
@@ -0,0 +1,493 @@
1
+ <template>
2
+ <div>
3
+ <NuxtLayout name="default">
4
+ <template #layout-content>
5
+ <PageRow tag="div" variant="popout">
6
+ <h1 class="page-heading-2">TabNavigation</h1>
7
+
8
+ <!-- ── QA Panel (dev only) ───────────────────────────────── -->
9
+ <div v-if="isDev" class="qa-panel">
10
+ <details class="qa-panel__details" open>
11
+ <summary class="qa-panel__summary">
12
+ <span class="qa-panel__title">QA — TabNavigation</span>
13
+ <code class="qa-panel__status">
14
+ align:{{ navAlign }} · size:{{ qaLinkSize }}rem · gap:{{ qaGap }}rem ·
15
+ dur:{{ qaTransitionDuration }}ms
16
+ </code>
17
+ </summary>
18
+ <div class="qa-panel__body">
19
+ <!-- Props -->
20
+ <div class="qa-panel__group qa-panel__group--full">
21
+ <span class="qa-panel__section">Props</span>
22
+ </div>
23
+
24
+ <div class="qa-panel__group">
25
+ <span class="qa-panel__label">nav-align</span>
26
+ <div class="qa-panel__chips">
27
+ <button
28
+ v-for="a in ['left', 'center', 'right']"
29
+ :key="a"
30
+ class="qa-panel__chip"
31
+ :class="{ 'is-active': navAlign === a }"
32
+ @click="navAlign = a as 'left' | 'center' | 'right'"
33
+ >
34
+ {{ a }}
35
+ </button>
36
+ </div>
37
+ </div>
38
+
39
+ <div class="qa-panel__group">
40
+ <span class="qa-panel__label">container width</span>
41
+ <div class="qa-panel__chips">
42
+ <button
43
+ class="qa-panel__chip"
44
+ :class="{ 'is-active': !isNarrow }"
45
+ @click="isNarrow = false"
46
+ >
47
+ full
48
+ </button>
49
+ <button
50
+ class="qa-panel__chip"
51
+ :class="{ 'is-active': isNarrow }"
52
+ @click="isNarrow = true"
53
+ >
54
+ narrow (burger)
55
+ </button>
56
+ </div>
57
+ </div>
58
+
59
+ <!-- Link tokens -->
60
+ <div class="qa-panel__group qa-panel__group--full">
61
+ <span class="qa-panel__section">Link tokens</span>
62
+ </div>
63
+
64
+ <div class="qa-panel__group">
65
+ <span class="qa-panel__label">link-color</span>
66
+ <input v-model="qaLinkColor" type="color" class="qa-panel__color" />
67
+ </div>
68
+
69
+ <div class="qa-panel__group">
70
+ <span class="qa-panel__label">link-hover-color</span>
71
+ <input v-model="qaLinkHoverColor" type="color" class="qa-panel__color" />
72
+ </div>
73
+
74
+ <div class="qa-panel__group">
75
+ <span class="qa-panel__label">link-active-color</span>
76
+ <input v-model="qaLinkActiveColor" type="color" class="qa-panel__color" />
77
+ </div>
78
+
79
+ <div class="qa-panel__group">
80
+ <span class="qa-panel__label">link-size — {{ qaLinkSize }}rem</span>
81
+ <input
82
+ v-model.number="qaLinkSize"
83
+ type="range"
84
+ min="1.2"
85
+ max="2.4"
86
+ step="0.1"
87
+ class="qa-panel__range"
88
+ />
89
+ </div>
90
+
91
+ <div class="qa-panel__group">
92
+ <span class="qa-panel__label">link-weight</span>
93
+ <div class="qa-panel__chips">
94
+ <button
95
+ v-for="w in [300, 400, 500, 600]"
96
+ :key="w"
97
+ class="qa-panel__chip"
98
+ :class="{ 'is-active': qaLinkWeight === w }"
99
+ @click="qaLinkWeight = w"
100
+ >
101
+ {{ w }}
102
+ </button>
103
+ </div>
104
+ </div>
105
+
106
+ <div class="qa-panel__group">
107
+ <span class="qa-panel__label">link-tracking — {{ qaLinkTracking }}em</span>
108
+ <input
109
+ v-model.number="qaLinkTracking"
110
+ type="range"
111
+ min="0"
112
+ max="0.2"
113
+ step="0.01"
114
+ class="qa-panel__range"
115
+ />
116
+ </div>
117
+
118
+ <div class="qa-panel__group">
119
+ <span class="qa-panel__label">gap — {{ qaGap }}rem</span>
120
+ <input
121
+ v-model.number="qaGap"
122
+ type="range"
123
+ min="0.5"
124
+ max="5"
125
+ step="0.1"
126
+ class="qa-panel__range"
127
+ />
128
+ </div>
129
+
130
+ <div class="qa-panel__group">
131
+ <span class="qa-panel__label">transition — {{ qaTransitionDuration }}ms</span>
132
+ <input
133
+ v-model.number="qaTransitionDuration"
134
+ type="range"
135
+ min="0"
136
+ max="800"
137
+ step="25"
138
+ class="qa-panel__range"
139
+ />
140
+ </div>
141
+
142
+ <!-- Indicator tokens -->
143
+ <div class="qa-panel__group qa-panel__group--full">
144
+ <span class="qa-panel__section">Indicator tokens</span>
145
+ </div>
146
+
147
+ <div class="qa-panel__group">
148
+ <span class="qa-panel__label">indicator-color</span>
149
+ <input v-model="qaIndicatorColor" type="color" class="qa-panel__color" />
150
+ </div>
151
+
152
+ <div class="qa-panel__group">
153
+ <span class="qa-panel__label">hovered-bg color</span>
154
+ <input v-model="qaHoveredBgColor" type="color" class="qa-panel__color" />
155
+ </div>
156
+
157
+ <div class="qa-panel__group">
158
+ <span class="qa-panel__label">hovered-bg opacity — {{ qaHoveredBgOpacity }}</span>
159
+ <input
160
+ v-model.number="qaHoveredBgOpacity"
161
+ type="range"
162
+ min="0"
163
+ max="1"
164
+ step="0.05"
165
+ class="qa-panel__range"
166
+ />
167
+ </div>
168
+
169
+ <!-- Panel tokens -->
170
+ <div class="qa-panel__group qa-panel__group--full">
171
+ <span class="qa-panel__section">Panel tokens (visible in narrow mode)</span>
172
+ </div>
173
+
174
+ <div class="qa-panel__group">
175
+ <span class="qa-panel__label">panel-bg</span>
176
+ <input v-model="qaPanelBg" type="color" class="qa-panel__color" />
177
+ </div>
178
+
179
+ <div class="qa-panel__group">
180
+ <span class="qa-panel__label">panel-link-color</span>
181
+ <input v-model="qaPanelLinkColor" type="color" class="qa-panel__color" />
182
+ </div>
183
+
184
+ <div class="qa-panel__group">
185
+ <span class="qa-panel__label">panel-slide-duration — {{ qaPanelSlideDuration }}ms</span>
186
+ <input
187
+ v-model.number="qaPanelSlideDuration"
188
+ type="range"
189
+ min="0"
190
+ max="800"
191
+ step="25"
192
+ class="qa-panel__range"
193
+ />
194
+ </div>
195
+
196
+ <!-- Burger tokens -->
197
+ <div class="qa-panel__group qa-panel__group--full">
198
+ <span class="qa-panel__section">Burger tokens (visible in narrow mode)</span>
199
+ </div>
200
+
201
+ <div class="qa-panel__group">
202
+ <span class="qa-panel__label">burger-color</span>
203
+ <input v-model="qaBurgerColor" type="color" class="qa-panel__color" />
204
+ </div>
205
+
206
+ <div class="qa-panel__group">
207
+ <span class="qa-panel__label">burger-width — {{ qaBurgerWidth }}px</span>
208
+ <input
209
+ v-model.number="qaBurgerWidth"
210
+ type="range"
211
+ min="14"
212
+ max="36"
213
+ step="1"
214
+ class="qa-panel__range"
215
+ />
216
+ </div>
217
+
218
+ <div class="qa-panel__group">
219
+ <span class="qa-panel__label">burger-gap — {{ qaBurgerGap }}px</span>
220
+ <input
221
+ v-model.number="qaBurgerGap"
222
+ type="range"
223
+ min="2"
224
+ max="12"
225
+ step="1"
226
+ class="qa-panel__range"
227
+ />
228
+ </div>
229
+ </div>
230
+ </details>
231
+ </div>
232
+
233
+ <!-- ── Component stage ───────────────────────────────────── -->
234
+ <div class="tab-nav-demo-stage" :class="{ 'is-narrow': isNarrow }" :style="tokenStyles">
235
+ <TabNavigation :nav-item-data="navData" :nav-align="navAlign" />
236
+ </div>
237
+ </PageRow>
238
+ </template>
239
+ </NuxtLayout>
240
+ </div>
241
+ </template>
242
+
243
+ <script setup lang="ts">
244
+ import type { NavItemData } from "~/types/components";
245
+
246
+ definePageMeta({ layout: false });
247
+ useHead({
248
+ title: "TabNavigation — Component Demo",
249
+ bodyAttrs: { class: "tab-nav-demo-page" },
250
+ });
251
+
252
+ const isDev = import.meta.dev;
253
+
254
+ // ── Props ──────────────────────────────────────────────────────────────────
255
+ const navAlign = ref<"left" | "center" | "right">("left");
256
+ const isNarrow = ref(false);
257
+
258
+ // ── Link tokens ────────────────────────────────────────────────────────────
259
+ const qaLinkColor = ref("#e8e8e8");
260
+ const qaLinkHoverColor = ref("#999999");
261
+ const qaLinkActiveColor = ref("#e8e8e8");
262
+ const qaLinkSize = ref(1.6);
263
+ const qaLinkWeight = ref(400);
264
+ const qaLinkTracking = ref(0.06);
265
+ const qaGap = ref(2.2);
266
+ const qaTransitionDuration = ref(250);
267
+
268
+ // ── Indicator tokens ───────────────────────────────────────────────────────
269
+ const qaIndicatorColor = ref("#e8e8e8");
270
+ const qaHoveredBgColor = ref("#ffffff");
271
+ const qaHoveredBgOpacity = ref(0.08);
272
+
273
+ // ── Panel tokens ───────────────────────────────────────────────────────────
274
+ const qaPanelBg = ref("#1a1614");
275
+ const qaPanelLinkColor = ref("#e8e8e8");
276
+ const qaPanelSlideDuration = ref(350);
277
+
278
+ // ── Burger tokens ──────────────────────────────────────────────────────────
279
+ const qaBurgerColor = ref("#e8e8e8");
280
+ const qaBurgerWidth = ref(22);
281
+ const qaBurgerGap = ref(5);
282
+
283
+ function hexToRgbParts(hex: string) {
284
+ const r = parseInt(hex.slice(1, 3), 16);
285
+ const g = parseInt(hex.slice(3, 5), 16);
286
+ const b = parseInt(hex.slice(5, 7), 16);
287
+ return `${r} ${g} ${b}`;
288
+ }
289
+
290
+ const tokenStyles = computed(() => ({
291
+ "--tab-nav-link-color": qaLinkColor.value,
292
+ "--tab-nav-link-hover-color": qaLinkHoverColor.value,
293
+ "--tab-nav-link-active-color": qaLinkActiveColor.value,
294
+ "--tab-nav-link-size": `${qaLinkSize.value}rem`,
295
+ "--tab-nav-link-weight": String(qaLinkWeight.value),
296
+ "--tab-nav-link-tracking": `${qaLinkTracking.value}em`,
297
+ "--tab-nav-gap": `${qaGap.value}rem`,
298
+ "--tab-nav-transition": `${qaTransitionDuration.value}ms ease`,
299
+ "--tab-nav-decorator-indicator-color": qaIndicatorColor.value,
300
+ "--tab-nav-decorator-hovered-bg": `rgb(${hexToRgbParts(qaHoveredBgColor.value)} / ${qaHoveredBgOpacity.value})`,
301
+ "--tab-nav-panel-bg": qaPanelBg.value,
302
+ "--tab-nav-panel-link-color": qaPanelLinkColor.value,
303
+ "--tab-nav-panel-slide-duration": `${qaPanelSlideDuration.value}ms`,
304
+ "--tab-nav-burger-color": qaBurgerColor.value,
305
+ "--tab-nav-burger-width": `${qaBurgerWidth.value}px`,
306
+ "--tab-nav-burger-gap": `${qaBurgerGap.value}px`,
307
+ }));
308
+
309
+ const navData: NavItemData = {
310
+ main: [
311
+ { text: "Components", href: "/ui/anchor-scroll" },
312
+ { text: "Layouts", href: "/ui/page-row" },
313
+ { text: "Forms", href: "/forms/examples/buttons" },
314
+ { text: "Typography", href: "/typography/hero-text" },
315
+ ],
316
+ };
317
+ </script>
318
+
319
+ <style lang="css">
320
+ .tab-nav-demo-page {
321
+ .tab-nav-demo-stage {
322
+ margin-block-start: 2rem;
323
+ border: 1px solid oklch(100% 0 0 / 12%);
324
+ border-radius: 0.8rem;
325
+ padding: 2rem;
326
+ background-color: oklch(100% 0 0 / 3%);
327
+ position: relative;
328
+ transition: max-inline-size 0.3s ease;
329
+
330
+ &.is-narrow {
331
+ max-inline-size: 260px;
332
+ overflow: hidden;
333
+ }
334
+ }
335
+
336
+ .qa-panel {
337
+ background: oklch(15% 0 0);
338
+ color: white;
339
+ font-size: 1.3rem;
340
+ margin-block-start: 2rem;
341
+ border-radius: 0.6rem;
342
+ overflow: hidden;
343
+ }
344
+
345
+ .qa-panel__details {
346
+ padding: 1rem 2rem;
347
+ }
348
+
349
+ .qa-panel__summary {
350
+ cursor: pointer;
351
+ display: flex;
352
+ align-items: center;
353
+ gap: 1.6rem;
354
+ list-style: none;
355
+ user-select: none;
356
+
357
+ &::-webkit-details-marker {
358
+ display: none;
359
+ }
360
+ }
361
+
362
+ .qa-panel__title {
363
+ font-weight: 600;
364
+ font-size: 1.1rem;
365
+ text-transform: uppercase;
366
+ letter-spacing: 0.08em;
367
+ }
368
+
369
+ .qa-panel__status {
370
+ font-family: monospace;
371
+ font-size: 1.2rem;
372
+ background: oklch(0% 0 0 / 0.3);
373
+ padding: 0.2rem 0.8rem;
374
+ border-radius: 0.4rem;
375
+ user-select: text;
376
+ cursor: text;
377
+ }
378
+
379
+ .qa-panel__body {
380
+ display: flex;
381
+ flex-wrap: wrap;
382
+ gap: 2.4rem;
383
+ padding-block: 1.2rem 1.6rem;
384
+ }
385
+
386
+ .qa-panel__group {
387
+ display: flex;
388
+ flex-direction: column;
389
+ gap: 0.6rem;
390
+
391
+ &.qa-panel__group--full {
392
+ flex-basis: 100%;
393
+ margin-block-start: 0.8rem;
394
+ padding-block-end: 0.4rem;
395
+ border-block-end: 1px solid oklch(100% 0 0 / 0.1);
396
+
397
+ &:first-child {
398
+ margin-block-start: 0;
399
+ }
400
+ }
401
+ }
402
+
403
+ .qa-panel__section {
404
+ font-size: 1.1rem;
405
+ font-weight: 600;
406
+ text-transform: uppercase;
407
+ letter-spacing: 0.1em;
408
+ color: oklch(65% 0.18 240);
409
+ }
410
+
411
+ .qa-panel__label {
412
+ font-size: 1.1rem;
413
+ text-transform: uppercase;
414
+ letter-spacing: 0.08em;
415
+ opacity: 0.55;
416
+ }
417
+
418
+ .qa-panel__chips {
419
+ display: flex;
420
+ flex-wrap: wrap;
421
+ gap: 0.4rem;
422
+ }
423
+
424
+ .qa-panel__chip {
425
+ font-family: monospace;
426
+ font-size: 1.2rem;
427
+ color: white;
428
+ background: oklch(0% 0 0 / 0.25);
429
+ border: 1px solid oklch(100% 0 0 / 0.18);
430
+ padding: 0.3rem 1rem;
431
+ border-radius: 0.4rem;
432
+ cursor: pointer;
433
+ transition: background 0.15s;
434
+
435
+ &:hover {
436
+ background: oklch(0% 0 0 / 0.4);
437
+ }
438
+
439
+ &.is-active {
440
+ background: oklch(55% 0.18 240);
441
+ border-color: oklch(55% 0.18 240);
442
+ }
443
+ }
444
+
445
+ .qa-panel__range {
446
+ appearance: none;
447
+ width: 18rem;
448
+ height: 0.4rem;
449
+ background: oklch(100% 0 0 / 0.18);
450
+ border-radius: 0.4rem;
451
+ outline: none;
452
+ cursor: pointer;
453
+
454
+ &::-webkit-slider-thumb {
455
+ appearance: none;
456
+ width: 1.4rem;
457
+ height: 1.4rem;
458
+ border-radius: 50%;
459
+ background: oklch(55% 0.18 240);
460
+ cursor: pointer;
461
+ transition: background 0.15s;
462
+ }
463
+
464
+ &::-moz-range-thumb {
465
+ width: 1.4rem;
466
+ height: 1.4rem;
467
+ border: none;
468
+ border-radius: 50%;
469
+ background: oklch(55% 0.18 240);
470
+ cursor: pointer;
471
+ transition: background 0.15s;
472
+ }
473
+
474
+ &:hover::-webkit-slider-thumb {
475
+ background: oklch(62% 0.18 240);
476
+ }
477
+
478
+ &:hover::-moz-range-thumb {
479
+ background: oklch(62% 0.18 240);
480
+ }
481
+ }
482
+
483
+ .qa-panel__color {
484
+ width: 4rem;
485
+ height: 2.8rem;
486
+ border: 1px solid oklch(100% 0 0 / 0.18);
487
+ border-radius: 0.4rem;
488
+ background: none;
489
+ cursor: pointer;
490
+ padding: 0.2rem;
491
+ }
492
+ }
493
+ </style>
@@ -0,0 +1,127 @@
1
+ <template>
2
+ <div>
3
+ <NuxtLayout name="default">
4
+ <template #layout-content>
5
+ <PageRow :style-class-passthrough="['mbe-4']">
6
+ <h1 class="page-heading-2">PageRow</h1>
7
+ <p>
8
+ Each
9
+ <code>PageRow</code>
10
+ is both a CSS grid container and a grid item. All direct children default to the
11
+ <strong>content</strong>
12
+ column (max 1064px). Nest a
13
+ <code>PageRow</code>
14
+ with a different
15
+ <code>variant</code>
16
+ to break out to a wider or narrower track.
17
+ </p>
18
+ </PageRow>
19
+
20
+ <!-- Direct content — defaults to content column -->
21
+ <PageRow tag="section" :style-class-passthrough="['mbe-20']">
22
+ <h2 class="page-heading-2">Default — content column</h2>
23
+ <pre>variant="content" (default)</pre>
24
+ <p>
25
+ Lorem ipsum odor amet, consectetuer adipiscing elit. Nec elementum maecenas placerat laoreet curae elit
26
+ convallis himenaeos. Tellus varius cursus convallis commodo suspendisse litora.
27
+ </p>
28
+ </PageRow>
29
+
30
+ <!-- Nesting: full-width background, constrained content -->
31
+ <PageRow
32
+ tag="section"
33
+ variant="full"
34
+ :style-class-passthrough="['mbe-20']"
35
+ style="background: #1e3a5f; color: white; padding-block: 4rem"
36
+ >
37
+ <h2 class="page-heading-2">Full-width background with constrained content</h2>
38
+ <pre style="color: #93c5fd">Outer: variant="full" — Inner: default content column</pre>
39
+ <p>
40
+ Wrap a
41
+ <code style="color: #93c5fd">PageRow</code>
42
+ in another with
43
+ <code style="color: #93c5fd">variant="full"</code>
44
+ to get a full-width background while keeping text in the content column. No extra wrapper divs required.
45
+ </p>
46
+ </PageRow>
47
+
48
+ <!-- Popout -->
49
+ <PageRow tag="section" :style-class-passthrough="['mbe-20']">
50
+ <PageRow variant="popout" :style-class-passthrough="['mbe-4']">
51
+ <h2 class="page-heading-2">Popout track (max 1400px)</h2>
52
+ <pre>variant="popout"</pre>
53
+ <p>
54
+ Lorem ipsum odor amet, consectetuer adipiscing elit. Nec elementum maecenas placerat laoreet curae elit
55
+ convallis himenaeos. Tellus varius cursus convallis commodo.
56
+ </p>
57
+ </PageRow>
58
+ </PageRow>
59
+
60
+ <!-- Inset content -->
61
+ <PageRow tag="section" :style-class-passthrough="['mbe-20']">
62
+ <PageRow variant="inset-content">
63
+ <h2 class="page-heading-2">Inset content track (max 840px)</h2>
64
+ <pre>variant="inset-content"</pre>
65
+ <p>
66
+ Lorem ipsum odor amet, consectetuer adipiscing elit. Nec elementum maecenas placerat laoreet curae elit
67
+ convallis himenaeos. Tellus varius cursus convallis commodo.
68
+ </p>
69
+ </PageRow>
70
+ </PageRow>
71
+
72
+ <!-- Mixed nesting: multiple tracks in one section -->
73
+ <PageRow
74
+ tag="section"
75
+ variant="full"
76
+ :style-class-passthrough="['mbe-20']"
77
+ style="background: #f00000; padding-block: 4rem"
78
+ >
79
+ <h2 class="page-heading-2">Mixed nesting</h2>
80
+ <p>Content column (default) alongside sibling rows at other tracks.</p>
81
+
82
+ <PageRow
83
+ variant="popout"
84
+ style="background: #00fc11; padding: 2rem; border-radius: 0.6rem; margin-block: 2rem"
85
+ >
86
+ <p>Popout sibling (max 1400px)</p>
87
+ </PageRow>
88
+
89
+ <PageRow variant="inset-content">
90
+ <p style="font-style: italic">Inset content sibling (max 840px) — ideal for pull-quotes or callouts.</p>
91
+ </PageRow>
92
+ </PageRow>
93
+
94
+ <!-- Semantic tags + landmark -->
95
+ <PageRow tag="section" is-landmark :style-class-passthrough="['mbe-20']">
96
+ <h2 class="page-heading-2">Semantic tag + landmark</h2>
97
+ <pre>tag="section" :is-landmark="true"</pre>
98
+ <p>
99
+ Any semantic HTML element is supported via the
100
+ <code>tag</code>
101
+ prop. Enabling
102
+ <code>isLandmark</code>
103
+ adds
104
+ <code>tabindex="0"</code>
105
+ and
106
+ <code>aria-label="Page Row"</code>
107
+ .
108
+ </p>
109
+ </PageRow>
110
+ </template>
111
+ </NuxtLayout>
112
+ </div>
113
+ </template>
114
+
115
+ <script setup lang="ts">
116
+ definePageMeta({
117
+ layout: false,
118
+ });
119
+
120
+ useHead({
121
+ title: "UI PageRow",
122
+ meta: [{ name: "description", content: "Examples of the PageRow layout component" }],
123
+ bodyAttrs: {
124
+ class: "home",
125
+ },
126
+ });
127
+ </script>
@@ -2,7 +2,7 @@
2
2
  <div>
3
3
  <NuxtLayout name="default">
4
4
  <template #layout-content>
5
- <LayoutRow tag="div" variant="content" :style-class-passthrough="['mbe-20']">
5
+ <PageRow tag="div" variant="content" :style-class-passthrough="['mbe-20']">
6
6
  <HeroText
7
7
  :tag="'h1'"
8
8
  font-size="display"
@@ -10,11 +10,11 @@
10
10
  :style-class-passthrough="['mbe-20']"
11
11
  />
12
12
  <p class="page-body-normal">Example of a services card grid component.</p>
13
- </LayoutRow>
13
+ </PageRow>
14
14
 
15
- <LayoutRow tag="div" variant="content" :style-class-passthrough="['mbe-20']">
15
+ <PageRow tag="div" variant="content" :style-class-passthrough="['mbe-20']">
16
16
  <PriceList :price-list-data="priceListData" :style-class-passthrough="['mbe-20']" />
17
- </LayoutRow>
17
+ </PageRow>
18
18
  </template>
19
19
  </NuxtLayout>
20
20
  </div>
@@ -2,11 +2,11 @@
2
2
  <div>
3
3
  <NuxtLayout name="default">
4
4
  <template #layout-content>
5
- <LayoutRow tag="div" variant="content" :style-class-passthrough="['mbe-20']">
5
+ <PageRow tag="div" variant="content" :style-class-passthrough="['mbe-20']">
6
6
  <h2 class="page-heading-2">Profile Section</h2>
7
- </LayoutRow>
7
+ </PageRow>
8
8
 
9
- <LayoutRow tag="div" variant="content" :style-class-passthrough="['mbe-20']">
9
+ <PageRow tag="div" variant="content" :style-class-passthrough="['mbe-20']">
10
10
  <ProfileSection
11
11
  :profile-picture="{
12
12
  src: '/images/services/service-balayage.jpg',
@@ -107,7 +107,7 @@
107
107
  </InputButtonCore>
108
108
  </template>
109
109
  </ProfileSection>
110
- </LayoutRow>
110
+ </PageRow>
111
111
  </template>
112
112
  </NuxtLayout>
113
113
  </div>