Form Validation
Pattern canonico per costruire form Qoovex comprensibili, recuperabili e accessibili usando le primitive già adottate nel prodotto.
Quando usarlo
Usa questa composizione per ogni form operativo o di account che valida dati prima o dopo il submit. Sirio documenta il contratto già presente nei form reali: non introduce un form builder, una nuova sorgente di errori o una seconda astrazione sopra il design system.
Contratto del campo
Ogni parte ha un compito preciso. Descrizione ed errore sono facoltativi, la label no.
- Label
- È sempre visibile e collegata al controllo tramite htmlFor e id. Il placeholder resta soltanto un esempio.
- Controllo
- Mantiene name, tipo, autocomplete e semantica nativa o della primitiva canonica.
- Descrizione
- Compare solo quando chiarisce contenuto, formato o conseguenza del campo.
- Errore locale
- Segue il controllo, usa linguaggio umano e viene incluso nel suo aria-describedby.
Specimen interattivi
Gli esempi coprono campo normale, descrizione, errore locale, più errori, invio in corso, successo ed errore generale. Sono dimostrativi e non inviano dati.
Stati del singolo campo
Label, descrizione ed errore hanno responsabilità distinte e ID stabili.
La nota sarà visibile alle persone coinvolte nel lavoro.
Form completo
Invia il form vuoto per verificare gli errori locali e il focus sul primo campo invalido.
Flusso di validazione
Il mapping degli errori resta vicino alla mutation reale; la composizione visuale resta comune.
- Mantieni lo stato del form e impedisci un secondo invio anche prima del re-render di pending.
- Mappa gli errori attribuibili ai campi, mostra un solo FieldError per controllo e imposta aria-invalid.
- Collega descrizione ed errore concatenando i rispettivi ID in aria-describedby.
- Dopo una risposta fallita porta il focus al primo controllo invalido visibile, seguendo l’ordine del form.
- Mostra un errore generale soltanto quando il problema non appartiene a un campo e non spostare arbitrariamente il focus.
- Durante l’invio usa aria-busy, controlli disabilitati e un solo messaggio di stato; dopo il successo comunica l’esito senza sottrarre il focus.
Controlli canonici
Componi Field,Label,FieldDescription eFieldError con input,textarea,select e checkbox esistenti.
I controlli composti legacy che non espongono ancora un contratto completo per ID, ref o messaggi locali non sono specimen canonici di questo pattern: vanno valutati separatamente prima di usarli in nuovi form.
Responsive e accessibilità
La tastiera, il focus e gli annunci fanno parte del comportamento del form, non sono decorazioni successive.
- Input e textarea usano label native associate; select e checkbox mantengono la stessa relazione accessibile tramite le primitive canoniche.
- L’errore non dipende dal colore: testo specifico, aria-invalid e associazione al controllo comunicano insieme lo stato.
- FieldError fornisce l’annuncio urgente del singolo errore. Non aggiungere un secondo role=alert attorno allo stesso messaggio.
- Pending e successo usano un solo role=status per cambiamento; lo spinner decorativo va nascosto se il testo annuncia già l’attesa.
- Il focus resta visibile e segue l’ordine DOM. Non usare tabIndex positivi né autofocus aggressivo dopo successo o errore generale.
- Su viewport stretti label, descrizioni, errori e azioni vanno a capo senza separarsi dal controllo a cui appartengono.
Errori da evitare
Questi anti-pattern rendono il recupero ambiguo anche quando la validazione tecnica è corretta.
- Usare il placeholder come unica label o come istruzione permanente.
- Mostrare tutti gli errori soltanto in cima al form, lontano dai controlli coinvolti.
- Comunicare l’errore soltanto con colore, bordo o icona.
- Perdere il focus dopo il submit o spostarlo quando non aiuta il recupero.
- Renderizzare label senza htmlFor/id corrispondenti o riutilizzare lo stesso ID.
- Mostrare nomi di proprietà backend, codici o messaggi raw ricevuti dal server.
- Annunciare lo stesso errore con più live region o usare role=alert per ogni feedback non urgente.