# Meter

> A bar that shows how much of an allowance is left, such as a usage limit that resets, full to start and draining as it is used.

Source: https://raft-design.botiverse.build/components/meter. Generated from the current release; where it differs from what you remember, this page is right.

A meter shows how much of an allowance is left: a usage limit that resets every few hours, a monthly quota. Like a phone battery, it starts full and drains as the allowance is used, because the question it answers is "can I keep working, and for how long". Next to it, a label says which allowance it is, and the value says how much is left and when it comes back.

```tsx
import {
  Meter,
  MeterHeader,
  MeterIndicator,
  MeterLabel,
  MeterTrack,
  MeterValue,
} from "@botiverse/raft-ui/wip";

export function MeterPreviewContent() {
  return (
    <div className="w-full max-w-sm stack-y-3">
      <Meter used={62} valueText="38% left · resets in 3h">
        <MeterHeader>
          <MeterLabel>5-hour limit</MeterLabel>
          <MeterValue />
        </MeterHeader>
        <MeterTrack>
          <MeterIndicator />
        </MeterTrack>
      </Meter>
      <Meter used={19} valueText="81% left · resets in 4d">
        <MeterHeader>
          <MeterLabel>Weekly limit</MeterLabel>
          <MeterValue />
        </MeterHeader>
        <MeterTrack>
          <MeterIndicator />
        </MeterTrack>
      </Meter>
    </div>
  );
}
```

## When to use

| Situation                                                               | Use                                                                                  |
| ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| How much of an allowance that is used up and comes back is left         | Meter                                                                                |
| How far a task with a known percentage has got: an upload, a conversion | [Progress](https://raft-design.botiverse.build/components/progress.md)                                                  |
| An amount with no limit, such as spend or tokens so far                 | Numbers in a [DescriptionList](https://raft-design.botiverse.build/components/description-list.md), with no bar |

Meter vs Progress: a meter is a quantity within a range that rises and falls; a progress bar is a task that only moves forward and is done at 100%. A full progress bar turns `success`, so an untouched allowance drawn as progress would read as finished.

## Anatomy

- `Meter`: the root. Required. Takes what is `used` and the whole allowance, `max` (100 unless set), as the provider reports them, and draws what is left, `max - used`. Takes `valueText`, the value in words, which `MeterValue` shows and assistive technology reads.
- `MeterHeader`: an optional row above the track, holding `MeterLabel` and `MeterValue`.
- `MeterLabel`: which allowance it is.
- `MeterValue`: the `valueText`. Leave it out for a bar with no words beside it; the text is still read out.
- `MeterTrack`: the `fill-muted` track. Required.
- `MeterIndicator`: the fill, a sticker with an ink edge. Required.

## Sizes

| Size                                    | Use for                                                                        |
| --------------------------------------- | ------------------------------------------------------------------------------ |
| The default (`size="md"`), an 8px track | A meter on its own: a settings page, a plan                                    |
| `size="sm"`, a 6px track                | Several meters stacked in a card or popover, such as the limits of one account |

## States

The color follows what is left; there is no `variant`.

| State       | When                                           | Looks                                                                                                  |
| ----------- | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| Plenty left | More than `low` is left                        | The `info` fill, as on Progress, up to a full bar. A full meter stays `info`: it has no complete color |
| Low         | `low` or less is left: 20% of `max` unless set | A `warning` fill and a `warning-strong` value                                                          |
| Used up     | `used` reaches `max`                           | An empty `warning-muted` track with a 1px `warning` edge, and a `warning-strong` value                 |

```tsx
import {
  Meter,
  MeterHeader,
  MeterIndicator,
  MeterLabel,
  MeterTrack,
  MeterValue,
} from "@botiverse/raft-ui/wip";

export function MeterStatesContent() {
  return (
    <div className="w-full max-w-sm stack-y-4">
      <Meter used={20} size="sm" valueText="80% left · resets in 3h">
        <MeterHeader>
          <MeterLabel>5-hour limit</MeterLabel>
          <MeterValue />
        </MeterHeader>
        <MeterTrack>
          <MeterIndicator />
        </MeterTrack>
      </Meter>
      <Meter used={75} size="sm" valueText="25% left · resets in 3h">
        <MeterHeader>
          <MeterLabel>5-hour limit</MeterLabel>
          <MeterValue />
        </MeterHeader>
        <MeterTrack>
          <MeterIndicator />
        </MeterTrack>
      </Meter>
      <Meter used={92} size="sm" valueText="8% left · resets in 3h">
        <MeterHeader>
          <MeterLabel>5-hour limit</MeterLabel>
          <MeterValue />
        </MeterHeader>
        <MeterTrack>
          <MeterIndicator />
        </MeterTrack>
      </Meter>
      <Meter used={100} size="sm" valueText="Used up · resets in 3h">
        <MeterHeader>
          <MeterLabel>5-hour limit</MeterLabel>
          <MeterValue />
        </MeterHeader>
        <MeterTrack>
          <MeterIndicator />
        </MeterTrack>
      </Meter>
    </div>
  );
}
```

- `low` means at or below, unlike HTML's `<meter low>`, which is strictly below: with the default, 20% left is already low. It is in the units of `max` and clamped to 0 to `max`.
- Give the used-up track its warning edge because the empty track has to read on its own: the edge measures 2.0:1 against white in light mode and 7.2:1 to 8.5:1 against the dark surfaces (popover to canvas), where a normal track is 1.1:1 and 1.1:1 to 1.5:1. The `warning-soft` wash alone measured 1.16:1 on the dark canvas, fainter than a normal track.
- Don't use `danger` for a low or used-up allowance: it comes back at the reset, so it interrupts work but isn't irreversible ([Color](https://raft-design.botiverse.build/foundations/color.md#meanings-of-color)).
- Keep the fill `info`, the color of Progress, so a meter and a progress bar read as one family, and let it turn orange only when little is left: the color changes when there is something to act on.
- Don't turn a full meter lime: a full allowance is untouched, not finished. This is why a meter isn't drawn with Progress, which turns `success` at 100%.
- Keep the default `low` unless an allowance needs another: the same amount left should look the same on every screen.

## Content

- Name the allowance in `MeterLabel`: "5-hour limit", "Weekly limit".
- Lead `valueText` with what is left, then when it comes back: "38% left · resets in 3h".
- When nothing is left, say so in place of the percentage: "Used up · resets in 3h".
- Don't write "% used": people would subtract it from 100 to know where they stand.
- When the reset time is unknown, leave the second half out: "38% left".

## Accessibility

Meter wraps Base UI's Meter, which gives it `role="meter"`. Its `aria-valuenow` is what is left, and its `aria-valuetext` is `valueText`.

- `MeterLabel` gives the meter its accessible name. Without a visible label, pass `aria-label` to `Meter`.
- `valueText` is required and is the only way to set the spoken value, so what a screen reader says ("38% left · resets in 3h") is always what is shown, and never a bare "38%" that could mean used or left.

## Rules

- Pass `used` as the provider reports it; don't work out what is left yourself. Meter does it, so the bar, the words and the spoken value can't disagree.
- Put the meter inside its container on its own track, never along an edge ([Shape](https://raft-design.botiverse.build/foundations/shape.md#nothing-on-the-edge-of-a-rounded-container)).

## API

### Meter

How much of an allowance is left, such as a usage limit that resets. Takes what is `used`; the bar shows what is left, full to start and draining. The info fill, like Progress, until `low` or less is left, then the warning color; never danger, and no success color at full.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `low` | `number` | `20% of `max`` | When as much as this is left, or less, the meter is low and takes the warning color ("at or below", unlike HTML's `<meter low>`, which is strictly below). In the units of `max`, clamped to 0 to `max`. |
| `max` | `number` | `100` | The whole allowance, in the same units as `used`. |
| `size` | `"sm" \| "md"` | `"md"` |  |
| `used` (required) | `number` |  | How much of the allowance is used, as the provider reports it, from 0 to `max`. The meter draws and announces what is left: `max - used`. |
| `valueText` (required) | `string` |  | What is left, in words: "38% left · resets in 3h". `MeterValue` shows it, and it is the meter's `aria-valuetext`, so the caller writes it once. |
| `render` | `ReactElement \| ((props, state) => ReactElement)` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |

Also takes the attributes of its element.

### MeterHeader

Also takes the attributes of its element.

### MeterIndicator

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `render` | `ReactElement \| ((props, state) => ReactElement)` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |

Also takes the attributes of its element.

### MeterLabel

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `render` | `ReactElement \| ((props, state) => ReactElement)` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |

Also takes the attributes of its element.

### MeterTrack

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `render` | `ReactElement \| ((props, state) => ReactElement)` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |

Also takes the attributes of its element.

### MeterValue

Shows the meter's `valueText`, at the end of `MeterHeader`.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `render` | `ReactElement \| ((props, state) => ReactElement)` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |

Also takes the attributes of its element.
