Alert Banner

Free

Dismissible alert banners in 5 semantic variants and multiple display styles.

</>sv-alert-banner alertbannerfeedback
import { SvAlertBannerComponent } from '@styloviz/alert-banner';

Demo & usage

Basic usage

Usage example — open the gallery for the full interactive demo.

An interactive demo for this component lives in the gallery.

Open live demo

More examples

With actions

example.htmlAngular
<!-- No autoDismissMs here, and it would be ignored if there were:
     a banner with actions must not remove itself while the user is
     aiming at one of them. Same for variant="danger". -->
<sv-alert-banner
  variant="success"
  message="Changes published."
  [actions]="bannerActions"
  (actionClick)="onAction($event)" />

Auto-dismiss, where it is allowed

example.htmlAngular
<!-- Allowed: no actions, and not a danger banner. The countdown
     pauses while the pointer or the keyboard focus is over the
     banner (WCAG 2.2.1). -->
<sv-alert-banner
  variant="success"
  message="Saved."
  [autoDismissMs]="5000" />

Two pinned banners that do not know about each other

example.htmlAngular
<!-- The shell renders one, the route renders the other. They used to
     get byte-identical "fixed top-0 left-0 right-0 z-50" and paint on
     top of each other, so one was simply never seen. Now the higher
     priority takes the edge and the other is stacked below it. -->
<sv-alert-banner
  position="top-fixed"
  [priority]="10"
  variant="danger"
  message="Read-only until 21:00 UTC" />

<sv-alert-banner
  position="top-fixed"
  variant="info"
  message="Your trial ends in 3 days" />

<!-- And two copies of the SAME notice are one notice: the later
     registration renders nothing. Give it a key when the wording
     differs but the subject does not. -->
<sv-alert-banner
  position="top-fixed"
  dedupeKey="maintenance"
  message="Maintenance in progress" />

Announcement bar (full-bleed top strip)

alertStyle="announcement" with position="top-fixed" renders a centered, edge-to-edge promo bar with an inline CTA and dismiss.

example.htmlAngular
<sv-alert-banner
  alertStyle="announcement"
  position="top-fixed"
  variant="info"
  title="New:"
  message="Styloviz 2.0 is here."
  [actions]="[{ id: 'learn', label: 'Learn more' }]" />

When to use

  • Communicating a persistent, page-level status or message (info, success, warning, error).
  • You need an inline banner the user can act on or dismiss.
  • For transient confirmations, use a Toast; for blocking decisions, a Confirm Dialog.

Async states

None — this component has nothing to load, so it has no loading, empty or error state to drive.

Inputs

NameTypeDefaultDescription
titlestring''Bold heading line. Leave empty to render body-only.
messagestring''Main alert message text.
variantAlertVariant'info'Semantic color.
alertStyleAlertStyle'soft'Visual treatment.
sizeAlertSize'md'Size controls padding and text scale.
positionAlertPosition'inline'Positioning mode. - `inline` — block element in document flow (default) - `top-fixed` — fixed to viewport top, full width - `bottom-fixed` — fixed to viewport bottom, full width - `top-sticky` — sticky inside its scroll container
showIconbooleantrueShow the leading icon.
iconstring''Icon-library NAME overriding the default variant icon — e.g. `'bell'`. Leave empty to use the built-in icon for the current variant. BREAKING (icon sweep): was `iconPath`, a raw `<path d="…">`. `iconViewBox` is GONE — it only existed because a raw path might not be 24-box.
actionsAlertAction[][]Up to 2 action buttons rendered inline. Each button emits its `id` via `actionClick`.
dismissiblebooleantrueShow the × close button.
autoDismissMsnumber0Auto-dismiss after N milliseconds. Set to 0 to disable auto-dismiss.
prioritynumber0Stack weight for a pinned banner: higher sits against the edge.
dedupeKeystring | null | undefinedundefinedIdentity for suppressing a duplicate pinned banner. | Value | Meaning | |-----------|------------------------------------------------------------| | omitted | derive from variant + style + title + message | | a string | suppress on that, whatever the text | | `null` | never suppress | A SUPPRESSED BANNER RENDERS NOTHING — no count, unlike a deduplicated toast. A toast reports an EVENT, so "it happened eleven times" is information; a banner reports a STATE, and "your trial expires ×2" is not a thing that can be true.
customClassstring''Additional CSS classes merged on the root element.

Outputs

EventPayload typeDescription
dismissedvoidEmitted after the alert finishes its close animation.
actionClickstringEmitted when an action button is clicked, carrying the action `id`.

Customization & theming

  • Five semantic variants.
  • Soft, solid and bordered styles.
  • Optional icon and action buttons.
  • Priority stacking for pinned banners: `[priority]` decides which gets the edge and the rest are offset by the measured height of the ones above them — `top` for a top-pinned banner, `bottom` for a bottom-pinned one, and `top-sticky` is a stack of its own because it scrolls with its container. Coordinated through a root service, because the banners on a page do not share a parent.
  • Duplicate suppression: a pinned banner identical to one already on screen renders nothing. Key it with `dedupeKey`, or `null` to opt out.
  • Auto-dismiss is REFUSED for a `danger` banner and for any banner with `actions`: a state the user has to know about does not stop being true after a few seconds, and a control cannot be used if it disappears while being aimed at. Everything else keeps its countdown, paused while the pointer is over it OR focus is inside it. The rule, stated: only a short, informational message the user needs to do nothing about may time out. The component enforces it three ways — the countdown is refused when projected content holds a link, button or field (not only for `actions`), and it is never shorter than the text takes to read (`readingTimeMs`: title + message length × `SV_ALERT_READING_MS_PER_CHAR`, 60 ms per character), so `effectiveAutoDismissMs` reports what actually runs.
  • A full-bleed `announcement` style: a centered, gradient top bar with an inline CTA and dismiss — pair with `position="top-fixed"`.

Best practices

  • Do: Match `variant` to severity so color reinforces the message.
  • Do: Keep the message actionable — say what happened and what to do next.
  • Don't: Don't auto-dismiss errors the user must read and act on.
  • Do: Set `priority` when two pinned banners can be on screen at once — higher takes the edge and the rest stack below it, in registration order among equals. Without it two `top-fixed` banners painted on top of each other and one was never seen.
  • Tip: A pinned banner whose variant, style, title and message match one already on screen renders nothing; `dedupeKey` keys that on a subject instead of the wording, and `[dedupeKey]="null"` opts out. Inline banners are never suppressed — two identical ones are usually feedback about two different fields.

Accessibility

  • Announces through the kit's single live region (`SvLiveAnnouncer`), assertively for `danger` and politely for everything else — including `warning`, because `assertive` cuts a screen reader off mid-word and a warning you are not blocked by does not earn that.
  • ⚠️ The banner itself is NO LONGER a live region. It used to carry `aria-live` and `role="alert"` on its own root, which means the region was inserted complete, with its text already inside it — the arrangement assistive technology is least likely to announce, because AT watches an EXISTING region for changes. The visible root keeps `role="status"` so you can still find it and reach its actions.
  • The same message is not repeated when the host re-renders the banner, which is what the shared announcer's deduplication is for.
  • Dismiss control is a labelled button, the auto-dismiss timer pauses on hover/focus (WCAG 2.2.1), and dismissing with the close button leaves focus in the region the banner was removed from rather than on `<body>`.

Feedback on Alert Banner

Spotted a gap in this page, or something that didn't work as described? Comments are GitHub Discussions in the public styloviz/community repo, so posting needs a GitHub account.

Loads giscus.app and GitHub — nothing is fetched until you click.