Metric Tile

v0.1.3

KPI stat tile with trend delta, severity accent, loading skeleton, and a responsive group layout.

View as Markdown

Install

npx shadcn@latest add @signalos/metric-tile

Requires a configured @signalos registry and a valid SIGNALOS_REGISTRY_TOKEN - get access. Registry dependencies (@signalos/tokens, @signalos/utils, @signalos/skeleton) are pulled automatically.

Preview

Example & code

metric-tile.example.tsx
// Example: KPI strip with severity accents, deltas, and a chip footer.
import { Activity, AlertTriangle, Inbox } from "lucide-react"

import {
  MetricTile,
  MetricTileGroup,
} from "@/components/widgets/metric-tile/MetricTile"
import { StatusBadge } from "@/components/widgets/status-badge/StatusBadge"

export default function Example() {
  return (
    <MetricTileGroup columns={3}>
      <MetricTile
        label="In flight"
        value={128}
        unit="active slots"
        icon={<Inbox />}
        footer={
          <>
            <StatusBadge severity="critical" appearance="chip">
              3 critical
            </StatusBadge>
            <StatusBadge severity="medium" appearance="chip">
              12 med
            </StatusBadge>
          </>
        }
      />
      <MetricTile
        label="Past due"
        value={6}
        icon={<AlertTriangle />}
        severity="critical"
        // For "bad" metrics, up is bad - flip the delta color:
        delta={{ value: "+2", trend: "up", positiveIsGood: false }}
        onClick={() => console.info("filter: past due")}
      />
      <MetricTile
        label="24h throughput"
        value={342}
        unit="resolved"
        icon={<Activity />}
        delta={{ value: "+12%", trend: "up" }}
      />
    </MetricTileGroup>
  )
}

Props

MetricDelta

PropTypeDefaultDescription
value*string-Display string, e.g. "+12%" or "-3".
trend*MetricTrend-Direction the arrow points and the color it takes.
positiveIsGoodboolean | undefinedtrueWhether the trend direction is good news. Controls color: positive up = success, positive down = error; invert for costs etc.

MetricTileProps

PropTypeDefaultDescription
label*string-Eyebrow label above the value, e.g. "In flight".
value*string | number-The headline stat.
unitstring | undefined-Small unit/context text next to the value, e.g. "active slots".
iconReactNode-Optional eyebrow icon (any ReactNode, typically a 12px icon).
deltaMetricDelta | undefined-Optional trend delta chip under the value.
severityMetricSeverity | undefined-Severity left-border accent.
isLoadingboolean | undefined-Renders a skeleton tile while true.
onClick(() => void) | undefined-Makes the tile interactive (button semantics + hover state).
footerReactNode-Free-form row rendered at the bottom of the tile (chips, breakdowns).
classNamestring | undefined-
data-testidstring | undefined-Test identifier rendered as `data-testid` on the root element.

MetricTileGroupProps

PropTypeDefaultDescription
columns2 | 4 | 3 | undefined4Column count at desktop width; collapses to 2 on tablet and 1 on mobile.
children*ReactNode-
classNamestring | undefined-

Supporting types

export type MetricTrend = "up" | "down" | "flat"
export type MetricSeverity = "critical" | "high" | "medium" | "low" | "info"

npm dependencies

lucide-react@^1.7.0

Changelog

metric-tile

0.1.3

  • Add a data-testid passthrough on the root element so consumers can target the tile without relying on markup structure.

0.1.2

  • Use semantic status tokens (text-text-error, bg-bg-warning, border-border-, bg-status-) instead of raw palette scales so client theme overrides restyle status colors.

0.1.1

  • Content sync fix to bring source in line with published registry payload.

0.1.0

  • Initial release, genericized from signal-core-ui RoutingSummaryCards: the domain RoutingDashboardSummary type is replaced by generic props (label, value, unit, icon, delta, severity, footer).
  • Adds MetricTileGroup responsive layout, keyboard-accessible interactive tiles, positiveIsGood delta coloring, and a skeleton loading state.