Alert
A message that stays on the page with the content it is about.
In Dense data
See it live
npm run storybookWhen to use it
In Dense data: A problem that stays on the page.
- Use it when: People need to read a standing notice or how to recover, on this page, tied to what they are doing.
- Not when: A short confirmation that can go away by itself, or one notice for the whole site.
Instead:
- Toast: Short, non-blocking, goes away.
- Dialog: Needs an answer before going on.
- Site banner: One full-width notice for the whole site.
Variants
What each variant is for in any design system, then what Dense data decided and why. Each sample is the live story with that variant set.
defaultvariantNot used in Dense dataWhat it is for
A notice that stays on the page: information or a heads-up.
In Dense data
Alerts here are for problems that stay on the page; news goes in a toast or a badge.
destructivevariantUsed in Dense dataWhat it is for
Something failed or will be lost, and people must act to recover.
In Dense data
A record that was not saved or an action that failed: name the record, then the fix, with an icon.
How Dense data uses it
Why it works this way
Alert looks the way it does because of 4 answers about this product. Each card is one answer, in three steps: the answer, what it decided for Alert, and what would move if it changed.
outcomes.q21The answer
Acting on the wrong row is the costly error.
2So Alert
- –does not use default: Alerts here are for problems that stay on the page; news goes in a toast or a badge.
- ✓uses destructive: A record that was not saved or an action that failed: name the record, then the fix, with an icon.
Button: primary Button: secondary Button: danger Toast: danger3If it changed
and 2 answers that follow from it: Status in tables, Errors and empty states.
tasks.q21The answer
The same actions repeat many times an hour.
2So Alert
- –does not use default: Alerts here are for problems that stay on the page; news goes in a toast or a badge.
Button: ghost Input group: inline-end Sidebar: default Toast: success Toggle: default3If it changed
and 11 answers that follow from it: Time on task, All day, Three, and 8 more.
accessibility.count1The answer
Many statuses share one table; color alone is not enough.
2So Alert
- ✓uses destructive: A record that was not saved or an action that failed: name the record, then the fix, with an icon.
Badge: neutral Badge: info Badge: success Badge: warning Badge: danger3If it changed
No other answer follows from it.
voice.values1The answer
Experts want short labels and short messages.
2So Alert
- ✓uses destructive: A record that was not saved or an action that failed: name the record, then the fix, with an icon.
Toast: neutral Toast: success Toast: danger3If it changed
No other answer follows from it.
Words
- Lead with the object, then the state: "Alert 2041 contained."
- Use numbers, not words for numbers.
- One verb per button. No "please", no exclamation marks.
- Use: Investigate, Filter, Assign, Escalated, Resolved. Avoid: Oops, Awesome, Please, Simply.
The labels components use, from the voice tokens:
content.action.commit: Savecontent.action.cancel: Cancelcontent.action.destroy: Deletecontent.action.retry: Retrycontent.action.empty-action: Change filters
See Voice and tone for the whole voice.
Accessibility and keyboard
Test before you ship:
- An error that appears after an action is announced (role alert); a standing note is not. undefined
- The tone also shows as an icon and words, never color alone. undefined
Use it in code
npx open-ds add alert
The component reads only component keys and semantic tokens, so it follows the brand and mode on <html>.
Tokens it reads
Alert reads 15 tokens of its own, each an alias of a semantic token. Each row is one part: its own token, the semantic it aliases, and the value it ends at. Change a semantic and every component that reads it follows; override one of Alert's tokens to change Alert alone.
Dense data decides what changes when you switch theme. Here a switch changes colors only, so the marked rows differ between light and dark; everything else holds steady.
| Part | Its token and the semantic it aliases | Value |
|---|---|---|
| Alert | ||
| Gap y | component.alert.gap-ycomponent-spacing-map.hairlinevar(--alert-gap-y) | space.2:0.125rem |
| Corner | component.alert.radiusradius.containervar(--alert-radius) | radius.4:0.25rem |
| Padding, left and right | component.alert.padding-xspace.inset.containervar(--alert-padding-x) | space.16:1rem |
| Padding, top and bottom | component.alert.padding-ycomponent-spacing-map.x3var(--alert-padding-y) | space.12:0.75rem |
| Text size | component.alert.font-sizetype.body.font-sizevar(--alert-font-size) | font.size.14:0.875rem |
| Gap x | component.alert.gap-xcomponent-spacing-map.x3var(--alert-gap-x) | space.12:0.75rem |
| Icon size | component.alert.icon-sizesize.iconvar(--alert-icon-size) | size.16:1rem |
| Default | ||
| Fill Changes with theme | component.alert.default.backgroundcolor.surface.defaultvar(--alert-default-background) | Lightslate.light.0:#FFFFFFDarkslate.dark.50:#161B23 |
| Text Changes with theme | component.alert.default.labelcolor.text.primaryvar(--alert-default-label) | Lightslate.light.900:#161B23Darkslate.dark.900:#F7F8FA |
| Destructive | ||
| Fill Changes with theme | component.alert.destructive.backgroundcolor.surface.defaultvar(--alert-destructive-background) | Lightslate.light.0:#FFFFFFDarkslate.dark.50:#161B23 |
| Text Changes with theme | component.alert.destructive.labelcolor.status.dangervar(--alert-destructive-label) | Lightred.light.600:#C42B2BDarkred.dark.600:#F28B8B |
| Title | ||
| Weight | component.alert.title.font-weighttype.label.font-weightvar(--alert-title-font-weight) | font.weight.500:500 |
| Description | ||
| Gap | component.alert.description.gapspace.gap.tightvar(--alert-description-gap) | space.4:0.25rem |
| Text size | component.alert.description.font-sizetype.body.font-sizevar(--alert-description-font-size) | font.size.14:0.875rem |
| Text Changes with theme | component.alert.description.labelcolor.text.mutedvar(--alert-description-label) | Lightslate.light.600:#535D6DDarkslate.dark.400:#969FAD |
| From the system | ||
| Edge Changes with theme | color.border.default straight from the system, through --border | Lightslate.light.200 · #DDE2EADarkslate.dark.100 · #262D38 |