États de chargement
Problème
Distinguer visuellement « en cours de chargement » de « vide » et de « erreur ». Un loader mal placé donne une impression de lenteur même sur une app rapide.
3 types d'états de chargement
1. loading.tsx (route-level)
Next.js rend automatiquement src/app/**/loading.tsx pendant la résolution d'un Server Component. Patrimo l'utilise pour les routes principales (dashboard, accounts, budget…).
Privilégier un skeleton qui reproduit la structure finale plutôt qu'un spinner plein écran.
2. Skeleton (component-level)
Pour un bloc dans une page déjà rendue : placeholder gris pulsant reproduisant la forme.
<div className="h-20 rounded-lg bg-[var(--color-surface)] animate-pulse" />
3. Spinner (action-level)
Pour une action utilisateur synchrone (submit, import, recalcul) : Loader2 de Lucide + animate-spin.
{loading && <Loader2 size={16} className="animate-spin" aria-label="Chargement" />}
Règles
- Skeleton pour un premier rendu de données (pas de spinner plein écran)
- Spinner pour une action déclenchée par l'utilisateur (bouton, toggle)
- Durée minimum imperceptible : si l'action prend < 100 ms, pas de loader (flash désagréable)
- Pas d'état de chargement non annoncé : chaque action bloquante doit signaler son état (bouton disabled + spinner)
À ne pas faire
- Remplacer toute la page par un spinner quand on pourrait conserver le layout et charger uniquement la zone concernée
- Utiliser un GIF pour un spinner (préférer CSS
animate-spinsur SVG) - Oublier
aria-labelsur un spinner icon-only