Centrim Design System — a token-first, accessible React component system.
V2 audit — Feedback
Success, warning, error and information, plus the empty and loading states that carry a screen when there is no data yet.
Toast / Notification
Transient confirmation or failure of a completed action.
ToastProvideruseToastNotificationLive component
Toasts live in the root viewport
Trigger them with useToast(); every toast announces politely and auto-dismisses. The specimen here stays inline so the audit page does not spam the viewport.
Legacy mapping
Legacy toasts appeared in three corners with different durations. V2 has one viewport and one duration scale.
| Attribute | Specification |
|---|---|
| Default | variant="neutral", auto-dismiss |
| Variants | neutral · success · warning · error |
| Sizes | Single width, max 400px |
| States | entering · visible · with action · dismissed |
| Icon behaviour | Status icon at `--size-icon-sm`, matching the Alert vocabulary. |
| Spacing | Padding 16px, viewport gap 8px. |
| Typography | Title `text-label-md`, body `text-body-sm`. |
| Border radius | `rounded-md`. |
| Colour usage | Soft-glass surface with a semantic status accent. |
| Responsive | Full-width at the bottom on mobile, bottom-right on desktop. |
When to use
- "Saved", "Invite sent", "Export failed"
When not to use
- Errors the person must act on — use inline validation or a dialog
Accessibility
- Viewport is a labelled `role="region"`; messages are announced politely (assertively on error).
- Never the only place a failure is reported.
Empty / Error / NoResults states
Carries a region when there is nothing to show, nothing matched, or something failed.
EmptyStateErrorStateNoResultsStateSuccessStateLive component
No residents yet
Add a resident to start building care plans.
No results found
No residents match “sunrise night shift”.
Something went wrong
We could not load the roster. Your connection may have dropped.
Legacy mapping
Legacy screens showed a bare "No data" line. V2 always pairs the explanation with the recovery action.
| Attribute | Specification |
|---|---|
| Default | Centred, with icon, title, description and one action |
| Variants | empty · no results · error · success |
| Sizes | compact (in-card) · full (page region) |
| States | static · with primary action · with secondary action |
| Icon behaviour | One illustrative Lucide icon at `--size-icon-xl` in `text-text-tertiary`. |
| Spacing | Vertical rhythm 8/12/24px; region padding 48px in full size. |
| Typography | Title `text-heading-6`, description `text-body-sm`. |
| Border radius | `rounded-lg` when framed in a card. |
| Colour usage | Neutral surface; only the action carries colour. Error state adds an `error-subtle` icon chip. |
| Responsive | Copy width capped at ~48ch; illustration hides under `sm` if space is tight. |
When to use
- First-run, filtered-to-nothing, and failed loads
When not to use
- While data is still loading — use the loading state
Accessibility
- Error states are announced; the retry action is a real button.
Loading states
Communicates work in progress: indeterminate (spinner/skeleton) or determinate (progress).
SpinnerSkeletonLoadingStateProgressCircularProgressLive component
Legacy mapping
Legacy screens blanked the region while loading. V2 preserves layout with skeletons and reserves spinners for actions.
| Attribute | Specification |
|---|---|
| Default | Skeleton for content, Spinner for in-control waits |
| Variants | skeleton block · skeleton text · spinner · linear progress · circular progress |
| Sizes | Spinner xs/sm/md/lg · Progress small/medium |
| States | indeterminate · determinate · complete |
| Icon behaviour | Spinner only; no additional icons while loading. |
| Spacing | Skeletons match the rhythm of the content they replace. |
| Typography | Skeleton lines match the line-height they stand in for. |
| Border radius | `rounded-sm` text skeletons, `rounded-md` blocks. |
| Colour usage | `bg-background-muted` shimmer; spinner uses `currentColor`. |
| Responsive | Skeletons mirror the responsive layout they replace. |
When to use
- Any wait longer than ~300ms
When not to use
- Instant local state changes
Accessibility
- `aria-busy` on the loading region and a polite status message; animation collapses under `prefers-reduced-motion`.