Skip to content

Banner

A full-width, solid-intent announcement bar with an optional dismiss button and top or bottom pinning. Made for page-level messages: maintenance notices, promos, and outage warnings.

Import

import { Banner } from "@hyzer-labs/ui"

Demo

Banner vs Alert

Use Banner for a solid, full-width announcement at page level: maintenance notices, promos, outage bars. You can pin it to an edge. When the message is inline and sits next to the thing it describes, use Alert instead.

There is deliberately no Toast component

A message that dismisses itself on a timer is hard to make accessible. The timing has to be adjustable or pausable, and a message that vanishes often goes unannounced. If you do need one, announce handles the announcement half. The library prefers a dismissal the reader chooses, so content never disappears out from under them. For a pinned or site-wide message, that is a Banner with role="status" and a dismiss you own.

The intent vocabulary, using a solid fill instead of the tint Alert uses.

Course note: hole 7 tee pads were resurfaced this week.
League night: tags round starts at 5:30pm on Thursday.
Doubles signup: random-draw doubles opens 30 minutes early.
Course closed: lightning in the area. Clear the course now.
High winds: gusts over 30mph expected after 2pm.
Round saved: your scorecard was synced to the league.
Cart friendly: the back nine is paved end to end.
<Banner>Course note: hole 7 tee pads were resurfaced this week.</Banner>
<Banner intent="primary">League night: tags round starts at 5:30pm on Thursday.</Banner>
<Banner intent="secondary">Doubles signup: random-draw doubles opens 30 minutes early.</Banner>
<Banner intent="danger">Course closed: lightning in the area. Clear the course now.</Banner>
<Banner intent="warning">High winds: gusts over 30mph expected after 2pm.</Banner>
<Banner intent="success">Round saved: your scorecard was synced to the league.</Banner>
<Banner intent="info">Cart friendly: the back nine is paved end to end.</Banner>

Props

NameTypeDefaultNote
childrenSnippet—Required. The banner body.
intentIntent'neutral'See Foundation → Colors & Intent.
pin'top' | 'bottom'—Sticks the bar to that edge, in flow (position: sticky). Static by default.
iconSnippet—Decorative; rendered aria-hidden.
actionsSnippet—Trailing slot — a Link or Button, e.g. "Learn more".
onDismiss() => void—Renders the dismiss button. Visibility is your state — the Banner never hides itself.
dismissLabelstring'Dismiss'
asstring'div'Polymorphic root — e.g. section or aside for landmark semantics.
classstring—Merged after the hz-banner class.

Anything not listed above is forwarded as an attribute to the root element (or the native control in form components). So id, data-*, aria-*, and event handlers just work.

Theme hooks

What this component promises your CSS. The reference theme styles exactly these — from @layer hz-theme, so your unlayered rules win. See Styling Components for the how.

Root class: .hz-banner

Data attributes

HookValuesStyles
data-intent'neutral' | any registered intentDrives the solid fill via --hz-banner-bg; spans the intent registry.
data-pin'top' | 'bottom'Present only when pinned; sticks the bar to that edge via position: sticky.
data-dismissiblepresent when dismissiblePresent only when onDismiss is set — target it to style the dismissible form.

Custom properties

HookValuesStyles
--hz-banner-bg<color> — default var(--hz-intent-neutral)The solid fill, switched per intent — override to restyle every intent's bar.
--hz-banner-fg<color> — default var(--hz-color-surface)On-fill text colour, the surface role so it flips with the mode and keeps text ≥ 4.5:1 in both.
--hz-banner-padding-block<length> — default 1.5remVertical padding of the bar.
--hz-banner-padding-inline<length> — default 2.5remHorizontal padding of the bar.

Part classes

HookValuesStyles
.hz-banner-iconchild elementThe decorative leading icon.
.hz-banner-contentchild elementThe message body.
.hz-banner-actionschild elementThe trailing actions slot.
.hz-banner-dismisschild elementThe dismiss button.
.hz-banner-titleopt-in classBanner never emits this — put it on your own lead element (strong, a heading) and it goes block-level semibold, stacking over the body copy. The .hz-card-title convention.

Accessibility

A statically rendered Banner is plain content: no role, no live region. For a Banner inserted after load, pass role="status" (polite) or role="alert" (assertive, use sparingly) via the rest props.

The icon slot is decorative (aria-hidden). Links inside are underlined, and color is never the only signal. The dismiss button is a real labeled <button>, and dismissal is your state change.

A pinned Banner can cover a focused element that scrolls under it. Keep pinned banners short, one line where possible. Give in-page anchor targets scroll-margin-block-start/-end equal to the banner height so they clear it. The Banner itself sets no scroll-margin.

References: WCAG 2.4.11: Focus Not Obscured (Minimum) · MDN: status role · MDN: alert role