docs(frontend): capitalise navigation et primitives UI

This commit is contained in:
MaksTinyWorkshop
2026-04-02 10:17:12 +02:00
parent 355d6130eb
commit 07f39ad433
2 changed files with 136 additions and 3 deletions

View File

@@ -84,3 +84,48 @@ function processLinks(content: string) {
3. Wrapper le `TextInput` dans `KeyboardAvoidingView` avec `behavior={Platform.OS === 'ios' ? 'padding' : 'height'}`.
- Contexte technique : React Native / Expo cross-platform — app-alexandrie 31-03-2026
---
<a id="risque-primitive-ui-couplee-contexte-parent"></a>
## Primitive UI couplée au contexte parent (layout ou namespace métier)
### Risques
- Une primitive générique (`PageShell`, `ContentCard`, `SectionWrapper`) qui embarque des classes de surface, de largeur ou de namespace métier devient non réutilisable hors de son premier contexte
- Le couplage reste silencieux au lint et au typecheck, puis force l'ajout progressif de props `variant`, `layout`, `width` ou de classes externes contradictoires
### Symptômes
- La primitive applique directement des classes comme `.card`, `.card--dashboard`, `.dashboard__item`, `.profile__card`
- Le parent doit contourner le style natif de la primitive pour l'utiliser dans un autre écran
- Les classes `namespace__element` fuitent dans des composants supposés agnostiques du domaine
### Bonnes pratiques / mitigations
- Une primitive pose le squelette sémantique ; le parent pose la surface visuelle (card, width, background, espacement de contexte)
- Ne pas injecter de classes de namespace métier sur une primitive générique via `class`
- Si une variation réutilisable existe vraiment, l'exprimer via une API explicite et bornée (`tone`, `variant`) plutôt que par des classes métier ad hoc
- Contexte technique : Vue 3 / CSS modulaire — RL799_V2, 02-04-2026
---
<a id="risque-migration-partielle-composant-classes-legacy"></a>
## Migration partielle vers un composant standard — classes legacy conservées
### Risques
- La coexistence de classes legacy (`.primary`, `.ghost`, `.danger`) et de classes du nouveau composant (`.app-btn--primary`, `.app-btn--ghost`) crée une ambiguïté durable de convention
- Les nouveaux développements continuent d'utiliser l'ancien système faute de règle claire, ce qui ralentit la standardisation
### Symptômes
- Deux façons de produire la même affordance coexistent dans le même repo
- Un composant dédié existe, mais des liens ou boutons continuent d'utiliser les anciennes classes globales
### Bonnes pratiques / mitigations
- Lorsqu'un composant standardise une affordance, supprimer en même temps les classes CSS globales équivalentes
- Si un reliquat legacy doit rester temporairement, documenter explicitement son périmètre et sa date de sortie attendue
- En review, traiter toute nouvelle utilisation d'une classe legacy équivalente comme une régression de standardisation
- Contexte technique : Vue 3 / design system léger — RL799_V2, 02-04-2026

View File

@@ -2,11 +2,11 @@
title: Frontend — Risques & vigilance : Navigation
domain: frontend
bucket: risques
tags: [navigation, expo-router, zustand, useeffect, deep-link]
tags: [navigation, expo-router, vue-router, vue, zustand, useeffect, deep-link, a11y]
applies_to: [implementation, review, debug]
severity: high
validated_on: 2026-03-25
source_projects: [app-alexandrie]
validated_on: 2026-04-02
source_projects: [app-alexandrie, RL799_V2]
---
# Frontend — Risques & vigilance : Navigation
@@ -144,3 +144,91 @@ router.push('/forgot-password' as never);
- Règle : les groupes `(auth)`, `(tabs)`, etc. sont des conventions d'organisation de fichiers, pas des segments de route — ne jamais les inclure dans les appels de navigation programmatique
- Contexte technique : Expo Router — app-alexandrie, 25-03-2026
---
<a id="risque-vue-router-double-route-racine"></a>
## Vue Router 4 — double route `/` avec `redirect` + layout parent
### Risques
- Déclarer à la fois `{ path: '/', redirect: ... }` et `{ path: '/', component: Layout, children: [...] }` dans le même tableau `routes` crée un conflit silencieux
- La première route `/` capturée empêche l'accès normal aux enfants du layout sur les accès directs à `/`
### Symptômes
- La redirection de `/` semble "fonctionner" en dev, mais uniquement parce qu'un guard global compense le problème
- Les enfants du layout parent ne sont jamais atteints directement depuis `/`
### Bonnes pratiques / mitigations
```typescript
// ❌ Anti-pattern — deux routes racine concurrentes
const routes = [
{ path: '/', redirect: '/home' },
{ path: '/', component: Layout, children: [...] },
];
// ✅ Pattern correct — une seule route racine + redirect enfant
const routes = [
{
path: '/',
component: Layout,
children: [
{ path: '', redirect: '/home' },
],
},
];
```
- Règle : ne jamais faire coexister deux entrées `path: '/'` concurrentes dans Vue Router
- Gérer la redirection de `/` soit via un enfant `path: ''`, soit via un guard global `beforeEach`, mais pas via une seconde route racine
- Contexte technique : Vue 3 / Vue Router 4 — RL799_V2, 02-04-2026
---
<a id="risque-router-link-disabled"></a>
## Navigation disabled via `router-link` + blocage au click
### Risques
- Un `router-link` rendu comme "disabled" continue de produire un `<a href="...">` valide dans le DOM
- Le lien reste accessible au clavier, aux lecteurs d'écran et aux tests a11y, même si `@click.prevent` bloque la navigation
### Symptômes
- Élément affiché avec `aria-disabled="true"` mais encore focusable et tabulable
- Faux positif visuel : l'UI semble désactivée, mais le DOM expose toujours un lien actif
### Bonnes pratiques / mitigations
```html
<!-- ❌ Anti-pattern -->
<router-link
:to="item.to"
aria-disabled="true"
@click.prevent="item.disabled"
>
{{ item.label }}
</router-link>
<!-- ✅ Pattern correct -->
<span
v-if="item.disabled"
class="nav__item nav__item--disabled"
aria-disabled="true"
>
{{ item.label }}
</span>
<router-link
v-else
:to="item.to"
class="nav__item"
>
{{ item.label }}
</router-link>
```
- Règle : un élément de navigation désactivé ne doit jamais être un lien
- Utiliser un élément non interactif (`span`) ou un vrai contrôle désactivable (`button disabled`) selon le besoin
- Contexte technique : Vue 3 / Vue Router 4 / accessibilité — RL799_V2, 02-04-2026