An inline message that stays on the page: an icon, a title, a description, and an optional action or dismiss control.
New version available
Options
| Choice | Values | Default | What it does |
|---|---|---|---|
tonesmbk-alert--tone-<value> | defaultinfosuccesswarningdanger | default | Neutral, or one of the four feedback families on their subtle surface. Figma calls this "Variant". |
Examples
Usage
Title and description on the default surface.
Scheduled maintenance
Tones
Five tones: neutral and the four feedback colors, each with its own icon.
Scheduled maintenance
New version available
Payment received
Storage almost full
Deploy failed
With action
A small secondary button at the end.
New version available
Dismissible
A close control appears when a dismiss handler is given.
Invite sent
Mobile
In a narrow space the action moves under the words, lined up with them.
The site stopped answering
With a list
The description holds paragraphs or a short bulleted list, in its own text style.
5 things to fix before you publish
The page can't go live until these are fixed:
- Add a title to the page.
- Write alt text for 3 images.
- Replace the broken link in the footer.
- Pick a date for the post.
- Choose a category.
Guidelines
Purpose
A message that belongs to the page and stays until the situation changes: a warning above a form, a notice that something is unavailable, confirmation that an action went through. It is inline, which is what separates it from a toast, which arrives and leaves on its own.
When to use
- Explaining a state the person needs to know about while they work.
- Confirming a completed action where the result stays visible.
- A note set into the page's own text, such as a warning at the step of a tutorial where things break. It is static, not live.
When not to use
- Short-lived confirmations. Use a toast.
- Field-level errors. Those sit under the field.
Usage rules
Do
- Write the title as the situation and the description as what to do about it.
Don't
- Show more than one alert of the same tone in one place. Combine them.
Storage almost full
Name the situation in the title and say what to do in the description, so the reader can act at once.
Warning
A title that only says "Warning" repeats the color and leaves the reader to work out the rest.
Two fields need attention
Combine problems of the same tone into one alert, so the page shows one message per concern.
Invalid email
Password too short
Stacked alerts of the same tone compete for attention and read as noise.
Anatomy
- The block, a bordered row on the default or a subtle feedback surface.
- The icon part, a glyph at the start, centered on the title's line. Each tone has its own: a bell for the neutral tone, an info circle, a tick, a warning sign and a crossed circle for info, success, warning and danger, in the tone's icon color. Any Phosphor icon can replace it.
- The body part, holding the title part and the description part, the title sitting straight on its text. The description holds a sentence, several paragraphs or a short bulleted list, in the description's text style.
- The action part, an optional small secondary button (Figma's Action boolean), or several.
- The dismiss part, an optional cross button, the size of the icon in a box big enough to press.
Behavior
None of its own. The dismiss control calls back and the page removes the alert; the action is whatever the page gives it.
In a narrow space, such as a phone, the action moves under the title and description, lined up with them, so the words keep the alert's full width; several buttons wrap onto more lines when they need to. The cross stays at the end of the first line. The form follows the layout switch, so an element around the alert can force either.
Accessibility
What it does for you
- An alert is live by default: a message that arrives while the reader is on the page. Danger and warning alerts carry the alert role and are announced at once; the others carry the status role and are announced politely.
- The wrapper sets the role from
liveand the tone, and a role given to it is ignored: choose the announcement withlive. - The dismiss control is a real button with an accessible name.
- The tone is shown by the icon's shape and the text as well as the color.
What you must do
- Give an alert that is part of the page as it loads
liveas false. A note inside an article or a standing notice under a heading is not a message and must not be announced. It carries the note role and is read in place with the text around it. Its tone still shows through the icon and the words, and it looks the same either way. - Choose by how the alert gets there, not by its tone. A warning written into the page is static; a success that appears after the reader saves is live.
- Keep a list in the description short, since it is read as part of the one message. Put nothing that can be pressed in it: the action and the dismiss control are the alert's only controls.
- Give a replacement icon that carries the tone as clearly as the one it replaces.
- In plain markup, give it the role the wrapper would: note for a static alert, alert for a live danger or warning alert, status for any other live alert.
- Give the dismiss cross's name, and every other word the alert says by itself, in the page's own language. They keep their English unless the page gives its own.
How to test
- Tab through it: the action and the dismiss control take focus in turn, with the focus ring showing in both themes and in a forced-color mode.
- Press Enter, then Space on the dismiss control: each dismisses the alert.
- With a screen reader, a live alert is announced when it appears, a danger or warning one at once. A static one is read in place and not announced.
- With text at 200% and the page 320 pixels wide, the title and description wrap and the controls stay reachable.
Keyboard
| Key | What it does |
|---|---|
| Tab | Moves focus to the action, then to the dismiss control. |
| EnterorSpace | Presses the focused action or dismiss control. |
Source
The files the alert is made of. Its folder on GitHub (opens in a new tab) holds them with its wrapper and its document.
Stylesheet
/* smbk-alert — Alert. Figma "Alert" 4139:6031. */
.smbk-alert {
/* The neutral tone; each feedback tone sets these again below (the tone recipe). */
--smbk-tone-surface: var(--smbk-color-surface-default);
--smbk-tone-border: var(--smbk-color-border-rim);
--smbk-tone-text: var(--smbk-color-text-default);
--smbk-tone-icon: var(--smbk-color-icon-subtle);
box-sizing: border-box;
display: flex;
align-items: flex-start;
gap: var(--smbk-space-inline-lg);
width: 100%;
padding: var(--smbk-space-inset-lg) var(--smbk-space-inset-xl);
border: var(--smbk-border-width-hairline) solid var(--smbk-tone-border);
border-radius: var(--smbk-radius-container-sm);
background: var(--smbk-tone-surface);
color: var(--smbk-tone-text);
}
/* The icon's box is as tall as the title's line, so the icon sits on the first line's middle. */
.smbk-alert__icon {
display: inline-flex;
flex-shrink: 0;
align-items: center;
height: calc(var(--smbk-typography-label-lg-font-size) * var(--smbk-typography-label-lg-line-height));
color: var(--smbk-tone-icon);
font-size: var(--smbk-size-icon-md);
}
/* The title sits on its text with no gap: the line heights give the air. */
.smbk-alert__body {
display: flex;
flex: 1 1 0;
flex-direction: column;
gap: var(--smbk-space-text-label);
min-width: 0;
}
.smbk-alert__title {
margin: 0;
font-family: var(--smbk-typography-label-lg-font-family);
font-size: var(--smbk-typography-label-lg-font-size);
font-weight: var(--smbk-typography-label-lg-font-weight);
line-height: var(--smbk-typography-label-lg-line-height);
letter-spacing: var(--smbk-typography-label-lg-letter-spacing);
text-transform: var(--smbk-typography-label-lg-text-transform);
}
.smbk-alert__description {
margin: 0;
color: var(--smbk-color-text-subtle);
font-family: var(--smbk-typography-body-sm-font-family);
font-size: var(--smbk-typography-body-sm-font-size);
font-weight: var(--smbk-typography-body-sm-font-weight);
line-height: var(--smbk-typography-body-sm-line-height);
letter-spacing: var(--smbk-typography-body-sm-letter-spacing);
}
/* The description holds a sentence, several paragraphs or a short bulleted list, in its own text
style: paragraphs a paragraph apart, list items a line of list spacing apart, the bullets inside
the alert's box. */
.smbk-alert__description > :where(p, ul, ol) {
margin: 0;
}
.smbk-alert__description > * + * {
margin-block-start: var(--smbk-space-text-paragraph);
}
.smbk-alert__description :where(ul, ol) {
display: flex;
flex-direction: column;
gap: var(--smbk-space-text-list);
padding-inline-start: var(--smbk-space-inset-xl);
}
/* One action or several; several wrap when the room runs out. */
.smbk-alert__action {
display: flex;
flex-shrink: 0;
flex-wrap: wrap;
gap: var(--smbk-space-inline-md);
}
/* .smbk-alert__dismiss: the cross is the size of the icon, in a box big enough to press, centred on the title's line;
the box reaches past the glyph by the same amount on every side, so the glyph sits where Figma draws it. It is the
small press box, with its focus ring and its press area on a touch screen, shared in press-box/press-box.css. */
/* ---- feedback tones: the tone recipe, each family's subtle surface, its border, its text and its icon ---- */
.smbk-alert--tone-info { --smbk-tone-surface: var(--smbk-color-feedback-info-surface-subtle); --smbk-tone-border: var(--smbk-color-feedback-info-border); --smbk-tone-text: var(--smbk-color-feedback-info-text-on-subtle); --smbk-tone-icon: var(--smbk-color-feedback-info-icon); }
.smbk-alert--tone-success { --smbk-tone-surface: var(--smbk-color-feedback-success-surface-subtle); --smbk-tone-border: var(--smbk-color-feedback-success-border); --smbk-tone-text: var(--smbk-color-feedback-success-text-on-subtle); --smbk-tone-icon: var(--smbk-color-feedback-success-icon); }
.smbk-alert--tone-warning { --smbk-tone-surface: var(--smbk-color-feedback-warning-surface-subtle); --smbk-tone-border: var(--smbk-color-feedback-warning-border); --smbk-tone-text: var(--smbk-color-feedback-warning-text-on-subtle); --smbk-tone-icon: var(--smbk-color-feedback-warning-icon); }
.smbk-alert--tone-danger { --smbk-tone-surface: var(--smbk-color-feedback-danger-surface-subtle); --smbk-tone-border: var(--smbk-color-feedback-danger-border); --smbk-tone-text: var(--smbk-color-feedback-danger-text-on-subtle); --smbk-tone-icon: var(--smbk-color-feedback-danger-icon); }
/* ---- the narrow form: the action goes under the title and description, lined up with them, so
the words keep the alert's full width (Figma's Narrow layout). The cross stays on the first line. ---- */
@container style(--smbk-layout: narrow) {
.smbk-alert {
flex-wrap: wrap;
row-gap: var(--smbk-space-stack-sm);
}
.smbk-alert__action {
box-sizing: border-box;
flex-basis: 100%;
order: 1;
padding-inline-start: calc(var(--smbk-size-icon-md) + var(--smbk-space-inline-lg));
}
}Tokens it reads
| Token and CSS | Value | Preview | Foundation |
|---|---|---|---|
| size.target.min--smbk-size-target-min | 24px | Size | |
| typography.label-lg--smbk-typography-label-lg-font-family--smbk-typography-label-lg-font-size--smbk-typography-label-lg-font-weight--smbk-typography-label-lg-line-height--smbk-typography-label-lg-letter-spacing--smbk-typography-label-lg-text-transform | fontFamily: Geist, Geist Fallback, system-ui, sans-seriffontSize: 16pxfontWeight: 500lineHeight: 1.4letterSpacing: 0px | The quick brown fox | Typography |
| size.icon.md--smbk-size-icon-md | 20px | Size | |
| radius.full--smbk-radius-full | 9999px | Radius | |
| focus.ring.width--smbk-focus-ring-width | 2px | Focus | |
| color.border.focus--smbk-color-border-focus | light: #cc0d0ddark: #f34336changes with theme | Color | |
| focus.ring.offset--smbk-focus-ring-offset | 2px | Focus | |
| size.target.comfortable--smbk-size-target-comfortable | 44px | Size | |
| color.surface.default--smbk-color-surface-default | light: #f3f5f8dark: #181a1cchanges with theme | Color | |
| color.border.rim--smbk-color-border-rim | light: #ffffffe6dark: #ffffff0dchanges with theme | Color | |
| color.text.default--smbk-color-text-default | light: #232527dark: #e7ebf0changes with theme | Color | |
| color.icon.subtle--smbk-color-icon-subtle | light: #4e555edark: #c4cdd8changes with theme | Color | |
| space.inline.lg--smbk-space-inline-lg | comfortable: 12pxcompact: 8pxchanges with density | Spacing | |
| space.inset.lg--smbk-space-inset-lg | comfortable: 12pxcompact: 8pxchanges with density | Spacing | |
| space.inset.xl--smbk-space-inset-xl | comfortable: 16pxcompact: 12pxchanges with density | Spacing | |
| border-width.hairline--smbk-border-width-hairline | 1px | Border width | |
| radius.container.sm--smbk-radius-container-sm | 8px | Radius | |
| space.text.label--smbk-space-text-label | 0px | Spacing | |
| color.text.subtle--smbk-color-text-subtle | light: #4e555edark: #9ba5b1changes with theme | Color | |
| typography.body-sm--smbk-typography-body-sm-font-family--smbk-typography-body-sm-font-size--smbk-typography-body-sm-font-weight--smbk-typography-body-sm-line-height--smbk-typography-body-sm-letter-spacing--smbk-typography-body-sm-text-transform | fontFamily: Geist, Geist Fallback, system-ui, sans-seriffontSize: 14pxfontWeight: 400lineHeight: 1.5letterSpacing: 0px | The quick brown fox | Typography |
| space.text.paragraph--smbk-space-text-paragraph | comfortable: 16pxcompact: 12px | Spacing | |
| space.text.list--smbk-space-text-list | comfortable: 8pxcompact: 6px | Spacing | |
| space.inline.md--smbk-space-inline-md | comfortable: 8pxcompact: 6pxchanges with density | Spacing | |
| color.feedback.info.surface-subtle--smbk-color-feedback-info-surface-subtle | light: #e3ebfedark: #162352changes with theme | Color | |
| color.feedback.info.border--smbk-color-feedback-info-border | #557bff | Color | |
| color.feedback.info.text-on-subtle--smbk-color-feedback-info-text-on-subtle | light: #2f4ab8dark: #b8ccffchanges with theme | Color | |
| color.feedback.info.icon--smbk-color-feedback-info-icon | light: #3b5ce3dark: #7fa0ffchanges with theme | Color | |
| color.feedback.success.surface-subtle--smbk-color-feedback-success-surface-subtle | light: #dffddfdark: #0a2d0echanges with theme | Color | |
| color.feedback.success.border--smbk-color-feedback-success-border | #269936 | Color | |
| color.feedback.success.text-on-subtle--smbk-color-feedback-success-text-on-subtle | light: #016317dark: #8ddf90changes with theme | Color | |
| color.feedback.success.icon--smbk-color-feedback-success-icon | light: #037a1fdark: #54b85bchanges with theme | Color | |
| color.feedback.warning.surface-subtle--smbk-color-feedback-warning-surface-subtle | light: #ffe6dbdark: #431b07changes with theme | Color | |
| color.feedback.warning.border--smbk-color-feedback-warning-border | #da601a | Color | |
| color.feedback.warning.text-on-subtle--smbk-color-feedback-warning-text-on-subtle | light: #913900dark: #febea2changes with theme | Color | |
| color.feedback.warning.icon--smbk-color-feedback-warning-icon | light: #b14904dark: #fa8349changes with theme | Color | |
| color.feedback.danger.surface-subtle--smbk-color-feedback-danger-surface-subtle | light: #fee5e1dark: #4b130echanges with theme | Color | |
| color.feedback.danger.border--smbk-color-feedback-danger-border | #f34336 | Color | |
| color.feedback.danger.text-on-subtle--smbk-color-feedback-danger-text-on-subtle | light: #a51d17dark: #febdb2changes with theme | Color | |
| color.feedback.danger.icon--smbk-color-feedback-danger-icon | light: #cc0d0ddark: #fe7d6dchanges with theme | Color | |
| space.stack.sm--smbk-space-stack-sm | comfortable: 8pxcompact: 6pxchanges with density | Spacing |
Manifest
{
"name": "alert",
"block": "smbk-alert",
"summary": "An inline message that stays on the page: an icon, a title, a description, and an optional action or dismiss control.",
"adapt": "css",
"axes": {
"tone": {
"values": [
"default",
"info",
"success",
"warning",
"danger"
],
"default": "default",
"description": "Neutral, or one of the four feedback families on their subtle surface. Figma calls this \"Variant\"."
}
},
"flags": {},
"parts": [
"icon",
"body",
"title",
"description",
"action",
"dismiss"
],
"figmaNodeId": "4139:6031"
}