Broadcast Bar System
A top broadcast bar system that stacks multiple announcements, rotates them through a priority queue, supports countdowns, CTAs, and dismissal memory, and springs its height changes so the content below is pushed smoothly.
Bring this into your project
Run this command in your project folder. The CLI adds the source and dependencies; then follow the usage example below.
npx webberui@latest add broadcast-bar-system.enPlayground
Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.
<BroadcastBarSystem/>
The complete example includes the preview layout and data. Install the component first, then paste this file into your project.
Installation
npx webberui@latest add https://webberui.com/r/broadcast-bar-system.en.jsonOr, once registries are configured in components.json, install it as @webberui/broadcast-bar-system.
Usage
import { BroadcastBarSystem } from "@/components/ui/broadcast-bar-system";
<BroadcastBarSystem
messages={[
{
id: "sale",
variant: "promo",
priority: 3,
content: "Final hours of the summer sale",
countdownTo: Date.now() + 1000 * 60 * 60 * 2,
cta: { label: "Shop now", href: "/sale" },
},
{
id: "maintenance",
variant: "warning",
priority: 1,
content: "The system will be under maintenance this Sunday at 02:00",
},
]}
/>Announcements are queued from highest to lowest priority and rotate automatically; the ones a user dismisses are remembered in localStorage and do not reappear after a refresh. The broadcast bar itself sits in normal flow layout, and its height transitions with a spring, so the page content below is pushed naturally and smoothly.
Props
BroadcastBarSystem
| Prop | Type | Default | Description |
|---|---|---|---|
messages | BroadcastMessage[] | — | The announcement array, rotated from highest to lowest priority |
rotateInterval | number | 5000 | Automatic rotation interval (milliseconds); set to 0 to disable |
storageKey | string | null | "wb-broadcast-dismissed" | localStorage key used to remember dismissed announcements; null disables persistence |
sticky | boolean | false | Whether it sticks to the top of the container |
onDismiss | (id: string) => void | — | Fires when a single announcement is dismissed |
onEmpty | () => void | — | Fires once when every announcement has been dismissed and the bar collapses to zero height |
BroadcastMessage
| Field | Type | Default | Description |
|---|---|---|---|
id | string | — | Unique identifier, used for rotation positioning and dismissal memory |
content | React.ReactNode | — | The main text content |
priority | number | 0 | Higher numbers rotate in earlier |
variant | "info" | "success" | "warning" | "critical" | "promo" | "info" | Accent color and default icon |
icon | React.ReactNode | — | Custom leading icon, overriding the variant default |
cta | BroadcastCTA | — | Call to action; renders a link when it has an href, otherwise a button |
countdownTo | number | Date | — | Countdown target, showing a live HH:MM:SS countdown |
onCountdownEnd | () => void | — | Fires once when the countdown reaches zero |
dismissible | boolean | true | Whether to show a dismiss button |
How it works
- Priority queue:
messagesis stably sorted bypriorityand only announcements that have not been dismissed are shown; exactly one appears at a time, rotating at a fixed interval. - Countdown:
countdownToaccepts a millisecond timestamp or aDateand updates every 250ms; past one day it showsDdays HH:MM:SS(a day count followed byHH:MM:SS). Reaching zero firesonCountdownEndonce. - Dismissal memory: the ids of dismissed announcements are written to
localStorage(customize it withstorageKeyor turn it off withnull); whenlocalStorageis unavailable it silently degrades to remembering only the current session. - Smooth pushing: the bar measures its content height and transitions its own height with a spring, so switching between announcements of different heights or dismissing them all pushes the content below smoothly or lets it fill back in.
Accessibility
- The broadcast bar is marked with
role="region"plus anaria-label, which makes it easy for assistive technology to locate. - With multiple announcements it provides keyboard-operable navigation dots (
role="tab"), each labeled "item N of M"; the dismiss button carries anaria-label. - Rotation pauses automatically on pointer hover or when keyboard focus enters, so the content does not jump while the user is reading.
- It respects the system "reduce motion" setting: automatic rotation and displacement animations are disabled, height switches instantly, and announcements fade in and out instead.
- The countdown only renders after mount, which avoids the hydration mismatch that depending on
Date.now()would cause.
Skeleton Orchestra
A skeleton-screen orchestration system: when loading finishes, the skeletons solidify into real content one by one in directional waves following the layout.
UI Sound Kit
Lightweight interface sounds — click, hover, success, error and more — synthesized live with Web Audio, with built-in volume control, a global switch, and preference-respecting behavior; no audio files, no extra requests.