Banner
Highlights a page or section-level status and the actions that resolve it.
Installation
- Install the package.
npm install @hashintel/ds-components- Import the component.
import { Banner } from "@hashintel/ds-components";
export const PermissionsChangeBanner = () => (
<Banner tone="warning">
<Banner.Title>Workspace permissions are changing</Banner.Title>
<Banner.Description>
Members inherited from parent teams must be re-added by 1 November.
</Banner.Description>
</Banner>
);When to use
- Do: Use Banner for a page or section-level condition the user didn't just cause — a permissions change, a failed sync, an expiring trial.
- Do: Place the banner at the top of the page or section it describes, so the status reads before the content it affects.
- Do: Use
Banner.Actionswhen the user can resolve the condition in place — review, retry, approve. - Do: Show one banner per view — when several conditions apply, keep the most severe and fold the rest into its description.
When not to use
- Don't: Don't confirm an action the user just took — show the result inline, next to the control that triggered it.
- Don't: Don't use banners for field-level validation — use Form's field errors under the input.
- Don't: Don't use a banner for a decision that must block the flow — use Dialog.
Anatomy
<Banner tone="neutral">
<Banner.Title>Title</Banner.Title>
<Banner.Description>Description</Banner.Description>
<Banner.Actions>
<Banner.ActionButton>Action</Banner.ActionButton>
</Banner.Actions>
</Banner>Examples
Basic
Description only
Most banners don't need a title — a lone Banner.Description keeps a short
status to a single line.
Tones
tone sets the palette and the default icon: neutral for routine context,
brand for product messages, success to confirm, warning to forewarn, and
error for failures that need attention now.
Variants
soft (the default) tints the surface for messages in the page flow.
outline sits flat on opaque surfaces such as cards and dialogs. solid is a
saturated fill — reserve it for the most prominent page-level messages.
With actions
Wrap Banner.ActionButtons in Banner.Actions so users can resolve the
condition in place — prefer one or two. Action buttons default to a compact
secondary treatment, and the solid variant restyles them to read on the
fill; pass an explicit variant to opt out.
Dismissible
Pass dismissible with an onDismiss callback to render a trailing dismiss
button. Dismissing doesn't automatically remove the banner — you must handle it via the callback. Make
banners dismissible unless they carry critical information or a required
action.
import { useState } from "react";
import { Banner } from "@hashintel/ds-components";
export const EditorTipBanner = () => {
const [dismissed, setDismissed] = useState(false);
if (dismissed) {
return null;
}
return (
<Banner tone="brand" dismissible={{ onDismiss: () => setDismissed(true) }}>
<Banner.Description>
{"Tip: drag a property onto the canvas to add it to the entity type."}
</Banner.Description>
</Banner>
);
};Leading icon
icon defaults to true, the tone's own icon — keep it unless a more
specific glyph adds meaning. Pass { iconName } for a named design-system
icon, or false for none. Pass icon={{ custom }} to lead with any node
Custom children
Children that aren't Banner.Actions render in the message column, so custom
markup can replace or sit alongside the built-in parts. Custom content doesn't
pick up the tone's text color — set your own.
Behavior
- When the banner runs narrow, the actions wrap beneath the message instead of squeezing it into a narrow column.
Content
- Lead the title with what happened, as a short sentence: "Workspace permissions are changing". Use sentence case and no trailing period.
- Keep descriptions to 1–2 sentences: what happened, then what to do about it.
- For
warninganderrorbanners, always say how to resolve the condition. - Write action labels verb-first, 1–3 words: "Review changes", "Retry sync".
- Don't write severity into the copy ("Error:", "Warning!") — the tone's icon and color already carry it.
Accessibility
A banner that announces an urgent problem should implement the WAI-ARIA alert pattern.
What Banner provides
Banner.Titlerenders a real heading —h2by default, but this can be adjusted withas.- No ARIA role is set by default — a banner rendered with the page needs none.
What you must do
- Set
role="status"on banners inserted after load so screen readers announce them politely; reserverole="alert"for urgent failures — it interrupts whatever is being read. - Choose the
Banner.Titleheading level withasso it slots into the page's heading outline.
API reference
Banner
| Prop | Type | Description |
|---|---|---|
| tone | "neutral" | "brand" | "error" | "warning" | "success" | |
| icon | boolean | { iconName: "function" | "filter" | "at" | "circle" | "square" | "error" | "warning" | "arrowDown" | "arrowLeft" | "arrowRight" | "arrowTrendDown" | "arrowTrendUp" | ... 128 more ... | "zoomOut"; } | { ...; } default: true | The leading icon: true for the tone's default icon, false for none, a named design-system icon, or arbitrary custom content. |
| variant | "solid" | "soft" | "outline" default: "soft" | solid fills with the saturated tone and contrast text; soft tints the surface; outline draws a border on an opaque, page-colored background. |
| dismissible | false | { onDismiss: () => void; } | Whether to render a trailing dismiss button. |
| role | AriaRole | The ARIA role for the banner: pass e.g. "status" (polite) or "alert" (assertive) to announce it to assistive technology. Omit to leave the banner unannounced. |
Banner.Title
| Prop | Type |
|---|---|
| as | "h2" | "h3" | "h4" | "h5" | "h6" default: "h2" |
Banner.Description
| Prop | Type |
|---|---|
| as | "p" | "div" default: "p" |
Banner.Actions
| Prop | Type | Description |
|---|---|---|
| children | ReactNode | The Banner.ActionButtons for resolving the condition in place. |
Banner.ActionButton
| Prop | Type | Description |
|---|---|---|
| type | "button" | "submit" | "reset" default: "button" | The native button type. Unlike a native <button>, it only submits forms when explicitly set to submit. |
| href | string | Renders the button as an anchor that navigates to this URL |
| target | "_blank" | Opens the link in a new tab |
| download | boolean | Whether to download the linked resource instead of navigating. |
| onClick | MouseEventHandler<HTMLButtonElement> | MouseEventHandler<HTMLAnchorElement> | |
| variant | "link" | "solid" | "subtle" | "ghost" | "linkSubtle" default: "subtle" | The overall visual style, from solid fill to inline link text; subtle and ghost sit between with a tinted or transparent background. |
| tone | "neutral" | "brand" | "error" default: "neutral" | The color treatment of the button, e.g. for primary or destructive actions. |
| size | "xxs" | "xs" | "sm" | "md" | "lg" default: "xs" | The size (height) of the button |
| shape | "round" | "default" default: "default" | The shape of the button. Non default shapes should very rarely be used |
| loading | boolean | Whether the button is in a loading state |
| pressed | boolean | Whether the button is in a pressed/active state |
| disabled | boolean | |
| tabIndex | number | |
| autoFocus | boolean | "never" | Whether to focus the element on mount; "never" prevents the element being focused automatically. |
| onMouseDown | MouseEventHandler<HTMLButtonElement> | MouseEventHandler<HTMLAnchorElement> | |
| onMouseUp | MouseEventHandler<HTMLButtonElement> | MouseEventHandler<HTMLAnchorElement> | |
| onMouseEnter | MouseEventHandler<HTMLButtonElement> | MouseEventHandler<HTMLAnchorElement> | |
| onMouseLeave | MouseEventHandler<HTMLButtonElement> | MouseEventHandler<HTMLAnchorElement> | |
| onKeyDown | KeyboardEventHandler<HTMLButtonElement> | KeyboardEventHandler<HTMLAnchorElement> | |
| onFocus | FocusEventHandler<HTMLButtonElement> | FocusEventHandler<HTMLAnchorElement> | |
| onBlur | FocusEventHandler<HTMLButtonElement> | FocusEventHandler<HTMLAnchorElement> | |
| tooltipOptions | Omit<BaseTooltipProps & { variant?: "light" | "dark"; }, "children" | "content"> | Options forwarded to the tooltip shown when tooltip is set |
| aria-label | string | Accessible name; required when there is no label or tooltip. Defines a string value that labels the current element. @see aria-labelledby. |
| children | ReactNode | The button's label |
| tooltip | string | Tooltip shown on hover/focus; also names icon-only buttons |
| iconName | "function" | "filter" | "at" | "circle" | … 137 more | Optional icon to display |
| iconPosition | "left" | "right" default: "left" | Which side of the label the icon is rendered on. |
| prefix | ReactNode | Element rendered at the start of the button. |
| suffix | ReactNode | Element rendered at the end of the button. |
Was this page helpful?