# Breakdown List

> Rows with their number and a pill bar, inside a card, for parts of a whole or a ranking, with targets, status tones, and change words.

- Name: `breakdown-list`
- Status: beta
- Categories: charts
- File: the install writes `breakdown-list.tsx` to your `ui` alias, `@/components/ui` by default.
- Other registry items: `@arbokui/chart`, `@arbokui/motion-timing`, `@arbokui/skeleton`. The install adds them.
- Gallery: https://arbokui.com/components/breakdown-list
- Registry item: https://arbokui.com/r/breakdown-list.json

## Install

1. Add the registry to `components.json`. Do this first, once:

   ```bash
   npx shadcn@latest registry add "@arbokui=https://arbokui.com/r/{name}.json"
   ```

   The command writes this entry. You can also add it by hand:

   ```json
   {
     "registries": {
       "@arbokui": "https://arbokui.com/r/{name}.json"
     }
   }
   ```

   Without this step, the shadcn CLI looks up `@arbokui` in a public list that Arbokui does not control.

2. Add the theme once per app. It replaces your color tokens with ones checked for contrast:

   ```bash
   npx shadcn@latest add @arbokui/theme
   ```

3. Add the component:

   ```bash
   npx shadcn@latest add @arbokui/breakdown-list
   ```

## Use it for

- Parts of a whole or a ranking with readable labels, like survey replies by team or tickets closed by person.
- Pass items, each with a label and a value, and a title or aria-label.
- Pass max for the value of a full bar, like 100 for percents. It defaults to the largest value.
- Give an item a target to draw a tick on its bar, and tone='success' or 'warning' when its value is a status.
- Give an item a change, like { text: 'Up 6', tone: 'success' }, for a short word on the right.
- Put an icon, a person's photo, or a color swatch in icon.
- Pass value: null when a row has no figure. It shows a dash, not a zero.

## Avoid it for

- Steps that narrow, like sign-ups to purchases. Use FunnelChart.
- A trend over time. Use LineChart or AreaChart.
- Many categories compared at once with several series. Use BarChart.
- More rows than people can scan, like 50. Show the top ten and link to the rest.

## Props

- `items`: `{ id?: string; label: string; value: number | null; meta?: ReactNode; icon?: ReactNode; target?: number; tone?: "success" | "warning" | "danger"; change?: { text: string; tone?: "success" | "warning" | "danger" } }[]`. Required. One row each, in order. A row's tone colors its bar as a status. Left out, the bar takes --chart-1.
- `title`: `ReactNode`. A visible title. It names the list. TypeScript requires title, aria-label, or aria-labelledby.
- `aria-label`: `string`. Names the list when it has no visible title.
- `max`: `number`. The value of a full bar. Default: the largest value.
- `valueFormat`: `Intl.NumberFormatOptions | ((value: number) => string)`. How values and targets print. Options work from a server component. A function works from a client component only.
- `locale`: `string`. Default `"en-US"`. The locale for valueFormat options.
- `loading`: `boolean`. Default `false`. Shows placeholder rows, as many as items, or three.
- `emptyText`: `ReactNode`. Default `"No data yet"`. Shown when items is empty.
- `className`: `string`. Extra classes for the card. Later classes win, so 'border-0 p-0' drops the card's edge and padding.

## Accessibility

- Renders a \<figure> named by its title, or by aria-label. TypeScript requires one. The rows are a list.
- Each row reads as its label, then its value, its target, and its change, like 'Design: 84%, target 80%, Up 6'.
- A row with no value reads 'no figure', and shows a dash with no bar, so it never reads as zero.
- The bars are hidden from screen readers. The track is quiet, so the number in text carries the meaning.
- Status bars use the tone's color, and plain bars use --chart-1, which the theme holds to 3:1 on the page.
- Bars grow in once the list is on screen, over three times --motion-duration-base. Reduced motion and motion off draw them at once.
- Loading is read out through a status line that stays on the page.

## Examples

### Status bars against a target

```tsx
<BreakdownList
  title="Survey replies by team"
  max={100}
  valueFormat={{ style: "unit", unit: "percent" }}
  items={[
    { label: "Design", value: 92, target: 80, tone: "success", change: { text: "Up 6", tone: "success" } },
    { label: "Engineering", value: 64, target: 80, tone: "warning" },
    { label: "Marketing", value: null },
  ]}
/>
```

### A ranking with icons

```tsx
import { Trophy, UserRound } from "lucide-react";

<BreakdownList
  aria-label="Tickets closed by person"
  items={[
    { label: "Ava Clarke", value: 14, icon: <Trophy /> },
    { label: "Sam Okafor", value: 11, icon: <UserRound /> },
  ]}
/>
```

### While it loads

```tsx
<BreakdownList title="Survey replies by team" items={data ?? []} loading={isLoading} />
```
