ContainersCallout
Callout
A small in-prose note. Used in the design system docs to add context, ask a question, or flag a warning.
Tones
Info is the default. Accent uses the editorial accent for "designer-to-designer" notes. Warning and success are reserved for cases where the reader needs to take an action.
Tones
Reading order matters
Read color first, then typography, then spacing.
A small note
This site is a portfolio, not a product. That changes which patterns apply.
Be careful
Two primary buttons in the same region means the design hasn't decided.
Looks good
All foreground/background pairings clear WCAG AA at 4.5:1.
Anatomy
- 1 px border on three sides, 3 px on the left in the tone color
--surface-elevatedbackground, 4 px radius- 20 px padding (1.25 rem vertical, 1.5 rem horizontal)
- Icon left, title + body right, all top-aligned
- Title at 0.875 rem weight 500; body at 0.9375 rem weight normal
Implementation
callout.tsx
import { type ReactNode } from "react"
import { Info, AlertTriangle, CheckCircle2, Sparkles } from "lucide-react"
import SiteIcon, type SiteIconProps } from "@/components/site-icon"
type Tone = "info" | "accent" | "warning" | "success"
interface CalloutProps {
title: string
tone?: Tone
children: ReactNode
}
const iconMap: Record<Tone, SiteIconProps["icon"]> = {
info: Info,
accent: Sparkles,
warning: AlertTriangle,
success: CheckCircle2,
}
export function Callout({ title, tone = "info", children }: CalloutProps) {
return (
<aside className={`ds-callout ${tone === "accent" ? "ds-callout--accent" : ""}`}>
<span className="ds-callout__icon">
<SiteIcon icon={iconMap[tone]} size="md" tone="muted" />
</span>
<div className="ds-callout__body">
<p className="ds-callout__title">{title}</p>
<p className="ds-callout__content">{children}</p>
</div>
</aside>
)
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | None | The bolded title |
tone | "info" | "warning" | "success" | "accent" | "info" | Visual style |
children | ReactNode | None | The body |