Skip to content

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

  1. Utilisateur sur /dashboard
  2. FAB affiche l'icône 🚲
  3. Tap sur FAB → Redirection vers /dashboard/bikes/new

Créer un nouvel entretien

  1. Utilisateur navigue vers Atelier → Maintenance
  2. FAB change pour icône 🔧
  3. Tap sur FAB → Sheet avec 2 options
  4. Sélection "Entretien programmé"
  5. Redirection vers /dashboard/maintenance/new
  1. Tap sur icône 🔧 Atelier dans la bottom nav
  2. Sheet s'ouvre avec 3 cartes
  3. Sélection d'une carte (ex: Bikefit)
  4. Redirection vers /dashboard/bikefit
  5. 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"
  • 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-28 pour 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

  1. Navigation de base
  2. [ ] Tap sur Accueil → Redirige vers /dashboard
  3. [ ] Tap sur Atelier → Ouvre le sheet
  4. [ ] Tap sur Données → Redirige vers /dashboard

  5. FAB contextuel

  6. [ ] Sur dashboard → Icône vélo
  7. [ ] Sur maintenance → Icône wrench
  8. [ ] Sur bikefit → Icône ruler
  9. [ ] Sur tools → Icône droplet

  10. Sheet Atelier

  11. [ ] 3 options visibles
  12. [ ] Tap sur une option → Ferme et redirige
  13. [ ] Swipe down → Ferme le sheet

  14. Indicateurs visuels

  15. [ ] Page active a une pastille colorée
  16. [ ] Transitions fluides
  17. [ ] Pas de flash de contenu

  18. Safe areas

  19. [ ] Aucun élément coupé sur iPhone avec encoche
  20. [ ] 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

  1. Historique de navigation
  2. Breadcrumbs contextuels
  3. Bouton retour intelligent

  4. Notifications contextuelles

  5. Badge sur Atelier si maintenance due
  6. Badge sur Données si nouvelle activité Strava

  7. Mode tablette

  8. Bottom nav devient side nav
  9. FAB reste mais ajuste sa position

  10. Raccourcis clavier

  11. 1 → Accueil
  12. 2 → Atelier
  13. 3 → Données
  14. N → FAB action

  15. Personnalisation

  16. Réorganiser les options du sheet Atelier
  17. 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