Alert
A message box that tells people about news, guidance, a finished task, something that needs attention, or an error. It comes in five variants and three types, the same as the Figma set, with an optional action and close button.
Installation
npx @smicolon/fasla-ui@latest add alertRun init once per project before adding components. See Installation.
Alert is built on Button, so adding it adds button too.
Preview
Variants
variant says what the message is about: default for news, info for guidance, success for a finished task, warning for something that needs attention soon, and destructive for an error. Each variant has its own icon as well as its own colour token, so the meaning never rests on colour alone.
defaultinfosuccesswarningdestructiveTypes
type sets how strongly the alert stands out. outline, the default, is a card with a 1px edge in the variant's colour. soft lays a 10% tint of that colour over the card. solid fills the alert with the colour and stands out most, so keep it for messages people must not miss. The action follows the type: an outline Button on outline, a solid Button on soft, and a secondary Button on solid.
outlinesoftsolidIcon and avatar
Each variant shows its own 16px icon, centred on the title's first line: an i in a circle for default and info, a check mark for success, a triangle for warning and an exclamation mark in a circle for destructive. Pass another icon to icon to replace it, an Avatar for a message from a person, or set icon to false to leave it out. An avatar is 32px and sits at the top.
Action and close button
AlertAction is a Button at xs, 26px tall, and takes every Button prop, so asChild makes it a link. AlertClose is a ghost Icon Button with a 16px ×. Both sit at the end of the first line, the action first, 12px apart.
Long text
The title and the description wrap in their own column. The icon stays on the title's first line, and the action and close button stay at the top. AlertDescription can hold more than a sentence: paragraphs, a list or a link.
Projects, members and files carry over as they are. Shared links made before the move keep working for 30 days, then ask viewers to sign in.
Read the full list of changes before the move, and tell your team which links to replace.
Closing
Pressing AlertClose hides the alert and calls onOpenChange(false). Control the alert with open to show it again, or to remember that someone closed it. To keep it open, call event.preventDefault() in the close button's onClick.
Accessibility
- The role follows the variant.
destructivehasrole="alert": an error needs attention now, so screen readers interrupt what they are reading to announce it. The other variants haverole="status", which screen readers announce once they finish the current sentence, because news, guidance, a finished task and a warning can wait that long. Passroleto choose another, such asrole="note"for a message that is part of the page from the start. - Screen readers announce an alert when it appears. Render it when the event happens, and keep the title and description short, since both are read out.
- The icon is decorative and hidden from assistive technology; the title says what the message is about.
- The close button is named “Close”, or “إغلاق” when the nearest
langis Arabic. Passlabelto say what it closes. - When the alert closes while it holds focus, move focus on in
onOpenChange, for example to the control that led to the message. Otherwise the next Tab starts again at the top of the page. - In Windows high contrast mode the alert keeps a border in the system's text colour, so its edge stays visible when the fill is dropped.
- Direction follows the page's
dir; there is no prop. Right to left, the row starts on the right with the icon and ends with the close button, and the text is set in Cairo on its taller line.
Props
Alert
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "default" | "info" | "success" | "warning" | "destructive" | "default" | What the message is about. Sets the icon, the colour and the default role. |
type | "outline" | "solid" | "soft" | "outline" | How strongly it stands out: a card with an edge, a tint, or a solid fill. |
icon | boolean | ReactNode | true | The variant's icon by default. false leaves it out; any element, such as an icon or an Avatar, replaces it. |
open | boolean | — | Whether the alert is shown. Set it to control the alert. |
defaultOpen | boolean | true | Whether the alert is shown at first, when you don't control it. |
onOpenChange | (open: boolean) => void | — | Called with false when the close button is pressed. |
role | string | — | alert for destructive, status for the rest, unless you pass another. |
children | ReactNode | — | The AlertTitle, AlertDescription, AlertAction and AlertClose, in that order. |
className | string | — | Extra classes for the alert. It fills its container's width. |
AlertTitle
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | The title: one short line that says what happened. |
className | string | — | Extra classes for the title. |
AlertDescription
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | More detail: a sentence, paragraphs, a list or a link. |
className | string | — | Extra classes for the description. |
AlertAction
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "default" | "outline" | "ghost" | "soft" | "link" | — | The Button type. Follows the alert's type unless you set it. |
tone | "primary" | "secondary" | "destructive" | — | The Button tone. Follows the alert's type unless you set it. |
size | "xs" | "sm" | "md" | "lg" | "xs" | The Button size. |
asChild | boolean | false | Makes its only child the action, with these styles: a link, say. |
onClick | (event) => void | — | Called when the action is pressed. |
children | ReactNode | — | The label: a verb for what happens next. |
className | string | — | Extra classes for the action. It takes every other Button prop too. |
AlertClose
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | — | The button's name for screen readers. “Close” by default, in the page's language. |
onClick | (event) => void | — | Called before the alert closes. Call event.preventDefault() to keep it open. |
children | ReactNode | — | Another icon in place of the ×. |
className | string | — | Extra classes for the close button. |
Usage
A message
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
export function MaintenanceNotice() {
return (
<Alert variant="info">
<AlertTitle>Maintenance tonight</AlertTitle>
<AlertDescription>The dashboard is offline from 22:00 to 23:00.</AlertDescription>
</Alert>
)
}With an action and a close button
import {
Alert,
AlertAction,
AlertClose,
AlertDescription,
AlertTitle,
} from "@/components/ui/alert"
export function SaveError({ onRetry }: { onRetry: () => void }) {
return (
<Alert variant="destructive" type="soft">
<AlertTitle>Changes not saved</AlertTitle>
<AlertDescription>The connection to the server dropped. Check your connection and try again.</AlertDescription>
<AlertAction onClick={onRetry}>Retry</AlertAction>
<AlertClose />
</Alert>
)
}Showing a closed alert again
"use client"
import { useState } from "react"
import { Alert, AlertClose, AlertDescription, AlertTitle } from "@/components/ui/alert"
import { Button } from "@/components/ui/button"
export function InboxNotice() {
const [open, setOpen] = useState(true)
if (!open) {
return (
<Button variant="outline" size="sm" onClick={() => setOpen(true)}>
Show it again
</Button>
)
}
return (
<Alert open={open} onOpenChange={setOpen}>
<AlertTitle>New message</AlertTitle>
<AlertDescription>You have 12 unread messages in your inbox.</AlertDescription>
<AlertClose />
</Alert>
)
}A message from a person
import { Alert, AlertAction, AlertDescription, AlertTitle } from "@/components/ui/alert"
import { Avatar } from "@/components/ui/avatar"
export function ReplyNotice() {
return (
<Alert icon={<Avatar src="/avatars/layla.png" name="" radius="rounded" />}>
<AlertTitle>Layla Haddad replied</AlertTitle>
<AlertDescription>“The new layout works. Ship it on Monday.”</AlertDescription>
<AlertAction asChild>
<a href="/messages/42">Reply</a>
</AlertAction>
</Alert>
)
}