Skip to content

System Views

Utility views that handle loading states and navigation dead ends. These are not linked to a specific model; they serve as default fallbacks when a route cannot be resolved or data is still in flight.

ViewLoading

Route-level loading fallback. Composes SystemMessageCard(tone="loading") with the loading icon registry key, optional request identity in the crest kind, a skeleton preview, and a heartbeat strip. Once slowAfterMs is reached the card flips to warning tone and switches its crest icon name to hourglass.

ViewNotFound

Route-level 404 fallback. Composes SystemMessageCard(tone="info") with a "404" crest showing the typed path, a TriedUrlCallout whose bad segments are diff'd against the closest registered route, a SuggestionList(shape="route") listing N-best matches with similarity-score chips, a DiagnosticStrip debug footer (route by default; extend via the diagnostics prop), and a Back + Go to home actions row.

Suggestion data comes from useSuggestRoutes({ limit }) (N-best matches with scores). The number of suggestions defaults to 5 and is configurable via the suggestionLimit prop. The home button navigates to homePath (default /). Both the blurb and actions slots accept overrides.

Customization surface

KeyElementDefault classes
rootOuter <div>flex min-h-full items-center justify-center p-8
blurbDefault <p>text-[13px] leading-[1.5] text-muted-foreground

ViewActionNotFound

Model-action 404 fallback. Composes SystemMessageCard(tone="info") with a "404" crest showing the app/model/action key (action segment tinted destructive in the callout), a TriedUrlCallout with label Action key, a SuggestionList(shape="action") listing all registered actions for the closest matching model sorted by similarity to the tried action, a DiagnosticStrip debug footer, and a Back + Browse all actions actions row.

Suggestions widen the previous closest-only behavior: every action on the closest model is rendered, sorted by stringSimilarity against the tried action name. HTTP verb chips in the action shape remain empty until the server exposes per-action verb metadata.

Customization surface

KeyElementDefault classes
rootOuter <div>flex min-h-full items-center justify-center p-8
blurbDefault <p>text-[13px] leading-[1.5] text-muted-foreground

SystemMessageCard

Centered 460 px card chassis shared by all four system views (NotFound, ActionNotFound, Loading, Deactivate) and by the AuthAndMFA card. Provides a tone-tracked 36 px crest icon tile above a border separator, a meta column (eyebrow label + mono kind text), an optional trailing status code, a body slot, and an optional actions footer.

The root carries data-tone and opens a group/system-message-card named scope. The crestIcon theme key routes soft tint colors (about 12 to 14 percent opacity) from that scope via group-data-[tone=*]/system-message-card: variants, so the icon resolved from icon-name inherits the tinted ink color automatically.

Set icon-name to a registry key to render the crest icon. Pass icon-props for per-call attributes or classes, and use iconOverride to replace the icon registry entry for this card and its descendants.

Customization surface

KeyElementDefault classes
rootCard <div>max-w-[460px] · flex column gap-5 · rounded-vueda-card border bg-card · px-8 pt-8 pb-7 · 1 px foreground/4 bottom shadow
crestCrest row <div>flex items-start gap-3 pb-4 border-b border-border
crestIconIcon tile <div>36 px square · 4 px radius · 18 px icon · tone-tinted bg + ink via named group scope
crestMetaEyebrow + kind stack <div>flex flex-col justify-center gap-0.5 min-w-0 flex-1
crestEyebrowEyebrow <span>10 px / 600 / uppercase / 0.06 em tracking · text-muted-foreground
crestKindKind <span>mono 12 px / 500 · text-foreground
crestCodeTrailing code <span>mono 36 px / 600 / tabular-nums · text-foreground/50 · hidden when slot absent
bodyBody wrapper <div>flex flex-col gap-3
actionsActions footer <div>flex items-center gap-2 · hidden when slot absent

ConsequencesBullets

Bulleted consequence list for destructive surfaces. Each row renders an optional leading icon, a bold label, and an optional muted description inside a 2-column grid (icon · label/sub stack). Per-row tone (default | warn | danger) tints only the leading icon via the toneWarn / toneDanger keys, so the list signals relative severity without overwhelming the surrounding card.

Icons resolve through useIcons("ConsequencesBullets"). Register a component under each icon name your messaging uses (or fall back to a Default registry entry). When the lookup misses, the icon cell still renders so labels stay aligned across rows.

Customization surface

KeyElementDefault classes
root<ul>flex column, gap-2, list-reset
item<li> rowgrid grid-cols-[18px_1fr] items-start gap-x-2.5
iconleading icon <span>18 px square cell, 14 px glyph, text-muted-foreground
textlabel/description stackflex flex-col gap-0.5 min-w-0
labellabel <span>13 px / 600 / --foreground
descriptiondescription <span>11.5 px / 400 / --muted-foreground
toneWarnapplied to icon wrappertext-warning (active when item.tone === "warn")
toneDangerapplied to icon wrappertext-destructive (active when item.tone === "danger")

ViewDeactivate

Self-service account deactivation view. Wraps the deactivate action in a SystemMessageCard(tone="warning") chassis: an icon crest identifies the action, an optional ConsequencesBullets list communicates the impact, and a TypedConfirmField gates the destructive button on the operator typing their own email address. Sends a PATCH to the model's deactivate endpoint on confirmation.

Props: app + model + pk (or array of PKs) identify the target. consequences[] forwards to ConsequencesBullets; when empty the bullet list is omitted. The message slot overrides the default suspension explanation paragraph.

The submit button stays disabled until TypedConfirmField emits a match and remains disabled while the request is in-flight. On success the component emits success. On a non-200 response an inline error paragraph appears.

Customization surface

KeyElementDefault classes
rootOuter <div>flex min-h-full items-center justify-center p-8
messageDefault message <p>text-[13px] leading-[1.5] text-muted-foreground
errorError <p>text-[12px] text-destructive leading-[1.5]

TypedConfirmField

Anti-mistake confirmation primitive shared by destroy, deactivate, and recovery-code regenerate flows. The operator must type the exact expectedValue before the consumer's destructive button enables. The chrome is the canonical "type it to mean it" recipe: a bordered, muted-tinted box with a 12 px sans label, an inline mono chip showing the expected literal, and a 32 px mono input.

Consumers read the match state via v-model:match (or the match event) and gate their submit control on it. The raw typed value is exposed via v-model for callers that need to echo or inspect it.

Customization surface

KeyElementDefault classes
rootOuter <label>muted-tinted box · rounded-vueda-card · 12 px gap-1.5 column
labelLabel text <span>12 px sans, foreground ink
expectedChipInline <code> chipmono 12 px semibold · rounded 3 px · border + background fill
inputText <input>32 px tall · mono 12.5 px · hairline + focus-visible:focus-ring-shadow

TriedUrlCallout

Bordered callout showing the URL path or action key the user attempted, with the bad segment tinted destructive. Used in ViewNotFound and ViewActionNotFound to ground the suggestion list visually rather than explaining the typo in prose.

The root is a 2-column grid: an 88 px uppercase eyebrow label column on the left, a 1fr mono value column on the right. The segments prop accepts a { text, bad? }[] array; segments with bad: true receive text-destructive, while non-bad segments receive the fade theme key (muted-foreground by default) so the destructive segment reads as the error signal.

Customization surface

KeyElementDefault classes
rootOuter <div>grid grid-cols-[88px_1fr] · rounded-vueda-card border · px-3 py-2
labelLabel <span>10 px / 600 / uppercase / 0.06 em tracking · text-muted-foreground
valueValue wrapper <span>mono 12.5 px / 400 · min-w-0 truncate
fadeNon-bad segment <span>text-muted-foreground — fades path so bad segments pop

SuggestionList

SuggestionList is the "Did you mean?" list the 404 views compose. It takes a head label, an optional mono source label, and a list of rows. Each row is a four-column grid: icon, label with an optional sub-line, a trailing chip, and a chevron. Two shapes decide what the trailing chip carries: route shows a similarity score, action shows an HTTP verb.

Each row renders a router-link, so an application installs vue-router and these navigate. This page has no router, so the rows below render the anchor a real RouterLink would produce and swallow the click; hover and focus are otherwise the real recipe.

Theme keys: SuggestionList.

DiagnosticStrip

DiagnosticStrip is the two-column definition list the system views put in their footer, so an operator can copy the request id, route, and session into a ticket rather than describing what they saw. Values render monospace by default because they exist to be pasted somewhere else.

It presents whatever the view hands it. Nothing in the strip is fetched, and nothing about it changes what the server did.

Theme keys: DiagnosticStrip.

ErrorDisplay

ErrorDisplay is the dismissible error card the view layer renders above a failed surface. ActionForm mounts one for every submit, which is why a failed save shows a card without the view doing anything. It takes an errored flag and an error, and formats whatever it is given: an Error, a FetchError carrying a response and server detail, an array of several, or a bare string.

It also reports each distinct error to Sentry once. That is part of its contract rather than a side effect of these demos: no Sentry client is initialised for this documentation site, so the calls below go nowhere.

Several error classes are deliberately ignorable, so a view can mount one card and still let the surfaces that own those failures present them instead: ignore-form-validation-errors for per-field validation that belongs on the fields, ignore-list-filter-errors for filter errors that belong on the chip, and ignore-aborted-requests for a request the user navigated away from.

Displaying an error changes nothing on the server. It reports what already happened, and dismissing the card does not retry or undo it.

Theme keys: ErrorDisplay.

Documents matching: server v3.0.0a1.post1client v3.0.0-alpha.2