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 {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "srcdev-nuxt-components",
3
3
  "type": "module",
4
- "version": "9.1.11",
4
+ "version": "9.1.13",
5
5
  "main": "nuxt.config.ts",
6
6
  "types": "types.d.ts",
7
7
  "license": "MIT",