srcdev-nuxt-components 6.0.0 → 6.0.1

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 (81) hide show
  1. package/README.md +2 -2
  2. package/app/assets/styles/extends-layer/srcdev-components/components/_display-prompt-core.css +72 -0
  3. package/app/assets/styles/extends-layer/srcdev-components/components/index.css +1 -0
  4. package/app/assets/styles/extends-layer/srcdev-components/index.css +2 -0
  5. package/app/assets/styles/extends-layer/srcdev-components/setup/index.css +1 -0
  6. package/app/assets/styles/extends-layer/srcdev-components/setup/themes/_error.css +15 -0
  7. package/app/assets/styles/extends-layer/srcdev-components/setup/themes/_info.css +15 -0
  8. package/app/assets/styles/extends-layer/srcdev-components/setup/themes/_secondary.css +15 -0
  9. package/app/assets/styles/extends-layer/srcdev-components/setup/themes/_success.css +15 -0
  10. package/app/assets/styles/extends-layer/srcdev-components/setup/themes/_warning.css +15 -0
  11. package/app/assets/styles/extends-layer/srcdev-components/setup/themes/index.css +5 -0
  12. package/app/assets/styles/main.css +2 -0
  13. package/app/assets/styles/setup/_head.css +36 -0
  14. package/app/assets/styles/setup/a11y/_utils.css +20 -0
  15. package/app/assets/styles/setup/a11y/_variables.css +8 -0
  16. package/app/assets/styles/setup/a11y/index.css +2 -0
  17. package/app/assets/styles/setup/index.css +5 -0
  18. package/app/assets/styles/setup/typography/index.css +2 -0
  19. package/app/assets/styles/setup/typography/utility-classes/_generic-font-classes.css +217 -0
  20. package/app/assets/styles/setup/typography/utility-classes/_generic-font-variation-settings.css +29 -0
  21. package/app/assets/styles/setup/typography/utility-classes/_generic-font-weights.css +39 -0
  22. package/app/assets/styles/setup/typography/utility-classes/index.css +3 -0
  23. package/app/assets/styles/setup/typography/vars/_colors.css +14 -0
  24. package/app/assets/styles/setup/typography/vars/_reponsive-font-sizes.css +12 -0
  25. package/app/assets/styles/setup/typography/vars/index.css +2 -0
  26. package/app/assets/styles/setup/utility-classes/_fluid-spacing.css +13 -0
  27. package/app/assets/styles/setup/utility-classes/animations/_auto-rotate.css +13 -0
  28. package/app/assets/styles/setup/utility-classes/animations/_entry-exit-blur.css +16 -0
  29. package/app/assets/styles/setup/utility-classes/animations/_entry-slide-in.css +15 -0
  30. package/app/assets/styles/setup/utility-classes/animations/_entry-zoom-reveal.css +15 -0
  31. package/app/assets/styles/setup/utility-classes/animations/index.css +4 -0
  32. package/app/assets/styles/setup/utility-classes/index.css +2 -0
  33. package/app/assets/styles/setup/variables/colors/_blue.css +15 -0
  34. package/app/assets/styles/setup/variables/colors/_gray.css +16 -0
  35. package/app/assets/styles/setup/variables/colors/_green.css +15 -0
  36. package/app/assets/styles/setup/variables/colors/_orange.css +15 -0
  37. package/app/assets/styles/setup/variables/colors/_red.css +15 -0
  38. package/app/assets/styles/setup/variables/colors/_yellow.css +15 -0
  39. package/app/assets/styles/setup/variables/colors/index.css +6 -0
  40. package/app/assets/styles/setup/variables/index.css +1 -0
  41. package/app/components/accordian/AccordianCore.vue +46 -0
  42. package/app/components/animated-svg-text/AnimatedSvgText.vue +87 -0
  43. package/app/components/canvas-switcher/CanvasSwitcher.vue +77 -0
  44. package/app/components/carousel-basic/CarouselBasic.vue +291 -0
  45. package/app/components/carousel-basic/CarouselFlip.vue +461 -0
  46. package/app/components/carousel-basic/CarouselInfinite.vue +325 -0
  47. package/app/components/clip-element/ClipElement.vue +73 -0
  48. package/app/components/clipped-panels/ClippedPanel.vue +73 -0
  49. package/app/components/container-glow/ContainerGlowCore.vue +211 -0
  50. package/app/components/content-grid/ContentGrid.vue +85 -0
  51. package/app/components/deep-expanding-menu/DeepExpandingMenu.vue +214 -0
  52. package/app/components/deep-expanding-menu/DeepExpandingMenuOld.vue +218 -0
  53. package/app/components/display-banner/DisplayBanner.vue +63 -0
  54. package/app/components/display-details/DisplayDetailsCore.vue +301 -0
  55. package/app/components/display-dialog/DisplayDialogCore.vue +255 -0
  56. package/app/components/display-dialog/variants/DisplayDialogConfirm.vue +45 -0
  57. package/app/components/display-dialog/variants/DisplayDialogScrollableContent.vue +49 -0
  58. package/app/components/display-grid/DisplayGridCore.vue +22 -0
  59. package/app/components/display-prompt/DisplayPromptCore.vue +187 -0
  60. package/app/components/display-prompt/variants/DisplayPromptError.vue +53 -0
  61. package/app/components/expanding-panel/ExpandingPanel.vue +124 -0
  62. package/app/components/image-galleries/SliderGallery.vue +784 -0
  63. package/app/components/layout-grids/LayoutGridA.vue +103 -0
  64. package/app/components/layout-grids/LayoutGridB.vue +132 -0
  65. package/app/components/layout-row/LayoutRow.vue +165 -0
  66. package/app/components/masonry-grid/MasonryGrid.vue +62 -0
  67. package/app/components/masonry-grid-ordered/MasonryGridOrdered.vue +158 -0
  68. package/app/components/masonry-grid-sorted/MasonryGridSorted.vue +115 -0
  69. package/app/components/pop-over/PopOver.vue +88 -0
  70. package/app/components/responsive-header/NavigationItems.vue +169 -0
  71. package/app/components/responsive-header/ResponsiveHeader.vue +686 -0
  72. package/app/components/rotating-carousel/RotatingCarouselImage.vue +200 -0
  73. package/app/components/skip-links/SkipLinks.vue +92 -0
  74. package/app/components/tabs/TabsCore.vue +277 -0
  75. package/app/composables/useDialogControls.ts +44 -0
  76. package/app/composables/useStyleClassPassthrough.ts +35 -0
  77. package/app/composables/useTabs.ts +201 -0
  78. package/app/types/gallery-data.ts +13 -0
  79. package/app/types/responsiveHeader.ts +38 -0
  80. package/app/types/types.carousel-basic.ts +19 -0
  81. package/package.json +3 -6
@@ -0,0 +1,686 @@
1
+ <template>
2
+ <div class="navigation" :class="[elementClasses, { loaded: navLoaded }]" ref="navigationWrapper" role="banner">
3
+ <nav class="main-navigation" ref="mainNav" aria-label="Main navigation">
4
+ <ul v-for="(navGroup, groupKey) in responsiveNavLinks" :key="groupKey" class="main-navigation-list" :ref="el => setNavRef(String(groupKey), el as HTMLUListElement | null)">
5
+ <template v-for="(link, localIndex) in navGroup" :key="localIndex">
6
+ <li
7
+ v-if="link.path"
8
+ class="main-navigation-item"
9
+ :class="{ 'visually-hidden': !mainNavigationState.clonedNavLinks?.[groupKey]?.[localIndex]?.config?.visible }"
10
+ :style="{ '--_main-navigation-item-width': mainNavigationState.clonedNavLinks?.[groupKey]?.[localIndex]?.config?.width + 'px' }"
11
+ ref="mainNavigationItems"
12
+ :data-group-key="groupKey"
13
+ :data-local-index="localIndex"
14
+ @mouseenter="handleNavigationItemHover"
15
+ @focusin="handleNavigationItemHover"
16
+ >
17
+ <NuxtLink class="main-navigation-link" :class="{ 'has-icon': link.iconName }" :to="link.path">
18
+ <Icon v-if="link.iconName" :name="link.iconName" class="decorator-icon" aria-hidden="true" />
19
+ {{ link.name }}
20
+ </NuxtLink>
21
+ </li>
22
+ <li
23
+ v-else
24
+ class="main-navigation-item"
25
+ :class="{ 'visually-hidden': !mainNavigationState.clonedNavLinks?.[groupKey]?.[localIndex]?.config?.visible }"
26
+ :style="{ '--_main-navigation-item-width': mainNavigationState.clonedNavLinks?.[groupKey]?.[localIndex]?.config?.width + 'px' }"
27
+ ref="mainNavigationItems"
28
+ :data-group-key="groupKey"
29
+ :data-local-index="localIndex"
30
+ >
31
+ <details class="main-navigation-details" name="navigation-group" ref="navigationDetails">
32
+ <summary
33
+ @mouseenter="handleSummaryHover($event)"
34
+ @focusin="handleSummaryHover($event)"
35
+ @click.prevent="handleSummaryAction($event)"
36
+ @keypup.prevent.stop="handleSummaryAction($event)"
37
+ class="main-navigation-details-summary has-toggle-icon"
38
+ :aria-label="`${link.childLinksTitle} submenu`"
39
+ >
40
+ <Icon name="mdi:chevron-down" class="icon" :aria-hidden="true" />
41
+ <Icon v-if="link.iconName" :name="link.iconName" class="decorator-icon" aria-hidden="true" />
42
+
43
+ {{ link.childLinksTitle }}
44
+ </summary>
45
+ <div class="main-navigation-sub-nav" role="menu" :aria-labelledby="`summary-${groupKey}-${localIndex}`">
46
+ <ul class="main-navigation-sub-nav-list">
47
+ <li class="main-navigation-sub-nav-item" v-for="childLink in link.childLinks" :key="childLink.name">
48
+ <NuxtLink :to="childLink.path" class="main-navigation-sub-nav-link" role="menuitem">{{ childLink.name }}</NuxtLink>
49
+ </li>
50
+ </ul>
51
+ </div>
52
+ </details>
53
+ </li>
54
+ </template>
55
+ </ul>
56
+ </nav>
57
+ <nav class="secondary-navigation" ref="secondaryNav" aria-label="Secondary navigation">
58
+ <details class="overflow-details" :class="[{ 'visually-hidden': !navLoaded || !showOverflowDetails }]" ref="overflowDetails" name="overflow-group">
59
+ <summary class="overflow-details-summary has-toggle-icon">
60
+ <Icon :name="overflowDetailsSummaryIcons.more" class="icon" :class="[{ show: !allowNavigationCollapse }]" :aria-hidden="true" />
61
+ <Icon :name="overflowDetailsSummaryIcons.burger" class="icon" :class="[{ show: allowNavigationCollapse }]" :aria-hidden="true" />
62
+ </summary>
63
+ <div class="overflow-details-nav" role="menu">
64
+ <NavigationItems :main-navigation-state="mainNavigationState" />
65
+ </div>
66
+ </details>
67
+ <slot v-if="hasSecondaryNavigation" name="secondaryNavigation"></slot>
68
+ </nav>
69
+ <LayoutRow tag="div" variant="full" :style-class-passthrough="['mb-20', 'debug-grid']">
70
+ <ClientOnly>
71
+ <div>
72
+ <h2 class="heading-4">navigationWrapperRects</h2>
73
+ <pre>{{ navigationWrapperRects }}</pre>
74
+ <hr />
75
+ <h2 class="heading-4">secondaryNavRects</h2>
76
+ <pre>{{ secondaryNavRects }}</pre>
77
+ </div>
78
+ <div>
79
+ <h2 class="heading-4">mainNavigationState</h2>
80
+ <pre>{{ mainNavigationState }}</pre>
81
+ </div>
82
+ </ClientOnly>
83
+ </LayoutRow>
84
+ </div>
85
+ </template>
86
+
87
+ <script setup lang="ts">
88
+ import { useResizeObserver, onClickOutside } from '@vueuse/core';
89
+ import type { ResponsiveHeaderProp, ResponsiveHeaderState, IFlooredRect } from '@/types/responsiveHeader';
90
+
91
+ const props = defineProps({
92
+ responsiveNavLinks: {
93
+ type: Object as PropType<ResponsiveHeaderProp>,
94
+ default: () => [],
95
+ },
96
+ gapBetweenFirstAndSecondNav: {
97
+ type: Number,
98
+ default: 12, // px
99
+ },
100
+ overflowDetailsSummaryIcons: {
101
+ type: Object as PropType<Record<string, string>>,
102
+ default: {
103
+ more: 'gravity-ui:ellipsis',
104
+ burger: 'gravity-ui:bars',
105
+ },
106
+ },
107
+ collapseBreakpoint: {
108
+ type: Number,
109
+ default: null, // px
110
+ },
111
+ collapseAtMainNavIntersection: {
112
+ type: Boolean,
113
+ default: false,
114
+ },
115
+ styleClassPassthrough: {
116
+ type: Array as PropType<string[]>,
117
+ default: () => [],
118
+ },
119
+ allowExpandOnGesture: {
120
+ type: Boolean,
121
+ default: true,
122
+ },
123
+ });
124
+
125
+ const slots = useSlots();
126
+ const hasSecondaryNavigation = computed(() => slots.secondaryNavigation !== undefined);
127
+ const collapseNavigationBelowWidth = computed(() => props.collapseBreakpoint !== null || props.collapseAtMainNavIntersection);
128
+ const collapseBreakpoint = ref(props.collapseBreakpoint);
129
+ const navLoaded = ref(false);
130
+ const navigationWrapperRef = useTemplateRef('navigationWrapper');
131
+
132
+ const closeAllNavigationDetails = () => {
133
+ navigationDetailsRefs.value?.forEach((element) => {
134
+ element?.removeAttribute('open');
135
+ });
136
+ overflowDetailsRef.value?.removeAttribute('open');
137
+ };
138
+
139
+ const toggleDetailsElement = (event: Event) => {
140
+ const summaryElement = event.currentTarget as HTMLElement;
141
+ const parentDetailsElement = summaryElement.closest('details');
142
+ if (!parentDetailsElement) return;
143
+
144
+ if (parentDetailsElement.hasAttribute('open')) {
145
+ parentDetailsElement.removeAttribute('open');
146
+ } else {
147
+ parentDetailsElement.setAttribute('open', '');
148
+ }
149
+ overflowDetailsRef.value?.removeAttribute('open');
150
+ };
151
+
152
+ const handleSummaryHover = (event: MouseEvent | FocusEvent) => {
153
+ if (!props.allowExpandOnGesture) {
154
+ return;
155
+ }
156
+
157
+ // Close all other open navigation details first
158
+ const summaryElement = event.currentTarget as HTMLElement;
159
+ const parentDetailsElement = summaryElement.closest('details');
160
+
161
+ navigationDetailsRefs.value?.forEach((element) => {
162
+ if (element !== parentDetailsElement) {
163
+ element?.removeAttribute('open');
164
+ }
165
+ });
166
+ overflowDetailsRef.value?.removeAttribute('open');
167
+
168
+ // Then toggle the current one
169
+ toggleDetailsElement(event);
170
+ };
171
+
172
+ const handleNavigationItemHover = () => {
173
+ if (!props.allowExpandOnGesture) {
174
+ return;
175
+ }
176
+
177
+ // Close all open navigation details when hovering over regular nav items
178
+ closeAllNavigationDetails();
179
+ };
180
+
181
+ const handleSummaryAction = (event: MouseEvent | KeyboardEvent) => {
182
+ toggleDetailsElement(event);
183
+ };
184
+
185
+ const mainNavigationState = ref<ResponsiveHeaderState>({
186
+ navListVisibility: {
187
+ firstNav: false,
188
+ secondNav: false,
189
+ },
190
+ clonedNavLinks: props.responsiveNavLinks,
191
+ hasSecondNav: Object.keys(props.responsiveNavLinks).length > 1,
192
+ });
193
+
194
+ const navRefs = ref<Record<string, HTMLUListElement | null>>({});
195
+
196
+ const setNavRef = (key: string, el: HTMLUListElement | null) => {
197
+ navRefs.value[key] = el;
198
+ };
199
+
200
+ const navigationWrapperRects = ref<IFlooredRect | null>(null);
201
+ const firstNavRef = ref<HTMLUListElement | null>(null);
202
+ const firstNavRects = ref<IFlooredRect | null>(null);
203
+
204
+ const secondNavRef = ref<HTMLUListElement | null>(null);
205
+ const secondNavRects = ref<IFlooredRect | null>(null);
206
+
207
+ const secondaryNavRef = useTemplateRef('secondaryNav');
208
+ const secondaryNavRects = ref<IFlooredRect | null>(null);
209
+
210
+ const mainNavigationItemsRefs = useTemplateRef<HTMLLIElement[]>('mainNavigationItems');
211
+
212
+ const navigationDetailsRefs = useTemplateRef<HTMLElement[]>('navigationDetails');
213
+
214
+ const overflowDetailsRef = useTemplateRef('overflowDetails');
215
+
216
+ const showOverflowDetails = computed(() => {
217
+ const hasHiddenNav = !mainNavigationState.value.navListVisibility['firstNav'] || (!mainNavigationState.value.navListVisibility['secondNav'] && mainNavigationState.value.hasSecondNav);
218
+ return hasHiddenNav;
219
+ });
220
+
221
+ const mainNavigationMarginBlockEnd = computed(() => {
222
+ return secondaryNavRects.value ? secondaryNavRects.value.width + props.gapBetweenFirstAndSecondNav : 0;
223
+ });
224
+
225
+ const mainNavigationMarginBlockEndStr = computed(() => {
226
+ return mainNavigationMarginBlockEnd.value + 'px';
227
+ });
228
+
229
+ const initTemplateRefs = async () => {
230
+ firstNavRef.value = navRefs.value['firstNav'] as HTMLUListElement | null;
231
+ secondNavRef.value = navRefs.value['secondNav'] as HTMLUListElement | null;
232
+ return;
233
+ };
234
+
235
+ const getFlooredRect = (rect: DOMRect | null) => {
236
+ if (!rect) return null;
237
+ return {
238
+ left: Math.floor(rect.left),
239
+ right: Math.floor(rect.right),
240
+ top: Math.floor(rect.top),
241
+ bottom: Math.floor(rect.bottom),
242
+ width: Math.floor(rect.width),
243
+ height: Math.floor(rect.height),
244
+ };
245
+ };
246
+
247
+ const updateNavigationConfig = async (source: string) => {
248
+ navigationWrapperRects.value = getFlooredRect((navigationWrapperRef.value && navigationWrapperRef.value.getBoundingClientRect()) ?? null) || null;
249
+ secondaryNavRects.value = getFlooredRect((secondaryNavRef.value && secondaryNavRef.value.getBoundingClientRect()) ?? null) || null;
250
+ firstNavRects.value = getFlooredRect((firstNavRef.value && firstNavRef.value.getBoundingClientRect()) ?? null) || null;
251
+ secondNavRects.value = getFlooredRect((secondNavRef.value && secondNavRef.value.getBoundingClientRect()) ?? null) || null;
252
+
253
+ if (collapseNavigationBelowWidth.value && firstNavRects.value) {
254
+ collapseBreakpoint.value = firstNavRects.value?.right;
255
+ }
256
+ };
257
+
258
+ const allowNavigationCollapse = computed(() => {
259
+ return (
260
+ collapseNavigationBelowWidth.value &&
261
+ navigationWrapperRects.value &&
262
+ secondaryNavRects.value !== null &&
263
+ Math.floor(secondaryNavRects.value.left - props.gapBetweenFirstAndSecondNav) <= collapseBreakpoint.value
264
+ );
265
+ });
266
+
267
+ const determineNavigationItemVisibility = (rect: DOMRect) => {
268
+ // Check if navigation should be collapsed based on width breakpoint
269
+ if (allowNavigationCollapse.value) {
270
+ return false;
271
+ }
272
+
273
+ // Use default responsive visibility logic if wrapper exists
274
+ if (navigationWrapperRects.value) {
275
+ return Math.floor(rect.right + mainNavigationMarginBlockEnd.value + props.gapBetweenFirstAndSecondNav) < navigationWrapperRects.value.right;
276
+ }
277
+
278
+ // Default to visible
279
+ return true;
280
+ };
281
+
282
+ const initMainNavigationState = () => {
283
+ if (!mainNavigationItemsRefs.value) return;
284
+
285
+ mainNavigationItemsRefs.value.forEach((item, index) => {
286
+ const rect = item.getBoundingClientRect();
287
+
288
+ const groupKey = item.dataset.groupKey;
289
+ const localIndex = item.dataset.localIndex ? parseInt(item.dataset.localIndex, 10) : 0;
290
+ if (
291
+ groupKey !== undefined &&
292
+ groupKey !== null &&
293
+ mainNavigationState.value.clonedNavLinks &&
294
+ mainNavigationState.value.clonedNavLinks[groupKey] &&
295
+ mainNavigationState.value.clonedNavLinks[groupKey][localIndex]
296
+ ) {
297
+ mainNavigationState.value.clonedNavLinks[groupKey][localIndex] = {
298
+ ...mainNavigationState.value.clonedNavLinks[groupKey][localIndex],
299
+ config: {
300
+ left: item.offsetLeft,
301
+ right: item.offsetLeft + item.offsetWidth,
302
+ width: item.offsetWidth,
303
+ visible: determineNavigationItemVisibility(rect),
304
+ },
305
+ };
306
+ }
307
+
308
+ // Check if a single item has visible set to false and set the visibility of the group accordingly
309
+ if (
310
+ typeof groupKey === 'string' &&
311
+ mainNavigationState.value.clonedNavLinks &&
312
+ mainNavigationState.value.clonedNavLinks[groupKey] &&
313
+ mainNavigationState.value.clonedNavLinks[groupKey][localIndex].config?.visible === false
314
+ ) {
315
+ mainNavigationState.value.navListVisibility[groupKey] = false;
316
+ } else if (typeof groupKey === 'string') {
317
+ mainNavigationState.value.navListVisibility[groupKey] = true;
318
+ }
319
+ });
320
+ };
321
+
322
+ onMounted(async () => {
323
+ await initTemplateRefs().then(() => {
324
+ setTimeout(() => {
325
+ navLoaded.value = true;
326
+ }, 100);
327
+ });
328
+
329
+ navigationDetailsRefs.value?.forEach((element, index) => {
330
+ onClickOutside(element, () => {
331
+ navigationDetailsRefs.value?.[index]?.removeAttribute('open');
332
+ });
333
+ });
334
+ // Add onClickOutside to overflowDetailsRef
335
+ overflowDetailsRef.value &&
336
+ onClickOutside(overflowDetailsRef.value, () => {
337
+ overflowDetailsRef.value?.removeAttribute('open');
338
+ });
339
+ });
340
+
341
+ useResizeObserver(navigationWrapperRef, async () => {
342
+ await updateNavigationConfig('useResizeObserver').then(() => {
343
+ initMainNavigationState();
344
+ });
345
+ });
346
+
347
+ const { elementClasses, resetElementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
348
+
349
+ watch(
350
+ () => props.styleClassPassthrough,
351
+ () => {
352
+ resetElementClasses(props.styleClassPassthrough);
353
+ }
354
+ );
355
+ </script>
356
+
357
+ <style lang="css">
358
+ .navigation {
359
+ ul,
360
+ ol {
361
+ list-style-type: none;
362
+ margin: 0;
363
+ padding: 0;
364
+
365
+ li {
366
+ /* text-box-trim: trim-both; */
367
+ /* text-box-edge: cap alphabetic; */
368
+ display: flex;
369
+ align-items: center;
370
+ }
371
+ }
372
+
373
+ --_link-visibility-transition: none;
374
+
375
+ &.loaded {
376
+ --_link-visibility-transition: all 0.2s ease-in-out;
377
+ }
378
+
379
+ /* flex-grow: 1; */
380
+ display: grid;
381
+ grid-template-areas: 'navStack';
382
+
383
+ margin: 12px;
384
+ border-radius: 8px;
385
+ background-color: #efefef05;
386
+ border: 1px solid #efefef75;
387
+ padding: 12px;
388
+
389
+ .main-navigation {
390
+ /* Set up some global vars */
391
+ --_link-padding-block: 0.8rem;
392
+ --_link-padding-inline: 0.2rem;
393
+ --_link-margin-block: 0.1rem;
394
+ --_link-margin-inline: 0.1rem;
395
+ --_link-focus-visible-outline-width: 0.2rem;
396
+ --_link-border-default: 2px solid transparent;
397
+ --_link-border-bottom-hover: var(--green-8);
398
+
399
+ grid-area: navStack;
400
+ display: flex;
401
+ flex-wrap: nowrap;
402
+ flex-grow: 1;
403
+ justify-content: space-between;
404
+ gap: 60px;
405
+
406
+ overflow-x: hidden;
407
+ margin-inline-end: v-bind(mainNavigationMarginBlockEndStr);
408
+
409
+ &.collapsed {
410
+ justify-content: flex-start;
411
+ }
412
+
413
+ .main-navigation-list {
414
+ display: flex;
415
+ flex-wrap: nowrap;
416
+
417
+ &:nth-of-type(1) {
418
+ gap: 30px;
419
+ }
420
+
421
+ &:nth-of-type(2) {
422
+ gap: 30px;
423
+ }
424
+
425
+ .main-navigation-item {
426
+ width: var(--_main-navigation-item-width);
427
+ overflow: hidden;
428
+ transition: opacity 0.2s ease-in-out, visibility 0.2s ease-in-out;
429
+ padding-block: var(--_link-focus-visible-outline-width);
430
+ padding-inline: var(--_link-focus-visible-outline-width);
431
+
432
+ .main-navigation-link {
433
+ display: flex;
434
+ gap: 6px;
435
+ text-wrap-mode: nowrap;
436
+ color: inherit;
437
+ text-decoration: none;
438
+ margin-inline-start: 0;
439
+ transition: var(--_link-visibility-transition);
440
+
441
+ padding-block: var(--_link-padding-block);
442
+ padding-inline: var(--_link-padding-inline);
443
+ margin-block: var(--_link-margin-block);
444
+ margin-inline: var(--_link-margin-inline);
445
+ border-bottom: var(--_link-border-default);
446
+
447
+ &:hover {
448
+ cursor: pointer;
449
+ border-bottom-color: var(--_link-border-bottom-hover);
450
+ }
451
+ }
452
+
453
+ .main-navigation-details {
454
+ --_icon-transform: scaleY(1);
455
+
456
+ margin-inline-start: 0;
457
+ transition: var(--_link-visibility-transition);
458
+
459
+ &[open] {
460
+ --_icon-transform: scaleY(-1);
461
+
462
+ .main-navigation-details-summary {
463
+ border-bottom-color: var(--_link-border-bottom-hover);
464
+ }
465
+ }
466
+
467
+ .has-toggle-icon {
468
+ display: flex;
469
+ gap: 6px;
470
+ text-wrap-mode: nowrap;
471
+
472
+ .icon {
473
+ display: block;
474
+ transform: var(--_icon-transform);
475
+ transition: transform 0.2s ease-in-out;
476
+ }
477
+ }
478
+
479
+ .main-navigation-details-summary {
480
+ padding-block: var(--_link-padding-block);
481
+ padding-inline: var(--_link-padding-inline);
482
+ margin-block: var(--_link-margin-block);
483
+ margin-inline: var(--_link-margin-inline);
484
+ border-bottom: var(--_link-border-default);
485
+
486
+ &::-webkit-details-marker,
487
+ &::marker {
488
+ display: none;
489
+ }
490
+
491
+ &:hover {
492
+ cursor: pointer;
493
+ border-bottom-color: var(--_link-border-bottom-hover);
494
+ }
495
+
496
+ .decorator-icon {
497
+ margin-inline-start: 8px;
498
+ }
499
+ }
500
+
501
+ .main-navigation-sub-nav {
502
+ position: absolute;
503
+ padding: 12px;
504
+ border: 1px solid #efefef75;
505
+ border-radius: 8px;
506
+ background-color: #000;
507
+ translate: 0 12px;
508
+
509
+ min-width: var(--_main-navigation-item-width);
510
+
511
+ .main-navigation-sub-nav-list {
512
+ display: grid;
513
+ grid-template-columns: repeat(2, auto);
514
+ gap: 12px;
515
+
516
+ .main-navigation-sub-nav-item {
517
+ margin-bottom: 8px;
518
+
519
+ &:last-child {
520
+ margin-bottom: 0;
521
+ }
522
+
523
+ .main-navigation-sub-nav-link {
524
+ display: block;
525
+ text-wrap-mode: nowrap;
526
+ text-decoration: none;
527
+ color: inherit;
528
+ }
529
+ }
530
+ }
531
+ }
532
+ }
533
+
534
+ &.visually-hidden {
535
+ visibility: hidden;
536
+ opacity: 0;
537
+
538
+ .main-navigation-details,
539
+ .main-navigation-link {
540
+ margin-inline-start: var(--_main-navigation-item-width);
541
+ }
542
+ }
543
+ }
544
+ }
545
+ }
546
+
547
+ .secondary-navigation {
548
+ grid-area: navStack;
549
+ justify-self: end;
550
+
551
+ display: flex;
552
+ gap: 12px;
553
+ align-items: center;
554
+
555
+ .secondary-navigation-list {
556
+ .secondary-navigation-item {
557
+ .secondary-navigation-link {
558
+ display: flex;
559
+ align-items: center;
560
+ font: inherit;
561
+ color: inherit;
562
+
563
+ .icon {
564
+ height: 1.35em;
565
+ width: 1.35em;
566
+ }
567
+ }
568
+ }
569
+ }
570
+
571
+ .main-navigation-link {
572
+ .icon {
573
+ height: 1.35em;
574
+ width: 1.35em;
575
+ }
576
+ }
577
+
578
+ .overflow-details {
579
+ list-style: none;
580
+ padding: 0;
581
+ margin: 0;
582
+ position: relative;
583
+ cursor: pointer;
584
+ width: fit-content;
585
+
586
+ transition: all 0.2s ease-in-out;
587
+
588
+ &.visually-hidden {
589
+ opacity: 0;
590
+ visibility: hidden;
591
+ width: 0;
592
+ }
593
+
594
+ .overflow-details-summary {
595
+ --_icon-zoom: 1;
596
+ --_icon-size: 20px;
597
+ --_border-width: 1px;
598
+ --_outline-width: 1px;
599
+ --_transition-duration: 0.2s;
600
+
601
+ display: grid;
602
+ grid-template-areas: 'icon';
603
+ align-items: center;
604
+ justify-content: center;
605
+ padding-inline: 5px;
606
+ text-wrap: nowrap;
607
+
608
+ aspect-ratio: 1;
609
+ border-radius: 4px;
610
+ border: var(--_border-width) solid #ffffff90;
611
+ outline: var(--_outline-width) solid #ffffff10;
612
+ background-color: Canvas;
613
+
614
+ width: var(--_icon-size);
615
+ height: var(--_icon-size);
616
+ overflow: hidden;
617
+ transition-property: all;
618
+ transition-timing-function: linear;
619
+ transition-duration: var(--_transition-duration);
620
+
621
+ &::-webkit-details-marker,
622
+ &::marker {
623
+ display: none;
624
+ }
625
+
626
+ &:hover,
627
+ &:focus-visible {
628
+ --_icon-zoom: 1.2;
629
+ outline: var(--_outline-width) solid #ffffff;
630
+ }
631
+
632
+ .icon {
633
+ grid-area: icon;
634
+ scale: var(--_icon-zoom);
635
+ transition: scale 0.2s ease-in-out;
636
+ width: calc(var(--_icon-size) - var(--_border-width) * 2 - var(--_outline-width) * 2);
637
+ height: calc(var(--_icon-size) - var(--_border-width) * 2 - var(--_outline-width) * 2);
638
+
639
+ opacity: 0;
640
+ transition-property: opacity, transform; /* For reference */
641
+ transition-timing-function: linear; /* For reference */
642
+ transition-duration: var(--_transition-duration); /* For reference */
643
+
644
+ &.show {
645
+ opacity: 1;
646
+ }
647
+ }
648
+ }
649
+
650
+ .overflow-details-nav {
651
+ position: absolute;
652
+ top: 135%;
653
+ right: 0;
654
+ background-color: #000;
655
+ border: 1px solid #ffffff90;
656
+ border-radius: 8px;
657
+ padding: 12px;
658
+ margin: 0;
659
+ z-index: 999;
660
+ min-width: var(--_overflow-drop-down-width, fit-content);
661
+
662
+ display: grid;
663
+ grid-auto-flow: row;
664
+ gap: 8px;
665
+ }
666
+ }
667
+ }
668
+ }
669
+
670
+ .debug-grid {
671
+ display: none;
672
+
673
+ .layout-row-inner > div {
674
+ display: flex;
675
+ flex-wrap: wrap;
676
+ gap: 12px;
677
+
678
+ margin-inline: 12px;
679
+
680
+ > div {
681
+ outline: 1px solid gray;
682
+ padding: 12px;
683
+ }
684
+ }
685
+ }
686
+ </style>