Callout
Styled message block with info, warning, success, and error variants. Supports data-driven rules, embedded metrics, collapsible detail, action buttons, and auto-dismiss.
import { Callout } from "metricui";Use Callout to surface contextual messages, alerts, and status notifications inside dashboards. It supports four semantic variants, data-driven rules that auto-select variant and message based on a numeric value, embedded formatted metrics, collapsible detail sections, action buttons, and auto-dismiss timers.
Basic Example
Heads up
<Callout variant="info" title="Heads up">
This is an informational message for the user.
</Callout>All Variants
Four semantic variants cover the most common dashboard alert scenarios. Each has a distinct icon, border color, and background tint.
Info
Warning
Success
Error
<Callout variant="info" title="Info">...</Callout>
<Callout variant="warning" title="Warning">...</Callout>
<Callout variant="success" title="Success">...</Callout>
<Callout variant="error" title="Error">...</Callout>Data-Driven Rules
Pass a value and rules array to let the Callout auto-select its variant and message. Rules are evaluated top-to-bottom; first match wins. Use {value} in title or message for interpolation.
Performance good
<Callout
value={85}
rules={[
{ min: 90, variant: "success", title: "Excellent", message: "Score: {value}." },
{ min: 70, max: 90, variant: "info", title: "Good", message: "Score: {value}." },
{ min: 50, max: 70, variant: "warning", title: "Degraded", message: "Score: {value}." },
{ max: 50, variant: "error", title: "Critical", message: "Score: {value}." },
]}
/>Metric Callout
The metric prop embeds a formatted numeric value inside the callout, using the same format engine as KpiCard (currency, percent, compact, etc.).
Revenue milestone reached
<Callout
variant="success"
title="Revenue milestone reached"
metric={{ value: 1000000, format: "currency", label: "total revenue" }}
>
Your team crossed the $1M revenue mark this quarter.
</Callout>Collapsible Detail
Use detail to tuck verbose information behind a toggle. Great for error stack traces, service breakdowns, or audit logs.
3 services experiencing elevated latency
<Callout
variant="warning"
title="3 services experiencing elevated latency"
detail={
<div className="space-y-1">
<p>API Gateway: p99 latency 450ms (threshold: 200ms)</p>
<p>Auth Service: p99 latency 320ms (threshold: 150ms)</p>
<p>Search: p99 latency 280ms (threshold: 100ms)</p>
</div>
}
>
Some services are responding slower than expected.
</Callout>Action Button
The action prop adds a button to the callout for inline user actions like retrying a failed operation or navigating to a detail view.
Payment failed
<Callout
variant="error"
title="Payment failed"
action={{ label: "Retry payment", onClick: () => alert("Retrying...") }}
>
The last payment attempt was declined.
</Callout>Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | CalloutVariant | "info" | Visual variant: "info", "warning", "success", or "error". Ignored when rules is used. |
title | string | — | Title text. |
children | React.ReactNode | — | Body content. |
icon | React.ReactNode | null | — | Icon override. Default: auto-picked per variant. Set to null to hide. |
value | number | null | — | Value to evaluate against rules (data-driven mode). |
rules | CalloutRule[] | — | Rules evaluated top-to-bottom. First match wins. Supports {value} placeholder in title/message. |
metric | CalloutMetric | — | Embedded formatted metric value with label. |
dismissible | boolean | false | Show dismiss button. |
onDismiss | () => void | — | Callback when dismissed. |
autoDismiss | number | 0 | Auto-dismiss after N milliseconds. 0 = never. |
action | CalloutAction | — | Action button with label and onClick. |
detail | React.ReactNode | — | Collapsible detail content — hidden by default, toggle to show. |
detailOpen | boolean | false | Whether detail starts expanded. |
dense | boolean | false | Compact layout. Falls back to config.dense. |
className | string | — | Additional CSS class names. |
classNames | { root?: string; icon?: string; title?: string; body?: string; metric?: string; action?: string } | — | Sub-element class overrides. |
id | string | — | HTML id attribute. |
data-testid | string | — | Test id. |
drillDown | boolean | ((event: { value: number | null; variant: CalloutVariant }) => React.ReactNode) | — | Enable drill-down on callout click. `true` auto-generates a detail panel. Pass a render function for full control over the panel content. Requires DrillDown.Root wrapper. |
drillDownMode | DrillDownMode | "slide-over" | Presentation mode for the drill-down panel. "slide-over" (default) slides from the right, full height. "modal" renders centered and compact. |
Data Shape
interface CalloutRule {
min?: number; // Minimum value (inclusive). Omit for fallback.
max?: number; // Maximum value (exclusive). Omit for no upper bound.
variant: CalloutVariant; // Variant to apply.
title?: string; // Title text. Supports {value} placeholder.
message?: string; // Message text. Supports {value} placeholder.
icon?: React.ReactNode;
}
interface CalloutMetric {
value: number;
format?: FormatOption;
label?: string;
}
interface CalloutAction {
label: string;
onClick: () => void;
}
type CalloutVariant = "info" | "warning" | "success" | "error";Notes
- Uses forwardRef — you can pass a ref to the root element.
- Rules are evaluated top-to-bottom; first match wins. Use {value} placeholder in title/message for interpolation.
- The metric prop uses the format engine — pass any FormatOption (currency, percent, compact, etc.).
- Dismissible callouts fade out with a 200ms animation before removing from the DOM.
- autoDismiss sets a timer in milliseconds; useful for transient success messages.
- Has role='alert' for screen readers.
- In MetricGrid, Callout takes full width automatically (__gridHint = 'full').
Playground
Experiment with every prop interactively. Adjust the controls on the right to see the component update in real time.
Live Preview
Heads up
Code
<Callout
variant="info"
title="Heads up"
>
This is an example callout message.
</Callout>Props
Adjust props to see the callout update in real time
Visual variant (ignored when data-driven)