Skip to content

Banner

A full-width element used to draw attention to a message.

To display a banner, pass a title and an optional description.

Congrats on being one of our top creators!

Set up your community profile now to build your audience.

import { Banner } from "stylus-ui/Banner";
import { faTrophy } from "@fortawesome/pro-regular-svg-icons";
export default () => (
<Banner
title="Congrats on being one of our top creators!"
description="Set up your community profile now to build your audience."
variant="info"
icon={faTrophy}
/>
);

Display different colors using the variant prop. info is the default. Each variant comes with its own preset icon. loud is a high-emphasis variant that renders as the inverse of the surrounding theme (dark on a light page, light on a dark page) and defaults its action to a primary button.

neutral is the opposite end from loud: it carries no status colour and sits on the surrounding surface, for a banner that is part of the page rather than an interruption. It and loud are the two variants that follow the ambient theme — neutral paints with bg-surface-default / text-default, so it would become a light card on a dark page if it stamped a theme of its own.

You have created 80 of the 100 allowed documents on your Basic plan.

Upgrade to Pro for unlimited documents.

You have created 85 of the 100 allowed documents on your Basic plan.

Upgrade to Pro for unlimited documents.

You have reached the 100 document limit on your Basic plan.

Upgrade to Pro to continue creating documents.

Welcome to Pro! You now have unlimited documents.

Enjoy creating without limits on your new Pro plan.

Go Pro for unlimited exports

Upgrade to unlock unlimited documents and exports.

Want to see all activities as an admin?
import { Banner } from "stylus-ui/Banner";
export default () => (
<div className="flex w-full flex-col gap-2">
<Banner
title="You have created 80 of the 100 allowed documents on your Basic plan."
description="Upgrade to Pro for unlimited documents."
variant="info"
/>
<Banner
title="You have created 85 of the 100 allowed documents on your Basic plan."
description="Upgrade to Pro for unlimited documents."
variant="warning"
/>
<Banner
title="You have reached the 100 document limit on your Basic plan."
description="Upgrade to Pro to continue creating documents."
variant="error"
/>
<Banner
title="Welcome to Pro! You now have unlimited documents."
description="Enjoy creating without limits on your new Pro plan."
variant="success"
/>
<Banner
title="Go Pro for unlimited exports"
description="Upgrade to unlock unlimited documents and exports."
variant="loud"
actions={[{ children: "Upgrade to Pro", onClick: () => {} }]}
/>
<Banner
title="Want to see all activities as an admin?"
variant="neutral"
align="center"
actions={[{ children: "Upgrade to Enterprise", onClick: () => {} }]}
/>
</div>
);

Every variant displays a preset icon. However, the default icon can be overridden. Import an icon from Font Awesome and pass it to icon.

An unknown error occurred.
import { Banner } from "stylus-ui/Banner";
import { faAlien } from "@fortawesome/pro-regular-svg-icons";
export default () => (
<Banner variant="error" title="An unknown error occurred." icon={faAlien} />
);

To render buttons beneath the description, pass an array of ButtonProps to the actions prop.

There was an error connecting to Confluence.

Please try again. If the issue persists, you can reconnect manually.

import { Banner } from "stylus-ui/Banner";
export default () => (
<Banner
title="There was an error connecting to Confluence."
description="Please try again. If the issue persists, you can reconnect manually."
variant="warning"
actions={[
{ children: "Reconnect", onClick: () => {} },
{ children: "Dismiss", onClick: () => {} },
]}
/>
);

If you need to display a list of items—for example, a list of errors—pass an array of strings to descriptionList.

We couldn't submit your form.

Please fix the following errors and try again:

  • Title is required
  • Description is required
  • Date is required
import { Banner } from "stylus-ui/Banner";
export default () => (
<Banner
title="We couldn't submit your form."
description="Please fix the following errors and try again:"
descriptionList={[
"Title is required",
"Description is required",
"Date is required",
]}
variant="error"
/>
);

When rendering this component dynamically in response to a user action, pass role="alert". Contents will be automatically announced to users with screen readers.

import { Banner } from "stylus-ui/Banner";
export default () => (
<Banner
title="Couldn't log in."
description="Please try again. If the issue persists, you can reconnect manually."
variant="error"
role="alert"
/>
);

An Banner can be made dismissible by passing an onDismiss handler. A close icon will appear in the top right of the banner.

Congrats on being one of our Top Creators!
import { Banner } from "stylus-ui/Banner";
import { Button } from "stylus-ui/Button";
import { faTrophy } from "@fortawesome/pro-regular-svg-icons";
import { useState } from "react";
export default () => {
const [isOpen, setIsOpen] = useState(true);
const handleDismiss = () => setIsOpen(false);
const handleReset = () => setIsOpen(true);
return isOpen ? (
<Banner
title="Congrats on being one of our Top Creators!"
icon={faTrophy}
onDismiss={handleDismiss}
/>
) : (
<Button variant="secondary" onClick={handleReset}>
Reset
</Button>
);
};

To group banners, import BannerGroup. By default, the group will only display the first two banners. To show additional banners, increment max.

Banner 1

Visible by default

Banner 2

Visible by default

Banner 3

Visible by default

import { Banner, BannerGroup } from "stylus-ui/Banner";
import { Button } from "stylus-ui/Button";
import { useState } from "react";
export default () => {
const maxBanners = 3;
const totalBanners = 5;
const [openBanners, setOpenBanners] = useState(new Set([1, 2, 3, 4, 5]));
const handleDismiss = (id) =>
setOpenBanners((prev) => new Set([...prev].filter((b) => b !== id)));
const handleResetAll = () =>
setOpenBanners(
new Set(Array.from({ length: totalBanners }, (_, i) => i + 1)),
);
const allUndismissedBanners = [...openBanners].map((id) => (
<Banner
key={id}
title={`Banner ${id}`}
description={id > maxBanners ? "Hidden by default" : "Visible by default"}
onDismiss={() => handleDismiss(id)}
/>
));
return allUndismissedBanners.length ? (
<BannerGroup max={maxBanners}>{allUndismissedBanners}</BannerGroup>
) : (
<Button variant="secondary" onClick={handleResetAll}>
Reset
</Button>
);
};

leading replaces the variant icon with content of your own — an avatar, a logo, a status dot. trailing puts content at the end of the banner, after the copy, for controls that belong to the banner rather than the actions list.

Both follow align, so a centred banner lines them up with the copy instead of pinning them to the top edge.

N
Nina Caldwell asked to view this activity

3 hours ago

import { Banner } from "stylus-ui/Banner";
import { Avatar } from "stylus-ui/Avatar";
import { Button } from "stylus-ui/Button";
export default () => (
<Banner
variant="neutral"
align="center"
layout="row"
title="Nina Caldwell asked to view this activity"
description="3 hours ago"
descriptionPlacement="below"
leading={<Avatar size="sm" uuid="nina">Nina Caldwell</Avatar>}
trailing={
<span className="flex shrink-0 gap-1">
<Button variant="secondary" size="small">Deny</Button>
<Button variant="primary" size="small">Approve</Button>
</span>
}
/>
);

By default the description flows after the title as continuing copy. Set descriptionPlacement="below" when the second line is metadata about the first — a timestamp, an author — and it becomes a stacked, muted subtitle instead.

Stacked copy ignores align. That prop is vertical alignment of the copy against the trailing content; once the copy is a column, applying it would centre the title and subtitle horizontally.

Log a Support Escalation on a Customer Account

Requested 3 hours ago

Log a Support Escalation on a Customer Account

Requested 3 hours ago

import { Banner } from "stylus-ui/Banner";
export default () => (
<div className="flex w-full flex-col gap-2">
<Banner
variant="neutral"
title="Log a Support Escalation on a Customer Account"
description="Requested 3 hours ago"
descriptionPlacement="inline"
/>
<Banner
variant="neutral"
title="Log a Support Escalation on a Customer Account"
description="Requested 3 hours ago"
descriptionPlacement="below"
/>
</div>
);

The copy and the trailing content stack on narrow containers and sit side by side once there is room. Set layout="row" to keep them on one line at every width — useful in a column too narrow for the responsive default to resolve the way you want.

A persistent message communicating state in response to a user action.

title

Required
string

Main heading text.


actions

ButtonProps[]

Buttons shown at the end of the banner.


align

"center" | "start" = "start"

Vertical alignment of the title row against trailing actions/children at wider widths. Use ‘center’ for a single-line title with a taller control.


children

ReactNode

Additional content after description/actions.


description

string | ReactNode

Body text or custom content below the title.


descriptionList

string[]

List of strings rendered as a bullet list below the title.


descriptionPlacement

"inline" | "below" = "inline"

Where the description sits relative to the title: flowing after it, or stacked beneath as a muted subtitle.


hideIcon

boolean = false

Hide the leading icon entirely, even for variants (info/success/warning/error) that show one by default.


icon

IconDefinition

Icon shown at the start; defaults by variant if not set.


iconClassName

string

Extra classes merged onto the icon after the variant’s icon styles (e.g. animate-spin).


layout

"row" | "stack" = "stack"

Layout of the title/description row against trailing actions/children. ‘row’ forces them onto one row at every width instead of only past the @xl container breakpoint.


leading

ReactNode

Custom content in the leading slot, in place of icon (e.g. an Avatar). Takes precedence over both icon and hideIcon.


onDismiss

() => void

Called when the user dismisses the banner; shows a close button when set.


role

"alert" | "region" | "status" = "region"

ARIA role: alert for assertive announcements, status for polite ones, region otherwise.


theme

"light" | "dark" = "light"

Theme for contrast.


trailing

ReactNode

Arbitrary content shown at the end of the banner, alongside/instead of actions, for a control actions can’t express (e.g. a component with its own conditional buttons).


variant

"info" | "success" | "warning" | "error" | "loud" | "neutral" = "info"

Visual style: info, success, warning, error, loud, or neutral (white/default surface, no default icon).


A container for banners with the option of defining how many to show at a time.

children

Required
ReactNode

Banner components to display; only the first max are shown.


className

string

Optional class for the group container.


max

number = 2

Maximum number of banners visible at once.