Banner
- Stable
- WCAG 2.2 evidence
- RTL
A page-wide notice across the top of a page or app shell: tone icon, message, optional link and close
button on a solid fill. A status region (role="status", or role="alert" when politeness="assertive"), so a banner
that appears is announced (WCAG 4.1.3); the tone has its own icon with a text alternative, never colour alone (1.4.1,
1.1.1). Presentational: renders in React Server Components. The close button is a small client island. Consumer duties: wording, urgency (politeness), removing the banner and moving focus in onDismiss. A sticky banner
must not hide the focused element: give the page scroll-padding-top equal to the banner height (WCAG 2.4.11). Use
Alert for feedback about one section and Toast for transient confirmations.
import { Banner } from "@nexera-ui/react";- 6
- examples
- 7
- props
- 2
- live controls
- 1
- platform
- 12
- WCAG criteria
- 2
- blocks use it
Try every prop. Copy the code.
Change the props and the code updates. Check light and dark, LTR and RTL, and phone width.
import { Banner } from "@nexera-ui/react";
<Banner />Examples 5
The same examples as Storybook, rendered live. Open Code to copy one.
Tones
Every Tone in a fluid container; each has its own icon and a visually hidden text alternative.
import { Banner } from "@nexera-ui/react";
const tones = ["info", "warning", "danger", "brand"] as const;
export function Tones() {
return (
<div className="flex flex-col gap-4">
{tones.map((tone) => (
<Banner
key={tone}
message="Payroll v2 is rolling out this week."
action={<a href="#payroll-v2">Learn more</a>}
onDismiss={() => undefined}
tone={tone}
politeness="polite"
/>
))}
</div>
);
}
Dismissible
The consumer removes the banner in onDismiss (and would remember the choice), then moves focus to the main heading because the focused close button disappears.
import { useState } from "react";
import { Banner, Button } from "@nexera-ui/react";
export function Dismissible() {
const [visible, setVisible] = useState(true);
return (
<div className="flex flex-col gap-4">
{visible ? (
<Banner
message="Payroll v2 is rolling out this week."
action={<a href="#payroll-v2">Learn more</a>}
onDismiss={() => {
setVisible(false);
document.getElementById("banner-page-title")?.focus();
}}
/>
) : null}
<div className="flex flex-col items-start gap-4 p-4">
<h1 id="banner-page-title" tabIndex={-1} className="m-0 text-heading-h2 text-primary">
Payroll
</h1>
<Button
variant="secondary"
onPress={() => {
setVisible(true);
}}
>
Show the banner again
</Button>
</div>
</div>
);
}
Long message
A long message wraps with the link at its end (translation adds 30 to 40 %); the close button stays at the end.
import { Banner } from "@nexera-ui/react";
<Banner
message="Payroll v2 is rolling out to every team this week, starting with finance and people operations on Monday. Expect short interruptions while we migrate."
action={<a href="#payroll-v2">Learn more</a>}
onDismiss={() => undefined}
tone="warning"
/>;
Sticky
A sticky banner at the top of a scrolling page. The page sets scroll-padding-top to the banner height, so focused elements scrolled into view are never hidden under it (WCAG 2.4.11).
import { Banner, Button } from "@nexera-ui/react";
export function Sticky() {
return (
<div className="h-80 overflow-auto [scroll-padding-top:3rem]">
<Banner
message="Payroll v2 is rolling out this week."
action={<a href="#payroll-v2">Learn more</a>}
onDismiss={() => undefined}
className="sticky top-0 z-sticky"
/>
<div className="flex flex-col items-start gap-4 p-4">
{Array.from({ length: 12 }, (_, index) => (
<Button key={index} variant="secondary">
Payslip {index + 1}
</Button>
))}
</div>
</div>
);
}
Right to left
Right-to-left: the icon and message start on the right; the close button sits at the left end.
import { Banner } from "@nexera-ui/react";
<Banner
message="يتم طرح الرواتب الإصدار 2 هذا الأسبوع."
action={<a href="#payroll-v2">اعرف المزيد</a>}
onDismiss={() => undefined}
iconLabel="معلومة"
dismissLabel="إغلاق"
/>;
Props 7
Press "Try it" on a card to load that prop into the playground.
7 props shown
message*NexeraReactNodeThe notice, for example "Payroll v2 is rolling out this week." Say what happened and what to do next. Wraps, never truncated.
toneNexera"info" | "warning" | "danger" | "brand"Colour set and icon: info, warning and danger notices, or brand for product news.
actionNexeraReactNodeLink after the message, for example <a href="/payroll-v2">Learn more</a>. Links inside
are underlined and get a focus outline in the banner's text colour.
politenessNexera"polite" | "assertive"How assistive technology announces the banner when it appears (WCAG 4.1.3): polite renders role="status",
assertive renders role="alert" (urgent problems only). A banner that is already on the page at load is not
announced.
iconLabelNexerastringText alternative of the tone icon, read before the message followed by a colon ("Warning:..."). Translate it for
your locale; pass "" when the message already states the severity.
onDismissNexera() => voidShows the close button and is called without arguments when it is activated; accepts a Server Action. The banner does not hide itself: remove it in this callback (and remember the choice), and move focus somewhere sensible, because the focused button disappears with it.
dismissLabelNexerastringAccessible name of the close button. Translate it for your locale.
* Required. React Aria props shown are the ones most apps use; the component accepts the rest of its React Aria props too.
Accessible by default.
Built on React Aria, and covered by the WCAG 2.2 evidence generated on every build.
WCAG 2.2 evidence
6 direct · 6 supporting- 1.1.1Non-text ContentLevel A · tested directly
- 1.3.1Info and RelationshipsLevel A · tested directly
- 1.3.2Meaningful SequenceLevel A · supporting test
- 1.4.1Use of ColorLevel A · tested directly
- 1.4.10ReflowLevel AA · supporting test
- 1.4.11Non-text ContrastLevel AA · supporting test
- 1.4.12Text SpacingLevel AA · supporting test
- 2.1.1KeyboardLevel A · tested directly
- 2.4.7Focus VisibleLevel AA · supporting test
- 2.5.8Target Size (Minimum)Level AA · supporting test
- 4.1.2Name, Role, ValueLevel A · tested directly
- 4.1.3Status MessagesLevel AA · tested directly
Fits any width.
Nexera components respond to the space they are given. Drag the corner of the frame, or pick a width.
Styling hooks
Pass className to add Tailwind classes (merged last). State is exposed as data attributes, so you can style it with variants like data-pressed:.
data-focus-visibledata-hovereddata-pressed
<Banner className="data-focus-visible:opacity-90 shadow-sm" />Used in blocks
Related components
- AlertAn inline status message about a section or a task: tone icon, title, optional description, actions and close button.
- CircularProgressShows progress as a ring with the value in the centre.
- EmptyStateExplains why a list, table or page has no content and what to do next.
- ProgressBarShows how far a task has progressed.
- ProgressStepsA segmented progress indicator for a flow with a known number of steps, such as onboarding or a form wizard: a header with "Step 2 of 5" and the step title above one segment per step.
- SpinnerSmall loading indicator.
- SpinnerLabelA spinner with a status message.
- ToastGives the components below it a toast queue through `useToast()` and renders its `ToastRegion`.