Skip to content

Actions

Error Summary

A focused list of form errors that lets people jump directly to each invalid answer.

When to use it: Use it after an unsuccessful submission in addition to inline FieldError messages.

On this page

Example

Loading example…
Error Summary.tsxtsx
import { useState } from "react";
import {
  Button,
  ErrorSummary,
  ErrorSummaryLink,
  ErrorSummaryList,
  ErrorSummaryTitle,
  FieldError,
  Input,
  Label,
  TextField,
} from "@comp0/react";

export function Example() {
  const [invalid, setInvalid] = useState(false);
  return (
    <form
      className="w-full max-w-md space-y-4 text-base sm:text-sm"
      noValidate
      onSubmit={(event) => {
        event.preventDefault();
        const email = String(new FormData(event.currentTarget).get("email") ?? "");
        setInvalid(!email.includes("@"));
      }}
    >
      {invalid && (
        <ErrorSummary className="rounded-lg border border-red-600/30 bg-red-50 p-4 text-red-950 outline-offset-2 focus-visible:outline-2 focus-visible:outline-red-700 dark:border-red-400/30 dark:bg-red-950 dark:text-red-100 dark:focus-visible:outline-red-300">
          <ErrorSummaryTitle className="font-semibold">There is a problem</ErrorSummaryTitle>
          <ErrorSummaryList className="mt-2 list-disc space-y-1 pl-5">
            <li>
              <ErrorSummaryLink className="underline underline-offset-2" href="#summary-email">
                Enter a valid email address
              </ErrorSummaryLink>
            </li>
          </ErrorSummaryList>
        </ErrorSummary>
      )}
      <TextField id="summary-email" invalid={invalid}>
        <Label className="mb-1 block font-medium">Email address</Label>
        <Input
          name="email"
          type="email"
          className="min-h-10 w-full rounded-lg border border-zinc-950/15 bg-white px-3 py-2 outline-teal-600 focus-visible:outline-2 dark:border-white/15 dark:bg-zinc-900 dark:outline-teal-400"
        />
        <FieldError className="mt-1 text-red-700 dark:text-red-300">
          Enter a valid email address
        </FieldError>
      </TextField>
      <Button
        type="submit"
        className="min-h-10 rounded-lg bg-teal-700 px-3 py-2 font-medium text-white outline-offset-2 focus-visible:outline-2 focus-visible:outline-teal-600 dark:bg-teal-400 dark:text-zinc-950 dark:focus-visible:outline-teal-300"
      >
        Continue
      </Button>
    </form>
  );
}

Anatomy

Dashed frames are invisible state providers; shaded shapes own real DOM. Numbered pins match the list below.

A wireframe sketch of the assembled component. Each numbered marker matches a part in the list that follows.

  1. ErrorSummary

    Assertive, programmatically focusable summary labelled by its title. Owns a DOM element.

  2. ErrorSummaryTitle

    Visible h2 that names the summary. Owns a DOM element.

  3. ErrorSummaryList

    Native unordered list of validation messages. Owns a DOM element.

  4. ErrorSummaryLink

    Native anchor pointing to one invalid control. Owns a DOM element.

Step by step

  1. 1

    Add the main part

    Conditionally render ErrorSummary with an ErrorSummaryTitle when validation fails.

  2. 2

    Add the supporting parts

    Put matching messages in ErrorSummaryList and link each ErrorSummaryLink to its field id.

  3. 3

    Make the behavior clear

    The summary focuses itself on mount by default; keep each inline FieldError visible and worded the same.

    Exampletsx
    <ErrorSummary>
      <ErrorSummaryTitle>There is a problem</ErrorSummaryTitle>
      <ErrorSummaryList>
        <li>
          <ErrorSummaryLink href="#email">Enter a valid email</ErrorSummaryLink>
        </li>
      </ErrorSummaryList>
    </ErrorSummary>;

Keyboard

Moves from the focused summary to its first error link.
Moves from an error link to its matching field.

Forms and accessibility

The summary submits nothing; its links point into the form and supplement inline FieldError messages.

Accessibility checklist

  • Render the summary only after validation fails so its alert and focus movement correspond to a new error state.
  • Link every ErrorSummaryLink to the native control, or to the first invalid control in a grouped answer.
  • Repeat every message beside its field with identical wording; the summary supplements inline errors rather than replacing them.
  • After destructive success or navigation, move focus to the new logical context instead of restoring the submit button.

API reference

Importtsx
import { Button, ErrorSummary, ErrorSummaryLink, ErrorSummaryList, ErrorSummaryTitle, FieldError, Input, Label, TextField } from "@comp0/react";

ErrorSummary

DOM element

Assertive, programmatically focusable summary labelled by its title.

PropTypeDescription
autoFocusbooleanMoves focus to the summary on mount; enabled by default.
tabIndexnumberDefaults to -1 so focus can land without adding a tab stop.

ErrorSummaryTitle

DOM element

Visible h2 that names the summary.

ErrorSummaryList

DOM element

Native unordered list of validation messages.

ErrorSummaryLink

DOM element

Native anchor pointing to one invalid control.

PropTypeDescription
hrefstringFragment URL for the matching invalid control id.

Style hooks

Attributes that appear while a state is true. Target them with Tailwind data variants such as data-open:bg-zinc-100, or with any CSS selector.

ErrorSummary

Style hookMeaning
:focus-visibleThe newly mounted summary received visible keyboard focus.

Keep exploring