Build / Molecules
Banner
An inline message attached to the surface it concerns.
Deck's workhorse for CRM sync failures, plan-cap warnings, the recipient "create your own MeetCard" invite, and offline notices.
error and warning announce themselves via role="alert"; the quieter
tones use role="status" so they don't interrupt. Tone is never the only
signal — always write a title or body that carries the meaning.
import { Banner } from '@meetcard/deck'Example
<Banner tone="warning" title="You're near your Solo limit" actions={<Button size="sm">Upgrade</Button>}> 92 of 100 connections used. </Banner>Stories
Source
const Default = () => <div style={{ maxWidth: 560 }}>
<Banner title="Heads up">Something worth knowing about.</Banner>
</div>;Every tone. Pick by what the reader has to do next, not by how serious it sounds.
Source
const Tones = (args) => (
<Stack gap={12} style={{ maxWidth: 560 }}>
{(['info', 'brand', 'success', 'warning', 'error'] as const).map((tone) => (
<Banner {...args} key={tone} tone={tone} title={tone}>
Tone is never the only signal — the copy carries the meaning.
</Banner>
))}
</Stack>
);A CRM write failed. Errors announce themselves via role="alert".
Source
const SyncFailed = () => <div style={{ maxWidth: 560 }}>
<Banner
title="CRM sync failed"
tone="error"
actions={<Button size="sm" variant="secondary">Retry</Button>}>3 connections could not be written to Salesforce.</Banner>
</div>;Nearing the Solo cap — an upgrade prompt at the moment of realised value.
Source
const PlanCap = () => <div style={{ maxWidth: 560 }}>
<Banner
title="You're close to your Solo limit"
tone="warning"
actions={<Button size="sm">Upgrade</Button>}>92 of 100 connections used.</Banner>
</div>;The recipient conversion invite. It must never block or degrade the core save action, so it is a quiet inline banner rather than a modal.
Source
const RecipientInvite = () => <div style={{ maxWidth: 560 }}>
<Banner
title="Want a card like this?"
tone="brand"
actions={<Button size="sm">Create my card</Button>}
onDismiss={fn()}>Create your own MeetCard in under a minute — free.</Banner>
</div>;Offline notice — the PWA keeps working, writes queue for background sync.
Source
const Offline = () => <div style={{ maxWidth: 560 }}>
<Banner title="You're offline" tone="info">Your card still shows. Changes will sync when you reconnect.</Banner>
</div>;No title, for a single sentence that is its own headline.
Source
const WithoutTitle = () => <div style={{ maxWidth: 560 }}>
<Banner title={undefined}>A single-line message with no title.</Banner>
</div>;Props
| Prop | Type | Default | Description |
|---|---|---|---|
actions | ReactNode | — | Trailing controls, e.g. an "Upgrade" or "Retry sync" Button. |
dismissLabel | string | 'Dismiss' | — |
onDismiss | () => void | — | Shows a dismiss control. Dismissal state is the caller's to hold. |
title | ReactNode | — | — |
tone | 'info' | 'success' | 'warning' | 'error' | 'brand' | 'info' | — |
Also accepts everything from Omit, so id, data-* and event handlers pass straight through.