Formulaire
Chapitre 3 : Formulaires — Ne perdez pas vos utilisateurs en route 📝
On entre dans le dur. Les formulaires.
C'est le moment où vous demandez à l'utilisateur de bosser pour vous (s'inscrire, payer, poster).
Si votre formulaire est une galère à utiliser, ils partiront. Point barre.
Pour un utilisateur de lecteur d'écran ou un utilisateur au clavier, un mauvais formulaire ressemble à un labyrinthe dans le noir. 🔦
Slides
https://gamma.app/docs/Chapitre-3-Formulaires-Accessibles--76qo8zcxto1dw4r
1. La Sainte Trinité du Formulaire 🔱
Pour qu'un champ soit accessible, il lui faut 3 choses :
-
Une étiquette (Label) : "C'est quoi ce champ ?"
-
Un type/état : "C'est du texte ? C'est obligatoire ? C'est en erreur ?"
-
Une description (si besoin) : "Ça doit faire 8 caractères ?" ou "Pourquoi c'est rouge ?"
Le Label : L'attachement vital 🔗
Visuellement, on voit que le texte "Email" est à côté de la case blanche.
Pour un robot, s'ils ne sont pas liés par le code, ils sont des étrangers.
-
❌ Mauvais :
HTML
<div>Email</div> <input type="text" /> -
✅ Bon (Avec Shadcn/HTML natif) :
HTML
<Label for="email">Email</Label> <Input id="email" name="email" />L'attribut
fordu Label doit matcher l'attributidde l'Input. C'est le lien magique. Quand on clique sur le label, ça active l'input.
2. Gestion des Erreurs : Ne soyez pas juste "Rouge" 🔴
Imaginez : vous êtes daltonien. Le champ devient rouge. Vous ne le voyez pas.
Imaginez : vous êtes aveugle. Un texte d'erreur apparaît sous le champ. Votre lecteur d'écran est focalisé sur le champ, pas sur le texte en dessous. Vous ne savez pas qu'il y a une erreur.
La solution technique : aria-describedby et aria-invalid.

3. Exemple Concret : Refactoring de "Créer une Maison" 🏠
Reprenons ton code Inertia/Vue pour la création immobilière. On va le transformer en Forteresse de l'Accessibilité.
Ce qu'on va ajouter :
-
aria-required="true": Pour dire au lecteur "Hé, faut remplir ça". -
aria-invalid="true": Si Inertia renvoie une erreur. -
aria-describedby: Pour lier l'input à son message d'erreur. -
autocomplete: Pour aider le navigateur à pré-remplir (ça aide énormément les troubles moteurs/cognitifs).
Le Code (Version a11y) ✨
Extrait de code
<script setup>
import { Form } from '@inertiajs/vue3'; // Le composant magique
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
// ... (imports et props inchangés)
</script>
<template>
<Form :action="store()" #default="{ errors, processing }" class="space-y-6">
<div class="space-y-2">
<Label for="title">
Titre de l'annonce
<span class="text-destructive" aria-hidden="true">*</span>
</Label>
<Input
id="title"
type="text"
name="title"
placeholder="Ex: Belle maison à Paris"
aria-required="true"
:aria-invalid="errors.title ? 'true' : 'false'"
:aria-describedby="errors.title ? 'title-error' : null"
/>
<p
v-if="errors.title"
id="title-error"
class="text-sm text-destructive"
role="alert"
>
{{ errors.title }}
</p>
</div>
<div class="space-y-2">
<Label for="price">Prix (€) <span aria-hidden="true">*</span></Label>
<Input
id="price"
type="number"
name="price"
autocomplete="transaction-amount"
aria-required="true"
:aria-invalid="errors.price ? 'true' : 'false'"
:aria-describedby="errors.price ? 'price-error' : null"
/>
<p v-if="errors.price" id="price-error" class="text-sm text-destructive" role="alert">
{{ errors.price }}
</p>
</div>
<div class="flex gap-4">
<Button type="submit" :disabled="processing">
<span v-if="processing" class="mr-2">⏳</span>
{{ processing ? 'Enregistrement en cours...' : 'Créer la maison' }}
</Button>
</div>
</Form>
</template>
4. Pourquoi c'est mieux ? 🤔
-
role="alert"sur l'erreur : Dès que le message apparaît, le lecteur d'écran l'interrompt pour le lire : "Alerte : Le titre est obligatoire". -
Connexion ID/For : Si je clique sur le label "Prix", le curseur va dans le champ Prix (super pour les tremblements ou gros doigts sur mobile).
-
aria-invalid: Le lecteur d'écran annonce "Titre, invalide, édition de texte". L'utilisateur sait immédiatement qu'il doit corriger.
💡 Astuce Shadcn : Les composants Shadcn propagent souvent les attributs (
...props). Donc si vous mettezaria-requiredsur le composant<Input>, il atterrira bien sur la balise HTML<input>finale.

Synthèse

On passe à la suite ? Le prochain chapitre concerne les trucs qui bougent et qui poppent (Modales, Toasts) ! 🍿
