Announcement Bar ported
One slim line for what everyone should see.
A top banner that rotates messages, counts down, and collapses smoothly when dismissed.
Loading demo…
Guidance
When to use
- For a site-wide note at the top of the page: launches, sales, maintenance.
- When several messages should rotate on one clock with pause on hover.
- When a message carries a call to action or a live countdown.
When not to use
- For transient results of an action — use toast or toast-stack.
- For persistent, in-flow messages tied to a form — use alert.
- When people must respond before continuing — use dialog.
pnpm add sveltearcUsage
<script lang="ts">
import AnnouncementBar from '$lib/components/announcement-bar/announcement-bar.svelte';
const messages = [
{
id: 'launch',
message: 'Aurora is live — see what is new.',
action: { label: 'Read the notes', href: '/changelog' }
}
];
</script>
<AnnouncementBar {messages} id="launch-2026" controls />Variants & Examples
Rotating with controls
Previous, next and pause buttons across several messages.
<AnnouncementBar {messages} controls />Countdown
A live countdown beside the message, with onCountdownEnd.
<AnnouncementBar messages={[{ id: 'sale', message: 'Sale ends in', countdown: { to: deadline, label: 'Ends in' } }]} />Inverted tone
Light-on-dark bar for high-contrast moments.
<AnnouncementBar {messages} tone="inverted" />API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
messages | Announcement[] | — | The rotating messages. Each has an id, a message (string or Snippet), an optional action and an optional countdown. |
id | string | — | Remembers dismissal under this id. Change the id to show a new campaign to everyone again. |
open | boolean | — | Whether the bar is shown. Leave it out to let the component manage it. |
defaultOpen | boolean | true | Initial visibility when uncontrolled. |
onOpenChange | (open: boolean) => void | — | Fired with false on dismiss. |
index | number | — | Index of the visible message. Leave it out for internal rotation. |
defaultIndex | number | 0 | Initial message when uncontrolled. |
onIndexChange | (index: number) => void | — | Fired when rotation advances or the visitor steps. |
interval | number | 6000 | Milliseconds each message stays before the next one. |
autoPlay | boolean | true | Rotate automatically. Pauses on hover, focus, or a hidden tab; off under reduced motion. |
controls | boolean | false | Show previous, next, and pause controls when there are several messages. |
dismissible | boolean | true | Show the dismiss button. |
tone | 'neutral' | 'inverted' | 'neutral' | Colour story of the bar. |
onAction | (announcement) => void | — | Fired after a message action, with the announcement. |
onCountdownEnd | (announcement) => void | — | Fired once when a countdown reaches zero. |
label | string | 'Announcements' | Accessible name of the region. |
class | string | — | Additional classes merged with the collapse class. |
ref | HTMLElement | null | — | Bindable reference to the outer section. |
Keyboard Interactions
| Key | Action |
|---|---|
Tab | Move between the message action and the controls. |
Enter / Space | Step, pause, or dismiss from the control buttons. |
Accessibility
- The bar is a labelled region; with several messages it is a carousel of labelled slides.
- The live countdown is role="timer" with aria-live="off" and a spoken hours/minutes label.
- Rotation pauses on hover, focus, or a hidden tab so no message changes under the reader.
Motion
Phase 1 still-state: no animation. Faces swap instantly, the viewport snaps to the face height, countdown digits swap instantly, and dismissal closes at once. Phase 2 wires the rise/blur face swap, the height spring, the digit roll, the pause-ring sweep and the collapse.
Notes for AI
- Pass an id to remember dismissal in localStorage; clearAnnouncementDismissal(id) forgets it.
- Rotation pauses itself on hover, focus, hidden tabs and reduced motion — no extra wiring needed.
Source of truth: registry/components/announcement-bar/announcement-bar.tsx