Étape 22 — Navigation responsive
Objectifs
- Ajouter un tiroir de navigation (
v-navigation-drawer) pour les écrans mobiles - Utiliser le bouton hamburger (
v-app-bar-nav-icon) pour ouvrir/fermer le tiroir - Cacher les boutons desktop sur mobile avec les classes utilitaires Vuetify
- Afficher les liens dans une
v-listà l'intérieur du tiroir
Contexte
Actuellement, la barre de navigation affiche tous les boutons en ligne. Sur un petit écran (smartphone), ces boutons prennent trop de place ou disparaissent. La solution standard : un menu hamburger qui ouvre un tiroir latéral sur mobile, et des boutons visibles uniquement sur desktop.
Encart oral — Classes d'affichage responsive Vuetify
Vuetify fournit des classes utilitaires pour afficher/cacher des éléments selon la taille de l'écran :
| Classe | Effet |
|---|---|
d-none | Caché par défaut (toutes tailles) |
d-md-flex | Affiché en flex à partir de md (960px) |
d-md-none | Caché à partir de md |
d-none d-md-flex | Caché sur mobile, visible sur desktop |
d-md-none | Visible sur mobile, caché sur desktop |
Combinées, ces classes permettent d'avoir deux navigations : une pour mobile (tiroir) et une pour desktop (boutons).
Tâches
1. Ajouter le bouton hamburger
Dans AppHeader.vue, ajoutez un v-app-bar-nav-icon au début du contenu de la v-app-bar. Ce bouton ne doit être visible que sur les petits écrans :
| Composant | Rôle | Documentation |
|---|---|---|
<v-app-bar-nav-icon> | Bouton hamburger standard pour ouvrir un tiroir | App bars |
<v-app-bar-nav-icon
class="d-md-none"
@click="drawer = !drawer"
/>class="d-md-none": visible uniquement sur mobile (caché à partir demd)@click="drawer = !drawer": bascule l'état du tiroir
Dans le <script setup>, créez la variable réactive :
const drawer = ref(false)2. Cacher les boutons desktop sur mobile
Ajoutez la classe d-none d-md-flex sur chaque <v-btn> de navigation dans la barre. Ainsi, ils sont cachés sur mobile et visibles à partir de md :
<v-btn
v-for="link in menuItems"
:key="link.title"
:icon="link.icon"
:to="link.path"
class="d-none d-md-flex"
/>Faites de même pour les autres boutons de la barre (favoris, login, etc.).
3. Définir les éléments de menu
Créez un tableau avec les liens de navigation :
const menuItems = [
{ title: 'Accueil', path: '/', icon: 'mdi-pokeball' },
{ title: 'Favoris', path: '/favoris', icon: 'mdi-heart' },
{ title: 'À propos', path: '/a-propos', icon: 'mdi-information' },
]4. Ajouter le tiroir de navigation
Après la </v-app-bar>, ajoutez un v-navigation-drawer :
| Composant | Rôle | Documentation |
|---|---|---|
<v-navigation-drawer> | Panneau latéral coulissant | Navigation drawers |
<v-list> | Liste d'éléments cliquables | Lists |
<v-navigation-drawer
v-model="drawer"
temporary
>
<v-list nav>
<v-list-item
v-for="link in menuItems"
:key="link.title"
:prepend-icon="link.icon"
:title="link.title"
:to="link.path"
@click="drawer = false"
/>
</v-list>
</v-navigation-drawer>Points importants :
v-model="drawer": contrôle l'ouverture/fermeture du tiroirtemporary: le tiroir se ferme quand on clique en dehorsnavsur<v-list>: ajoute du padding adapté à la navigation@click="drawer = false": ferme le tiroir quand on clique sur un lien:to="link.path": navigation avec Vue Router (pas de rechargement de page)
5. Tester le responsive
- Ouvrez les DevTools de votre navigateur (F12)
- Activez le mode responsive (icône smartphone/tablette)
- Réduisez la largeur sous 960px → le hamburger apparaît, les boutons disparaissent
- Cliquez sur le hamburger → le tiroir s'ouvre avec les liens
- Cliquez sur un lien → le tiroir se ferme et la navigation fonctionne
- Élargissez au-dessus de 960px → les boutons réapparaissent, le hamburger disparaît
Tests
- Sur mobile (< 960px) : le bouton hamburger est visible
- Sur mobile : les boutons de navigation desktop sont cachés
- Cliquer sur le hamburger ouvre le tiroir latéral
- Le tiroir contient tous les liens de navigation
- Cliquer sur un lien dans le tiroir navigue et ferme le tiroir
- Cliquer en dehors du tiroir le ferme
- Sur desktop (>= 960px) : les boutons sont visibles, le hamburger est caché
- 0 erreurs dans la console
Solution
src/components/AppHeader.vue
<template>
<!--
Barre d'application plate
* flat supprime l'ombre sous la barre
-->
<v-app-bar flat>
<v-container class="d-flex align-center">
<!--
Bouton hamburger pour le tiroir de navigation (mobile)
* Visible uniquement sur les petits écrans grâce à d-md-none
-->
<v-app-bar-nav-icon
class="d-md-none"
@click="drawer = !drawer"
/>
<!-- Titre de l'application -->
<v-toolbar-title>Pokédex</v-toolbar-title>
<!--
Liens de navigation (desktop uniquement)
* d-none d-md-flex : cachés sur mobile, affichés à partir de md
-->
<v-btn
v-for="link in menuItems"
:key="link.title"
:icon="link.icon"
:to="link.path"
class="d-none d-md-flex"
/>
</v-container>
</v-app-bar>
<!--
Tiroir de navigation (mobile)
* v-model contrôle l'ouverture/fermeture
* temporary : le tiroir se ferme automatiquement quand on clique ailleurs
-->
<v-navigation-drawer
v-model="drawer"
temporary
>
<v-list nav>
<v-list-item
v-for="link in menuItems"
:key="link.title"
:prepend-icon="link.icon"
:title="link.title"
:to="link.path"
@click="drawer = false"
/>
</v-list>
</v-navigation-drawer>
</template>
<script setup>
/**
* Éléments de menu pour la navigation
* Chaque élément contient un titre, un chemin et une icône
*/
const menuItems = [
{ title: 'Accueil', path: '/', icon: 'mdi-pokeball' },
{ title: 'Favoris', path: '/favoris', icon: 'mdi-heart' },
{ title: 'À propos', path: '/a-propos', icon: 'mdi-information' },
]
/**
* État du tiroir de navigation mobile
*/
const drawer = ref(false)
</script>Commit
git add -A
git commit -m "feat: navigation responsive avec tiroir mobile"Projet perso — À faire en parallèle
Dans votre projet individuel :
- Ajoutez un
v-navigation-draweravectemporary - Cachez les boutons desktop sur mobile avec
d-none d-md-flex - Ajoutez un
v-app-bar-nav-iconvisible uniquement sur mobile - Testez en redimensionnant la fenêtre du navigateur