MetricUIMetricUI
UI

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

<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.

<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.

<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.).

<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.

<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.

<Callout
  variant="error"
  title="Payment failed"
  action={{ label: "Retry payment", onClick: () => alert("Retrying...") }}
>
  The last payment attempt was declined.
</Callout>

Props

PropTypeDescription
variant
CalloutVariant

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

Show dismiss button.

onDismiss
() => void

Callback when dismissed.

autoDismiss
number

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

Whether detail starts expanded.

dense
boolean

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

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').
  • The aiContext prop (inherited from BaseComponentProps) adds business context for AI Insights analysis. See the AI Insights guide for details.

Playground

Experiment with every prop interactively. Adjust the controls on the right to see the component update in real time.

Live Preview

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)