Centrim Design System — a token-first, accessible React component 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.
| Component | Scope | Persistence | Use it for |
|---|---|---|---|
| Alert | Section | Until resolved or dismissed | Contextual message about the section it sits in |
| Banner | Page or app shell | Until resolved or dismissed | System notices, maintenance, account-level warnings |
| Toast | Floating overlay | Auto-dismisses | Temporary confirmation of a completed action |
| InlineFeedback | One field or row | Until the value changes | Field validation, inline save results |
| Callout | Body copy | Static | A sentence or two of inline guidance |
| EmptyState | Whole region | Until content exists | Nothing has been created yet |
| NoResultsState | Whole region | Until the query changes | Search or filters matched nothing |
| LoadingState / Skeleton / Spinner | Region or control | While pending | Work in progress |
| ErrorState | Whole region | Until retried | Loading or processing failed |
| SuccessState | Whole region | Until dismissed | A meaningful workflow completed |
| WarningState | Whole region | Until resolved | Attention 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.
Your changes have not been saved
Leaving this page now will discard the last 4 edits.
Unable to load residents
The records service did not respond. Retry, or continue with cached data.
With action, dismissible and solid appearance
Connection lost
We stopped receiving updates from the care records service.
Shift handover notes are now available
Open a resident record to see notes from the previous shift.
Two mandatory training records expire this week
Accent appearance
Tinted panel with a status bar on the leading edge — use inside dense card bodies.
Medication chart is out of date
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
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
Field validation in context
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.
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
Page and region loading
Loading residents…
Fetching the Willow Ward roster.
Loading care notes…
This usually takes a few seconds.
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.
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.