mirror of
https://github.com/MaksTinyWorkshop/_Assistant_Lead_Tech
synced 2026-06-28 01:53:40 +02:00
docs(knowledge): capitalisation frontend — intégration du triage local (mai-juin 2026)
Triage et intégration des propositions frontend du buffer 95_a_capitaliser.md (lot local RL799_V2/Vue3 + app-alexandrie/RN-Expo, mai-juin 2026). ~73 entrées intégrées sur knowledge/frontend/ + 1 nouveau fichier, dont : - patterns/state.md : race-token partagé latest-wins (fusion 3 props), capture sync anti-race, event bus timestamp, clé cache composite, état dérivé = computed - risques/state.md : 9 risques Zustand/store (fetchId reset, useRef remount, re-fetch infini sur [], flag optimiste écrasé, cache détail/liste stale, latch sans reset, :key index) - patterns/navigation.md : Expo Router (tab bar, useFocusEffect, Href typé, routing pur fusionné) - patterns/general.md : helpers temps purs, composants génériques + skeleton, fail-fast, touch target - risques/general.md : 24 risques (sweep statique, filtre client liste paginée, hooks avant return, a11y VoiceOver/disabled, redirection allowlist, RangeError toISOString, section i18n...) - design-tokens (cluster theming light/dark MD3), tests, performance, react-native, nextjs - NOUVEAU risques/responsive.md (gating par capacité d'input + checklist régressions mobile) - READMEs patterns/risques mis à jour Doublons inter-fichiers évités (vérifié : aucune ancre dupliquée introduite). Rejets (doublons 91/9/87), reciblages workflow (156/257) et bloc 32 (CLAUDE projet) non intégrés ici. Source 95_a_capitaliser.md non purgée (purge en fin de capitalisation complète). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -88,3 +88,88 @@ return json;
|
||||
|
||||
- Règle : tout `fetch` dans le http-client doit vérifier `response.ok` avant de retourner le JSON parsé
|
||||
- Contexte technique : React Native / fetch — app-alexandrie review 5.2, 27-03-2026
|
||||
|
||||
---
|
||||
|
||||
<a id="risque-accessibility-role-summary-wrapper-header"></a>
|
||||
## `accessibilityRole="summary"` sur wrapper avec enfant `header` → double annonce
|
||||
|
||||
### Risques
|
||||
|
||||
- `accessibilityRole="summary"` sur un `<View>` wrapper dont un enfant texte porte déjà `accessibilityRole="header"` : sur Android, TalkBack annonce le `accessibilityLabel` du wrapper **et** le titre enfant (double annonce). Sur iOS, `summary` est un no-op silencieux
|
||||
- Le dev croit renforcer l'a11y, il la dégrade
|
||||
|
||||
### Symptômes
|
||||
|
||||
- Lecteur d'écran qui répète le titre de section sur Android
|
||||
|
||||
### Bonnes pratiques / mitigations
|
||||
|
||||
```tsx
|
||||
// ✅ le role "header" sur le titre enfant suffit à structurer la section
|
||||
<View accessibilityLabel="Mon compte">
|
||||
<Text accessibilityRole="header">MON COMPTE</Text>
|
||||
{children}
|
||||
</View>
|
||||
```
|
||||
|
||||
- Ne pas poser `accessibilityRole="summary"` sur un wrapper si le titre enfant porte déjà `accessibilityRole="header"` ; conserver uniquement `accessibilityLabel` sur le wrapper si besoin de regrouper
|
||||
- Contexte technique : React Native — app-alexandrie (`section-card.tsx`, IA-v2.4 H3), 27-05-2026
|
||||
|
||||
---
|
||||
|
||||
<a id="risque-bouton-retour-dans-scrollview"></a>
|
||||
## Bouton retour placé dans le `ScrollView` → disparaît au scroll
|
||||
|
||||
### Risques
|
||||
|
||||
- Sur une app RN/Expo avec une TopBar globale sans back natif, un bouton retour ajouté comme premier enfant du `<ScrollView>` disparaît dès que l'utilisateur défile
|
||||
- Critique sur une page business (gestion abonnement, résiliation) : perdre l'accès au retour pendant le scroll est un piège UX direct
|
||||
|
||||
### Symptômes
|
||||
|
||||
- Le back est visible en haut de page puis introuvable une fois scrollé
|
||||
|
||||
### Bonnes pratiques / mitigations
|
||||
|
||||
```tsx
|
||||
<View style={styles.root}> {/* flex:1, background */}
|
||||
<View style={[styles.headerBar, { paddingTop: insets.top }]}>
|
||||
<Pressable onPress={handleBack} hitSlop={8}>…Retour</Pressable>
|
||||
</View>
|
||||
<ScrollView contentInset={{ top: 0 }}>{/* contenu */}</ScrollView>
|
||||
</View>
|
||||
```
|
||||
|
||||
- Le header local sticky vit **hors** du ScrollView (View parent + ScrollView frère)
|
||||
- Ne PAS doubler `insets.top` (le header le consomme → `contentInset.top = 0`) ; ne PAS mettre le back dans le `contentContainerStyle`
|
||||
- Si `<Stack.Screen>` Expo Router avec `headerShown: true`, préférer le header natif (`headerBackVisible: true`)
|
||||
- Test défensif : vérifier statiquement qu'un `<Pressable accessibilityLabel="Retour">` n'est pas dans un `<ScrollView>`
|
||||
- Contexte technique : React Native / Expo Router — app-alexandrie (ux-cleanup-2, `subscription/manage`), 28-05-2026
|
||||
|
||||
---
|
||||
|
||||
<a id="risque-ptr-custom-mobile-vs-lib"></a>
|
||||
## Pull-to-refresh mobile web : préférer une lib battle-test à un PTR custom
|
||||
|
||||
### Risques
|
||||
|
||||
- Un PTR custom (écouter `pointerdown`/`pointermove` sur un wrapper) est intrinsèquement fragile : le navigateur mobile **préempte** les touch events pour son scroll natif dès que la page est en haut → les `pointerdown`/`pointermove` du composant sont absents ou annulés par `pointercancel`
|
||||
- Chrome Android a SON PTR natif qui déclenche un vrai `location.reload()` : sur une PWA standalone, ça vide l'état Pinia/Redux et affiche le SW cache (souvent une version pré-login) — l'utilisateur croit s'être déconnecté
|
||||
- Un wrapper PTR casse les layouts grid (`display: contents` rend `place-items` inopérant, `display: block` brise le centrage)
|
||||
|
||||
### Symptômes
|
||||
|
||||
- PTR custom OK en simulation desktop, inopérant sur device ; ou rechargement natif affichant le contenu pré-login
|
||||
|
||||
### Bonnes pratiques / mitigations
|
||||
|
||||
```css
|
||||
/* AVANT toute autre tentative : neutraliser le PTR natif Chrome Android */
|
||||
body { overscroll-behavior-y: contain; } /* Chrome 63+/Safari 16+/Firefox 59+ */
|
||||
```
|
||||
|
||||
- Préférer une lib battle-test (`pulltorefreshjs`, ~6 kB) qui s'attache à `<body>` (zéro impact layout grid) et gère iOS/Android/desktop ; API `PullToRefresh.init({ mainElement, onRefresh })`, destroy au unmount
|
||||
- Indicateur : SVG inline avec viewBox contrôlé, pas un glyphe unicode (rendu variable selon la font)
|
||||
- **Tester sur vrai device** Android ET iOS (DevTools "device toolbar" ne reproduit pas la préemption native)
|
||||
- Contexte technique : Vue 3.5 / Vite / PWA Workbox — RL799_V2 (4 itérations custom ratées → `pulltorefreshjs`), 11-05-2026
|
||||
|
||||
Reference in New Issue
Block a user