Skip to main content

Alert

Implemented

Inline alert (success, error, warning, info) — distinct from Banner. Used for form validation, system messages.

Categorymolecules
Sourcepatterns/molecules/alert.html
AI HintInline feedback for success/error/warning/info. error maps to role='alert' (assertive); other variants map to role='status' (polite). Page-level messaging → Banner; inline form-field errors → FormFieldError.

An inline alert for form validation, system messages, and contextual feedback. Renders with role="alert" for errors and role="status" for everything else, so assistive tech announces the message without interrupting the current task.

Alert

Feedback & Overlay — Family 4

A self-contained inline alert. Owns its semantic color tokens, accent bar, icon, dismiss button, and ARIA wiring. Use it for validation outcomes, save confirmations, and short system messages that sit next to the content they describe — distinct from Banner (page-level announcements) and FormFieldError (errors attached to a single form field).

Tickets on sale Friday

The OSM concert opens at 10:00 — set a reminder so you don't miss the on-sale.
Payment accepted — your tickets are in your wallet.

Low stock

Only 14 tickets left for the July 5th show.

Dismissible

Pass dismissible plus an onDismiss function to add the close button.

This component supports light and dark mode.

Usage

An Alert is an inline message — it sits inside the flow of the page, next to the form field or panel it describes. Pair a semantic variant with children for the body; add a title when the message benefits from a heading.

import { Alert } from '@epasslive/design-system'

<Alert variant="success" title="Profile updated">
  Your display name and email are now visible to collaborators.
</Alert>

<Alert
  variant="error"
  title="Payment could not be processed"
  dismissible
  onDismiss={() => setShowError(false)}
  dismissLabel={t('common.close')}
>
  Your card was declined. Update your payment method to finish the order.
</Alert>

Alert vs. Banner vs. Notification

Use Alert for short, contextual messages that live inside a form, panel, or card. Use Banner for page-level announcements that span the full width of the layout. Both expose the same four variants — Banner composes the Alert variant contract (ALERT_VARIANT_STYLES) instead of re-declaring its own — but Banner reserves more vertical space and accepts an optional action with its own treatment. For persistent per-user notifications that accumulate in a feed (the bell dropdown), use Notification rows inside a container that owns aria-live="polite" — an Alert is a single inline message in page flow, not a feed item, and an ephemeral auto-dismissing message is a Toast. See the full Alert vs. Toast vs. Notification boundary table on the Notification page.

Alert vs. FormFieldError

Use FormFieldError for validation messages attached to a single form field — it renders inline below the input, wired to the field's aria-invalid state. Use Alert for everything broader: panel-level validation summaries, system messages, and contextual feedback that is not owned by one field. The split is enforced by convention — do not migrate one into the other.

Dismiss behavior

The dismiss button is only rendered when both dismissible is true and onDismiss is a function. The parent owns the visible state — the component does not unmount itself. Pass dismissLabel for i18n parity; the same label is exposed via aria-label on the button.

Accessibility

The root element carries role="alert" with aria-live="assertive" for the error variant, and role="status" with aria-live="polite" for success, warning, and info. When a title is set, the heading is wired to the root via aria-labelledby. Icons are decorative (aria-hidden) — announcement is owned by the role + aria-live pair. The variant is mirrored to data-variant for end-to-end testing.

Dark mode

Alert supports light and dark themes through the ADR-027 semantic token family: each variant has a dedicated --ep-semantic-{success,warning,error,info}-tint background, -fg foreground, and -tint-border border, with light and dark values tuned so text meets WCAG AA (≥4.5:1) on its own tint in both themes (Tailwind: bg-ep-semantic-success-tint, text-ep-semantic-success-fg, border-ep-semantic-success-tint-border). When styling custom alert-like surfaces, consume these theme-tuned token pairs rather than layering /10-alpha variants of the raw accent tokens — alpha transparency over the page background does not hold contrast in both themes, and some alpha steps are not registered for every accent (ghost utilities).

Props

Prop
Type
Default
Description
variant*
AlertVariant
—

Semantic tone: "success" | "error" | "warning" | "info". Drives the container background, border, accent bar, and icon color, and the role/aria-live pair (error → alert / assertive, everything else → status / polite).

title
string
—

Optional visible heading. When set, the heading element is wired to the root via aria-labelledby so screen readers read the title before the body.

children*
React.ReactNode
—

Body copy. Plain text, inline links, or short fragments — the alert is non-interactive aside from the optional dismiss button.

dismissible
boolean
false

When true, the dismiss button renders. The button is only rendered when dismissible is true AND onDismiss is a function — both must be set to avoid a non-functional button.

onDismiss
() => void
—

Callback fired when the dismiss button is clicked. The parent owns the visible state — the component does not unmount itself.

dismissLabel
string
Dismiss alert

i18n-ready label for the dismiss button, exposed via aria-label. Override it on non-English locales (the default is English).

className
string
—

Extra classes appended to the root wrapper.

id
string
alert-<useId()>

Optional explicit id. When set, the title gets a derived id ("<id>-title") for the aria-labelledby wiring.

icon
React.ReactNode
—

Optional override for the variant default icon. Pass a DS icon atom (e.g. <PhosphorIcon icon={Warning} size={20} aria-hidden />) so screen readers still rely on the parent role + aria-live for announcement.

Props

Preview

Alert

Prop
Type
Required
Default
Description
variant
'success' | 'error' | 'warning' | 'info'
Required
—

Alert type

title
string
Optional
—

Alert title

children
React.ReactNode
Required
—

Alert content

dismissible
boolean
Optional
false

Show dismiss button

onDismiss
() => void
Optional
—

Dismiss handler

dismissLabel
string
Optional
'Dismiss alert'

Accessible label for the dismiss button. Default is English — pass a localized label.

icon
React.ReactNode
Optional
variant default

Overrides the variant's default icon. Pass a DS icon atom (aria-hidden).

role
'alert' | 'status' | 'note'
Optional
variant default ('alert' for error, 'status' otherwise)

Override the variant-default ARIA role. Pass explicitly when the announcement semantics differ from what the variant implies.

ariaLive
'polite' | 'assertive' | 'off'
Optional
variant default ('assertive' for error, 'polite' otherwise)

Override the variant-default aria-live politeness.

className
string
Optional
—

Additional CSS classes on the alert container.

id
string
Optional
—

Root element id.

Quick use:<Alert />

Accessibility

ARIA rolealert

ARIA

2 rules

WCAG 4.1.3

role='alert' (or role='status' for non-urgent) is required

WAI-ARIA APG

aria-live='assertive' for errors, 'polite' for info

validation

1 rule

NASA Rule 5

Message text must be present (not empty) when shown

Usage

Import

tsxSnippet
import { Alert } from "@epasslive/design-system"

Example 1

tsxSnippet
<Alert variant='info' title='Saved'>Preferences updated.</Alert>

Example 2

tsxSnippet
<Alert variant='error' title='Checkout failed' dismissible onDismiss={closeAlert}>Card declined — try another payment method.</Alert>

Anti-patterns

— Do not hardcode data in molecules

— Avoid complex business logic in molecules

Design System v4.1.0 | ePassLive