# Ring Progress

> A small ring that fills toward a goal, with the percent inside. It turns green once the goal is met.

- Name: `ring-progress`
- Status: beta
- Categories: data, display
- File: the install writes `ring-progress.tsx` to your `ui` alias, `@/components/ui` by default.
- Other registry items: `@arbokui/dither`. The install adds them.
- Gallery: https://arbokui.com/components/ring-progress
- Registry item: https://arbokui.com/r/ring-progress.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/ring-progress
   ```

## Use it for

- Progress toward a goal in a small space, like tasks done this week, a profile that is 75% done, or a target in a card.
- Pass value as a percent, or value and max, like value={3} max={4}.
- Pass aria-label to say what it measures, like 'Tasks'. Screen readers hear 'Tasks: 75%'.
- Pass showValue={false} for a small ring beside its own words, like '3 of 4'.
- Leave tone out, and the ring turns success once it is full. Pass a tone to keep one color.

## Avoid it for

- A task that runs, like an upload. Use Progress.
- Parts of a whole, like a budget split. Use DonutChart.
- A ranking or many values side by side. Use BreakdownList.

## Props

- `value`: `number`. Required. How much is done, from 0 to max. Values outside the range are clamped.
- `max`: `number`. Default `100`. The value of a full ring.
- `tone`: `"neutral" | "brand" | "danger" | "success" | "warning"`. Default `"neutral"`. Color of the filled part. Left out, the ring is neutral and turns success once it is full. Passed, it stays that tone.
- `size`: `"sm" | "md" | "lg"`. Default `"md"`. 36, 44, or 66px across at the default density. lg uses larger text.
- `showValue`: `boolean`. Default `true`. Shows the percent inside. The percent is read out either way.
- `aria-label`: `string`. What the ring measures, like 'Tasks'. Screen readers hear it before the percent.
- `texture`: `"flat" | "dither" | "gradient" | "grain"`. dither draws the filled part as dots, gradient fades it along the arc to full at its end, and grain speckles it, with a glow on dark pages. Hover fills gradient and grain in. Left out, the ring follows the Texture around it.
- `className`: `string`. Extra classes. Later classes win.

## Accessibility

- Renders role="img", named by aria-label and the percent, like 'Tasks: 75%'. With no aria-label, the name is the percent.
- The number inside is hidden from screen readers, since the name already says it. With showValue={false} the name still does.
- The filled part uses the tone's color on the track. The track is quiet, so the percent carries the meaning, in text or in the name.
- The fill sweeps to a new value over --motion-duration-slow. Reduced motion jumps straight to it.

## Examples

### A percent, named by its label

```tsx
<RingProgress value={75} aria-label="Tasks" />
```

### A count toward a target

```tsx
<RingProgress value={3} max={4} aria-label="Sessions this week" />
```

### Beside its own words

```tsx
<span className="flex items-center gap-2">
  <RingProgress value={3} max={4} size="sm" showValue={false} aria-label="Forms returned" />
  3 of 4 forms returned
</span>
```

### One color, even when full

```tsx
<RingProgress value={100} tone="brand" aria-label="Ticket sales" />
```

### A gradient ring that fills in on hover

```tsx
<RingProgress value={68} tone="brand" texture="gradient" aria-label="CPU load" />
```
