Design System

Feedback & status

One vocabulary for telling people what happened: five statuses, ten components, and a strict rule about which one belongs where.

What is this?

The feedback family covers every way Centrim Life reports state: contextual alerts, page banners, floating toasts, inline field feedback, and full-region empty, no-results, loading, error, success and warning states.

When to use it

  • Reporting the outcome of an action the user took.
  • Explaining why a region has no content to show.
  • Signalling that work is in progress or that attention is required.

How to use it

  • Pick by scope: field → inline, section → Alert, page → Banner, transient → Toast, whole region → a state.
  • Always pair the status colour with an icon and a text label.
  • Compose actions from Button; never hand-roll a link-styled action.

What to avoid

  • Using EmptyState after the user has searched or filtered.
  • Using a large SuccessState where a Toast is enough.
  • Inventing a new status colour or a one-off feedback style.

Status language

Five statuses, used identically across every feedback component and every screen.

Information — informational contentSuccess — completed, positive outcomeWarning — attention requiredError — failure or critical issueNeutral — general or inactive
Which feedback component to reach for
ComponentScopePersistenceUse it for
AlertSectionUntil resolved or dismissedContextual message about the section it sits in
BannerPage or app shellUntil resolved or dismissedSystem notices, maintenance, account-level warnings
ToastFloating overlayAuto-dismissesTemporary confirmation of a completed action
InlineFeedbackOne field or rowUntil the value changesField validation, inline save results
CalloutBody copyStaticA sentence or two of inline guidance
EmptyStateWhole regionUntil content existsNothing has been created yet
NoResultsStateWhole regionUntil the query changesSearch or filters matched nothing
LoadingState / Skeleton / SpinnerRegion or controlWhile pendingWork in progress
ErrorStateWhole regionUntil retriedLoading or processing failed
SuccessStateWhole regionUntil dismissedA meaningful workflow completed
WarningStateWhole regionUntil resolvedAttention required before continuing

Components

Alert

A contextual status message tied to the section it sits in — the result of a save, a validation summary, or a condition the user must know about before continuing.

import { Alert } from "@/design-system";

When to use

  • Reporting the outcome of a submit that keeps the user on the page.
  • Summarising the errors of a form above the fields.
  • Explaining a condition that affects the section it is placed in.

When not to use

  • For page-wide announcements spanning the whole app — use Banner.
  • For transient confirmation of a small action — use Toast.
  • For a single field's validation message — use InlineFeedback.

Variants

Scheduled maintenance on Sunday

Reporting will be read-only between 02:00 and 04:00 GMT.

Resident profile saved

Changes are visible to the care team immediately.

With action, dismissible and solid appearance

Shift handover notes are now available

Open a resident record to see notes from the previous shift.

Accent appearance

Tinted panel with a status bar on the leading edge — use inside dense card bodies.

Accessibility

  • Error and warning alerts render role=alert; info, success and neutral render role=status.
  • The status icon plus the title text carry meaning, so colour is never the only signal.
  • The dismiss control is an IconButton with an accessible label, keyboard reachable and focus-visible.
  • Subtle and solid appearances both meet WCAG 2.2 AA text contrast in light and dark themes.

Toast

Temporary, floating confirmation of something the user just did. Auto-dismisses and never shifts page layout.

import { ToastProvider, useToast } from "@/design-system";

When to use

  • Confirming a completed action the user does not need to act on (saved, sent, copied).
  • Reporting a background failure with an optional retry.
  • Undo affordances immediately after a destructive action.

When not to use

  • For information the user must not miss — use Alert or Banner.
  • For field validation — use InlineFeedback next to the field.
  • For anything requiring a decision: toasts disappear.

Trigger the four statuses

Accessibility

  • Error and warning toasts use role=alert with aria-live=assertive; others use polite status.
  • The viewport is a labelled region, bottom-right, so it never covers primary page controls.
  • Hover, focus and keyboard focus pause the auto-dismiss timer.
  • Every toast has an explicitly labelled dismiss button; duration 0 disables auto-dismiss.

Inline feedback

One line of feedback rendered directly beside the content it describes: field validation, a save result on a row, a hint about a control.

import { InlineFeedback, Callout } from "@/design-system";

When to use

  • Field-level validation under an input, when Field's own message slot is not available.
  • Confirming an inline edit saved, next to the edited value.
  • A short note attached to one control or one table row.

When not to use

  • For a section-level message with a title and actions — use Alert.
  • For a paragraph of guidance inside body copy — use Callout.

Statuses

Success: Saved successfully.
Info: Visible to the care team only.

Field validation in context

Success: Saved successfully.

Callout — longer inline guidance

Who can see this

Care notes are shared with every member of the resident's care team and retained for seven years.

Accessibility

  • Errors and warnings announce with role=alert; success and info announce politely.
  • A visually hidden status word ("Error:", "Success:") precedes the message so status is not colour-only.
  • Icons are aria-hidden — the text is the accessible content.

Loading states

Five standardised ways to show progress: skeleton for predictable layouts, spinner for short indeterminate work, inline loading beside content, button loading during submits, and page loading for a whole route.

import { Skeleton, SkeletonText, Spinner, InlineLoading, PageLoading, LoadingState } from "@/design-system";

When to use

  • Skeleton when the eventual layout is known — lists, cards, tables.
  • Spinner or InlineLoading for short, indeterminate operations.
  • Button loading while a submit is in flight, keeping the label visible.
  • PageLoading or LoadingState while a route's primary data resolves.

When not to use

  • Do not use a spinner where a skeleton can preserve the layout.
  • Do not stack several spinners on one screen.
  • Do not swap a populated region for a spinner on background refresh — use InlineLoading.

Skeleton — predictable layouts

Spinner, inline and button loading

Refreshing resident list…Saving…

Page and region loading

Loading residents…

Fetching the Willow Ward roster.

Loading care notes…

This usually takes a few seconds.

Accessibility

  • Skeletons are aria-hidden decoration; the live region announcing progress is the surrounding status.
  • Spinner, InlineLoading and PageLoading expose role=status with polite announcements.
  • Button loading keeps the accessible name and disables activation while pending.
  • All animations collapse under prefers-reduced-motion.

Empty, no-results, error, success and warning states

Full-region states that replace content when there is nothing to show, the request failed, a workflow completed, or attention is required. All five compose one shell, so icon, title, description and actions align everywhere.

import { EmptyState, NoResultsState, ErrorState, SuccessState, WarningState } from "@/design-system";

When to use

  • EmptyState: nothing exists yet — offer the action that creates the first record.
  • NoResultsState: content exists but the current search or filters match none of it.
  • ErrorState: loading or processing failed — lead with retry.
  • SuccessState: a multi-step workflow finished and the user needs a next step.
  • WarningState: the region needs attention before it can be used.

When not to use

  • Never show EmptyState when the user has actively searched or filtered.
  • Do not use SuccessState for a small action — use a Toast.
  • Do not use these for messages that sit alongside existing content — use Alert.

Empty vs no results

No residents yet

Add your first resident to start recording care notes and daily observations.

No residents found

No resident matches “okoro” with the Discharged filter applied.

Error, success and warning

Unable to load residents

We could not reach the care records service. Your last synced data is still available offline.

Resident admitted

Joy Okoro is now on the Willow Ward roster and her care plan is active.

Your changes have not been saved

Four fields on this care plan are still in draft. Save them before leaving the page.

No notifications

You are all caught up. New alerts about your wards will appear here.

Accessibility

  • Each state is a heading plus description, so it reads as content rather than decoration.
  • Icons are aria-hidden; the title text carries the meaning.
  • Primary and secondary actions are real Buttons, keyboard reachable with visible focus.
  • Status tone is reinforced by the icon shape, not colour alone.

Rules

How the family stays consistent as screens are built on top of it.

Do

  • Match the component to the scope of the message: field, section, page, overlay or region.
  • Pair every status colour with an icon and a text label so meaning survives greyscale and colour blindness.
  • Write concise, specific copy: “Unable to load residents”, not “Error occurred”.
  • Lead error and warning states with the recovery action (Retry, Save changes, Clear filters).
  • Reuse the semantic status tokens so light and dark themes both pass WCAG 2.2 AA.

Don't

  • Do not stack banners, or use a banner for section-level feedback.
  • Do not put a required decision in a toast — it disappears.
  • Do not show EmptyState when a search or filter is active.
  • Do not introduce new status colours, arbitrary spacing, or one-off feedback styles.
  • Do not replace populated content with a spinner during a background refresh.

Why it is designed this way

Every component here draws from the same five semantic statuses and the same icon vocabulary, so a warning reads the same whether it arrives as a toast, an alert or a full-region state. Differentiation comes from scope and persistence, not from colour or styling — which is what keeps them from becoming interchangeable.

Statuses are rendered with the status-* foreground tokens rather than the fill tokens, so text and icon contrast holds in both themes. Toasts sit in a bottom-right region above the elevation scale and never take layout space, so they cannot cover primary page controls.