SKILL-10 — Navigation¶
Ordre de focus, cohérence et positionnement dans l'application
Critères couverts¶
| Critère RAAM | Intitulé | Niveau | WCAG |
|---|---|---|---|
| 10.1 | L'utilisateur est informé de sa position dans l'application | [A] | WCAG 2.4.8 |
| 10.2 | L'ordre de focus est cohérent et logique | [A] | WCAG 1.3.2, 2.4.3 |
| 10.3 | Les raccourcis ne créent pas de conflits | [A] | WCAG 2.1.4 |
| 10.4 | La navigation est cohérente entre les écrans | [AA] | WCAG 3.2.3, 3.2.4 |
| 10.5 | L'indicateur de focus est visible | [AA] | WCAG 2.4.7 |
| 10.6 | Le focus ne peut pas être piégé | [AA] | WCAG 2.1.2 |
Pourquoi c'est important¶
Le piège du focus
Une modale qui s'ouvre sans contraindre le focus est un défaut majeur. Le lecteur d'écran peut atteindre le contenu derrière et l'utilisateur est totalement perdu.
La navigation concerne l'ordre et le cheminement. L'ordre de focus de haut en bas et de gauche à droite doit être respecté pour que la lecture par VoiceOver ou TalkBack soit logique.
Patterns¶
1. Ordre de Focus [A]¶
Column(modifier = Modifier.padding(16.dp)) {
Text(
text = "Titre de la carte",
modifier = Modifier.semantics { traversalIndex = -1f } // Index petit = en premier
)
Text("Description...", modifier = Modifier.semantics { traversalIndex = 0f })
Button(onClick = {}, modifier = Modifier.semantics { traversalIndex = 1f }) {
Text("Action principale")
}
}
2. Position dans l'App [A]¶
3. Focus Non Piégé [AA]¶
4. Navigation Cohérente [AA]¶
5. Focus VoiceOver : @AccessibilityFocusState [A]¶
@FocusState ≠ focus VoiceOver
@FocusState gère le focus clavier. Il ne déplace pas le curseur VoiceOver : utiliser @AccessibilityFocusState avec .accessibilityFocused(_:).
@AccessibilityFocusState private var triggerFocused: Bool
Button("Filtrer les résultats") { showFilters = true }
.accessibilityFocused($triggerFocused)
.sheet(
isPresented: $showFilters,
onDismiss: { triggerFocused = true }, // sinon VoiceOver retombe en haut de l'écran
content: { FiltersView().accessibilityAddTraits(.isModal) }
)
Ce pattern est spécifique à iOS. Pour les dialogs Compose, voir le pattern 3 (AlertDialog).
6. Focus non masqué [2.2 · AA]¶
Hors RAAM 1.1, hors scoring
2.4.11 : une barre fixe ne doit pas cacher entièrement l'élément qui a le focus. iOS : .safeAreaInset(edge: .bottom) plutôt qu'un overlay ; Compose : Scaffold + paddingValues et imePadding(). Détails : Extensions WCAG 2.2.
Checklist [A] / [AA]¶
- L'ordre de focus (lecture) correspond à la structure visuelle.
- Les modales piègent correctement le focus (
isModal/AlertDialog). - Le focus revient sur le déclencheur après la fermeture d'une modale.
- Le titre des écrans est clair et annonce la position.