mirror of
https://github.com/MaksTinyWorkshop/_Assistant_Lead_Tech
synced 2026-06-28 10:03:40 +02:00
5f5c87296e
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>
7.2 KiB
7.2 KiB
Frontend — Risques & vigilance : React Native
Extrait de la base de connaissance Lead_tech. Voir
knowledge/frontend/risques/README.mdpour l'index complet.
Focus ring sur TextInput React Native
Risques
- React Native n'a pas de pseudo-classe
:focus— le focus visuel ne s'implémente pas en CSS - Tâche souvent marquée [x] sans vérification effective du state
focused
Symptômes
TextInputsans indication visuelle de focus → accessibilité et UX dégradées- Story marquée done mais aucun handler
onFocus/onBlurprésent dans le composant
Bonnes pratiques / mitigations
const [focused, setFocused] = useState(false);
<TextInput
onFocus={() => setFocused(true)}
onBlur={() => setFocused(false)}
style={[styles.input, focused && styles.inputFocused]}
/>
- Règle de review : toute story "focus ring" doit présenter un state
focused+ handlers + style conditionnel - Contexte technique : React Native — app-alexandrie, 25-03-2026
ScrollView.contentInset — propriété iOS-only
Risques
contentInsetn'est pas supporté sur Android — le contenu passe sous la bottom tab bar sans aucune erreur de build- Pattern fréquent quand on copie un pattern iOS existant dans un nouvel écran
Symptômes
- Sur iOS : rendu correct avec padding bottom
- Sur Android : contenu masqué sous la bottom tab bar
Bonnes pratiques / mitigations
// ❌ Anti-pattern — iOS-only, cassé sur Android
<ScrollView contentInset={{ bottom: insets.bottom }}>
// ✅ Pattern correct — cross-platform
<ScrollView contentContainerStyle={{ paddingBottom: insets.bottom }}>
- Règle de review : auditer systématiquement tout
ScrollViewaveccontentInsetdans les PR concernant des écrans avec bottom navigation - Contexte technique : React Native / react-native-safe-area-context — app-alexandrie, 25-03-2026
fetch sans vérification response.ok — erreurs non-2xx silencieuses
Risques
- Sans vérification de
response.ok, les réponses 404/500 retournent le JSON d'erreur sans exception → le code appelant ne sait pas que la requête a échoué - En cas de proxy qui retourne du HTML sur erreur (ex : 502 Bad Gateway),
response.json()throw uneSyntaxErrorcryptique plutôt qu'une erreur métier
Symptômes
- Store qui reçoit
{ error: { code, message } }comme si c'était une réponse valide SyntaxError: JSON Parse errorinexpliquée lors des erreurs réseau
Bonnes pratiques / mitigations
const response = await fetch(url, options);
const json = (await response.json()) as T;
if (!response.ok) {
throw json; // throw le body d'erreur structuré pour un catch cohérent
}
return json;
- Règle : tout
fetchdans le http-client doit vérifierresponse.okavant de retourner le JSON parsé - Contexte technique : React Native / fetch — app-alexandrie review 5.2, 27-03-2026
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 leaccessibilityLabeldu wrapper et le titre enfant (double annonce). Sur iOS,summaryest 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
// ✅ 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 uniquementaccessibilityLabelsur le wrapper si besoin de regrouper - Contexte technique : React Native — app-alexandrie (
section-card.tsx, IA-v2.4 H3), 27-05-2026
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
<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 lecontentContainerStyle - Si
<Stack.Screen>Expo Router avecheaderShown: 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
Pull-to-refresh mobile web : préférer une lib battle-test à un PTR custom
Risques
- Un PTR custom (écouter
pointerdown/pointermovesur 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 → lespointerdown/pointermovedu composant sont absents ou annulés parpointercancel - 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: contentsrendplace-itemsinopérant,display: blockbrise 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
/* 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 ; APIPullToRefresh.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