# Counter

A count against its total, such as "142 / 200". A bold accent count over a muted total.

![A bold accent count over a muted total, in small, default and large.](https://ui.terratcg.app/previews/progress/counter-sizes/ios-light.png)

```tsx
import { Counter } from "@terratcg/ui";
import { View } from "react-native";

export default function CounterSizes() {
  return (
    <View style={{ flexDirection: "row", alignItems: "baseline", gap: 24 }}>
      <Counter value={12} total={30} size="sm" />
      <Counter value={142} total={200} />
      <Counter value={7} total={9} size="lg" />
    </View>
  );
}
```

## Import

```tsx
import { Counter } from "@terratcg/ui";
```

## Usage

```tsx
<Counter value={142} total={200} />
```

Counter sits wherever progress is read as numbers: beside a SectionHeader, in a Shelf's header, or next to a Progress track in a Task footer.

## Examples

### Tone and format

tone changes the count only, the total stays muted; format writes both numbers in your locale.

![tone changes the count only, the total stays muted; format writes both numbers in your locale.](https://ui.terratcg.app/previews/progress/counter-tones/ios-light.png)

```tsx
import { Counter } from "@terratcg/ui";
import { View } from "react-native";

const thousands = new Intl.NumberFormat("en-US");

export default function CounterTones() {
  return (
    <View style={{ flexDirection: "row", alignItems: "baseline", gap: 24 }}>
      <Counter value={3} total={9} tone="secondary" />
      <Counter value={1200} total={4000} format={(n) => thousands.format(n)} />
    </View>
  );
}
```

## Props

### CounterProps

| Prop      | Type                                                          | Description                                                                                                  |
| --------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `value`   | `number`                                                      | The count so far, the numerator.                                                                             |
| `total`   | `number`                                                      | The count to reach, the denominator.                                                                         |
| `size?`   | `"default" \| "lg" \| "sm"`                                   | The count's type role: `label`, `title` or `headline`, with the total one step smaller. Default: `"default"` |
| `tone?`   | `"accent" \| "danger" \| "default" \| "muted" \| "secondary"` | Numerator tone. The denominator is always muted. Default: `"accent"`                                         |
| `format?` | `((value: number) => string)`                                 | Writes each number; the host passes its locale's formatter. Plain digits by default.                         |

Counter also accepts React Native's `View` props, such as `accessibilityLabel` and `testID`.

## Accessibility

- **Label:** one accessible element, read as "142 of 200" by default. That label is English: pass your own `accessibilityLabel` in other languages ("142 sur 200").
- **Format:** `format` writes both the shown numbers and the default label, so a locale formatter reaches screen readers too.
- **Figures:** both numbers use tabular figures, so a count that ticks up doesn't shift its neighbours.

## Platform differences

- **iOS and Android:** the same layout, on the text baseline.
- **Web:** Counter renders through react-native-web for these docs, but the web is not a supported target.

## Rules

- Pass numbers, not strings: `format` is where your locale's grouping goes.
- Keep the total muted. `tone` changes the count only; use `secondary` when the count is not the subject of the view.
- Pick `sm` inside headers and footers, `default` on its own, `lg` when the count is the page's headline.
