FeedbackAlert
Alert
A persistent, in-flow message. The page-level way to say something is or isn't right.
Tones
Info (default) is for general notes. Success is for completed actions. Warning is for non-fatal issues. Destructive is for blocking errors.
Tones
Note
A general note about the section above.
Saved
Your changes have been saved.
Be careful
This action can be undone, but only for 24 hours.
Could not save
A network error interrupted the request. Try again.
Dismissible
The close button appears in the top-right. The alert animates out on dismiss.
Dismissible
Note
You can dismiss this alert by clicking the ×.
Anatomy
- 3 px left border in the tone color; 1 px
--borderon the other three sides --surface-elevatedbackground, 4 px radius- Icon, title, body, optional close button — all four on a single row, vertically aligned to the top
- Default: 0.875 rem title, 0.875 rem body, 0.5 rem gap between icon and content
Implementation
alert.tsx
import { type ReactNode } from "react"
import { Info, AlertTriangle, CheckCircle2, X } from "lucide-react"
import SiteIcon from "@/components/site-icon"
type Tone = "info" | "warning" | "success" | "destructive"
interface AlertProps {
tone?: Tone
title: string
children: ReactNode
dismissible?: boolean
onDismiss?: () => void
}
const iconMap = {
info: Info,
warning: AlertTriangle,
success: CheckCircle2,
destructive: X,
}
export function Alert({ tone = "info", title, children, dismissible, onDismiss }: AlertProps) {
const Icon = iconMap[tone]
return (
<div
className={`ds-alert ${tone === "destructive" ? "ds-alert--destructive" : ""}`}
role={tone === "destructive" ? "alert" : "status"}
>
<span className="ds-alert__icon">
<SiteIcon icon={Icon} size="md" tone={tone === "destructive" ? "emphasis" : "muted"} />
</span>
<div style={{ flex: 1 }}>
<p className="ds-alert__title">{title}</p>
<p className="ds-alert__body">{children}</p>
</div>
{dismissible ? (
<button className="ds-alert__close" onClick={onDismiss} aria-label="Dismiss">
<SiteIcon icon={X} size="sm" tone="muted" />
</button>
) : null}
</div>
)
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
tone | "info" | "warning" | "success" | "destructive" | "info" | The visual style |
title | string | None | The bolded title |
dismissible | boolean | false | Adds a close button |
onDismiss | () => void | None | Required if dismissible |