srcdev-nuxt-components 9.0.15 → 9.0.17

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 (112) hide show
  1. package/.claude/settings.json +25 -0
  2. package/.claude/skills/component-aria-landmark.md +68 -0
  3. package/.claude/skills/component-dynamic-slots.md +150 -0
  4. package/.claude/skills/component-export-types.md +61 -0
  5. package/.claude/skills/component-local-style-override.md +126 -0
  6. package/.claude/skills/component-prop-driven-container-layout.md +42 -0
  7. package/.claude/skills/components/accordian-core.md +159 -0
  8. package/.claude/skills/components/contact-section.md +101 -0
  9. package/.claude/skills/components/expanding-panel.md +156 -0
  10. package/.claude/skills/components/eyebrow-text.md +25 -0
  11. package/.claude/skills/components/hero-text.md +25 -0
  12. package/.claude/skills/components/layout-grid-by-cols.md +147 -0
  13. package/.claude/skills/components/layout-row.md +35 -0
  14. package/.claude/skills/components/link-text.md +33 -0
  15. package/.claude/skills/components/page-hero-highlights.md +224 -0
  16. package/.claude/skills/components/services-card.md +28 -0
  17. package/.claude/skills/components/services-section.md +25 -0
  18. package/.claude/skills/components/stepper-list.md +227 -0
  19. package/.claude/skills/css-grid-max-width-gutters.md +67 -0
  20. package/.claude/skills/index.md +15 -3
  21. package/.claude/skills/storybook-add-story.md +60 -0
  22. package/.claude/skills/testing-add-unit-test.md +56 -0
  23. package/app/assets/styles/setup/01.config/index.css +0 -1
  24. package/app/assets/styles/setup/03.theming/default/_dark.css +2 -2
  25. package/app/assets/styles/setup/04.elements/forms/02.typography.css +1 -0
  26. package/app/assets/styles/setup/05.typography/02.utility-classes/_font-classes-page-link.css +14 -14
  27. package/app/assets/styles/setup/index.css +0 -1
  28. package/app/components/01.atoms/card/CardCore.vue +92 -0
  29. package/app/components/01.atoms/card/stories/CardCore.stories.ts +132 -0
  30. package/app/components/01.atoms/card/tests/CardCore.spec.ts +207 -0
  31. package/app/components/01.atoms/card/tests/__snapshots__/CardCore.spec.ts.snap +43 -0
  32. package/app/components/01.atoms/content-wrappers/content-columns-2/ContentColumns2.vue +51 -0
  33. package/app/components/01.atoms/content-wrappers/content-columns-2/stories/ContentColumns2.stories.ts +110 -0
  34. package/app/components/01.atoms/content-wrappers/content-columns-2/tests/ContentColumns2.spec.ts +105 -0
  35. package/app/components/01.atoms/content-wrappers/content-columns-2/tests/__snapshots__/ContentColumns2.spec.ts.snap +14 -0
  36. package/app/components/01.atoms/content-wrappers/content-width/ContentWidth.vue +88 -0
  37. package/app/components/01.atoms/content-wrappers/content-width/stories/ContentWidth.stories.ts +362 -0
  38. package/app/components/01.atoms/content-wrappers/content-width/tests/ContentWidth.spec.ts +132 -0
  39. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/LayoutGridByCols.vue +71 -0
  40. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/stories/LayoutGridByCols.stories.ts +219 -0
  41. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/tests/LayoutGridByCols.spec.ts +174 -0
  42. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/tests/__snapshots__/LayoutGrid.spec.ts.snap +36 -0
  43. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-cols/tests/__snapshots__/LayoutGridByCols.spec.ts.snap +36 -0
  44. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/LayoutGridByWidth.vue +70 -0
  45. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/stories/LayoutGridByWidth.stories.ts +220 -0
  46. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/tests/LayoutGridByWidth.spec.ts +174 -0
  47. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/tests/__snapshots__/LayoutGrid.spec.ts.snap +36 -0
  48. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/tests/__snapshots__/LayoutGridByCols.spec.ts.snap +36 -0
  49. package/app/components/01.atoms/content-wrappers/layout-grid/layout-grid-by-width/tests/__snapshots__/LayoutGridByWidth.spec.ts.snap +36 -0
  50. package/app/components/01.atoms/text-blocks/eyebrow-text/stories/EyebrowText.stories.ts +1 -1
  51. package/app/components/01.atoms/text-blocks/hero-text/stories/HeroText.stories.ts +1 -1
  52. package/app/components/01.atoms/text-blocks/link-text/stories/LinkText.stories.ts +1 -1
  53. package/app/components/02.molecules/contact-section/stories/ContactSection.stories.ts +5 -0
  54. package/app/components/02.molecules/contact-section/tests/ContactSection.spec.ts +15 -0
  55. package/app/components/02.molecules/contact-section/tests/ContactSection.vue +25 -17
  56. package/app/components/{accordian → 02.molecules/expandable/accordian}/stories/AccordianCore.stories.ts +1 -1
  57. package/app/components/02.molecules/expandable/expanding-panel/stories/ExpandingPanel.stories.ts +245 -0
  58. package/app/components/02.molecules/expandable/expanding-panel/tests/ExpandingPanel.spec.ts +351 -0
  59. package/app/components/02.molecules/expandable/expanding-panel/tests/__snapshots__/ExpandingPanel.spec.ts.snap +38 -0
  60. package/app/components/02.molecules/navigation/navigation-horizontal/NavigationHorizontal.vue +162 -0
  61. package/app/components/02.molecules/navigation/navigation-horizontal/stories/NavigationHorizontal.stories.ts +373 -0
  62. package/app/components/02.molecules/navigation/navigation-horizontal/tests/NavigationHorizontal.spec.ts +152 -0
  63. package/app/components/02.molecules/navigation/navigation-horizontal/tests/__snapshots__/NavigationHorizontal.spec.ts.snap +17 -0
  64. package/app/components/02.molecules/profile-section/ProfileSection.vue +2 -3
  65. package/app/components/02.molecules/profile-section/tests/ProfileSection.spec.ts +2 -2
  66. package/app/components/02.molecules/stepper-list/StepperList.vue +131 -92
  67. package/app/components/02.molecules/stepper-list/stories/StepperList.stories.ts +31 -0
  68. package/app/components/02.molecules/stepper-list/tests/StepperList.spec.ts +24 -0
  69. package/app/components/02.molecules/stepper-list/tests/__snapshots__/StepperList.spec.ts.snap +22 -9
  70. package/app/components/03.organisms/image-galleries/slider-gallery/SliderGallery.vue +782 -0
  71. package/app/components/03.organisms/image-galleries/slider-gallery/stories/SliderGallery.stories.ts +233 -0
  72. package/app/components/03.organisms/image-galleries/slider-gallery/tests/SliderGallery.spec.ts +226 -0
  73. package/app/components/03.organisms/image-galleries/slider-gallery/tests/__snapshots__/SliderGallery.spec.ts.snap +69 -0
  74. package/app/components/03.organisms/services/services-grids/ServicesCardGrid.vue +1 -1
  75. package/app/components/03.organisms/services/services-grids/ServicesSectionGrid.vue +1 -1
  76. package/app/components/03.organisms/services/services-section/ServicesSection.vue +2 -3
  77. package/app/components/04.templates/page-hero-highlights/PageHeroHighlights.vue +239 -0
  78. package/app/components/04.templates/page-hero-highlights/stories/PageHeroHighlights.stories.ts +404 -0
  79. package/app/components/04.templates/page-hero-highlights/tests/PageHeroHighlights.spec.ts +198 -0
  80. package/app/components/04.templates/page-hero-highlights/tests/__snapshots__/PageHeroHighlights.spec.ts.snap +19 -0
  81. package/app/components/container-glow/ContainerGlowCore.vue +20 -27
  82. package/app/components/forms/input-button/InputButtonCore.vue +105 -104
  83. package/app/components/glowing-border/stories/GlowingBorder.stories.ts +21 -21
  84. package/app/composables/useAriaLabelledById.ts +13 -0
  85. package/app/layouts/default.vue +8 -3
  86. package/app/pages/forms/examples/buttons/index.vue +6 -6
  87. package/app/pages/forms/examples/material/checkbox-radio-panels.vue +3 -3
  88. package/app/pages/forms/examples/material/text-fields.vue +607 -610
  89. package/app/pages/page-hero-highlights.vue +81 -0
  90. package/app/pages/ui/{display-card.vue → card-core.vue} +15 -15
  91. package/app/pages/ui/contact-section.vue +1 -1
  92. package/app/pages/ui/container-glow.vue +1 -1
  93. package/app/pages/ui/content-width.vue +126 -0
  94. package/app/pages/ui/glowing-border.vue +9 -9
  95. package/app/pages/ui/navigation/navigation-horizontal.vue +484 -0
  96. package/app/pages/ui/services/services-section/[slug].vue +3 -1
  97. package/app/types/components/index.ts +1 -0
  98. package/app/types/components/navigation-horizontal.d.ts +11 -0
  99. package/package.json +2 -2
  100. package/app/assets/styles/setup/01.config/_basic-resets.css +0 -9
  101. package/app/components/content-columns/TwoColumns.vue +0 -59
  102. package/app/components/content-columns/stories/TwoColumns.stories.ts +0 -561
  103. package/app/components/content-containers/ContentContainer.vue +0 -89
  104. package/app/components/content-containers/stories/ContentContainer.stories.ts +0 -465
  105. package/app/components/content-grid/ContentGrid.vue +0 -85
  106. package/app/components/display-card/DisplayCard.vue +0 -122
  107. package/app/components/image-galleries/SliderGallery.vue +0 -786
  108. package/app/pages/ui/content-container.vue +0 -112
  109. /package/app/components/{accordian → 02.molecules/expandable/accordian}/AccordianCore.vue +0 -0
  110. /package/app/components/{accordian → 02.molecules/expandable/accordian}/tests/AccordianCore.spec.ts +0 -0
  111. /package/app/components/{accordian → 02.molecules/expandable/accordian}/tests/__snapshots__/AccordianCore.spec.ts.snap +0 -0
  112. /package/app/components/{expanding-panel → 02.molecules/expandable/expanding-panel}/ExpandingPanel.vue +0 -0
@@ -0,0 +1,484 @@
1
+ <template>
2
+ <div>
3
+ <NuxtLayout name="default">
4
+ <template #layout-content>
5
+ <LayoutRow tag="div" variant="content" :style-class-passthrough="['mbe-20']">
6
+ <h2 class="page-heading-2">Navigation Horizontal</h2>
7
+ <p class="page-body-medium">This navigation has a reflective glow effect</p>
8
+ </LayoutRow>
9
+
10
+ <LayoutRow tag="div" variant="content" :style-class-passthrough="['mbe-20']">
11
+ <DisplayThemeSwitch />
12
+ </LayoutRow>
13
+
14
+ <LayoutRow tag="div" variant="full-width" :style-class-passthrough="['mbe-4']">
15
+ <LayoutRow tag="div" variant="content">
16
+ <h3 class="page-heading-3">User controllable</h3>
17
+ </LayoutRow>
18
+ <div class="nav-preview" :class="`theme-${theme}`" :style="navStyle">
19
+ <NavigationHorizontal :nav-item-data="navItemData" />
20
+ </div>
21
+ </LayoutRow>
22
+
23
+ <LayoutRow tag="div" variant="content" :style-class-passthrough="['mbe-20']">
24
+ <div class="nav-playground">
25
+ <fieldset>
26
+ <legend>Theme</legend>
27
+ <div class="control-row">
28
+ <label>Light / Dark</label>
29
+ <div class="theme-toggle">
30
+ <button :class="{ active: theme === 'light' }" @click="setTheme('light')">Light</button>
31
+ <button :class="{ active: theme === 'dark' }" @click="setTheme('dark')">Dark</button>
32
+ </div>
33
+ </div>
34
+ </fieldset>
35
+
36
+ <fieldset>
37
+ <legend>Colours</legend>
38
+ <div class="control-row">
39
+ <label for="active-colour">Active / glow colour</label>
40
+ <input id="active-colour" v-model="controls.activeColour" type="color" />
41
+ </div>
42
+ <div class="control-row">
43
+ <label for="link-colour">Link text colour</label>
44
+ <input id="link-colour" v-model="controls.linkColour" type="color" />
45
+ </div>
46
+ <div class="control-row">
47
+ <label for="link-bg">Link background</label>
48
+ <input id="link-bg" v-model="controls.linkBg" type="color" />
49
+ </div>
50
+ <div class="control-row">
51
+ <label for="border-colour">Border colour</label>
52
+ <input id="border-colour" v-model="controls.borderColour" type="color" />
53
+ </div>
54
+ <div class="control-row">
55
+ <label for="border-opacity">Border opacity — {{ controls.borderOpacity }}</label>
56
+ <input
57
+ id="border-opacity"
58
+ v-model.number="controls.borderOpacity"
59
+ type="range"
60
+ min="0"
61
+ max="1"
62
+ step="0.05"
63
+ />
64
+ </div>
65
+ </fieldset>
66
+
67
+ <fieldset>
68
+ <legend>Borders</legend>
69
+ <div class="control-row">
70
+ <label for="border-start">Border top — {{ controls.borderStart }}px</label>
71
+ <input id="border-start" v-model.number="controls.borderStart" type="range" min="0" max="10" step="1" />
72
+ </div>
73
+ <div class="control-row">
74
+ <label for="border-end">Border bottom — {{ controls.borderEnd }}px</label>
75
+ <input id="border-end" v-model.number="controls.borderEnd" type="range" min="0" max="10" step="1" />
76
+ </div>
77
+ </fieldset>
78
+
79
+ <fieldset>
80
+ <legend>Layout</legend>
81
+ <div class="control-row">
82
+ <label for="list-padding">List padding — {{ controls.listPadding }}rem</label>
83
+ <input
84
+ id="list-padding"
85
+ v-model.number="controls.listPadding"
86
+ type="range"
87
+ min="0"
88
+ max="6"
89
+ step="0.5"
90
+ />
91
+ </div>
92
+ <div class="control-row">
93
+ <label for="list-gap">List gap — {{ controls.listGap }}rem</label>
94
+ <input id="list-gap" v-model.number="controls.listGap" type="range" min="0" max="10" step="0.25" />
95
+ </div>
96
+ <div class="control-row">
97
+ <label for="link-padding-block">Link vertical padding — {{ controls.linkPaddingBlock }}rem</label>
98
+ <input
99
+ id="link-padding-block"
100
+ v-model.number="controls.linkPaddingBlock"
101
+ type="range"
102
+ min="0"
103
+ max="2"
104
+ step="0.1"
105
+ />
106
+ </div>
107
+ <div class="control-row">
108
+ <label for="link-padding-inline">Link horizontal padding — {{ controls.linkPaddingInline }}rem</label>
109
+ <input
110
+ id="link-padding-inline"
111
+ v-model.number="controls.linkPaddingInline"
112
+ type="range"
113
+ min="0"
114
+ max="3"
115
+ step="0.1"
116
+ />
117
+ </div>
118
+ <div class="control-row">
119
+ <label for="link-border-radius">Link border radius — {{ controls.linkBorderRadius }}rem</label>
120
+ <input
121
+ id="link-border-radius"
122
+ v-model.number="controls.linkBorderRadius"
123
+ type="range"
124
+ min="0"
125
+ max="2"
126
+ step="0.1"
127
+ />
128
+ </div>
129
+ </fieldset>
130
+
131
+ <fieldset>
132
+ <legend>Glow Effect</legend>
133
+ <div class="control-row">
134
+ <label for="glow-pos-x">Origin X — {{ controls.glowPosX }}%</label>
135
+ <input id="glow-pos-x" v-model.number="controls.glowPosX" type="range" min="-100" max="100" step="1" />
136
+ </div>
137
+ <div class="control-row">
138
+ <label for="glow-pos-y">Origin Y — {{ controls.glowPosY }}%</label>
139
+ <input id="glow-pos-y" v-model.number="controls.glowPosY" type="range" min="-100" max="200" step="1" />
140
+ </div>
141
+ <div class="control-row">
142
+ <label for="glow-inner-stop">Inner gradient stop — {{ controls.glowInnerStop }}%</label>
143
+ <input
144
+ id="glow-inner-stop"
145
+ v-model.number="controls.glowInnerStop"
146
+ type="range"
147
+ min="0"
148
+ max="50"
149
+ step="1"
150
+ />
151
+ </div>
152
+ <div class="control-row">
153
+ <label for="glow-outer-stop">Outer gradient stop — {{ controls.glowOuterStop }}%</label>
154
+ <input
155
+ id="glow-outer-stop"
156
+ v-model.number="controls.glowOuterStop"
157
+ type="range"
158
+ min="50"
159
+ max="100"
160
+ step="1"
161
+ />
162
+ </div>
163
+ <div class="control-row">
164
+ <label for="glow-size">Glow spread — {{ controls.glowSize }}px</label>
165
+ <input id="glow-size" v-model.number="controls.glowSize" type="range" min="0" max="100" step="1" />
166
+ </div>
167
+ <div class="control-row">
168
+ <label for="glow-opacity">Glow opacity — {{ controls.glowOpacity }}</label>
169
+ <input
170
+ id="glow-opacity"
171
+ v-model.number="controls.glowOpacity"
172
+ type="range"
173
+ min="0"
174
+ max="1"
175
+ step="0.05"
176
+ />
177
+ </div>
178
+ <div class="control-row">
179
+ <label for="anchor-offset">Anchor spread — {{ controls.anchorOffset }}px</label>
180
+ <input
181
+ id="anchor-offset"
182
+ v-model.number="controls.anchorOffset"
183
+ type="range"
184
+ min="0"
185
+ max="100"
186
+ step="1"
187
+ />
188
+ </div>
189
+ </fieldset>
190
+
191
+ <fieldset>
192
+ <legend>Animation</legend>
193
+ <div class="control-row">
194
+ <label for="transition-duration">Transition — {{ controls.transitionDuration }}ms</label>
195
+ <input
196
+ id="transition-duration"
197
+ v-model.number="controls.transitionDuration"
198
+ type="range"
199
+ min="0"
200
+ max="1000"
201
+ step="50"
202
+ />
203
+ </div>
204
+ </fieldset>
205
+ </div>
206
+ </LayoutRow>
207
+
208
+ <LayoutRow tag="div" variant="content" :style-class-passthrough="['mbe-20']">
209
+ <div class="css-snippet">
210
+ <div class="css-snippet-header">
211
+ <h3 class="page-heading-3">CSS Token Snippet</h3>
212
+ <button class="copy-btn" @click="copySnippet">{{ copied ? "Copied!" : "Copy" }}</button>
213
+ </div>
214
+ <pre class="css-snippet-code">{{ cssSnippet }}</pre>
215
+ </div>
216
+ </LayoutRow>
217
+ </template>
218
+ </NuxtLayout>
219
+ </div>
220
+ </template>
221
+
222
+ <script setup lang="ts">
223
+ import type { NavItemData } from "~/types/components/navigation-horizontal.d";
224
+ definePageMeta({
225
+ layout: false,
226
+ });
227
+
228
+ useHead({
229
+ title: "Navigation Horizontal",
230
+ meta: [
231
+ {
232
+ name: "description",
233
+ content: "Navigation Horizontal Meta description content",
234
+ },
235
+ ],
236
+ bodyAttrs: {
237
+ class: "navigation-horizontal-page",
238
+ },
239
+ });
240
+
241
+ const navItemData: NavItemData = {
242
+ main: [
243
+ { text: "Home", href: "#", isExternal: true, iconName: "home", cssName: "home-link" },
244
+ { text: "About", href: "#", isExternal: true, iconName: "info", cssName: "about-link" },
245
+ { text: "Services", href: "#", isExternal: true, iconName: "services", cssName: "services-link" },
246
+ { text: "Contact", href: "#", isExternal: true, iconName: "contact", cssName: "contact-link" },
247
+ ],
248
+ };
249
+
250
+ type Theme = "light" | "dark";
251
+
252
+ const themeDefaults: Record<
253
+ Theme,
254
+ { linkColour: string; linkBg: string; borderColour: string; borderOpacity: number }
255
+ > = {
256
+ dark: { linkColour: "#ffffff", linkBg: "#333333", borderColour: "#ffffff", borderOpacity: 0.2 },
257
+ light: { linkColour: "#1a1a1a", linkBg: "#e8e8e8", borderColour: "#000000", borderOpacity: 0.15 },
258
+ };
259
+
260
+ const theme = ref<Theme>("dark");
261
+
262
+ const controls = reactive({
263
+ activeColour: "#00ff00",
264
+ linkColour: themeDefaults.dark.linkColour,
265
+ linkBg: themeDefaults.dark.linkBg,
266
+ borderColour: themeDefaults.dark.borderColour,
267
+ borderOpacity: themeDefaults.dark.borderOpacity,
268
+ borderStart: 0,
269
+ borderEnd: 3,
270
+ listPadding: 2,
271
+ listGap: 3,
272
+ linkPaddingBlock: 0.5,
273
+ linkPaddingInline: 1,
274
+ linkBorderRadius: 0.2,
275
+ glowPosX: 50,
276
+ glowPosY: 100,
277
+ glowInnerStop: 10,
278
+ glowOuterStop: 75,
279
+ glowSize: 32,
280
+ glowOpacity: 0.5,
281
+ anchorOffset: 40,
282
+ transitionDuration: 300,
283
+ });
284
+
285
+ const setTheme = (newTheme: Theme) => {
286
+ theme.value = newTheme;
287
+ const defaults = themeDefaults[newTheme];
288
+ controls.linkColour = defaults.linkColour;
289
+ controls.linkBg = defaults.linkBg;
290
+ controls.borderColour = defaults.borderColour;
291
+ controls.borderOpacity = defaults.borderOpacity;
292
+ };
293
+
294
+ const cssSnippet = computed(() => {
295
+ const borderColour = `color-mix(in srgb, ${controls.borderColour} ${Math.round(controls.borderOpacity * 100)}%, transparent)`;
296
+ return `.your-selector {
297
+ /* Colours */
298
+ --nav-active-colour: ${controls.activeColour};
299
+ --nav-link-colour: ${controls.linkColour};
300
+ --nav-link-bg: ${controls.linkBg};
301
+ --nav-border-colour: ${borderColour};
302
+
303
+ /* Borders */
304
+ --nav-border-start: ${controls.borderStart}px;
305
+ --nav-border-end: ${controls.borderEnd}px;
306
+
307
+ /* Layout */
308
+ --nav-list-padding: ${controls.listPadding}rem;
309
+ --nav-list-gap: ${controls.listGap}rem;
310
+ --nav-link-padding-block: ${controls.linkPaddingBlock}rem;
311
+ --nav-link-padding-inline: ${controls.linkPaddingInline}rem;
312
+ --nav-link-border-radius: ${controls.linkBorderRadius}rem;
313
+
314
+ /* Glow effect */
315
+ --nav-glow-pos-x: ${controls.glowPosX}%;
316
+ --nav-glow-pos-y: ${controls.glowPosY}%;
317
+ --nav-glow-inner-stop: ${controls.glowInnerStop}%;
318
+ --nav-glow-outer-stop: ${controls.glowOuterStop}%;
319
+ --nav-glow-size: ${controls.glowSize}px;
320
+ --nav-glow-opacity: ${controls.glowOpacity};
321
+ --nav-anchor-offset: ${controls.anchorOffset}px;
322
+
323
+ /* Animation */
324
+ --nav-transition-duration: ${controls.transitionDuration}ms;
325
+ }`;
326
+ });
327
+
328
+ const copied = ref(false);
329
+ const copySnippet = async () => {
330
+ await navigator.clipboard.writeText(cssSnippet.value);
331
+ copied.value = true;
332
+ setTimeout(() => {
333
+ copied.value = false;
334
+ }, 2000);
335
+ };
336
+
337
+ const navStyle = computed(() => ({
338
+ "--nav-active-colour": controls.activeColour,
339
+ "--nav-link-colour": controls.linkColour,
340
+ "--nav-link-bg": controls.linkBg,
341
+ "--nav-border-colour": `color-mix(in srgb, ${controls.borderColour} ${Math.round(controls.borderOpacity * 100)}%, transparent)`,
342
+ "--nav-border-start": `${controls.borderStart}px`,
343
+ "--nav-border-end": `${controls.borderEnd}px`,
344
+ "--nav-list-padding": `${controls.listPadding}rem`,
345
+ "--nav-list-gap": `${controls.listGap}rem`,
346
+ "--nav-link-padding-block": `${controls.linkPaddingBlock}rem`,
347
+ "--nav-link-padding-inline": `${controls.linkPaddingInline}rem`,
348
+ "--nav-link-border-radius": `${controls.linkBorderRadius}rem`,
349
+ "--nav-glow-pos-x": `${controls.glowPosX}%`,
350
+ "--nav-glow-pos-y": `${controls.glowPosY}%`,
351
+ "--nav-glow-inner-stop": `${controls.glowInnerStop}%`,
352
+ "--nav-glow-outer-stop": `${controls.glowOuterStop}%`,
353
+ "--nav-glow-size": `${controls.glowSize}px`,
354
+ "--nav-glow-opacity": String(controls.glowOpacity),
355
+ "--nav-anchor-offset": `${controls.anchorOffset}px`,
356
+ "--nav-transition-duration": `${controls.transitionDuration}ms`,
357
+ "color-scheme": theme.value,
358
+ }));
359
+ </script>
360
+
361
+ <style lang="css">
362
+ .navigation-horizontal-page {
363
+ .nav-preview {
364
+ padding: 4rem 0;
365
+ transition: background 300ms;
366
+
367
+ &.theme-dark {
368
+ --page-bg: hsl(0 0% 8%);
369
+ /* background: var(--page-bg); */
370
+ }
371
+
372
+ &.theme-light {
373
+ --page-bg: hsl(0 0% 95%);
374
+ /* background: var(--page-bg); */
375
+ }
376
+ }
377
+
378
+ .nav-playground {
379
+ display: grid;
380
+ grid-template-columns: repeat(auto-fit, minmax(30rem, 1fr));
381
+ gap: 2rem;
382
+ padding-block: 2rem;
383
+
384
+ fieldset {
385
+ border: 1px solid light-dark(var(--slate-04), var(--slate-06));
386
+ border-radius: 0.4rem;
387
+ padding: 1.6rem;
388
+
389
+ legend {
390
+ font-weight: bold;
391
+ padding: 0 0.8rem;
392
+ font-size: 1.4rem;
393
+ }
394
+
395
+ .control-row {
396
+ display: grid;
397
+ grid-template-columns: 1fr 14rem;
398
+ gap: 1rem;
399
+ align-items: center;
400
+ padding: 0.5rem 0;
401
+
402
+ label {
403
+ font-size: 1.3rem;
404
+ }
405
+
406
+ input[type="range"] {
407
+ width: 100%;
408
+ cursor: pointer;
409
+ }
410
+
411
+ input[type="color"] {
412
+ height: 3.2rem;
413
+ width: 100%;
414
+ padding: 0.2rem;
415
+ border: 1px solid light-dark(var(--slate-04), var(--slate-06));
416
+ border-radius: 0.2rem;
417
+ cursor: pointer;
418
+ background: transparent;
419
+ }
420
+ }
421
+ }
422
+
423
+ .theme-toggle {
424
+ display: flex;
425
+ gap: 0.4rem;
426
+
427
+ button {
428
+ padding: 0.4rem 1.6rem;
429
+ border: 1px solid light-dark(var(--slate-05), var(--slate-06));
430
+ border-radius: 0.2rem;
431
+ cursor: pointer;
432
+ background: transparent;
433
+ font-size: 1.3rem;
434
+ color: inherit;
435
+
436
+ &.active {
437
+ background: light-dark(var(--slate-03), var(--slate-07));
438
+ font-weight: bold;
439
+ }
440
+ }
441
+ }
442
+ }
443
+
444
+ .css-snippet {
445
+ border: 1px solid light-dark(var(--slate-04), var(--slate-06));
446
+ border-radius: 0.4rem;
447
+ overflow: hidden;
448
+
449
+ .css-snippet-header {
450
+ display: flex;
451
+ justify-content: space-between;
452
+ align-items: center;
453
+ padding: 1rem 1.6rem;
454
+ border-block-end: 1px solid light-dark(var(--slate-04), var(--slate-06));
455
+ /* background: light-dark(var(--slate-02), var(--slate-08)); */
456
+ }
457
+
458
+ .css-snippet-code {
459
+ margin: 0;
460
+ padding: 1.6rem;
461
+ font-family: monospace;
462
+ font-size: 1.3rem;
463
+ line-height: 1.6;
464
+ overflow-x: auto;
465
+ white-space: pre;
466
+ /* background: light-dark(var(--slate-01), var(--slate-09)); */
467
+ }
468
+
469
+ .copy-btn {
470
+ padding: 0.4rem 1.2rem;
471
+ border: 1px solid light-dark(var(--slate-05), var(--slate-06));
472
+ border-radius: 0.2rem;
473
+ cursor: pointer;
474
+ background: transparent;
475
+ font-size: 1.3rem;
476
+ color: inherit;
477
+
478
+ &:hover {
479
+ background: light-dark(var(--slate-03), var(--slate-07));
480
+ }
481
+ }
482
+ }
483
+ }
484
+ </style>
@@ -17,7 +17,9 @@
17
17
  :style-class-passthrough="['mb-20']"
18
18
  />
19
19
 
20
- <p class="page-body-normal"><NuxtLink to="/ui/services/services-cards">Back to Services</NuxtLink></p>
20
+ <p class="page-body-normal">
21
+ <NuxtLink to="/ui/services/services-cards" class="page-link-normal">Back to Services</NuxtLink>
22
+ </p>
21
23
  </LayoutRow>
22
24
 
23
25
  <LayoutRow tag="div" variant="content" :style-class-passthrough="['mbe-20']">
@@ -9,3 +9,4 @@ export * from "./display-toast.d"
9
9
  export * from "./qr-code.d"
10
10
  export * from "./alert-mask-core.d"
11
11
  export * from "./hero-text"
12
+ export * from "./navigation-horizontal.d"
@@ -0,0 +1,11 @@
1
+ export interface NavItem {
2
+ text: string;
3
+ href?: string;
4
+ isExternal?: boolean;
5
+ iconName?: string;
6
+ cssName?: string;
7
+ }
8
+
9
+ export interface NavItemData {
10
+ [key: string]: NavItem[];
11
+ }
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "srcdev-nuxt-components",
3
3
  "type": "module",
4
- "version": "9.0.15",
4
+ "version": "9.0.17",
5
5
  "main": "nuxt.config.ts",
6
6
  "types": "types.d.ts",
7
7
  "license": "MIT",
8
8
  "engines": {
9
- "node": ">=20.19.0",
9
+ "node": ">=20.19.0 <23",
10
10
  "npm": ">=10.0.0"
11
11
  },
12
12
  "scripts": {
@@ -1,9 +0,0 @@
1
- /**
2
- Reset list elements
3
- */
4
- ul,
5
- ol {
6
- padding: 0;
7
- margin: 0;
8
- list-style: none;
9
- }
@@ -1,59 +0,0 @@
1
- <template>
2
- <component
3
- :is="props.tag"
4
- class="two-column-layout-container"
5
- :class="[elementClasses]"
6
- :data-testid="props.dataTestid"
7
- >
8
- <div class="two-column-layout">
9
- <div v-if="slots.col1" class="col-1">
10
- <slot name="col1"></slot>
11
- </div>
12
- <div v-if="slots.col2" class="col-2">
13
- <slot name="col2"></slot>
14
- </div>
15
- </div>
16
- </component>
17
- </template>
18
-
19
- <script setup lang="ts">
20
- const props = defineProps({
21
- dataTestid: {
22
- type: String,
23
- default: "two-column-layout",
24
- },
25
- tag: {
26
- type: String,
27
- default: "div",
28
- validator(value: string) {
29
- return ["div", "section", "article", "aside", "header", "footer", "main", "nav"].includes(value);
30
- },
31
- },
32
- styleClassPassthrough: {
33
- type: [String, Array] as PropType<string | string[]>,
34
- default: () => [],
35
- },
36
- });
37
- const slots = useSlots();
38
- const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
39
- </script>
40
-
41
- <style lang="css">
42
- @layer components {
43
- .two-column-layout-container {
44
- container-type: inline-size;
45
- container-name: two-column-layout;
46
-
47
- .two-column-layout {
48
- display: grid;
49
- justify-content: start;
50
- grid-auto-flow: row;
51
- gap: 32px;
52
-
53
- @container two-column-layout (width >= 1064px) {
54
- grid-template-columns: repeat(2, 1fr);
55
- }
56
- }
57
- }
58
- }
59
- </style>