Data display
Alert
Alerts are inline messages that sit in the flow of a page: a heads-up before something goes wrong, the result of an action, or a problem the user needs to fix. Each tone has its own icon and a spoken prefix, actions go under the text, and alerts can be dismissible. For brief, self-dismissing messages use a toast instead.
On this page
Warning: Your card expires on April 30
Error: 2 invoices could not be sent
<Alert tone="warning" title="Your card expires on April 30"> Update your payment method to keep Ledgerly running without interruption.</Alert><Alert tone="danger" title="2 invoices could not be sent" actions={ <> <Button size="sm" variant="secondary">Review invoices</Button> <Button size="sm" variant="ghost">Retry all</Button> </> }> The recipients for INV-2041 and INV-2047 bounced. Check the email addresses and try again.</Alert>Usage
import { Alert } from "@/components/ui/alert"; <Alert tone="warning" title="Your card expires on April 30"> Update your payment method to keep Ledgerly running.</Alert>Examples
Overview
Warning: Your card expires on April 30
Error: 2 invoices could not be sent
<Alert tone="warning" title="Your card expires on April 30"> Update your payment method to keep Ledgerly running without interruption.</Alert><Alert tone="danger" title="2 invoices could not be sent" actions={ <> <Button size="sm" variant="secondary">Review invoices</Button> <Button size="sm" variant="ghost">Retry all</Button> </> }> The recipients for INV-2041 and INV-2047 bounced. Check the email addresses and try again.</Alert>Tones
Info for neutral news, success for completed actions, warning for something that needs attention soon, danger for failures. Neutral is for state that is neither good nor bad.
Info: Scheduled maintenance
Success: Payout sent
Warning: Approaching your seat limit
Error: Sync failed
Note: Read-only mode
<Alert tone="info" title="Scheduled maintenance">Exports are paused on Sunday from 02:00 to 03:00 UTC.</Alert><Alert tone="success" title="Payout sent">$12,480.00 is on its way to the account ending in 4821.</Alert><Alert tone="warning" title="Approaching your seat limit">9 of 10 seats are in use on the Team plan.</Alert><Alert tone="danger" title="Sync failed">We couldn’t reach your bank. Reconnect it to resume syncing.</Alert><Alert tone="neutral" title="Read-only mode">This workspace was archived by Ada Moreno on March 3.</Alert>Without a title
Short messages can skip the title. Links in the description are underlined. Swap the icon with icon, or hide it with icon={false}.
<Alert tone="info"> Prices exclude VAT. <a href="/docs/tax">See how tax is calculated</a>.</Alert><Alert tone="success" icon={<Sparkles strokeWidth={1.75} />}> Smart categories are now on for all new transactions.</Alert>Dismissible
Pass onDismiss to add a close button. Remember the choice if the alert should stay closed.
Info: New: recurring invoices
const [open, setOpen] = useState(true); {open ? ( <Alert tone="info" title="New: recurring invoices" onDismiss={() => setOpen(false)} dismissLabel="Dismiss announcement"> Bill retainers automatically every month. Set it up from any invoice. </Alert>) : null}Announced after an action
Set live on alerts that appear in response to something the user did. Danger and warning use role="alert", the others role="status".
{saved === "ok" ? ( <Alert live tone="success" title="Settings saved" onDismiss={() => setSaved(null)}> Your billing email is now billing@fernhill.example. </Alert>) : null}{saved === "error" ? ( <Alert live tone="danger" title="Couldn’t save settings" onDismiss={() => setSaved(null)}> The billing email is not valid. Check it and try again. </Alert>) : null}Props
tone"info" | "success" | "warning" | "danger" | "neutral"default: "info"Color, icon and spoken prefix.titleReactNodedefault: —One short sentence in medium weight.childrenReactNodedefault: —Description. Links inside are underlined automatically.iconReactNode | falsedefault: —Replace the tone icon, or false to hide it.actionsReactNodedefault: —Buttons or links under the description.onDismiss() => voiddefault: —Shows a close button in the corner.dismissLabelstringdefault: "Dismiss"Accessible name of the close button.livebooleandefault: falseAnnounce on appearance: role="alert" for warning and danger, role="status" otherwise.
Accessibility
- Static alerts have no live role, so they are read in order with the page instead of interrupting on load. Use live only for alerts that appear after an action.
- Every alert starts with a visually hidden word ("Warning:", "Error:", "Success:") so the tone is not carried by color and icon alone.
- The tone icon is decorative and hidden from assistive tech.
- The dismiss button is a real button with an accessible name; after dismissing, move focus to a sensible place if the alert had focus.
- Tinted backgrounds keep body text at 4.5:1 or better in light and dark themes.