ValidationSummary
<caos-validation-summary>
every blocking error on one save, each linked to its field
May be placed on a record page, a page inside an app and a step of a guided flow.
Inputs
Section titled “Inputs”| Name | Attribute | Description | Type | Default | Required |
|---|---|---|---|---|---|
title |
title, markup only |
The heading. Left unset it counts the errors itself — “There are 3 problems to fix”, and the singular when there is one — which is a count that cannot disagree with the list under it. Override it only to say something the count cannot, and note that title is also the standard HTML attribute, so whatever is set here doubles as the element’s hover tooltip. |
text | none declared | Optional |
items |
property only | The blocking errors, as { message, field?, target? }[]. message is the sentence, field is the field name printed in bold ahead of it, and target is the id of the element in the host document to scroll to and focus when the error is pressed. An item with no target is drawn as plain text and skipped by the keyboard. |
json | none declared | Optional |
Events
Section titled “Events”| Name | When it fires | What it carries |
|---|---|---|
caos-validation-focus |
An error carrying a target is pressed — before the summary scrolls to the field and focuses it. It bubbles and crosses the shadow boundary, so a form can listen once at its root. |
{ target, field } — the id being focused, and the field name if the item carried one. |
Nothing goes inside this piece.
Styling hooks
Section titled “Styling hooks”| Design token | What it controls |
|---|---|
--caos-color-danger-bg |
The pale fill behind the whole summary. |
--caos-color-danger |
The glyph, and the list markers. |
--caos-color-danger-text |
The heading and each error link — the on-tint ink, so they hold up in both themes. |
--caos-color-danger-text-muted |
The field name ahead of each message, and the body ink. |
--caos-radius |
The corner radius of the summary. |
--caos-radius-sm |
The corner radius of an error’s focus ring. |
--caos-focus-ring |
The ring drawn on an error reached by keyboard. |
--caos-font |
The typeface the summary is set in. |
--caos-text-row |
The size of the heading. |
--caos-space-4 |
The horizontal padding, and the indent of the list. |
--caos-space-3 |
The vertical padding, and the gap between the glyph and the content. |
--caos-space-2 |
The gap between the heading and the list. |
Methods
Section titled “Methods”Nothing else drives this piece by calling it.
Readable state
Section titled “Readable state”Nothing on this piece can be read back.
Styling parts
Section titled “Styling parts”| Part | Which piece of it | When it is there |
|---|---|---|
::part(summary) |
the alert box | Always |
::part(icon) |
the danger glyph | Always |
::part(title) |
the count line | Always |
::part(list) |
the list of problems | Always |
::part(error) |
one problem, which is the control that jumps to its field | Always |
When to use it
Section titled “When to use it”A save the server refused, where more than one thing is wrong or where what is wrong is off screen. Reach for it whenever the alternative is letting somebody discover the errors one submit at a time.
What to use instead
Section titled “What to use instead”- ErrorPanel — The save FAILED rather than being rejected — the request never got a verdict. That is the line between these two: a rejection is a list of things this person can fix now, a failure is a code and a correlation id for somebody else to look up. A rejected save reported as a failure sends a correctable form to the on-call engineer; a failure reported as a rejection leaves somebody re-reading their own input for a mistake that was never there.
- NoticeBanner — There is one thing to say about the page as a whole and it does not belong to a field — a closed period, a locked record, a decision to make before continuing. The banner says one thing; this piece enumerates and links.
- BaseField — Exactly one field is wrong and it is on screen. Every field draws its own message under itself and turns red when invalid, which is closer to the problem than a summary at the top of the form — use both together when the form is long enough to scroll.
- AccessDeniedPanel — The save was refused because of a missing grant. Nothing in the input is wrong, so there is no list to fix and nothing to link to.
- Toast — The save SUCCEEDED, or failed with nothing for the person to correct. A list of errors must stay on screen while they are being worked through, which is the one thing a toast will not do.
Accessibility
Section titled “Accessibility”The summary is a role="alert" labelled by its own heading, so the whole failure is announced when it appears rather than when somebody happens to reach it, and the glyph is hidden because the heading says the same thing. Each error is a real button inside a real list, so the count is announced and every error is reachable by keyboard — and an error with no target is marked static and given tabindex="-1", which is the deliberate part: a keyboard user is never landed on something that looks pressable and does nothing. Focus moves INTO the field, delegating through a field wrapper’s shadow root to the real control. Left to the author: giving each item a target, and taking the summary off the page once the errors are fixed.
Examples
Section titled “Examples”Every error, linked to its field
Section titled “Every error, linked to its field”One rejected save reported whole: three errors, each naming its field and each pressable — pressing one scrolls to that field and puts the caret in it.
The page around it: The surrounding page supplies the three fields these errors point at, so pressing an error really moves the caret to its field instead of doing nothing.
{ "id": "example", "section": "Every error, linked to its field", "columns": 1, "items": [ { "id": "validation_summary_1", "type": "component", "key": "validation_summary", "inputs": { "title": "This order could not be saved", "items": [ { "field": "Account", "message": "Choose an account.", "target": "vs-account" }, { "field": "Due date", "message": "Must be in the future.", "target": "vs-due-date" }, { "field": "Amount", "message": "Enter an amount before submitting for review.", "target": "vs-amount" } ] } } ]}<caos-validation-summary id="validationSummary1" title="This order could not be saved"></caos-validation-summary>// What an attribute cannot hold, set as a property — the same values the preview is drawn with.const validationSummary1 = document.getElementById('validationSummary1');validationSummary1.items = [ { "field": "Account", "message": "Choose an account.", "target": "vs-account" }, { "field": "Due date", "message": "Must be in the future.", "target": "vs-due-date" }, { "field": "Amount", "message": "Enter an amount before submitting for review.", "target": "vs-amount" }];Errors with no field to point at
Section titled “Errors with no field to point at”What a rejection that does not map onto the form looks like: the messages are drawn as plain text rather than links, and the keyboard skips past them because there is nowhere to go.
{ "id": "example", "section": "Errors with no field to point at", "columns": 1, "items": [ { "id": "validation_summary_1", "type": "component", "key": "validation_summary", "inputs": { "items": [ { "message": "This record is locked while the order it belongs to is being invoiced." }, { "message": "The template it was created from is no longer available." } ] } } ]}<caos-validation-summary id="validationSummary1"></caos-validation-summary>// What an attribute cannot hold, set as a property — the same values the preview is drawn with.const validationSummary1 = document.getElementById('validationSummary1');validationSummary1.items = [ { "message": "This record is locked while the order it belongs to is being invoiced." }, { "message": "The template it was created from is no longer available." }];Errors written as markup
Section titled “Errors written as markup”The same list authored as <li> children instead of set as a property — read once on connect and re-drawn, for a form rendered on the server rather than assembled in script.
Cannot be shown as a page placement:
<caos-validation-summary> <li data-field="Account" data-target="vs-account">Choose an account.</li> <li data-field="Due date" data-target="vs-due-date">Must be in the future.</li></caos-validation-summary>