# TallyMarks (/docs/charts/tally-marks)

The chart below prints 23 as four clusters of five plus three loose strokes, the way a person counts. The count reads
back exactly: there is no scale to calibrate and no color to decode. Past `total` the marks stop growing and a `+N`
numeral carries the rest, so a cell never blows out its width. Marks are never resized to fit; width grows with the
count until the cap, then the numeral takes over.

```tsx
<TallyMarks value={23} title="Signatures" height={20} />
```

## Install

```tsx
import { TallyMarks } from "@microcharts/react/tally-marks";

<TallyMarks value={23} title="Signatures" />
```

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

## Try it

```tsx
import { TallyMarks } from "@microcharts/react/tally-marks/interactive";

<TallyMarks
  value={23}
/>
```

## When to use it

Use it for a small running count in a sentence or cell, a live event or score counter, or an editorial hand-tallied
context. Large magnitudes belong in MiniBar, trends over time in Sparkline, and proportions in Progress.

## Sizing

**hand-drawn pen for an editorial count**

```tsx
<TallyMarks value={17} pen="drawn" />
```

**cap the width — the numeral tells the truth past total**

```tsx
<TallyMarks value={38} total={20} />
```

## Variants

The ruled pen is the default, because evenly ruled strokes count back fastest in a product table. The `drawn` pen adds a
seeded, deterministic jitter for an editorial voice: the same count always renders identically, on the server and after
hydration, and the jitter only changes how each stroke is drawn, never the count.

```tsx
<TallyMarks value={17} pen="drawn" />
<TallyMarks value={38} total={20} />
```

## Edge cases

```tsx
<TallyMarks value={0} />
```

```tsx
<TallyMarks value={-5} />
```

```tsx
<TallyMarks value={5000} total={5000} />
```

A negative value clamps to 0 and a non-physical value saturates at the 200-mark ceiling. Past `total`, the default
`overflow="numeral"` appends a `+N` so the true total survives even when the marks can't; `overflow="clamp"` suppresses
the numeral for dense columns, and the accessible name still carries the exact count.

## Four homes

**In a sentence**

```tsx
<p>
  Petition signatures{" "}
  <span className="mc-inline">
    <TallyMarks value={12} summary={false} />
  </span>{" "}
  — 23 collected, 27 to goal.
</p>
```

**In a table cell**

```tsx
<td>
  <TallyMarks value={12} />
</td>
```

**In a KPI card**

```tsx
<div className="kpi">
  <span className="figure">23</span>
  <span className="unit">of 50 goal</span>
  <TallyMarks value={12} />
</div>
```

**In a tab header**

```tsx
<button className="tab">
  D1 <TallyMarks value={12} />
</button>
```

## Accessibility

The accessible name is the exact count, **"17 counted."**, and stays the true value even when the marks overflow to a
`+N` numeral or clamp. The interactive entry announces the new total through a polite live region on change and draws
newly added marks in with a brief, reduced-motion-gated sweep. A count has no sub-parts, so focus reads the summary and
there is no cursor to move.

This chart is a single unit, so there is nothing to rove between: a click, tap, `Enter` or `Space` selects it
and fires `onSelect`, and no selection stays pinned. That is the scalar half of the shared
[interaction contract](/docs/accessibility#one-interaction-contract).

## Props

| Prop | Type | Description |
| --- | --- | --- |
| `value` (required) | `number` | The count. Floored; negatives clamp to 0. |
| `total` | `number` | Marks drawn before overflow (default 25). |
| `overflow` | `"numeral" \| "clamp"` | numeral appends +N; clamp stops drawing. The summary always keeps the true count. |
| `pen` | `"ruled" \| "drawn"` | Hand-drawn jitter for editorial contexts. |

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).
