A one-line announcement across the top of a site or app: a short message, an optional link and an optional dismiss control, on a full-width strip.
Options
| Choice | Values | Default | What it does |
|---|---|---|---|
tonesmbk-banner--tone-<value> | defaultinfosuccesswarningdanger | default | Neutral, or one of the four feedback families on their subtle surface with their border beneath, each with its own icon. |
Examples
Usage
A message, a link and the dismiss control across the full width.
Tones
Five tones: neutral and the four feedback colors, each with its own icon and its border beneath.
Without a link
The link is optional; the message stays centered.
Without dismiss
Without a dismiss handler the control is left out, for a notice that must stay.
Mobile
In a narrow space the message wraps beside its icon and the link sits under them, from the start edge.
Custom icon
Any Phosphor icon replaces the tone's own.
Guidelines
Purpose
A short announcement that runs across the full width at the very top of a site or an app, above the header or the app bar: a new release, planned maintenance, a trial about to end. It speaks about the whole site, not about the page under it, which is what separates it from an alert, which sits inside the page next to what it is about.
When to use
- News or a notice that concerns every page of a site, shown until the reader dismisses it or the situation ends.
- A notice that must stay, such as a service outage, without the dismiss control.
When not to use
Usage rules
Do
- Keep the message to one short sentence and let the link carry the details.
- Show one banner at a time.
- Give the link words that say where it goes, such as "Read the notes", never "Click here".
Don't
- Write a paragraph in it. It wraps into a block that pushes the page down.
- Stack banners, or use one for a message about the page below it.
- Pass a link component as the message. Give the wrapper the link as
link, with its address and its words, and it draws the link after the message.
Keep the message to one short sentence and let the link carry the details, so the strip reads at a glance.
A paragraph in a banner wraps into a block that pushes the page down and is skipped unread.
Show one banner at a time, so the top of the page holds one announcement.
Stacked banners compete for the same place and read as noise.
Anatomy
- The block, a full-width strip with no rounding and one hairline line along its bottom edge, drawn inside the strip so it takes no room.
- The content part, which centers the lead and the link in the room the dismiss control leaves.
- The lead part, holding the icon part and the message part side by side.
- The icon part: a megaphone on the neutral tone, and on the feedback tones an info circle, a tick, a warning sign or a crossed circle, in the tone's icon color. Any Phosphor icon can replace it, and it can be left out.
- The message part, one short sentence.
- The link part, optional: the small link, underlined, placed after the message.
- The dismiss part, optional: the small ghost button with a cross.
Behavior
None of its own. The dismiss control calls back and the page removes the banner; the page also remembers that it was dismissed, so it does not come back on the next page. The link goes wherever the page points it.
The strip is one line tall. In a wide space too narrow for the message, the message wraps beside its icon and stays centered, and the link follows it or drops beneath it; the strip grows to fit. In a narrow space, such as a phone, everything starts at the start edge: the message wraps beside its icon and the link sits under them. The form follows the layout switch, so an element around the banner can force either. The difference is presentational only.
Accessibility
What it does for you
- The strip is a region of the page with a name, "Announcement" unless the page gives it another, so a screen reader can find it and skip it.
- It is part of the page as it loads, so it is not announced as a live message.
- The dismiss control is a real button named "Dismiss".
- The tone is shown by the icon's shape and the words as well as the color.
What you must do
- Give each banner its own name when a page shows more than one.
- Use an alert for a banner that appears while the reader is on the page, such as an outage notice pushed in later. That is an alert's job, not a banner's.
- When the reader dismisses the banner, move focus to the start of the page that remains, not to nowhere.
- Write the message so it makes sense without the color, and keep the icon on a feedback tone.
- Never give the strip the
bannerrole. That role marks the page's own header, so a screen reader would report two headers. In plain markup, give it the region role and a name, as the wrapper does. - Give the dismiss control's name, and every other word the banner 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: its link 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 banner, and focus lands on the page that remains.
- With a screen reader, the banner is found as a region named "Announcement" or the name you gave, and it is not announced when the page loads.
- With text at 200% and the page 320 pixels wide, the message wraps and the controls stay reachable.
Keyboard
| Key | What it does |
|---|---|
| Tab | Moves focus to the banner's link, then to the dismiss control. |
| Enter | Follows the focused link, or presses the dismiss control. |
| Space | Presses the dismiss control. |
Source
The files the banner is made of. Its folder on GitHub (opens in a new tab) holds them with its wrapper and its document.
Stylesheet
/* smbk-banner — Banner. Figma "Banner" 4381:2200. */
.smbk-banner {
/* 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-subtle);
--smbk-tone-text: var(--smbk-color-text-subtle);
--smbk-tone-icon: var(--smbk-color-icon-subtle);
box-sizing: border-box;
display: flex;
align-items: center;
gap: var(--smbk-space-inline-xl);
width: 100%;
min-height: var(--smbk-size-control-md);
padding: var(--smbk-space-inset-xs) var(--smbk-space-inset-md);
background: var(--smbk-tone-surface);
/* The line along the bottom edge. Figma strokes it inside the frame, over the padding, so it takes
no room: drawn as an inner shadow, as the accordion draws its own, the strip stays one control tall. */
box-shadow: inset 0 calc(-1 * var(--smbk-border-width-hairline)) 0 var(--smbk-tone-border);
color: var(--smbk-tone-text);
}
/* The lead (the icon and the message) and the link, centered in the room the dismiss control
leaves. A message too long for one line wraps beside its icon, centered, and the link follows
it or drops beneath it. Figma draws one line only in a wide space. */
.smbk-banner__content {
display: flex;
flex: 1 1 auto;
flex-wrap: wrap;
align-items: center;
justify-content: center;
column-gap: var(--smbk-space-inline-xl);
row-gap: var(--smbk-space-stack-xs);
min-width: 0;
text-align: center;
}
/* The icon beside the message, its box as tall as the message's line so it sits on the first line's middle. */
.smbk-banner__lead {
display: flex;
align-items: flex-start;
gap: var(--smbk-space-inline-md);
min-width: 0;
}
.smbk-banner__icon {
display: inline-flex;
flex-shrink: 0;
align-items: center;
height: calc(var(--smbk-typography-body-sm-font-size) * var(--smbk-typography-body-sm-line-height));
color: var(--smbk-tone-icon);
font-size: var(--smbk-size-icon-md);
}
.smbk-banner__message {
margin: 0;
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);
}
.smbk-banner__dismiss {
flex-shrink: 0;
}
/* ---- feedback tones: the tone recipe, each family's subtle surface, its border on the line beneath, its text and
its icon ---- */
.smbk-banner--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-banner--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-banner--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-banner--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 (Figma's Platform=Mobile): the strip grows to hold its words; the message
wraps beside its icon and the link sits under them, all from the start edge. ---- */
@container style(--smbk-layout: narrow) {
.smbk-banner__content {
flex-direction: column;
flex-wrap: nowrap;
align-items: flex-start;
text-align: start;
}
}
/* ---- touch: the link takes an invisible press area ----
On a touch screen an invisible area, centred on it, takes the press out to the comfortable target in each direction
it falls short of it; its look, its focus ring and its place stay as drawn. */
@media (pointer: coarse) {
.smbk-banner__link {
position: relative;
}
.smbk-banner__link::after {
content: '';
position: absolute;
inset: min(0%, (100% - var(--smbk-size-target-comfortable)) / 2);
}
}Tokens it reads
| Token and CSS | Value | Preview | Foundation |
|---|---|---|---|
| color.surface.default--smbk-color-surface-default | light: #f3f5f8dark: #181a1cchanges with theme | Color | |
| color.border.subtle--smbk-color-border-subtle | light: #c4cdd8dark: #2d3237changes with theme | Color | |
| color.text.subtle--smbk-color-text-subtle | light: #4e555edark: #9ba5b1changes with theme | Color | |
| color.icon.subtle--smbk-color-icon-subtle | light: #4e555edark: #c4cdd8changes with theme | Color | |
| space.inline.xl--smbk-space-inline-xl | comfortable: 16pxcompact: 12pxchanges with density | Spacing | |
| size.control.md--smbk-size-control-md | comfortable: 40pxcompact: 32pxchanges with density | Size | |
| space.inset.xs--smbk-space-inset-xs | 4px | Spacing | |
| space.inset.md--smbk-space-inset-md | comfortable: 8pxcompact: 6pxchanges with density | Spacing | |
| border-width.hairline--smbk-border-width-hairline | 1px | Border width | |
| space.stack.xs--smbk-space-stack-xs | 4px | Spacing | |
| space.inline.md--smbk-space-inline-md | comfortable: 8pxcompact: 6pxchanges with density | Spacing | |
| 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 |
| size.icon.md--smbk-size-icon-md | 20px | Size | |
| 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 | |
| size.target.comfortable--smbk-size-target-comfortable | 44px | Size |
Manifest
{
"name": "banner",
"block": "smbk-banner",
"summary": "A one-line announcement across the top of a site or app: a short message, an optional link and an optional dismiss control, on a full-width strip.",
"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 with their border beneath, each with its own icon."
}
},
"flags": {},
"parts": [
"content",
"lead",
"icon",
"message",
"link",
"dismiss"
],
"figmaNodeId": "4381:2200"
}