Warren UI

BulletBar

SLO bullet rows — a measure bar against qualitative zones with a vertical target tick.

SERVICE SLO WALL · TARGETS + QUALITY ZONES
Source
"use client"

import { BulletBar, type BulletItem } from "@/registry/warren/bullet-bar/bullet-bar"

const ITEMS: BulletItem[] = [
  {
    label: "API AVAILABILITY",
    value: 99.2,
    target: 99.9,
    bands: [
      { limit: 99, tone: "danger" },
      { limit: 99.5, tone: "warning" },
      { limit: 100, tone: "success" },
    ],
    unit: "%",
    burnRate: 2.1,
  },
  {
    label: "P99 LATENCY BUDGET",
    value: 310,
    target: 250,
    bands: [
      { limit: 200, tone: "success" },
      { limit: 400, tone: "warning" },
      { limit: 500, tone: "danger" },
    ],
    unit: "ms",
  },
  {
    label: "ERROR RATE",
    value: 0.4,
    bands: [
      { limit: 0.1, tone: "success" },
      { limit: 1, tone: "warning" },
    ],
    unit: "%",
  },
]

export default function BulletBarDemo() {
  return (
    <div className="flex flex-col gap-3 border-2 border-border bg-panel p-2">
      <span className="font-mono text-[10px] uppercase tracking-wide text-muted-foreground">
        SERVICE SLO WALL · TARGETS + QUALITY ZONES
      </span>
      <BulletBar items={ITEMS} />
    </div>
  )
}

Installation

npx shadcn@latest add https://warren.eduard3v.com/r/bullet-bar.json

Usage

import { BulletBar } from "@/components/ui/bullet-bar"
<BulletBar
  max={100}
  items={[
    {
      label: "API AVAILABILITY",
      value: 99.2,
      target: 99.9,
      bands: [
        { limit: 99, tone: "danger" },
        { limit: 99.5, tone: "warning" },
        { limit: 100, tone: "success" },
      ],
      unit: "%",
      burnRate: 2.1,
    },
  ]}
/>

Encoding

Stephen Few's bullet chart, console-grade: each row stacks a mono uppercase label, the value (+ optional unit) in mono tabular numerals, and one flat bar — qualitative zones from ascending bands[].limit edges rendered as *-soft washes, the measure as a saturated fill, and target as a 2px ink tick punched through the track (zones() / scaleMax() in zones.ts).

The measure tone is state, not decoration: it takes the tone of the zone the value lands in, flips to danger once the value escapes every zone, and stays primary for tone-less bands. The shared max pins the scale across rows; without it (or per-row item.max) each row scales to its own largest edge.

burnRate renders a 2.1× annotation before the value — danger text above 1, muted at or below.

Interactive

SLO WALL · CLICK A ROW
API AVAILABILITY99.2
WORKER THROUGHPUT6400msg/s
LAST CLICK:
Source
"use client"

import { useState } from "react"
import { BulletBar, type BulletItem } from "@/registry/warren/bullet-bar/bullet-bar"

const ITEMS: BulletItem[] = [
  {
    label: "API AVAILABILITY",
    value: 99.2,
    target: 99.9,
    bands: [
      { limit: 99, tone: "danger" },
      { limit: 99.5, tone: "warning" },
      { limit: 100, tone: "success" },
    ],
  },
  {
    label: "WORKER THROUGHPUT",
    value: 6400,
    target: 7000,
    bands: [
      { limit: 5000, tone: "danger" },
      { limit: 8000, tone: "success" },
    ],
    unit: "msg/s",
  },
]

export default function BulletBarInteractive() {
  const [last, setLast] = useState<string | null>(null)
  const onItemClick = (item: BulletItem) => setLast(String(item.label))

  return (
    <div className="flex flex-col gap-3 border-2 border-border bg-panel p-2">
      <span className="font-mono text-[10px] uppercase tracking-wide text-muted-foreground">
        SLO WALL · CLICK A ROW
      </span>
      <BulletBar items={ITEMS} onItemClick={onItemClick} />
      <span className="font-mono text-[10px] uppercase tracking-wide text-muted-foreground">
        LAST CLICK: {last ?? "—"}
      </span>
    </div>
  )
}

With onItemClick(item), each row's bar becomes a real <button> whose accessible name is the row summary ("<label>: <value><unit> · target <t> · <n>× burn") and the container flips from role="img" to role="group". Set showTooltips for native title tooltips.

API Reference

Prop

Type

Prop

Type

Prop

Type

On this page