# RubricStrip (/docs/charts/rubric-strip)

RubricStrip answers "how did this thing score per criterion — with each criterion's importance visible — without a fake
composite number?". Each bar's length is its score and its thickness is its weight share, so the things that matter most
are literally the biggest marks. There is no total bar, and none may be added — the type exists to resist collapsing
quality into one number.

```tsx
import { RubricStrip } from "@microcharts/react/rubric-strip";

<RubricStrip
  data={[
    { label: "Correctness", score: 0.92, weight: 3 },
    { label: "Coverage", score: 0.78, weight: 2 },
    { label: "Clarity", score: 0.65, weight: 1 },
    { label: "Style", score: 0.41, weight: 1 },
  ]}
  target={0.7}
  title="Model eval"
/>
```

## Install

```tsx
import { RubricStrip } from "@microcharts/react/rubric-strip";

<RubricStrip
  data={[
    { label: "Correctness", score: 0.92, weight: 3 },
    { label: "Coverage", score: 0.78, weight: 2 },
    { label: "Clarity", score: 0.65, weight: 1 },
    { label: "Style", score: 0.41, weight: 1 },
  ]}
  title="Model eval"
/>
```

Setup (package + stylesheet): [Quickstart](/docs/quickstart#set-up-with-an-ai-agent) or paste [`/agent-setup.md`](/agent-setup.md) into your agent.


## When to use it

- **Good for** — model / code-review scorecards, weighted vendor comparison.
- **Avoid for** — a single criterion (Bullet) or parts of a whole (SegmentedBar).


## Variants

```tsx
<RubricStrip
  data={[
    { label: "Lint", score: 1 },
    { label: "Types", score: 1 },
    { label: "Tests", score: 0.8 },
    { label: "Docs", score: 0.5 },
  ]}
/>
```

## Edge cases

```tsx
// a score of 2 on a [0, 1] domain draws a full-length bar instead of
// overflowing the track
<RubricStrip data={[{ label: "Bonus", score: 2, weight: 1 }]} />
```

```tsx
<RubricStrip data={[{ label: "Overall fit", score: 0.83 }]} />
```


## Why this default

Weight-as-thickness keeps "importance" visible where a table hides it — a light criterion that scores well can't
visually outweigh a heavy one that scores poorly. The summary names the extremes, never a weighted average, because the
whole point is that a single number throws away the structure. A `target` draws one honest pass line across every row
instead.

## Accessibility

The accessible name names the extremes — **"4 criteria; highest Lint (1), lowest Docs (0.5)."** The interactive entry
roves the criteria, announcing each one's score and its weight share of the total (**"Coverage: 0.78, weight 29% of
total."**).

The interactive entry follows the shared [interaction contract](/docs/accessibility#one-interaction-contract):
arrow keys rove between units on both axes, `Home` and `End` jump to the ends, and a click, tap, `Enter` or
`Space` selects a unit — pinning its readout so it survives blur, until you select it again or press `Escape`.
On touch, a tap pins and a drag scrubs.

## Props

| Prop | Type | Description |
| --- | --- | --- |
| `data` (required) | `{ label, score, weight? }[]` | Criteria; weights default equal. |
| `target` | `number` | Pass target — one tick across all rows. |
| `labels` | `boolean` | Criterion names in the left gutter. |
| `animate` | `boolean` | (interactive) Opt-in entrance motion when the chart mounts client-side — add `import "@microcharts/react/motion"` once. Inert on the server, on hydrated server HTML, and under `prefers-reduced-motion`. |

Plus the shared grammar — `data`, `domain`, `color`, `title`, `summary`, `format` — and the layout props (`width`, `height`, `className`, `style`) that every chart accepts. Interactive entries also share `animate` and `live`, and — wherever a chart has more than one navigable unit — `onActive`, `onSelect`, `selectedIndex` and `defaultSelectedIndex`; and — wherever the chart shows a hover value — `readout`. See [the shared grammar](/docs/quickstart#the-shared-grammar).
