StickyBanner
A fixed-to-viewport action bar for something worth interrupting every page for until it is resolved or dismissed — production’s add-phone-bar / add-mail-bar. Unlike Toast, it does not auto-dismiss and is not tied to an event: the caller decides whether to render it at all.
import StickyBanner from '@/components/ui/StickyBanner';Source: src/components/ui/StickyBanner.tsx
Examples
Dismiss and re-show
Fixed to the bottom of the viewport (edge-to-edge on mobile, a floating bar on larger screens). The close button submits `dismissAction` — normally a server action that writes a cookie, like WelcomeCard’s, so the dismissal survives a reload.
Protect your account!
Add your phone number to keep your account secure.
Props
<StickyBanner> props
| Prop | Type | Default | Description |
|---|---|---|---|
titlerequired | string | — | — |
childrenrequired | ReactNode | — | — |
ctaLabelrequired | string | — | — |
ctaHrefrequired | ComponentProps<typeof Button>['href'] | — | — |
dismissLabelrequired | string | — | — |
dismissActionrequired | () => Promise<void> | void | — | A server action, like WelcomeCard's `dismissWelcomeCard` — the banner is meant to persist a dismissal (a cookie, typically), and a form action is the only way to do that write without an onClick handler that outlives the element it's attached to. |
color | ButtonColor | 'red' | — |
className | string | '' | — |
Accessibility
- Rendered as a labelled region (`role="region"`, `aria-label` from `title`) so a screen-reader user can find and skip it.
Usage
Do
- Gate whether it renders at all in the server component that knows the condition (see PhoneReminderBanner) — do not render it and hide it with CSS.
- Pass a form action for `dismissAction` so the dismissal is a durable, server-side write rather than component state that resets on reload.
Don’t
- Don’t use it for a transient confirmation — that is a Toast.
- Don’t stack more than one at a time; production’s own info-bar only ever shows the highest-priority one.