mirror of
https://github.com/MaksTinyWorkshop/_Assistant_Lead_Tech
synced 2026-06-28 01:53: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>
79 lines
5.3 KiB
Markdown
79 lines
5.3 KiB
Markdown
# Frontend — Risques & vigilance : Responsive / adaptation mobile
|
|
|
|
> Extrait de la base de connaissance Lead_tech. Voir `knowledge/frontend/risques/README.md` pour l'index complet.
|
|
|
|
---
|
|
|
|
<a id="risque-gating-responsive-largeur-vs-input"></a>
|
|
## Gating responsive par largeur seule → fuite sur tablettes tactiles
|
|
|
|
### Risques
|
|
|
|
- Le réflexe `@media (min-width: 768px|900px|1024px)` traite la largeur comme un proxy de l'UX cible ; ça casse sur **tablettes tactiles** (iPad Air 1180px, iPad Pro 1366px, Surface, Galaxy Tab) qui ont la largeur d'un desktop mais l'UX d'un doigt
|
|
- Conséquences observées : swipe gestures désactivés sur iPad (alors que le swipe est l'UX tactile naturelle), scrollbars custom visibles en permanence, hover states bloquants au tap (1er tap = hover, 2e = click), pagination trop dense pour le doigt
|
|
|
|
### Symptômes
|
|
|
|
- Une règle "desktop" gated par `min-width` seul se comporte mal sur iPad : interactions désactivées ou inadaptées, scrollbars inutiles
|
|
|
|
### Bonnes pratiques / mitigations
|
|
|
|
**Gater par capacité d'input dès que la règle concerne une interaction** (hover, swipe, scrollbar visible, densité tactile, drag-and-drop, focus-ring discret).
|
|
|
|
```css
|
|
@media (pointer: fine) { /* souris/trackpad précis : desktop, laptop */ }
|
|
@media (pointer: coarse) { /* doigt/stylet imprécis : mobile, tablette tactile */ }
|
|
@media (hover: hover) { /* hover stable */ }
|
|
@media (hover: none) { /* hover simulé (tap) */ }
|
|
|
|
/* "Vraie expérience desktop" : largeur ≥ X ET souris */
|
|
@media (pointer: fine) and (min-width: 900px) { /* scrollbars custom, hover, pagination dense */ }
|
|
|
|
/* "Expérience tactile" : doigt, peu importe la largeur */
|
|
@media (pointer: coarse) { /* swipe, touch targets ≥44px, pas de hover stylé */ }
|
|
```
|
|
|
|
```ts
|
|
// équivalent runtime
|
|
const isFinePointer = window.matchMedia('(pointer: fine)').matches;
|
|
const isCoarseLarge = window.matchMedia('(pointer: coarse) and (min-width: 900px)').matches;
|
|
```
|
|
|
|
- **Garder `min-width` seul** pour le **layout pur** (grille, max-width container) : la largeur détermine la place, pas l'input.
|
|
- Critère de décision : « Si je donne à un user iPad cette règle, préfère-t-il le comportement mobile ou desktop ? » Réponse "mobile" (swipe, touch dense) → `pointer: coarse` ; réponse "desktop" (layout 2 colonnes, max-width) → `min-width` seul. Doute → `pointer: fine` + `min-width`.
|
|
- Support : `pointer:` / `hover:` (Interaction Media Features L4) universel depuis 2018, aucun fallback en 2026. Pattern CSS pur, applicable à toute stack.
|
|
- Contexte technique : Vue 3 / Vite — RL799_V2 (chantier `feat/desktop-experience`, swipe rows / scrollbar globale / pagination Audit), 12-05-2026
|
|
|
|
---
|
|
|
|
<a id="risque-regressions-mobile-chantier-desktop"></a>
|
|
## Régressions mobile invisibles lors d'un chantier desktop responsive
|
|
|
|
### Risques
|
|
|
|
- Un chantier "ajout desktop" sur une app mobile-first crée des régressions mobile par **effets de bord indirects**. Les devs travaillent en majorité sur viewport desktop → les régressions mobile n'apparaissent qu'au test final sur device, tardivement
|
|
- 4 vecteurs récurrents : wrappers retirés qui fournissaient un gap implicite, classes globales qui cumulent leurs paddings, `display: contents`/grid qui change l'ordre DOM mobile, règles `min-width` qui fuient sur tablette tactile
|
|
|
|
### Symptômes
|
|
|
|
- "Les espaces ont été mangés" (éléments mobiles collés), "le contenu est plus étroit qu'avant" (marges doublées), "l'ordre des cartes a changé" sans changement mobile intentionnel
|
|
|
|
### Bonnes pratiques / mitigations
|
|
|
|
Les 4 vecteurs et leur fix :
|
|
|
|
1. **Wrapper retiré → gap implicite perdu** : un `<PageShell>`/`<ContentCard>` retiré côté desktop portait un `gap`/`padding-top` qui structurait le rythme mobile. Fix : remettre explicitement `gap: var(--space-X)` sur le nouveau wrapper mobile, mesurer en pixels avant/après.
|
|
2. **Classes globales qui cumulent les paddings** : `.tenue-detail-container { padding-inline: 16px }` + `.page--dashboard { padding-inline: 16px }` = 32px sur mobile. Fix : neutraliser côté mobile (`.page--dashboard .tenue-detail-container { padding-inline: 0; }`).
|
|
3. **`display: contents` qui change l'ordre DOM mobile** : sur mobile le wrapper transparent fait suivre l'ordre HTML (réordonné pour le desktop), pas l'ordre historique mobile. Fix : préserver l'ordre via `flex` + `order` en `@media (max-width: 899px)`.
|
|
4. **Règles `@media (min-width)` qui fuient sur tablette tactile** : cf. `#risque-gating-responsive-largeur-vs-input`. Fix : ajouter `and (pointer: fine)` aux règles concernant une interaction.
|
|
|
|
**Checklist QA mobile post-chantier desktop** (avant merge) :
|
|
|
|
1. Audit gap/padding mobile (diff visuel page par page vs version précédente)
|
|
2. Audit ordre DOM mobile pour chaque page touchée (surtout `display: contents`/grid)
|
|
3. Grep `@media (min-width:` dans le diff ; pour chaque règle concernant une interaction, ajouter `and (pointer: fine)`
|
|
4. Audit cumul de paddings : pour chaque nouvelle classe wrapper, vérifier qu'aucune classe interne globale n'ajoute son propre `padding-inline`
|
|
5. Test sur appareil **physique** réel (iPhone + Android + iPad tactile), pas seulement les émulateurs DevTools (qui simulent la largeur mais pas la nature du pointer)
|
|
|
|
- Contexte technique : Vue 3.5 / Vite 7 — RL799_V2 (chantier `feat/desktop-experience`, passe QA mobile ~2h sur 7 fichiers), 12-05-2026
|