Spec version v0.9.0

Callout Card

Purpose

A Callout Card is a compact metric display unit used to surface a single key performance indicator (KPI), count, or at-a-glance measurement. Use it on overview tabs, dashboard surfaces, and summary sections where a small set of numeric or categorical values must be immediately visible without the user needing to read into a detailed data table. Do NOT use a Callout Card for bodies of explanatory text, form inputs, or interactive controls — it is a read-only display primitive. Do NOT use a Callout Card as a general-purpose card container; use the Card component for structural grouping of multi-part content.

Callout Cards are always displayed as a group. A single isolated Callout Card is unusual and should be questioned at the design level. The canonical use pattern is a horizontal 3-column grid of Callout Cards at the top of an overview tab, presenting the three most important measurements for the current entity (e.g., total builds, success rate, last run time).

Anatomy

A Callout Card is a minimal container with two required elements and one optional element:

  • Container (required): the outer element that establishes background, border, radius, and padding. Size and variant props drive visual treatment. Layout is centered — both label and value are horizontally centered within the card.
  • Label (required): a short descriptor that identifies the metric. Labels are displayed in 12px, uppercase, wide letter-spacing, and tertiary text color. The label is visually subordinate to the value. Keep labels to two to four words. Do NOT write verbose label text — the label provides the minimum context needed to interpret the value (e.g., "Total builds", "Pass rate", "Last run"). Do NOT use sentence case for labels; the uppercase treatment is applied by the component.
  • Value (required): the primary data point. Displayed in 18px (--force-font-size-lg), semibold weight, primary text color. The value is the most visually prominent element in the card. Values can be a number, a percentage, a formatted date, a duration, or any other compact data representation. Keep values to a single line — if the value requires explanation, it belongs in a DataTable or a detailed section, not a Callout Card.
  • Trend indicator (optional): a directional signal showing how the value has changed, placed below the value. A trend indicator consists of an arrow icon (up or down, from Material Symbols Rounded) and a percentage or delta text string. Arrow direction and icon color must match the semantic meaning: positive trends use --force-color-text-success and a chevron-up or trending-up icon; negative trends use --force-color-text-error and a chevron-down or trending-down icon; neutral/flat trends use --force-color-text-tertiary and a minus icon. Do NOT use success green for an upward trend that is contextually bad (e.g., error rate increased) — use error color for negative outcomes regardless of arrow direction.

Variants

All Callout Card variants share the same layout and typography structure. Variants differ only in background, border, and text color treatment.

default

White background (--force-color-bg-surface), 1px border in --force-color-border-default. Label uses --force-color-text-tertiary. Value uses --force-color-text-primary. This is the correct variant for the majority of KPI metrics that have no inherent status. Use default when the value is a neutral measurement — counts, totals, dates, durations that are not contextually good or bad.

gray

Muted background (--force-color-bg-muted), 1px border in --force-color-border-default. Label and value use slightly de-emphasized text. Use gray when the metric is secondary or contextually less important than adjacent default-variant cards. In a three-card row, the primary metric uses default (white) and supporting metrics may use gray to establish a visual weight hierarchy.

success

Background: --force-color-bg-success-subtle. Border: 1px solid var(--force-color-border-success). Text: --force-color-text-success for both label and value. Use success when the displayed value represents a known-good or target-met condition — for example, a "100% pass rate" card after a successful test run, or an "All checks passed" count. Do NOT apply success variant speculatively before the value is known to be positive.

warning

Background: --force-color-bg-warning-subtle. Border: 1px solid var(--force-color-border-warning). Text: --force-color-text-warning for both label and value. Use warning when the displayed value indicates a condition that requires attention — for example, a "3 expiring licenses" card or a "Build queue depth: 47" card that exceeds a healthy threshold. Warning tinting should be applied dynamically based on the value, not statically.

error (danger)

Background: --force-color-bg-error-subtle. Border: 1px solid var(--force-color-border-error). Text: --force-color-text-error for both label and value. Use error when the displayed value represents a failed or critical state — for example, "Failed builds: 12" when failures exist, or "Blocked deployments: 1". As with warning, apply this variant dynamically.

info

Background: --force-color-bg-info-subtle. Border: 1px solid var(--force-color-border-info). Text: --force-color-text-info for both label and value. Use info for neutral measurements that belong to an in-progress or scheduled process — for example, "Scheduled runs: 4" or "In review: 7". Info communicates process state without urgency.

brand

Background: --force-color-bg-primary-subtle. Border: 1px solid var(--force-color-border-primary). Text: --force-color-text-primary-brand (indigo). Use for the primary headline metric in a branded context where the most important KPI is being deliberately highlighted with brand color. Use sparingly — at most one brand-variant Callout Card per row. Do NOT use brand for multiple metrics simultaneously; it dilutes the signaling effect.

Sizes

Callout Cards are available in three size presets that scale the container and value display:

  • sm: minimum container width of 200px, --force-spacing-2 (8px) internal padding. Value uses --force-font-size-xl (20px). Use in very tight grids or secondary metric rows.
  • md (default): minimum container width of 250px, --force-spacing-3 (12px) internal padding. Value uses --force-font-size-2xl (24px). Use in standard overview tabs and dashboard sections.
  • lg: minimum container width of 300px, --force-spacing-5 (20px) internal padding. Value uses --force-font-size-3xl (30px). Use in prominent dashboard landing pages where metrics are the primary focus and larger display scale is intentional.

Do not use lg size in a three-column grid inside a standard detail page tab — it will overflow on medium viewports. Reserve lg for dedicated dashboard layouts with generous horizontal space.

States

Callout Cards are non-interactive by default and have no hover, active, or focus states.

Default: Card renders at full opacity with its variant treatment. This is the only state for a read-only Callout Card.

Loading (data pending): When the metric value has not yet loaded, replace the value slot with a Skeleton component of equal height and approximately equal width. Do NOT show a zero or an empty string while loading — the Skeleton communicates that data is in transit. The label remains visible during loading so the user knows what metric is being fetched.

Empty / not applicable: When a metric does not apply in the current context (e.g., "Last deploy" when nothing has been deployed), display a dash (—) as the value using --force-color-text-disabled. Do NOT display "N/A" in all caps — use an em dash for visual cleanliness.

Error state (data failed to load): When the API call for a metric fails, display a warning icon in place of the value, using --force-color-icon-warning. This is distinct from the warning variant — the warning-variant card tints the entire background to signal that the metric's value is in a warned condition. The error-state treatment is used only when the metric itself could not be fetched.

Behavior

Callout Cards render as a CSS grid. The canonical layout is three equal columns with --force-spacing-4 (16px) gap:

display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--force-spacing-4);

This grid is placed at the top of an overview tab content area, above the main content grid. It is the first visible content after the tab panel header.

On narrow viewports (below --force-breakpoint-md, 768px), a three-column Callout Card grid should collapse to a two-column or single-column layout. The breakpoint for collapse is left to the implementing layout — the Callout Card itself is responsive to its container, not prescriptive about the column count.

Callout Cards do not link to other pages by themselves. If the metric value should navigate to a filtered view (e.g., clicking "Failed builds: 12" opens a filtered builds list), wrap the card in an anchor element or use the Card component's interactive prop with an aria-label. In that case, the full interactive state set described in the Card pattern applies.

Accessibility

Callout Cards use standard <div> elements with no special ARIA role. Screen readers read label and value in DOM order (label first, then value). This order must be preserved in the DOM — do NOT use CSS to visually reverse the label/value order by manipulating grid rows or flex direction, because the DOM order is what assistive technologies use.

When a Callout Card uses a semantic variant (success, warning, error) applied dynamically, ensure the accessible meaning is communicated in text — do NOT rely on color alone. For example, a "Failed builds: 12" card that is red is only accessible if the value "12" carries enough context for a color-blind user to understand its significance. Where needed, add a visually-hidden text annotation such as "12 failed" rather than just "12".

Trend indicators must be read intelligibly by screen readers. An up arrow followed by "12%" in green is not accessible on its own. Use a visually-hidden text equivalent such as "Increased by 12%" or "Down 8% from last week" alongside the visual indicator.

Composition

Callout Cards always appear within a containing grid. The canonical composition is:

  1. Overview tab layout: the tab content area opens with a Callout Card grid (three columns, --force-spacing-4 gap), followed by a content grid of full Cards. The Callout Card grid provides the at-a-glance summary; the content grid below provides the detail.
  2. Dashboard layout: a dedicated dashboard page may open with a row of Callout Cards at larger (md or lg) size spanning the full content width, above chart or table sections.
  3. Summary sidebar panel: a narrow panel inside a detail page may contain a vertical stack of Callout Cards (single column) as a quick-facts sidebar.

Callout Cards do not contain other components internally. Do not place a DataTable, a Chart, or a Button inside a Callout Card. If a metric requires any additional interactive affordance, it belongs in a Card, not a Callout Card.

The Callout Card is distinct from the Card component:

  • Card: multi-part content container, supports header/content/footer slots, used for structural grouping
  • Callout Card: single-purpose metric display, label + value + optional trend, no slots

Do not use a Card to replicate Callout Card behavior by manually styling a label and value pair. Use the Callout Card component for any label + value + trend display unit.

Guidance

Limit the metric label to four words or fewer. The label's role is to name the number below it, not to explain it. If explanation is needed, the metric is too ambiguous to surface as a standalone KPI.

Apply semantic variants dynamically based on thresholds, not statically. A "Failed builds" Callout Card should render as the default variant when the value is zero and as the error variant when the value is greater than zero. Hardcoding a Callout Card as error-variant regardless of the current value means the tinting loses its signal.

Do NOT place more than one brand-variant Callout Card in a single row. Brand indigo is the strongest visual signal in the set. Two brand cards fight each other and degrade the brand color's meaning.

Do NOT display the trend indicator when trend data is unavailable or unreliable. It is better to show no trend than to show a fabricated or low-confidence trend. A missing trend indicator is a valid state.

Keep value strings short. Values that exceed approximately eight characters at semibold 18px will overflow or wrap on narrow cards. If a value is inherently long (e.g., a full timestamp), truncate with an ellipsis and surface the full value in a Tooltip.

Do NOT use Callout Cards in forms. Their purely numeric display treatment creates a false visual parallel with form inputs.

Token Usage

Container

  • Border radius: --force-radius-card (8px)
  • Border: 1px solid per variant (see below)
  • Padding (sm): --force-spacing-2 (8px)
  • Padding (md): --force-spacing-3 (12px)
  • Padding (lg): --force-spacing-5 (20px)
  • Text alignment: center
  • Layout: vertical stack, gap: --force-spacing-1 (4px) between label and value

Per-variant token pairings

Variant Background Border Label + Value text
default --force-color-bg-surface --force-color-border-default label: --force-color-text-tertiary, value: --force-color-text-primary
gray --force-color-bg-muted --force-color-border-default label: --force-color-text-tertiary, value: --force-color-text-secondary
success --force-color-bg-success-subtle --force-color-border-success --force-color-text-success
warning --force-color-bg-warning-subtle --force-color-border-warning --force-color-text-warning
error --force-color-bg-error-subtle --force-color-border-error --force-color-text-error
info --force-color-bg-info-subtle --force-color-border-info --force-color-text-info
brand --force-color-bg-primary-subtle --force-color-border-primary --force-color-text-primary-brand

Label typography

  • Font size: --force-font-size-xs (12px)
  • Font weight: --force-font-weight-medium (500)
  • Text transform: uppercase (applied by component)
  • Letter spacing: --force-font-letter-spacing-wider (0.05em). Wider than the standard --force-font-letter-spacing-wide (0.025em) used on badges.
  • Line height: --force-font-line-height-tight (1.25)
  • Color: --force-color-text-tertiary for default/gray variants; variant text token for semantic variants

Value typography

  • Font size: --force-font-size-xl (20px, sm size); --force-font-size-2xl (24px, md size); --force-font-size-3xl (30px, lg size)
  • Font weight: --force-font-weight-semibold (600)
  • Line height: --force-font-line-height-tight (1.25)
  • Color: --force-color-text-primary for default; variant text token for semantic variants

Trend indicator

  • Icon size: 16px
  • Up / positive trend: --force-color-text-success, --force-color-icon-success
  • Down / negative trend: --force-color-text-error, --force-color-icon-error
  • Neutral / flat trend: --force-color-text-tertiary, --force-color-icon-default
  • Text size: --force-font-size-xs (12px), --force-font-weight-regular
  • Gap to value: --force-spacing-1 (4px)

Grid layout

  • Columns: repeat(3, 1fr) (standard overview)
  • Gap: --force-spacing-4 (16px)
  • Position: first element in overview tab content, above the main content grid