Browse Source

handle hydratation better

Olivier Massot 1 year ago
parent
commit
3c6140b501
3 changed files with 56 additions and 41 deletions
  1. 1 0
      .eslintrc.cjs
  2. 48 40
      components/Common/ActionMenu.vue
  3. 7 1
      components/Layout/Navigation.vue

+ 1 - 0
.eslintrc.cjs

@@ -47,5 +47,6 @@ module.exports = {
     useLayoutStore: 'readonly',
     useLayoutStore: 'readonly',
     useClientDevice: 'readonly',
     useClientDevice: 'readonly',
     useSeoMeta: 'readonly',
     useSeoMeta: 'readonly',
+    onNuxtReady: 'readonly',
   },
   },
 }
 }

+ 48 - 40
components/Common/ActionMenu.vue

@@ -3,46 +3,51 @@ Menu d'actions rapides (appel, contact, ...), qui reste accroché au bord droit
 de l'écran (ou au bas de l'écran sur les petits écrans)
 de l'écran (ou au bas de l'écran sur les petits écrans)
 -->
 -->
 <template>
 <template>
-  <!-- Écrans larges : menu lateral, accroché au bord droit de l'écran -->
-  <div v-if="lgAndUp && isVisible" class="sticky-menu lateral">
-    <v-row
-      v-for="(action, index) in actionsOrDefault"
-      :key="index"
-      :class="['square', action.color]"
-      @click="() => onActionClick(action)"
+  <div v-show="showMenu">
+    <!-- Écrans larges : menu lateral, accroché au bord droit de l'écran -->
+    <div
+      v-if="lgAndUp && isVisible"
+      class="sticky-menu lateral"
     >
     >
-      <NuxtLink class="link">
-        <div>
-          <v-icon :class="action.icon" />
-
-          <p class="text-square mt-2">
-            {{ action.text }}
-          </p>
-        </div>
-      </NuxtLink>
-    </v-row>
-  </div>
+      <v-row
+        v-for="(action, index) in actionsOrDefault"
+        :key="index"
+        :class="['square', action.color]"
+        @click="() => onActionClick(action)"
+      >
+        <NuxtLink class="link">
+          <div>
+            <v-icon :class="action.icon" />
+
+            <p class="text-square mt-2">
+              {{ action.text }}
+            </p>
+          </div>
+        </NuxtLink>
+      </v-row>
+    </div>
+
+    <!-- Petits écrans : menu sous forme de bandeau en pied de page (sauf si le footer du site est visible) -->
+    <div v-else-if="isVisible" class="sticky-menu band">
+      <v-btn
+        v-for="(action, index) in actionsOrDefault"
+        :key="index"
+        :class="[action.color]"
+        @click="() => onActionClick(action)"
+      >
+        <span v-if="mdAndUp">{{ action.text }}</span>
+        <v-icon v-else>{{ action.icon }}</v-icon>
+      </v-btn>
+    </div>
 
 
-  <!-- Petits écrans : menu sous forme de bandeau en pied de page (sauf si le footer du site est visible) -->
-  <div v-else-if="isVisible" class="sticky-menu band">
     <v-btn
     <v-btn
-      v-for="(action, index) in actionsOrDefault"
-      :key="index"
-      :class="[action.color]"
-      @click="() => onActionClick(action)"
+      v-if="isVisible"
+      :to="{ path: '', hash: '#top' }"
+      class="back-to-the-top secondary"
     >
     >
-      <span v-if="mdAndUp">{{ action.text }}</span>
-      <v-icon v-else>{{ action.icon }}</v-icon>
+      <v-icon>fas fa-arrow-up</v-icon>
     </v-btn>
     </v-btn>
   </div>
   </div>
-
-  <v-btn
-    v-if="isVisible"
-    :to="{ path: '', hash: '#top' }"
-    class="back-to-the-top secondary"
-  >
-    <v-icon>fas fa-arrow-up</v-icon>
-  </v-btn>
 </template>
 </template>
 
 
 <script setup lang="ts">
 <script setup lang="ts">
@@ -67,6 +72,12 @@ const isVisible: ComputedRef<boolean> = computed(
     !layoutStore.isFooterVisible
     !layoutStore.isFooterVisible
 )
 )
 
 
+// Attend l'hydratation avant d'afficher
+const showMenu = ref(false)
+onNuxtReady(() => {
+  showMenu.value = true
+})
+
 // Actions par défaut du menu, peut-être surchargé via la propriété `actions`
 // Actions par défaut du menu, peut-être surchargé via la propriété `actions`
 const defaultActions: Array<ActionMenuItem> = [
 const defaultActions: Array<ActionMenuItem> = [
   {
   {
@@ -125,12 +136,9 @@ const onActionClick = (action: ActionMenuItem) => {
       if (!action.url) {
       if (!action.url) {
         throw new Error('Missing prop : url')
         throw new Error('Missing prop : url')
       }
       }
-      navigateTo(
-        action.url,
-        {
-          open: { target: '_blank' }
-        }
-      )
+      navigateTo(action.url, {
+        open: { target: '_blank' },
+      })
       break
       break
 
 
     default:
     default:

+ 7 - 1
components/Layout/Navigation.vue

@@ -4,7 +4,7 @@ Menu Navigation
 <template>
 <template>
   <div v-intersect="onIntersect">
   <div v-intersect="onIntersect">
     <!-- Navigation (écran large) -->
     <!-- Navigation (écran large) -->
-    <div v-if="lgAndUp">
+    <div v-if="lgAndUp || !nuxtReady">
       <LayoutNavigationLg :menu="menu" />
       <LayoutNavigationLg :menu="menu" />
     </div>
     </div>
 
 
@@ -22,6 +22,12 @@ import { useLayoutStore } from '~/stores/layoutStore'
 
 
 const { lgAndUp } = useDisplay()
 const { lgAndUp } = useDisplay()
 
 
+// On force la version écran large au build côté serveur
+const nuxtReady = ref(false)
+onNuxtReady(() => {
+  nuxtReady.value = true
+})
+
 const menu: Array<MainMenuItem> = [
 const menu: Array<MainMenuItem> = [
   {
   {
     label: 'Nos logiciels',
     label: 'Nos logiciels',