Alert
A message in the page: what happened, and what to do.
import { Alert } from "@flinbu/seed";Subtle
The default: a neutral petal with the card hairline. Only the icon carries the tone.
Info: Seed 1.2.0 is out
Success: cs_204 applied
Warning: 4 text colors fail contrast in Light
Error: We couldn’t sync to Figma
import { Alert, Button, Link } from "@flinbu/seed";
<div className="flex w-full max-w-xl flex-col gap-sm">
<Alert title="Seed 1.2.0 is out">Focus ring tokens and a pill Tabs variant. <Link href="#">See what’s new</Link></Alert>
<Alert variant="success" title="cs_204 applied">Figma updates on the next sync.</Alert>
<Alert variant="warning" title="4 text colors fail contrast in Light" action={<Button size="sm" variant="secondary">Fix them</Button>}>
They sit below 4.5:1 on bg-primary since yesterday’s sync.
</Alert>
<Alert variant="error" title="We couldn’t sync to Figma" onDismiss={() => {}}>Figma didn’t respond. Your changes are safe.</Alert>
</div>Loud
The same surface with a hairline in the tone, for the few alerts that must stand out.
Info: Seed 2.0 needs a migration
Success: Your system is healthy again
Warning: You’re out of credits
Error: Sync to Figma failed
import { Alert, Button, Link } from "@flinbu/seed";
<div className="flex w-full max-w-xl flex-col gap-sm">
<Alert emphasis="loud" title="Seed 2.0 needs a migration">Token names change on March 3. <Link href="#">Read the guide</Link></Alert>
<Alert emphasis="loud" variant="success" title="Your system is healthy again">All 446 tokens pass AA in Light and Dark.</Alert>
<Alert emphasis="loud" variant="warning" title="You’re out of credits" action={<Button size="sm" variant="secondary">Add credits</Button>}>
Pluto pauses until the 1st, or until you add more.
</Alert>
<Alert emphasis="loud" variant="error" title="Sync to Figma failed" action={<Button size="sm" variant="secondary">Try again</Button>}>
Figma didn’t respond three times in a row. Your changes are safe here.
</Alert>
</div>Light and Dark
Both modes and all four tones in each theme.
Info: Subtle info
Success: Subtle success
Warning: Subtle warning
Error: Subtle error
Info: Loud info
Success: Loud success
Warning: Loud warning
Error: Loud error
Info: Subtle info
Success: Subtle success
Warning: Subtle warning
Error: Subtle error
Info: Loud info
Success: Loud success
Warning: Loud warning
Error: Loud error
import { Alert, Link } from "@flinbu/seed";
<div className="grid w-full gap-base md:grid-cols-2">
{(["light", "dark"] as const).map((theme) => (
<div key={theme} data-theme={theme} className="flex flex-col gap-sm rounded-xl border border-secondary bg-primary p-base">
<span className="mono-label-medium text-tertiary">{theme === "light" ? "Light" : "Dark"}</span>
{(["info", "success", "warning", "error"] as const).map((v) => <Alert key={v} variant={v} title={`Subtle ${v}`}>Only the icon is in color. <Link href="#">A link</Link></Alert>)}
{(["info", "success", "warning", "error"] as const).map((v) => <Alert key={v} variant={v} emphasis="loud" title={`Loud ${v}`}>The hairline takes the tone.</Alert>)}
</div>
))}
</div>Appears after an action
live announces it: role alert for this error, role status for the other tones.
import { Alert, Button } from "@flinbu/seed";
const [failed, setFailed] = React.useState(false);
<div className="flex w-full max-w-xl flex-col items-start gap-sm">
<Button variant="secondary" onClick={() => setFailed(true)}>Sync to Figma</Button>
{failed ? (
<Alert live emphasis="loud" variant="error" title="Sync to Figma failed" onDismiss={() => setFailed(false)} className="w-full">
Figma didn’t respond. Your changes are safe here.
</Alert>
) : null}
</div>Use it for
- Errors and warnings about the page, success after an action, information people need now.
- Subtle, the default, for almost every alert. Loud only when one must stand out: a health drop, no credits left, a failed sync, an error that blocks the work.
Use something else for
- Messages that should disappear on their own: use a toast.
- Several loud alerts on one screen: if everything is loud, nothing is.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'neutral''info''success''warning''error''offer' | 'info' | Meaning and icon. |
emphasis | 'subtle''loud' | 'subtle' | subtle: only the icon is in color. loud: the hairline takes the tone (border-{tone}-subtle). |
title | ReactNode | – | One line. |
icon | IconPropfalse | – | Replace or hide the variant's icon. |
action | ReactNode | – | One or two small Buttons. |
onDismiss | () => void | – | Shows a close button. |
live | boolean | – | Set when the alert appears after the page loads, so it's announced. |
toneLabel | stringfalse | – | The hidden word read before the message. Default Info, Success, Warning or Error; none for neutral and offer. |
className | string | – | Extra classes. They win over Seed's, so you can adjust one thing without forking. |
Accessibility
- An alert rendered with the page has no live role. Set live when it appears later (after an action, a sync, a failed request): it becomes role status, or role alert for errors only.
- A visually hidden Info:, Success:, Warning: or Error: is read before the message, so the tone never depends on color. Translate it with toneLabel.
- Icons hold 3:1 on bg-primary in both themes (5.0 to 8.3:1 in Light, 6.4 to 12.7:1 in Dark). Links use text-accent-primary (5.2:1 Light, 9.9:1 Dark).
- The loud hairline is decorative (1.4 to 1.9:1 in Light, 2.1 to 2.6:1 in Dark): the icon, the hidden prefix and the words carry the meaning.
- The close button is labelled Dismiss (change it with dismissLabel).