Architecture de Navigation - Bécik¶
Vue d'ensemble¶
Ce document décrit la nouvelle architecture de navigation de l'application Bécik, conçue pour une expérience mobile intuitive et évolutive.
Principes de conception¶
1. Hiérarchie claire en 3 zones¶
L'application est organisée autour de 3 concepts principaux :
- 🏠 Accueil (Dashboard) : Point d'entrée principal avec un aperçu de tout
- 🔧 Atelier : Services techniques pour la gestion des vélos
- 📊 Données : Visualisation et historique
2. Séparation Navigation / Action¶
- Bottom Navigation : Navigation entre les grandes sections de l'app
- Contextual FAB : Actions de création/ajout contextuelle
Cette séparation évite la confusion et rend l'interface plus claire.
Composants¶
BottomNav (/src/components/navigation/bottom-nav.tsx)¶
Rôle : Barre de navigation principale fixée en bas de l'écran (mobile uniquement)
Structure :
┌─────────────────────────────────┐
│ 🏠 Accueil 🔧 Atelier 📊 Données │
└─────────────────────────────────┘
Icône 1 : Accueil (Home)
- Destination :
/dashboard - Vue d'ensemble avec cartes récapitulatives
Icône 2 : Atelier (Chain/Gear)
- Ouvre un sheet avec 3 options :
- Maintenance →
/dashboard/maintenance - Bikefit →
/dashboard/bikefit - Pression des pneus →
/dashboard/tools
Icône 3 : Données (BarChart)
- Destination :
/dashboard - Liste des vélos, stats, intégrations Strava
Caractéristiques :
- Respecte les safe areas (encoche, home indicator iOS)
- Indicateur visuel de page active (pastille de couleur)
- Transitions fluides
- Compatible dark mode
ContextualFAB (/src/components/navigation/contextual-fab.tsx)¶
Rôle : Bouton d'action flottant (Floating Action Button) dont l'action change selon le contexte
Position :
- Fixed bottom:
80px(au-dessus de la bottom nav) - Fixed right:
16px - z-index: 50 (au-dessus de tout)
Comportement contextuel :
| Page active | Icône | Action unique | Actions multiples |
|---|---|---|---|
/dashboard |
🚲 Bike | → Ajouter un vélo | - |
/dashboard/maintenance |
🔧 Wrench | - | Entretien programmé Intervention rapide |
/dashboard/bikefit |
📏 Ruler | - | Mesure autonome Mesure pro |
/dashboard/tools |
💧 Droplet | - | Saisie manuelle Calcul auto |
| Autre page | ➕ Plus | - | Menu global (4 options) |
Logique :
- Action unique → Redirection directe au clic
- Actions multiples → Ouvre un bottom sheet avec les options
Avantages :
- Toujours accessible (zone ergonomique du pouce)
- Action primaire bien visible
- Contextuel = pertinent pour l'utilisateur
- Ne surcharge pas la bottom nav
Flux utilisateur¶
Ajouter un vélo depuis le dashboard¶
- Utilisateur sur
/dashboard - FAB affiche l'icône 🚲
- Tap sur FAB → Redirection vers
/dashboard/bikes/new
Créer un nouvel entretien¶
- Utilisateur navigue vers Atelier → Maintenance
- FAB change pour icône 🔧
- Tap sur FAB → Sheet avec 2 options
- Sélection "Entretien programmé"
- Redirection vers
/dashboard/maintenance/new
Naviguer entre les services de l'atelier¶
- Tap sur icône 🔧 Atelier dans la bottom nav
- Sheet s'ouvre avec 3 cartes
- Sélection d'une carte (ex: Bikefit)
- Redirection vers
/dashboard/bikefit - FAB change automatiquement pour 📏 Ruler
Structure des routes¶
/dashboard
├── / # Accueil (dashboard)
├── /bikes
│ ├── / # Liste des vélos
│ ├── /new # Ajouter un vélo
│ └── /[id]
│ ├── / # Détail du vélo
│ ├── /edit # Modifier le vélo
│ ├── /bikefit # Bikefit pour ce vélo
│ └── /tire-pressure # Historique pression
├── /maintenance
│ ├── / # Liste maintenance
│ ├── /new # Nouvel entretien
│ └── /intervention # Intervention rapide
├── /bikefit
│ ├── / # Liste des mesures
│ └── /new # Nouvelle mesure
│ └── ?type=self|pro # Type de mesure
└── /tools
├── / # Page outils
└── /tire-pressure
└── /new # Calcul/saisie pression
└── ?mode=manual|auto
Gestion des données relationnelles¶
Cycliste ↔ Vélo ↔ Services¶
Relations :
Cycliste (user)
↓
Vélo (bike)
↓
├─ Bikefit (bikefit_measurements)
├─ Pression (tire_pressure_history)
└─ Maintenance (maintenance_records)
Poids total (calcul automatique) :
- Poids vélo défini → Utiliser
- Poids vélo non défini → Estimer à partir du profil cycliste
Commentaires/Feedback :
- Distinction Ajouter vs Modifier
- Ajouter une nouvelle config → Via FAB
- Commenter une config existante → Bouton dans la fiche
Exemple : Bikefit
interface BikefitMeasurement {
id: string;
bike_id: string;
created_at: Date;
measurements: {
saddle_height: number;
reach: number;
// ...
};
feedback: BikefitFeedback[];
}
interface BikefitFeedback {
id: string;
measurement_id: string;
created_at: Date;
comment: string;
rating?: number;
usage_context?: string;
}
Patterns de code¶
Hook useElementWidth¶
Utilisé dans BottomNav pour calculer la largeur dynamique :
const { ref: barRef, width: barWidth } = useElementWidth<HTMLDivElement>();
Sheet (shadcn/ui)¶
Pattern pour les menus contextuels :
<Sheet open={sheetOpen} onOpenChange={setSheetOpen}>
<SheetTrigger asChild>
<Button>...</Button>
</SheetTrigger>
<SheetContent side="bottom">{/* Options */}</SheetContent>
</Sheet>
Détection de page active¶
const pathname = usePathname();
const isDashboard = pathname === "/dashboard";
const isAtelier = pathname.startsWith("/dashboard/maintenance");
Accessibilité¶
ARIA Labels¶
- Tous les boutons ont un
aria-label - Les pages actives ont
aria-current="page" - Les éléments décoratifs ont
aria-hidden="true"
Navigation au clavier¶
- Les sheets peuvent être fermés avec
Escape - Focus trap dans les sheets ouverts
Contraste et lisibilité¶
- Indicateurs visuels clairs (pastilles de couleur)
- Icônes de 24px minimum
- Texte de 11px minimum (labels)
Responsive design¶
Mobile (< 768px)¶
- BottomNav visible
- ContextualFAB visible
- Padding bottom:
pb-28pour le contenu
Desktop (≥ 768px)¶
- BottomNav cachée (
md:hidden) - ContextualFAB cachée (
md:hidden) - Navigation via sidebar ou top nav
Variables CSS personnalisées¶
:root {
--becik-primary: hsl(var(--primary));
--becik-primary-soft: hsl(var(--primary) / 0.1);
--becik-primary-dark: hsl(var(--primary) / 0.9);
--becik-ink: hsl(var(--foreground));
}
Tests et validation¶
Points de test¶
- Navigation de base
- [ ] Tap sur Accueil → Redirige vers
/dashboard - [ ] Tap sur Atelier → Ouvre le sheet
-
[ ] Tap sur Données → Redirige vers
/dashboard -
FAB contextuel
- [ ] Sur dashboard → Icône vélo
- [ ] Sur maintenance → Icône wrench
- [ ] Sur bikefit → Icône ruler
-
[ ] Sur tools → Icône droplet
-
Sheet Atelier
- [ ] 3 options visibles
- [ ] Tap sur une option → Ferme et redirige
-
[ ] Swipe down → Ferme le sheet
-
Indicateurs visuels
- [ ] Page active a une pastille colorée
- [ ] Transitions fluides
-
[ ] Pas de flash de contenu
-
Safe areas
- [ ] Aucun élément coupé sur iPhone avec encoche
- [ ] Home indicator iOS ne masque rien
Migration depuis l'ancienne version¶
Changements clés¶
Avant :
- MobileAppBottomNav : 3 icônes + bouton central notch
- Bouton central : Atelier ou Plus (toggle)
Après :
- BottomNav : 3 icônes simples et égales
- ContextualFAB : Bouton séparé, flottant, contextuel
Avantages de la nouvelle architecture¶
✅ Plus simple : Pas de toggle Atelier/Plus
✅ Plus clair : Navigation ≠ Actions
✅ Plus flexible : FAB s'adapte au contexte
✅ Plus maintenable : Code modulaire
✅ Plus accessible : Zones de tap plus grandes
✅ Plus évolutif : Facile d'ajouter des services
Évolutions futures¶
Fonctionnalités prévues¶
- Historique de navigation
- Breadcrumbs contextuels
-
Bouton retour intelligent
-
Notifications contextuelles
- Badge sur Atelier si maintenance due
-
Badge sur Données si nouvelle activité Strava
-
Mode tablette
- Bottom nav devient side nav
-
FAB reste mais ajuste sa position
-
Raccourcis clavier
1→ Accueil2→ Atelier3→ Données-
N→ FAB action -
Personnalisation
- Réorganiser les options du sheet Atelier
- Cacher des sections non utilisées
Support et maintenance¶
Fichiers clés¶
/src/components/navigation/bottom-nav.tsx/src/components/navigation/contextual-fab.tsx/src/components/icons/becik-chain-icon.tsx/src/app/dashboard/layout.tsx
Points de vigilance¶
⚠️ Toujours tester sur :
- iPhone SE (petit écran)
- iPhone 15 Pro Max (encoche)
- Android avec navigation gestuelle
⚠️ Vérifier le z-index :
- BottomNav : z-40
- ContextualFAB : z-50
- Modals/Dialogs : z-60+
⚠️ Safe areas :
- Utiliser
env(safe-area-inset-bottom)pour iOS
Questions fréquentes¶
Q : Pourquoi le FAB et pas un bouton dans la bottom nav ?
R : Le FAB permet une action contextuelle sans encombrer la nav principale. C'est le pattern recommandé par Material Design et Apple HIG.
Q : Pourquoi "Atelier" et pas "Maintenance" ?
R : "Atelier" englobe les 3 services techniques (Maintenance, Bikefit, Pression). C'est plus large et évolutif.
Q : Le FAB ne risque-t-il pas de cacher du contenu ?
R : Non, le contenu a un padding-bottom de 112px (64px nav + 48px FAB + marge). Le FAB est dans une zone "safe".
Q : Peut-on cacher le FAB sur certaines pages ?
R : Oui, il suffit d'ajouter une condition dans getContextualAction() pour retourner null.
Q : Comment ajouter un 4e service dans l'atelier ?
R : Ajouter une entrée dans le tableau atelierOptions du composant BottomNav.
Dernière mise à jour : 21 janvier 2026
Version : 2.0.0
Auteur : Équipe Bécik