Banner

Highlights a page or section-level status and the actions that resolve it.

A new entity editor is available

Turn it on for this workspace from Settings → Labs.

Workspace permissions are changing

Members inherited from parent teams must be re-added by 1 November.

Sync with the graph failed — recent edits aren't saved.

Installation

  1. Install the package.
npm install @hashintel/ds-components
  1. 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.Actions when 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

Scheduled maintenance on Saturday

HASH will be read-only from 02:00 to 04:00 UTC while the graph is upgraded.

Description only

Most banners don't need a title — a lone Banner.Description keeps a short status to a single line.

This flow is shared with everyone in the workspace.

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.

Neutral — routine context that needs no action.

Brand — product announcements and feature promotion.

Success — a background task completed as expected.

Warning — something needs attention before it becomes a problem.

Error — something failed and needs fixing 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.

Soft — the tinted default for messages in the page flow.

Outline — flat on opaque surfaces such as cards and dialogs.

Solid — a saturated fill for the most prominent 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.

Workspace permissions are changing

Members inherited from parent teams must be re-added by 1 November.

Sync with the graph failed — recent edits aren't saved.

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.

Tip: drag a property onto the canvas to add it to the entity type.

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

A new entity editor is available for this workspace.

HASH AI suggested 3 property mappings for this flow.

This workspace is on the free plan.

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.

3 of 5 import steps complete — mapping properties for Person entities.

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 warning and error banners, 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.Title renders a real heading — h2 by default, but this can be adjusted with as.
  • 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; reserve role="alert" for urgent failures — it interrupts whatever is being read.
  • Choose the Banner.Title heading level with as so it slots into the page's heading outline.

API reference

PropTypeDescription
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
variant
"solid" |⁠ "soft" |⁠ "outline"
default: "soft"
dismissible
false |⁠ { onDismiss: () => void; }
role
AriaRole

Banner.Title

PropType
as
"h2" |⁠ "h3" |⁠ "h4" |⁠ "h5" |⁠ "h6"
default: "h2"

Banner.Description

PropType
as
"p" |⁠ "div"
default: "p"

Banner.Actions

PropTypeDescription
children
ReactNode

Banner.ActionButton

PropTypeDescription
type
"button" |⁠ "submit" |⁠ "reset"
default: "button"
href
string
target
"_blank"
download
boolean
onClick
MouseEventHandler<HTMLButtonElement> |⁠ MouseEventHandler<HTMLAnchorElement>
variant
"link" |⁠ "solid" |⁠ "subtle" |⁠ "ghost" |⁠ "linkSubtle"
default: "subtle"
tone
"neutral" |⁠ "brand" |⁠ "error"
default: "neutral"
size
"xxs" |⁠ "xs" |⁠ "sm" |⁠ "md" |⁠ "lg"
default: "xs"
shape
"round" |⁠ "default"
default: "default"
loading
boolean
pressed
boolean
disabled
boolean
tabIndex
number
autoFocus
boolean |⁠ "never"
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">
aria-label
string
children
ReactNode
tooltip
string
iconName
"function" |⁠ "filter" |⁠ "at" |⁠ "circle" |⁠ … 137 more
iconPosition
"left" |⁠ "right"
default: "left"
prefix
ReactNode
suffix
ReactNode

Was this page helpful?

On this page