Error Summary
import { ErrorSummary } from '@absoluteui/components/error-summary';import '@absoluteui/components/error-summary/style.css';Using Angular? See Error Summary for Angular.
What it does
Section titled “What it does”Accessible error navigation. ErrorSummary lists every error after a failed submission as links that move focus to the offending field, following the GOV.UK error summary pattern. The summary is a labelled region that receives focus when shown, so screen readers announce its heading and contents once, without a live region. Form creates and fills one automatically; it can also be used on its own, for example for server-rendered errors.
When to use
Section titled “When to use”- After a failed form submission, to list all errors at the top of the form with links to each field.
- Showing server-side errors after a full page load, including errors that belong to no field.
When not to use
Section titled “When not to use”- Inline messages next to a field: controls render those; for other controls use Validation Message.
- Non-error notices or confirmations: use an alert or toast.
- Forms managed by Form: it creates and fills the summary itself (use Form’s summaryHost to place it).
Examples
Section titled “Examples”Standalone summary linking to invalid fields
Section titled “Standalone summary linking to invalid fields”import { ErrorSummary } from '@absoluteui/components/error-summary';import { TextInput } from '@absoluteui/components/text-input';
const summaryHost = document.createElement('div');const nameHost = document.createElement('div');document.body.append(summaryHost, nameHost);const name = TextInput.create(nameHost, { label: 'Full name' }).input;const summary = ErrorSummary.create(summaryHost);// Focus moves to the summary; each linked item focuses its target on activation.summary.show([ { message: 'Enter your full name', target: name }, { message: 'The service is busy. Try again in a few minutes.' },]);Summary for AbsoluteUI controls with a custom focus callback
Section titled “Summary for AbsoluteUI controls with a custom focus callback”import { ErrorSummary, type ErrorSummaryNavigateDetail } from '@absoluteui/components/error-summary';import { TextInput } from '@absoluteui/components/text-input';
const summaryHost = document.createElement('div');const emailHost = document.createElement('div');document.body.append(summaryHost, emailHost);const email = TextInput.create(emailHost, { label: 'Email', name: 'email', type: 'email', required: true });const summary = ErrorSummary.create(summaryHost, { headingLevel: 3, description: 'Fix the following to continue.' });
if (!email.reportValidity()) { summary.show([{ message: email.validity.message, target: email.host, focus: () => { email.focus(); } }]);}summaryHost.addEventListener('aui-navigate', (event) => { const { index } = (event as CustomEvent<ErrorSummaryNavigateDetail>).detail; summaryHost.dataset.lastNavigated = String(index);});Heading level for pages whose form sits under an h2 (Mode B)
Section titled “Heading level for pages whose form sits under an h2 (Mode B)”import { configureAbsoluteUI } from '@absoluteui/core';import '@absoluteui/components/error-summary';
configureAbsoluteUI({ components: { errorSummary: { headingLevel: 3 } } });import { ErrorSummary } from '@absoluteui/components/error-summary';import '@absoluteui/components/error-summary/style.css';
// Errors rendered by the server into data attributes on each invalid input.const host = document.querySelector<HTMLElement>('#error-summary');if (host) { const invalid = Array.from(document.querySelectorAll<HTMLInputElement>('input[data-error]')); const summary = ErrorSummary.create(host); summary.show(invalid.map((input) => ({ message: input.dataset.error ?? '', target: input })).filter((item) => item.message !== ''));}More usage
Section titled “More usage”import { ErrorSummary } from '@absoluteui/components/error-summary';
const summaryHost = document.createElement('div');const name = document.createElement('input');name.id = 'full-name';document.body.append(summaryHost, name);ErrorSummary.create(summaryHost).show([{ message: 'Enter your full name', target: name }]);Anatomy
Section titled “Anatomy”<div class="aui-error-summary" role="region" aria-labelledby=title tabindex="-1" hidden> (consumer host) <h2 class="aui-error-summary__title" id=title> <svg class="aui-error-summary__icon aui-icon" aria-hidden="true"><span>There is a problem</span> </h2> <p class="aui-error-summary__description"> (optional) <ul class="aui-error-summary__list"> <li><a class="aui-error-summary__link" href="#field-id">Message</a></li> (item with target) <li>Message</li> (item without target) </ul></div>API reference
Section titled “API reference”Factory
Section titled “Factory”ErrorSummary.create(host: HTMLElement, options?: ErrorSummaryOptions): ErrorSummaryGlobal configuration key: errorSummary (see Configuration).
Options
Section titled “Options”| Option | Type | Default | Description |
|---|---|---|---|
title |
string |
Heading text. Default: localized “There is a problem”. | |
description |
string |
Optional text under the heading. | |
icons |
Partial<{ error: IconRef }> |
Heading icon override. | |
headingLevel |
2 | 3 | 4 |
2 |
Native heading element level. Globally configurable. |
focusOnShow |
boolean |
true |
Move focus to the summary when show() displays items. show(items, { focus }) overrides it per call. Globally configurable. |
locale |
string |
"en-US" |
Locale of the default heading. Globally configurable. Inherited from common configuration. |
Properties
Section titled “Properties”| Property | Type | Description |
|---|---|---|
host |
HTMLElement |
Consumer host; becomes the summary region. |
items |
readonly ErrorSummaryItem[] |
Items currently shown. |
isVisible |
boolean |
True while items are shown. |
Methods
Section titled “Methods”| Method | Description |
|---|---|
show(items: readonly ErrorSummaryItem[], options?: { focus?: boolean }): void |
Replace the items and show the summary (an empty list hides it). Focuses and scrolls to the summary unless focus is false or focusOnShow is false. Throws on an empty message before changing anything. |
clear(): void |
Remove all items and hide the summary without moving focus. |
update(options: Partial<ErrorSummaryOptions>): void |
Merge options and re-render the heading and description. Invalid options leave the previous options in place. |
destroy(): void |
Remove rendering, attributes, class, and the configuration subscription; unhide the host. |
Events
Section titled “Events”| Event | Detail | Bubbles | Cancelable | Description |
|---|---|---|---|---|
aui-navigate |
{ index: number; message: string } |
Yes | No | A summary link was activated and focus moved to its target. |
CSS classes
Section titled “CSS classes”All rules live in the aui.components cascade layer, so application styles override them without specificity battles.
| Class | Purpose |
|---|---|
aui-error-summary |
Host (role=region, tabindex=-1). |
aui-error-summary__title |
Heading (h2, h3, or h4). |
aui-error-summary__icon |
Heading icon. |
aui-error-summary__description |
Optional text under the heading. |
aui-error-summary__list |
List of errors. |
aui-error-summary__link |
Link to a field; items without a target are plain list text. |
Icon slots
Section titled “Icon slots”| Slot | Default icon |
|---|---|
error |
alert-circle |
Design tokens
Section titled “Design tokens”Tokens this stylesheet reads (verified in CI). Override them in a theme or with the Theme Designer.
--aui-border-width | --aui-border-width-strong | --aui-color-error-fg | --aui-color-error-subtle | --aui-color-focus-ring | --aui-color-text | --aui-focus-ring-offset | --aui-focus-ring-width | --aui-font-family-sans | --aui-font-size-md | --aui-font-weight-medium | --aui-font-weight-semibold | --aui-icon-size-md | --aui-line-height-normal | --aui-line-height-tight | --aui-radius-md | --aui-space-1 | --aui-space-2 | --aui-space-4 | --aui-space-5
TypeScript definitions
Section titled “TypeScript definitions”type HeadingLevel = 2 | 3 | 4;interface ErrorSummaryItem { readonly message: string; readonly target?: HTMLElement | null; readonly focus?: () => void }interface ErrorSummaryIcons { error: IconRef }interface ErrorSummaryOptions { title?: string; description?: string; headingLevel?: HeadingLevel; focusOnShow?: boolean; locale?: string; icons?: Partial<ErrorSummaryIcons> }interface ErrorSummaryNavigateDetail { index: number; message: string }Accessibility
Section titled “Accessibility”Pattern: GOV.UK error summary: a focusable, labelled region with a native heading and a list of in-page links to the invalid fields.
Keyboard
Section titled “Keyboard”| Key | Context | Action |
|---|---|---|
| Tab / Shift+Tab | Summary or a link focused | Moves between the summary links and the rest of the page. |
| Enter | Link focused | Focuses the target (or calls its focus callback), scrolls it to the center, and emits aui-navigate. |
| Element | Role |
|---|---|
| host | region |
| heading | heading (native h2, h3, or h4) |
| list | list (native ul) |
| item with target | link (native a href=#id) |
| icon | none (aria-hidden=true) |
ARIA attributes
Section titled “ARIA attributes”| Attribute | Element | Value |
|---|---|---|
aria-labelledby |
host | Heading id |
tabindex |
host | -1, so the summary can receive programmatic focus without entering the Tab order |
show() moves focus to the summary and scrolls it into view (focusOnShow). The host shows the shared focus ring on :focus-visible; links have their own 1px-offset focus ring.
WCAG 2.2 success criteria addressed
Section titled “WCAG 2.2 success criteria addressed”| Criterion | Level | Note |
|---|---|---|
| 1.3.1 Info and Relationships | A | |
| 1.4.1 Use of Color | A | |
| 1.4.3 Contrast (Minimum) | AA | |
| 2.1.1 Keyboard | A | |
| 2.4.3 Focus Order | A | |
| 2.4.6 Headings and Labels | AA | |
| 2.4.7 Focus Visible | AA | |
| 3.3.1 Error Identification | A | |
| 3.3.3 Error Suggestion | AA | |
| 4.1.2 Name, Role, Value | A |
Automated test results: Accessibility and compliance.
Notes and known caveats
Section titled “Notes and known caveats”- Focusing the summary makes screen readers announce the region name (the heading) and its contents once; no live region is used.
- Link activation prevents the fragment navigation, so the URL hash does not change and focus lands on the control, not its container.
- Links are underlined and error-colored; color is not the only cue.
- Choose headingLevel to fit the page’s heading outline.
- Announcement on focus has not yet been manually verified with NVDA, JAWS, and VoiceOver.
Behavior
Section titled “Behavior”States
Section titled “States”hidden, visible, focused (:focus-visible ring), link hover (thicker underline), link focus-visible.
State transitions
Section titled “State transitions”| From | Trigger | To |
|---|---|---|
| hidden | show(items) with items |
visible; focused unless disabled |
| visible | show(items) |
items replaced; focused again unless disabled |
| visible | show([]) or clear() |
hidden; focus unchanged |
| visible | link activated | focus on target; aui-navigate |
Accessibility notes
Section titled “Accessibility notes”- Focus moves to the summary when shown, so its name and contents are read once; no live region is used.
- Link activation prevents the fragment navigation: the URL hash does not change and focus lands on the control itself.
- Links are underlined and error-colored; color is not the only cue (WCAG 1.4.1).
- Choose
headingLevelto fit the page’s heading outline. - Manual screen-reader verification is pending (see Known limitations).
Responsive behavior
Section titled “Responsive behavior”Block-level grid filling its container; long messages wrap.
Right-to-left
Section titled “Right-to-left”Logical properties: the thick border sits on the inline-start side and the list indents from the inline start.
Theming
Section titled “Theming”Error-subtle background with error-foreground border, heading, and links, from role tokens only. Forced-colors mode uses CanvasText for the border and LinkText for links.
Global configuration
Section titled “Global configuration”configureAbsoluteUI({ components: { errorSummary: { headingLevel: 3 } } });Changes apply to existing instances immediately. Form passes focus explicitly (from its focusOnInvalid option), so focusOnShow does not affect Form-owned summaries.
Component configuration
Section titled “Component configuration”Instance options override global and theme defaults. All options are dynamic.
icons.error (default alert-circle), shown in the heading.
Security
Section titled “Security”Heading, description, and messages use textContent and are never parsed as HTML. Link hrefs are only #id fragments of the targets. CSP-safe.
Data handling
Section titled “Data handling”No persistence, network access, or telemetry.
Performance
Section titled “Performance”One configuration subscription and one click listener per link. show() rebuilds the list. No dedicated performance budget.
Supported data scale
Section titled “Supported data scale”Unit tests cover up to four items. A summary is meant for the errors of one form; dozens of items render without issue but become hard to use.
Edge cases
Section titled “Edge cases”- An item with an empty or non-string
messagethrowsERROR_SUMMARY_ITEMbefore anything changes. - A target without an id receives a generated one.
show([])hides the summary and never moves focus.- Calling
show()again while visible re-focuses the summary (unlessfocus: false).
Errors
Section titled “Errors”| Code | Category | Cause |
|---|---|---|
ERROR_SUMMARY_ITEM |
configuration | An item’s message is empty or not a string. |
CFG_INVALID_VALUE |
configuration | headingLevel is not 2, 3, or 4, or focusOnShow is not a boolean. |
Invalid options at construction throw before rendering; in update() they leave the previous options in place.
Known limitations
Section titled “Known limitations”- A target without an id is modified (an id is generated).
- Without script, the
#idlink only scrolls; focus lands on the target only if it is focusable. - Heading levels are limited to 2, 3, and 4.
- Announcement on focus has not yet been manually verified with NVDA, JAWS, and VoiceOver.
Unsupported scenarios
Section titled “Unsupported scenarios”- HTML or custom content in items.
- Item actions other than navigation.