Field Error
A presentational error line that sits under any input. Pass a resolved message string — it renders a danger-colored line (matching esa-form-field's error styling) or nothing when empty.
Preview
Error: This field is required.
<EsaFieldError message="This field is required." /> Empty state
With no message the component renders nothing and collapses out of layout, so it never reserves a gap under the input.
<EsaFieldError message="" />
<EsaFieldError message={null} /> With icon
Set icon for a small leading alert glyph.
Error: Enter a valid email address.
<EsaFieldError message="Enter a valid email address." icon /> Under an input
It is presentational and composable — drop it beneath any control. Your validation layer decides the message.
Error: Enter a valid email address.
<label for="email">Email</label>
<input id="email" type="email" value="not-an-email"
aria-invalid="true" aria-describedby="email-error" />
<EsaFieldError id="email-error" message="Enter a valid email address." icon /> API
| Prop | Type | Default | Description |
|---|---|---|---|
message | string | null | '' | Resolved error message. Renders nothing when null or empty. |
icon | boolean | true | Show the leading alert icon. On by default — without it, an error line and a help line are the same element in the same slot differing only by colour, which is SC 1.4.1. |
id | string | — | The element id, so a control's aria-describedby can point at this message. Without one the association this component exists for cannot be written. |
Accessibility
- This does not announce itself. It is an
.astrocomponent rendered at build time, and it renders nothing at all whenmessageis empty — so there is no element in the DOM for a live region to update. A live region has to already exist, and be empty, before the text arrives; one created together with its content is routinely not announced. This page previously claimed otherwise. -
Its scope is therefore server-rendered errors already present on page load —
the message a form comes back with after a failed round trip. For an error that appears
during a session, use the control's own
error-text: those keep a persistent empty message node exactly so the region can fire, and exposelive-errorto opt into announcing it. -
Purely presentational — it does not own the input's
aria-invalidoraria-describedby. Give it anidand point the control at it, as the example above does. -
The leading icon is decorative (
aria-hidden) and the text carries the meaning — but the icon is doing real work for sighted users, since colour alone cannot distinguish an error line from a hint (SC 1.4.1). Prefericonon.
Theming surface
Every public token this component reads, extracted from its source at build time,
split by blast radius: the hooks that belong to this component,
then the shared and system tokens it consumes alongside everything else. The
Resolves to column walks each token's real lineage —
component → semantic → primitive → raw value — so you
can see exactly where re-pointing it lands. A spoke re-skins by overriding these in
its theme-<slug>.css; component internals are never edited. No
hook for what you need? File it with /request-lego.
Type roles it names
This component does not set a size, weight, face or tracking of its own — it names a composite, and the composite carries all five. A composite is a class rather than a token, so none of it appears in the tables below; re-theme text by re-pointing the token family, not by editing the component.
| Role | Re-point | Reach |
|---|---|---|
.typography-body-xs |
| +14 more componentsesa-breadcrumbs, esa-checkbox, esa-checkbox-group, esa-combobox, esa-command-palette, esa-empty-state, esa-entity-search, esa-header-nav, esa-input-tag, esa-progress-bar, esa-radio-group, esa-search-panel, esa-select, esa-textarea |
Wired to this component
None. This component has no hooks of its own — it themes entirely through the shared tokens below, so every override here also moves its siblings.
Shared tokens it reads
Owned by a family or by the semantic layer. Still overridable — but scope the
override (esa-foo { --form-border-color: … }) unless you mean to move
everything that reads it. Reach says what else that is.
| Token | Reach | Resolves to |
|---|---|---|
--form-help-gap | component forms group · +5 more | 0.25rem via --spacing-100 |
--color-content-utility-danger | semantic every component | #ce2c31 via --color-red-11 |
--spacing-100 | primitive every component | 0.25rem |