Components · Feedback
SaveStatus
The line under a setting that applies at once, which appears only when the change failed and says what failed; otherwise it takes no room.
Also called Save result, Save error, ImmediateSaveStatus
import { SaveStatus } from "@botiverse/raft-ui/wip";SaveStatus is the line under a setting that saves itself: a select, a segmented control or a settings row with a switch. It shows only when the change failed, and says what failed. While the change saves and once it is stored, it shows nothing and takes no room: the control showing its new value is the confirmation, as in macOS's and iOS's settings.
When to use
Which settings apply at once is in Forms.
Anatomy
SaveStatus: the line. Put it right after the control: after the select or the segmented control in aField, before anyFieldDescription, or last in a settings row'sListRowBody, after the description or, in a row with none, the title. Render it in every state; with nothing in it, it is hidden and takes no height. Required.SaveStatusError: what failed, indanger-strong, one footnote line (18px) that wraps. Put it inSaveStatusonly while the change has failed.SaveStatusSaved: deprecated. It renders nothing, whatever its children, so aSaveStatusholding it stays empty. Leave it out.
States
- Idle, saving and saved:
SaveStatuswith nothing in it. It shows nothing and takes no room. The control already shows the new value, which is the confirmation; a "Saved" would repeat it, and a line kept for it made every such row taller than its neighbors (cindyz, 2026-11-10, #proj-raft-ui:4ae1a74e). - Failed: the control goes back to its old value, so it never shows a value that isn't true, and
SaveStatusErrorsays what failed until the next change.
Behavior
- Empty, the line takes no height and no gap, so a setting with it is exactly as tall as one without it. In a settings row, the switch (or the value, chevron or button at the row's end) centers on the whole row, as in any row.
- When a change fails, the line appears 4px under what comes before it: the select or the segmented control in a
Field, or the description in a settings row, or its title when the row has no description, so the error takes the description's place. The setting grows by that line, and in a settings row the switch moves down by half of it, centered on the whole row with the error in it. In aFieldthe line moves up 2px from the field's 6px gap; in aListRowBodyit adds 2px to the body's 2px gap. Anywhere else, put the control and the line together in a block of their own with no gap, and the line is 4px under it. - A failure longer than one line wraps rather than being cut off; keep it to one short sentence.
Content
- Write a failure as what didn't happen and what to do: Couldn't mute this server. Try again. When the request comes back with a reason, show that reason (Writing).
- Don't write "Saved", and don't say where a setting is stored on its row. "Saved on this device" is said once for a section (Forms).
Accessibility
SaveStatusErrorhasrole="alert", so the failure is announced when it appears.- The control announces its own new value (a switch's on or off, a segmented control's or a select's choice), so a change that saves needs no announcement of its own.
- Point the control's
aria-describedbyat the line'sid(onSaveStatus), beside any description, so a failure is read with the control.
API
SaveStatus, SaveStatusError
The line under a setting that applies at once. Render it whatever the setting's state, with `SaveStatusError` inside when the change failed and nothing inside otherwise: empty, it is hidden and takes no height. A `span` (shown as a block), like every ListRow part, so it stays valid inside a row's body; give it an `id` for the control's `aria-describedby`.
Takes the attributes of its element.
SaveStatusSaved
A setting that applies at once no longer says "Saved": the
control showing its new value is the confirmation (Forms, settings that
apply at once). Renders nothing, whatever its children, so its
`SaveStatus` stays empty and takes no height. Leave it out: render
`SaveStatusError` when the change failed and nothing otherwise. It drops
every prop, its `id` too: point a control's `aria-describedby` at the
`SaveStatus` instead.
Takes the attributes of its element.
Related
Changes
- 0.83.0 · FixedA settings row's switch centers on its text, not on the SaveStatus line under it: in a
ListRow variant="plain"whoseListRowBodyends with aSaveStatus, both ends (the switch, value, chevron, checkbox, radio or button, and a leading icon, avatar or tile) center on the title and description. The row moves the line's reserved space (4px and one footnote line) into its bottom padding, so its height is unchanged and nothing moves when "Saved" or a one-line error appears. There is no new prop. - 0.54.0 · AddedSaveStatus (wip, +
SaveStatusSaved,SaveStatusError): the result line under a setting that applies at once. It always keeps one footnote line of height, so "Saved" appearing or going never resizes the card or moves a switch, and it sits 4px under a select, a segmented control or a settings row's description alike.