Skip to content

Form Error Summary

The error pattern that actually works with a screen reader: focus the summary, link to the fields, punish late.

Prominimaleditorial
Category
Patterns
Added
2026-09-21
Deps
none
Updated
2026-09-21

This is a viberdy Pro component

The live preview, the props panel and the write-up are open to everyone. The full source, the AI prompt and CLI install are part of Pro.

Preview

As it appears on your card.

Six letters or digits.

Props

Clear errors while typing
Focus summary on submit
No runtime dependencies
"use client";

import { useRef, useState } from "react";

type Errors = Record<string, string>;

const FIELDS = [
  { id: "name", label: "Full name", type: "text", hint: "As it appears on your card." },
  { id: "email", label: "Email", type: "email", hint: "" },
  { id: "code", label: "Access code", type: "text", hint: "Six characters, letters and digits." },
];

function validate(values: Record<string, string>): Errors {
  const e: Errors = {};
  if (!values.name?.trim()) e.name = "Enter your full name.";
  // A SHAPE CHECK, not validation. Only sending mail proves an address exists,
  // and every clever regex here rejects somebody's real address.
  else if (values.name.trim().length < 2) e.name = "Enter your full name, not an initial.";

  // ---------------------------------------------------------------
  // Full source available with a viberdy Pro subscription.
  // https://viberdy.dev/pricing
  // ---------------------------------------------------------------
}
Notes

About this pattern

Form validation is where accessibility and ordinary usability turn out to be the same problem, and the pattern that solves both is the one the GOV.UK Design System arrived at after more testing than anyone else has done. On a failed submit, focus moves to a summary panel rather than to the first invalid field. That is deliberate twice over: a live region whose contents appeared in the same render is announced inconsistently across screen readers and sometimes not at all, while moving focus is reliable everywhere; and jumping to the first bad field tells someone about one problem while hiding the others, when what they need first is how many there are and where. The summary takes a negative tabindex so it can receive focus programmatically without joining the tab order, and each error is a link that explicitly focuses its field, because a fragment link scrolls but does not reliably move focus. The timing rule matters as much as the markup. Validation runs on submit, and after that a field is only re-checked while typing if it is ALREADY in error — so a message clears the moment it is fixed, but nobody is told their email address is wrong while they are on the third character. Each field carries aria-invalid and an aria-describedby that references its hint and its error in that order, and the message is repeated inline as well as in the summary, because the summary is for orientation and the inline copy is what you read while fixing it.

Curator’s note

Focus the summary, not the first bad field. Jumping to a field tells the user about one problem and hides the rest.

Related

Pairs well with

Matched on shared tags and category — the entries most likely to be used alongside this one.

Featured
NewPro

An undo window that defers the action instead of reversing it, and pauses when you tab toward the button.

undotoastasync
Pro

A validated wizard with per-step gating, an editable review step, and a real success state.

formwizardmulti-step
Featured
NewPro

A button that survives a real round trip — a minimum pending duration, a width that never twitches, aria-disabled instead of disabled.

buttonasyncloading