Banner
A full-width announcement bar typically rendered at the top of a page or layout. Eight colors,
optional icon, inline actions, dismiss button, clickable mode, and localStorage-backed
dismissal persistence when an id is provided.
Basic Usage
A minimal banner with just a title.
<script lang="ts">
import { Banner } from 'sv5ui';
</script>
<Banner title="A neutral announcement at the top of the page." />With Icon
Pass any Iconify icon name to icon.
<Banner
icon="lucide:megaphone"
title="New features available — check the changelog!"
/>Colors
8 color tokens map to the theme's background/foreground pairs.
<Banner color="primary" icon="lucide:sparkles" title="Primary" />
<Banner color="secondary" icon="lucide:sparkles" title="Secondary" />
<Banner color="tertiary" icon="lucide:sparkles" title="Tertiary" />
<Banner color="success" icon="lucide:check-circle" title="Success" />
<Banner color="warning" icon="lucide:alert-triangle" title="Warning" />
<Banner color="error" icon="lucide:x-circle" title="Error" />
<Banner color="info" icon="lucide:info" title="Info" />
<Banner color="surface" icon="lucide:bell" title="Surface" />With Actions
Pass actions as an array of ButtonProps. Banner applies size="xs" and inherits the bar color — override per item.
<!-- Each action is spread onto a <Button>. -->
<Banner
color="primary"
icon="lucide:rocket"
title="A new version is available."
actions={[
{ label: 'Release notes', variant: 'outline' },
{ label: 'Update now', trailingIcon: 'lucide:arrow-right' }
]}
/>Dismissible (session only)
Set close to show a close button. Without an id the dismissal is session-only — the banner returns on the next reload.
<!-- Session-only dismissal (no `id`) — close hides the banner
but it returns on the next reload. -->
<Banner
color="info"
icon="lucide:info"
title="A neutral notice you can dismiss for this session."
close
/>Persisted Dismissal
Pass an id alongside close — once dismissed, the banner writes sv5ui-banner-{id} to localStorage and stays hidden across reloads.
To bring the banner back after testing, run in DevTools: localStorage.removeItem('sv5ui-banner-announce-2026-q2')
<!-- Pass an `id` to opt into localStorage persistence.
Once dismissed, the banner stays hidden across reloads. -->
<Banner
id="announce-2026-q2"
color="warning"
icon="lucide:alert-triangle"
title="Scheduled maintenance this weekend."
close
/>Clickable
Set to to make the whole banner act as a link. It uses an absolute-positioned overlay anchor so any inner buttons (close / actions) stay outside the <a> — valid HTML.
<!-- Whole banner is a link — `to` adds an overlay anchor so
inner buttons stay outside the <a>, which is valid HTML. -->
<Banner
color="primary"
icon="lucide:gift"
title="Black Friday — 30% off all plans. Click for details."
to="/pricing"
/>
<!-- External link with target="_blank" -->
<Banner
color="info"
icon="lucide:book-open"
title="Read our latest blog post →"
to="https://example.com/blog"
target="_blank"
/>Custom Snippets
Replace any of leading, titleSlot, actionsSlot, or closeSlot. When you use closeSlot, you own the dismiss logic — bind open.
<script lang="ts">
import { Banner, Button, Badge } from 'sv5ui';
let open = $state(true);
</script>
<!-- Replace any of: leading, titleSlot, actionsSlot, closeSlot.
When you use closeSlot you own the dismiss logic — bind `open`. -->
<Banner color="primary" bind:open close>
{#snippet leading()}
<Badge label="v1.8" variant="solid" color="surface" size="xs" />
{/snippet}
{#snippet titleSlot()}
<span class="font-semibold">Editor, Stepper & Banner are here.</span>
{/snippet}
{#snippet actionsSlot()}
<Button label="Try the Editor" variant="outline" size="xs" href="/docs/components/editor" />
{/snippet}
</Banner>Forgetting a Dismissal
If you ever need to bring a persisted banner back programmatically (e.g. when the announcement updates), remove the matching localStorage key. The exact key is sv5ui-banner-{sanitized-id} — non-alphanumeric / dash / underscore characters in id are replaced with -.
No interactive demo — call this helper from your own code whenever you want to re-show a previously dismissed banner.
<script lang="ts">
// Forget the dismissal so the banner reappears on the next mount.
function resetBannerDismissal(id: string) {
const key = `sv5ui-banner-${id.replace(/[^a-zA-Z0-9_-]/g, '-')}`;
localStorage.removeItem(key);
}
</script>UI Slots
Use the `ui` prop to override classes on internal elements.
| Slot | Description |
|---|---|
root | Outermost wrapper — full-width bar, controls background color |
container | Inner flex container with horizontal padding |
left | Left spacer area (hidden below `lg` breakpoint) |
center | Center area holding icon + title + actions |
right | Right spacer area holding the close button |
icon | Leading icon |
title | Title text |
actions | Action buttons container |
close | Close button |
Snippets
| Snippet | Description |
|---|---|
leading | Custom leading content — replaces the default `icon` rendering |
titleSlot | Custom title content — replaces the default `title` text |
actionsSlot | Custom actions content — replaces the default `actions` array |
closeSlot | Custom close button. You own the dismiss logic — bind `open` externally |
Props
| Prop | Type | Default |
|---|---|---|
id | string | - |
title | string | - |
icon | string | - |
color | 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'error' | 'info' | 'surface' | 'primary' |
to | string | - |
target | string | - |
close | boolean | ButtonProps | false |
closeIcon | string | 'lucide:x' |
actions | ButtonProps[] | - |
open | boolean | true |
onClose | () => void | - |
as | keyof HTMLElementTagNameMap | 'div' |
ref | HTMLElement | null | null |
class | string | - |
ui | Record<Slot, Class> | - |