Banner
A banner is a full-width strip at the top of the app for a message about the whole app or account. You put any content inside it.
<tk-banner tone="warning" label="Trial ending"> Your Team trial ends in 3 days. <tk-button slot="actions" size="small">Upgrade</tk-button> </tk-banner>
Anatomy
| Part | What it is |
|---|---|
tk-banner |
the element; spans the full width |
banner part |
the strip: background and bottom border |
content part |
the centered row inside, up to --tk-banner-max-width wide |
icon slot and part |
the leading intent icon; decorative |
default slot (body part) |
your content: text, a link, a countdown, a small form |
actions slot and part |
optional actions at the end of the row |
| dismiss button | the ✕, only with dismissible |
Variants
<tk-banner label="Announcement">We've refreshed the dashboard.</tk-banner> <tk-banner tone="info" label="New version">A new version is available.</tk-banner> <tk-banner tone="success" label="Connection">You're back online.</tk-banner> <tk-banner tone="warning" label="Maintenance">Maintenance tonight at 22:00 UTC.</tk-banner> <tk-banner tone="error" label="Billing">Your payment failed. Update your card.</tk-banner>
neutral(default): a plain announcement.info: a notice or advice.success: good news about the whole app.warning: a caution, such as maintenance or a trial ending.error: a problem to fix, such as billing or being offline.
Each tone has its own icon shape, a triangle for warning and circles for the rest. Say the intent in the text too; color alone doesn't tell everyone.
Treatment
treatment="loud" makes an inverse strip: dark in the light theme, light in the dark theme.
It ignores the tone's color, but the tone still picks the icon.
<tk-banner treatment="loud" label="Cookie notice"> We use cookies to improve your experience. <tk-link slot="actions" href="/privacy" color="inverse">Privacy policy</tk-link> </tk-banner>
Use subtle (default) for everyday banners and loud for a message that must stand out.
There is no solid red or amber strip.
Placement
static(default): the banner sits in the page flow and pushes the content down.sticky: the banner stays at the top while the page scrolls and keeps its space.
The strip spans the full width. Its content row is centered and caps at 1200px; set
--tk-banner-max-width to your page column so the text lines up with the page below.
Put the banner early in the DOM, so keyboard and screen reader users meet it first, as they see it. To pin a banner over the content, reserve the space for it in your page layout.
Actions
<tk-banner tone="info" label="New version"> Version 3.2 is ready. <tk-link slot="actions" href="/changelog" treatment="quiet">What's new</tk-link> <tk-button slot="actions" size="small">Reload</tk-button> </tk-banner>
- Put a quiet
or atk-linksecondaryorghost intk-buttonslot="actions". - Use at most one main and one secondary action. If you need more, use a dialog or a page.
- On a
loudstrip, usetk-link color="inverse". Buttons have no inverse style and may lack contrast there.
Dismiss
<tk-banner tone="success" label="Connection" dismissible>You're back online.</tk-banner>
dismissible adds a ✕ named by dismiss-label. Clicking it fires a cancelable
tk-dismiss event, and the banner hides itself unless you call preventDefault().
banner.addEventListener('tk-dismiss', (event) => {
event.preventDefault();
saveDismissed('maintenance');
banner.remove();
});- Don't make a banner dismissible if the user must act on it, such as a blocked account.
- If the banner had focus, move focus somewhere sensible after it closes.
When to use
- Use a banner for an app-wide message: scheduled maintenance, a trial ending, offline, a new version, a cookie notice.
- Use a
Section message for a note about one part of the page. Both can appear on one screen: a billing banner in the chrome and an invoice note inside the billing page. - Use a
Toast for a short confirmation that goes away on its own. - Use a
Dialog when the user must act before going on. A banner never blocks and never takes focus. - Show one banner at a time. Decide in your app which one wins.
Content
- Say what happened or what's coming, then what to do, in one or two sentences.
- Give a date when there's a deadline: "Your trial ends on Monday. Upgrade to keep your projects."
- Name the next step in the action: "Update card", "Reload". Never "OK".
More in
Do / Don't
| ✅ Do | ❌ Don't |
|---|---|
| Use it for a message about the whole app | Use it for a note about one section; use a section message |
| Show one banner at a time | Stack several banners at the top |
Set live when you add the banner after load |
Announce a banner that was there on load |
| Use a dialog when the user must act first | Make a must-act banner dismissible |
Use tk-link color="inverse" on a loud strip |
Set role="banner" on it |
Related
Section message : a message inside the page content.Toast : a short message that disappears on its own.Dialog : a message that blocks until the user acts.Button andLink : what goes inactions.
API
Attributes
| Attribute | Type | Default | What it does |
|---|---|---|---|
tone |
neutral | info | success | warning | error |
neutral |
intent: tint, icon, and border |
treatment |
subtle | loud |
subtle |
tinted strip or inverse strip |
placement |
static | sticky |
static |
in the flow, or pinned to the top while scrolling |
live |
off | polite | assertive |
off |
announce a banner added after load |
label |
string | "" |
accessible name; makes the banner a named region |
dismissible |
boolean | false |
shows the ✕ |
dismiss-label |
string | "Dismiss" |
accessible name of the ✕ |
hide-icon |
boolean | false |
removes the intent icon |
Slots
| Slot | Content |
|---|---|
| default | the message: any content |
icon |
replaces the intent icon; hidden from screen readers |
actions |
links and buttons at the end of the row |
Events
| Event | What it means |
|---|---|
tk-dismiss |
the ✕ was clicked; cancelable, and the banner hides unless you prevent it |
CSS
- Parts:
banner,content,icon,body,actions. --tk-banner-max-width: the content row's maximum width,1200pxby default.
Tokens
| Treatment / tone | Fill | Text | Icon | Bottom border |
|---|---|---|---|---|
subtle, neutral |
surface/sunken |
text/secondary |
icon/secondary |
border/default |
subtle, info · success · warning · error |
surface/{tone} |
text/{tone} |
icon/{tone} |
border/{tone} |
loud |
surface/inverse |
text/inverse |
icon/inverse |
none |
sticky uses z-sticky. On a loud strip the focus ring is border/inverse. Values per
theme:
Accessibility
Built in:
- Never
role="banner", which is the page header landmark. The banner removes it if set. - With a
label, the banner is a named region screen reader users can jump to. Without one, it's a plain container. - It's not announced by default; a banner present on load is read in page order.
live="polite"gives itrole="status";live="assertive"gives itrole="alert".- It never takes focus. The ✕ has an accessible name, and the intent icon is hidden.
- Text is at least 4.5:1 and the icon at least 3:1 in every tone and theme.
Your part:
- Set a
labelwithout the word "banner": "Maintenance", not "Maintenance banner". - Pick
liveby how the banner appears:offon page load,politefor news added later,assertiveonly for something urgent, such as going offline. - Place it early in the DOM.
- Say the intent in words.