Banner group
Vertical stack of Banner elements with locked spacing, for a surface carrying more than one notice.
BannerGroup is the vertical-axis sibling of BadgeGroup and TagGroup. It replaces the per-banner marginBottom and the ad-hoc Stack wrapper consumers reach for when a page needs more than one Banner.
The order, placement, and don't-stack rules live in the banner-groups build standard — this page is the API.
Use it for
- A page whose top region carries two or more banners (an account-level alert plus a page-level nudge)
- A small, bounded set of same-tone banners where each item needs its own action
- Any surface where the banner set is assembled from data and the count varies
Import
import { BannerGroup, Banner } from '@brikdesigns/bds';Variants
Default
Children render in source order — sort before you map. negative → warning → info → positive → announcement.
Gap sizes
Three locked gaps — md (default) so the banners read as one notice block, sm for two facets of one incident, lg only when the banners are genuinely unrelated.
Pattern: the top of a page
The canonical use — the first child of PageContent, above the first section. The group spaces its own children; the space below it comes from PageContent's gap, so nothing here carries a margin.
import { Banner, BannerGroup, Button, Page, PageContent, PageHeader } from '@brikdesigns/bds';
<Page padding="none">
<PageHeader title="Good morning, Nick" subtitle="Portal activity and quick stats." />
<PageContent>
<BannerGroup>
{alerts.map((a) => (
<Banner key={a.id} tone="warning" title={a.title} description={a.description} />
))}
<Banner
title="Want to set up a new client?"
description="Click to begin the setup workflow for new clients."
action={<Button variant="on-color" size="md" href="/admin/companies/new">Get Started</Button>}
/>
</BannerGroup>
{/* sections… */}
</PageContent>
</Page>When not to use
Don't wrap a statically single Banner. If the surface has one banner and always will, the group adds a DOM node and no arrangement — render <Banner> directly and let the parent layout's gap space it. The same rule BadgeGroup and TagGroup carry.
A data-driven set keeps its group even when today's data yields one banner: the count varies per render, and toggling between a group and a bare banner puts the arrangement rule back in the page.
- Don't stack more than three. Three
role="alert"banners announce serially with no way to skip. Cap the rendered set and roll the remainder into one summarizing banner. See when not to stack banners. - Don't render a per-item status list as banners. Items sharing an attribute set are a table with a status column or a list with a trailing Badge.
- Don't put an
announcementin a group carrying anegative. Suppress the marketing banner while anything is broken. - Don't use non-Banner children. The group locks the vertical rhythm for Banner's footprint; arbitrary nodes misalign.
- Don't add margins to the children. The group's
gapis the only spacing mechanism between banners, and the parent layout owns the space below.
Accessibility
- Renders a plain
<div>— norole, noaria-label. Each Banner keeps its own semantics (role="alert"fornegative/warning/info,role="status"forpositive,role="banner"forannouncement). - Source order is announced order. The severity ordering rule is the screen-reader experience, not a sighted-only convention.
- The three-banner cap exists because assertive roles compound — see the standard's accessibility section.
API
| Prop | Type | Default |
|---|---|---|
gap | 'sm' | 'md' | 'lg' | 'md' |
children | ReactNode | — |
Related
- Banner — the child component
- Banner groups — order, placement, and when not to stack
- BadgeGroup / TagGroup — horizontal-axis siblings
- Storybook playground