srcdev-nuxt-components 9.1.11 → 9.1.13
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.
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
:class="[
|
|
6
6
|
elementClasses,
|
|
7
7
|
`site-navigation--${navAlign}`,
|
|
8
|
-
{ 'is-collapsed': isCollapsed, 'is-loaded': isLoaded, 'menu-open': isMenuOpen },
|
|
8
|
+
{ 'is-collapsed': isCollapsed, 'is-loaded': isLoaded, 'menu-open': isMenuOpen, 'is-animated': isAnimated },
|
|
9
9
|
]"
|
|
10
10
|
aria-label="Site navigation"
|
|
11
11
|
>
|
|
@@ -113,6 +113,13 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
113
113
|
styleClassPassthrough: () => [],
|
|
114
114
|
});
|
|
115
115
|
|
|
116
|
+
// ─── Animation gate — prevents indicator from transitioning on first paint ───
|
|
117
|
+
|
|
118
|
+
const isAnimated = ref(false);
|
|
119
|
+
// Stays false until ResizeObserver confirms the nav has been laid out (stronger
|
|
120
|
+
// guarantee than nextTick / RAF which don't ensure layout is complete).
|
|
121
|
+
let hasFirstLayout = false;
|
|
122
|
+
|
|
116
123
|
// ─── Nav decorators (active / hover indicators) ─────────────────────────────
|
|
117
124
|
|
|
118
125
|
const NAV_DECORATOR_DURATION = 200;
|
|
@@ -330,18 +337,30 @@ const { navRef, navListRef, isCollapsed, isLoaded, isMenuOpen, activeHref, isAct
|
|
|
330
337
|
onResize: async () => {
|
|
331
338
|
await nextTick(); // wait for Vue to re-render after any isCollapsed change
|
|
332
339
|
initNavDecorators();
|
|
340
|
+
if (!hasFirstLayout) {
|
|
341
|
+
hasFirstLayout = true;
|
|
342
|
+
nextTick(() => {
|
|
343
|
+
isAnimated.value = true;
|
|
344
|
+
});
|
|
345
|
+
}
|
|
333
346
|
if (isMenuOpen.value) {
|
|
334
347
|
setFinalPanelActivePositions(true);
|
|
335
348
|
setFinalPanelHoveredPositions(true);
|
|
336
349
|
}
|
|
337
350
|
},
|
|
338
351
|
onRouteChange: () => {
|
|
352
|
+
isAnimated.value = false;
|
|
339
353
|
requestAnimationFrame(() => {
|
|
340
354
|
initNavDecorators();
|
|
355
|
+
nextTick(() => {
|
|
356
|
+
isAnimated.value = true;
|
|
357
|
+
});
|
|
341
358
|
});
|
|
342
359
|
},
|
|
343
360
|
onMounted: () => {
|
|
344
361
|
initNavDecorators();
|
|
362
|
+
// isAnimated is set in onResize — ResizeObserver guarantees layout is
|
|
363
|
+
// complete before we enable transitions, unlike nextTick / RAF.
|
|
345
364
|
},
|
|
346
365
|
});
|
|
347
366
|
|
|
@@ -473,10 +492,15 @@ watch(
|
|
|
473
492
|
scale: var(--_width-hovered, 0.001) 1;
|
|
474
493
|
translate: var(--_x-hovered, 0) 0;
|
|
475
494
|
transform-origin: left;
|
|
495
|
+
pointer-events: none;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
.site-navigation.is-animated & .nav__hovered,
|
|
499
|
+
.site-navigation.is-animated & .nav__active,
|
|
500
|
+
.site-navigation.is-animated & .nav__active-indicator {
|
|
476
501
|
transition:
|
|
477
502
|
scale var(--_transition-duration, 200ms),
|
|
478
503
|
translate var(--_transition-duration, 200ms);
|
|
479
|
-
pointer-events: none;
|
|
480
504
|
}
|
|
481
505
|
|
|
482
506
|
.nav__active {
|
|
@@ -661,10 +685,15 @@ watch(
|
|
|
661
685
|
scale: 1 var(--_panel-height-hovered, 0.001);
|
|
662
686
|
translate: 0 var(--_panel-y-hovered, 0);
|
|
663
687
|
transform-origin: top;
|
|
688
|
+
pointer-events: none;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
.site-navigation.is-animated & .nav__hovered,
|
|
692
|
+
.site-navigation.is-animated & .nav__active,
|
|
693
|
+
.site-navigation.is-animated & .nav__active-indicator {
|
|
664
694
|
transition:
|
|
665
695
|
scale var(--_panel-transition-duration, 200ms),
|
|
666
696
|
translate var(--_panel-transition-duration, 200ms);
|
|
667
|
-
pointer-events: none;
|
|
668
697
|
}
|
|
669
698
|
|
|
670
699
|
.nav__active {
|