Gå til innholdet

Error Summary

Når en innsending stopper, skal brukeren få vite hvorfor, og komme til feltet med ett klikk. Serveren skriver overskriften og lista. Komponenten gjør de to tingene nettleseren ikke gjør selv: flytter fokus hit når boksen kommer til syne, og gir fokus til selve kontrollen når en lenke følges.

// main.ts, kjøres én gang når appen starter
import { defineFsErrorSummary } from "@fristil/designsystem/error-summary"
import "@fristil/designsystem/tokens.css"
import "@fristil/designsystem/error-summary.css"
defineFsErrorSummary()
const feil = fs.errorSummary({ count: feilene.length, id: "feil" })
<fs-error-summary class="fs-error-summary" role="alert" tabindex="-1" id="feil">
<h2 class="fs-error-summary__title">Skjemaet har to feil</h2>
<ul class="fs-list">
<li><a href="#epost">Skriv en e-postadresse med krøllalfa</a></li>
<li><a href="#fodselsdato">Skriv datoen som dag, måned og år</a></li>
</ul>
</fs-error-summary>

Overskriften og lista skriver serveren. Komponenten lagde overskriften tidligere selv, og da forsvant den ved første oppdatering fra serveren, uten å komme tilbake. Klassen, role="alert" og tabindex="-1" skriver fs.errorSummary() når markupen lages med JavaScript; ellers setter komponenten dem, og klassen på overskriften, og setter dem tilbake om en patch tar dem. Har serveren skrevet en annen rolle, står den. Se Markup og oppførsel.

Er det ingen feil, setter byggefunksjonen hidden på boksen. En tom oppsummering med overskriften «Skjemaet har 0 feil» er verre enn ingen.

Hver lenke i lista skal peke på id-en til kontrollen som feilet. Peker den på en <label>, følger komponenten ledeteksten videre til kontrollen, enten den peker med for eller omslutter den.

<li><a href="#fodselsdato">Skriv datoen som dag, måned og år</a></li>
...
<input class="fs-input" id="fodselsdato" type="date">
KlasseHva det er
.fs-error-summarySelve boksen. Ligger på <fs-error-summary>
.fs-error-summary__titleOverskriften over lista
VariabelReserve
--fs-error-summary-paddingvar(--fs-spacing-4)
--fs-error-summary-radiusvar(--fs-spacing-1)
.fs-error-summary {
--fs-error-summary-padding: var(--fs-spacing-6);
}

Boksen er role="alert", så den leses opp når den kommer til syne. Den har tabindex="-1" for å kunne få fokus uten å bli en tabbestopp.

To ting er lette å glemme, og begge er grunnen til at komponenten finnes:

  • Fokus flyttes til boksen når den blir synlig. Uten det vet ikke den som hører siden at innsendingen stoppet. Sett data-autofocus="false" hvis du ikke vil ha det. Attributtet heter ikke autofocus, fordi det er en boolsk egenskap på elementet, og React 19 setter egenskapen i stedet for attributtet. Da ville avslaget ikke virket. Signalet er at hidden tas bort. Står boksen synlig fra før når skjemaet feiler på nytt, må appen slå hidden på og av, eller kalle focus() selv. Komponenten flytter ikke fokus av at lista endrer seg, for da ville en oppsummering som krymper mens brukeren retter, rykket fokus ut av feltet. Ett unntak: landet ikke fokus første gang, fordi boksen sto i et skjult panel, prøver den igjen ved neste endring i lista, men bare når ingen står i et felt. Mangler tabindex på boksen, setter komponenten den.
  • Fokus går til selve kontrollen når en lenke følges. En vanlig ankerlenke ruller bare dit, og neste tastetrykk fortsetter der fokus sto før, altså i oppsummeringen.

Komponenten kobler seg også på lenker serveren sender inn senere, så en oppsummering som oppdateres mens brukeren retter, fortsetter å virke.