Alert
ImplementedInline alert (success, error, warning, info) — distinct from Banner. Used for form validation, system messages.
patterns/molecules/alert.htmlAn 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
Low stock
Payment failed
Dismissible
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
variant*AlertVariantSemantic 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).
titlestringOptional 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.ReactNodeBody copy. Plain text, inline links, or short fragments — the alert is non-interactive aside from the optional dismiss button.
dismissiblebooleanfalseWhen 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() => voidCallback fired when the dismiss button is clicked. The parent owns the visible state — the component does not unmount itself.
dismissLabelstringDismiss alerti18n-ready label for the dismiss button, exposed via aria-label. Override it on non-English locales (the default is English).
classNamestringExtra classes appended to the root wrapper.
idstringalert-<useId()>Optional explicit id. When set, the title gets a derived id ("<id>-title") for the aria-labelledby wiring.
iconReact.ReactNodeOptional 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
Alert
variant'success' | 'error' | 'warning' | 'info'—Alert type
titlestring—Alert title
childrenReact.ReactNode—Alert content
dismissiblebooleanfalseShow dismiss button
onDismiss() => void—Dismiss handler
dismissLabelstring'Dismiss alert'Accessible label for the dismiss button. Default is English — pass a localized label.
iconReact.ReactNodevariant defaultOverrides the variant's default icon. Pass a DS icon atom (aria-hidden).
role'alert' | 'status' | 'note'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'variant default ('assertive' for error, 'polite' otherwise)Override the variant-default aria-live politeness.
classNamestring—Additional CSS classes on the alert container.
idstring—Root element id.
<Alert />Accessibility
ARIA
2 rulesvalidation
1 ruleUsage
Import
import { Alert } from "@epasslive/design-system"Example 1
<Alert variant='info' title='Saved'>Preferences updated.</Alert>Example 2
<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