Skip to main content

Alert

An alert is a message that stays in the page, next to what it is about. Each variant is a 10% tint and a 30% border of its hue under text-foreground, so a brand only sets --success, --warning and --destructive for alerts to follow.

import Alert from '@zuilib/components/alert'

Variants

info tints from --primary (--info is a surface token, not a hue); neutral is the muted surface. Each has a default status icon, painted in the variant colour.

Loading example

Icon and actions

icon replaces the default glyph; false removes the icon column. Alert.Actions is a row for buttons under the text.

Loading example

Dismissible

dismissible adds a close button named Dismiss, <title>. Uncontrolled, a click removes the alert (remount with a new key to show it again). With open, the click only calls onDismiss and the parent decides.

Loading example

Props

AlertProps extends div props (minus title).

PropTypeDefaultDescription
variant'info' | 'success' | 'warning' | 'destructive' | 'neutral''info'
iconReactNode | falsevariant iconfalse or null removes the icon column; decorative (aria-hidden)
live'assertive' | 'polite' | 'off''assertive'assertive is role="alert"; polite is role="status" for info / success / neutral (warning and destructive stay alert); off renders no live role. An explicit role prop wins
dismissiblebooleanfalseRenders the close button
onDismiss() => voidCalled when the close button is pressed
openbooleanControlled visibility; when given the close button only calls onDismiss
dismissLabelstring'Dismiss'Close button name, composed with the Alert.Title text
classNamestringMerged last, after the variant classes

Alert.Title, Alert.Description and Alert.Actions take div props. The title is a div, not a heading; pass role="heading" aria-level={n} when it belongs in the outline. Its id (generated unless you pass one) is what the close button's name refers to.

Slots

SlotElementNotes
[data-slot="alert"]divRoot. Also data-variant, data-live, data-dismissible
[data-slot="alert-icon"]spanIcon column; aria-hidden
[data-slot="alert-content"]divColumn holding the children
[data-slot="alert-title"]div
[data-slot="alert-description"]divLinks inside are underlined
[data-slot="alert-actions"]divFlex row, wraps
[data-slot="alert-close"]buttonPresent when dismissible
[data-slot="alert-close-icon"]svg
/* Consumer CSS: informational alerts in a hue of your own */
[data-slot="alert"][data-variant="info"] {
background-color: color-mix(in oklch, var(--brand-blue) 10%, transparent);
border-color: color-mix(in oklch, var(--brand-blue) 30%, transparent);
}

Tokens

TokenUsed for
--primary, --success, --warning, --destructiveTint and border per variant
--success-text, --warning-textIcon colour where the base hue is too light on the tint
--muted, --border, --muted-foregroundThe neutral surface and icon
--foregroundTitle and description text
--radius-lgCorner radius
--ringClose button focus ring

Accessibility

  • role="alert" by default (screen readers interrupt); live="polite" downgrades non-urgent variants to role="status"; live="off" for a callout that is part of the page on load.
  • The icon is decorative; Alert.Title carries the meaning.
  • The close button is named "{dismissLabel}, {title}" through aria-labelledby, so several alerts' close buttons are distinguishable.
  • When the alert disappears while focus is inside it, focus moves to the element it came from, else the next tabbable element after the alert, then the previous one, then a focusable ancestor. It never lands on <body>.
  • Description text keeps full --foreground colour: --muted-foreground sits under 4.5:1 on the tints.
  • Message: the inline validation line under a field.
  • Badge: shares the -text contrast twins.