Notifications
On this page
The system has four notification primitives, each with a locked anatomy and attention budget.
The hierarchy
Four tiers, in descending order of persistence and ascending order of attention demanded:
| Tier | Primitive | Persistence | Use when… |
|---|---|---|---|
| Classification strip | fdt-classification |
Always visible | It’s the classification / security context of the surface itself. Structural, not notifying. See FDT-specific primitives. |
| Banner | wa-callout |
Stays until resolved or dismissed | Persistent information applies to the current surface - “You’re viewing read-only data from a snapshot,” “Sync is delayed, last update 14:23Z” |
| Toast | wa-toast |
Ephemeral, auto-dismisses | Confirmation of a user action - “Mission saved,” “Track classified as hostile” |
| Alert / Dialog | wa-dialog |
Blocks interaction until resolved | Requires user decision - “Discard changes?”, “Confirm termination?” |
The rule for picking one: match the persistence to the information. Ephemeral action feedback is a toast. Persistent surface-state information is a banner. Required decision is a dialog.
Severity mapping
All four tiers share the same severity palette, driven by the same semantic tokens:
| Severity | Color | Use |
|---|---|---|
| Info / brand | electric-500 / electric-400 text |
Neutral informational - “System updated to v1.2.3” |
| Success | neutral |
User action completed - “Mission saved” |
| Caution | caution |
Recoverable warning - “Sync is slower than usual” |
| Danger | hostile / hostile-400 text |
Action failed or critical condition - “Request denied: insufficient clearance” |
The severity determines the left border color on banners, the icon color on toasts, and the primary button variant on dialogs. Severity is also announced via ARIA live regions (aria-live="polite" for info/success, aria-live="assertive" for caution/danger).
Toast
Ephemeral confirmations of user actions. Toasts announce that something the user did succeeded, failed, or produced a recoverable condition.
Anatomy
- Position: bottom-right on desktop, bottom-center on mobile
- Width: 320–480px
- Icon: FA Sharp Regular, 16px, in semantic color
- Message: Inter 500 13px,
fog-100, one line preferred, two maximum - Dismiss control:
xmarkicon top-right, 12px,steel-300 - Optional action: one text button right-aligned, Inter 500 13px,
electric-400- e.g.,Undo
Stacking
- Maximum 3 toasts visible at a time. Newest at the top of the stack.
- A fourth toast replaces the oldest (first-in-first-out).
- Stack spacing: 8px between toasts.
Dismissal timing
| Severity | Auto-dismiss after |
|---|---|
| Info / success | 5 seconds |
| Caution | 8 seconds |
| Danger | Never - manual dismiss only |
Danger toasts require the operator to see and acknowledge them. An auto-dismissing “Request denied” toast is worse than useless.
Never use a toast for
- Information the operator must act on (use a dialog or banner)
- Confirmation of passive actions the user already saw happen (field saves, menu opens) - the UI already shows the outcome
- Multi-line explanations (toast is a headline, not an article)
Banner (callout)
Persistent surface-level information. Banners stay visible as long as the condition they describe is active.
Anatomy
- Position: top of the main content area, directly below the classification strip if one is present
- Width: full width of the content area
- Left border: 3px in semantic color
- Background:
navy-800, 1pxnavy-600border on the non-accent sides - Icon: 16px semantic color, top-aligned left
- Content: Inter 400 14px,
fog-200, up to 3 lines - Optional primary action: inline
wa-buttonon the right of the banner - e.g.,Refresh data - Dismiss control:
xmarkicon far-right, only when the banner is dismissible (non-critical banners). Critical banners (security notices, data-integrity warnings) are not dismissible until the condition resolves.
Stacking
- Maximum 2 banners visible at a time. If more conditions apply, consolidate into one banner or let the most critical take the slot.
- Banners stack vertically with 8px gap, highest-severity on top.
Never use a banner for
- Fleeting confirmations (use a toast)
- Required decisions (use a dialog)
- Dense dashboards where the banner would compete with data content - if the surface is packed, the banner should probably be a toast with a persistent status indicator
Alert / Dialog
Blocks the surface until the operator makes a decision. Used for destructive actions, permission requests, unsaved changes warnings, confirmation of irreversible operations.
Anatomy (wa-dialog)
- Overlay:
navy-900at 70% opacity behind the dialog - Dialog:
navy-800background,navy-6001px border,--fdt-glow-lghalo, 4px border radius - Width: 480px standard, 640px for dialogs with form content, 320px for terse confirmations (all responsive down to mobile full-width minus 32px)
- Title: H3, Inter 600 16px,
fog-100 - Body: Inter 400 14px,
fog-200, describes the action and its consequences - Actions: right-aligned at the bottom, horizontal row. Minimum one action. Destructive actions use
dangervariant with an action-named label (“Terminate program,” not “OK”). Cancel / non-destructive options useneutral plain.
Rules
- Always at least one action. A dialog with no action is a banner.
- Never dismiss by clicking outside. Require an explicit action - clicking outside closes consumer dialogs, but operator dialogs protect against accidental decisions.
- Keyboard:
Esccancels (triggers the secondary / cancel action),Enterconfirms the primary action. - Never auto-dismiss. Dialogs wait for the operator.
- Never more than one dialog at a time. If a second dialog would appear, queue it behind the first - never stack.
Destructive dialog pattern
Title: Terminate program?
Body: This will stop all in-flight operations for PROGRAM-23-ALPHA
and archive the workspace. This cannot be undone.
Actions: [Cancel] [Terminate program]
^ danger variant
The destructive action button carries the action name, not “OK.” The operator’s last read before clicking is what they’re about to do, not an affirmation.
ARIA and screen readers
- Toasts: wrapped in
role="status"(info/success) orrole="alert"(caution/danger), witharia-livematching the severity - Banners: the container has
role="region"witharia-labeldescribing the banner’s purpose - Dialogs:
wa-dialoghandlesrole="dialog",aria-modal="true", and focus trapping automatically. The dialog title is the accessible name. - Announce timing: severity determines urgency -
aria-live="polite"for info/success (doesn’t interrupt),aria-live="assertive"for caution/danger (interrupts current announcement)
Anti-patterns
- Toasts for critical information. They disappear. If the operator looks away for 5 seconds, it’s gone.
- Multiple simultaneous dialogs. Stack-overflow of user decisions. Queue or consolidate.
- Banners in dense dashboards. They compete with the data content. Use a persistent status indicator in the header instead.
- Toasts that acknowledge expected behavior. “Clicked a button,” “Saved a field,” “Navigated to a page” - if the UI already visibly changed, the toast is noise.
- Classification strips used as notifications. They’re structural and always present - not a signal of change. If you need to signal a classification change, use a banner with the classification change as the content.
- Dialogs for informational messages. If no decision is required, it’s a banner (persistent info) or toast (ephemeral). Dialogs are for decisions.
- “X” close button as the only action on a dialog. Every dialog has at least one labeled action button.
- Ambiguous action names.
OK,Submit,Yes,Confirmdon’t describe what happens. UseTerminate program,Delete user,Revoke access,Save draft- the button label is what the operator reads before clicking.