M
MetricUI
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').

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)