# Sync Status

> Where a save stands, beside what changed: saving, saved, waiting for a signal, or failed, with a retry icon.

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

## Use it for

- Beside what changed: a card header, next to a form's buttons, under a total that just changed.
- Put it in a field's status slot, like FieldFrame's or an editor's, with size sm. It sits on the label line, 16px tall.
- offline counts what waits to send: Offline · 3 changes will send when you're back online. Apply changes on screen at once anyway. This line is the promise they'll send.
- failed says why in plain words with reason, like No signal, and onRetry ends the line with a retry icon.
- saved is quiet. Pass at, like 18:04, to say when.

## Avoid it for

- A toast for a save. The status sits beside what changed.
- A status on a row or in a table. Use StatusText.
- Saying Saved after every keystroke. Show saving while a save runs, then saved.

## Props

- `state`: `"saving" | "saved" | "offline" | "failed"`. Required. Where the save stands.
- `count`: `number`. offline: how many changes wait to send.
- `at`: `string`. saved: when, like "18:04".
- `reason`: `string`. failed: why, in plain words, like "No signal".
- `onRetry`: `() => void`. failed: a retry icon ends the line.
- `retryLabel`: `string`. Default `"Try again"`. Names the retry icon, in its tooltip and to screen readers.
- `size`: `"sm" | "md" | "lg"`. Default `"md"`. sm sits on a field's label line: meta type, 16px tall. md is body type, and lg is section type.
- `className`: `string`. Extra classes on the line. Later classes win.

## Accessibility

- The words sit in a polite status region, so a change is said once, without taking focus.
- The state is said in words: Saving, Saved, Offline, Couldn't save. Color only marks it.
- The retry icon is a button named by retryLabel, which also shows in its tooltip. It sits outside the status region, so its name is not said with every change.
- The icons are hidden from screen readers, since the words say the same.

## Examples

### Saving

```tsx
<SyncStatus state="saving" />
```

### Offline

```tsx
<SyncStatus state="offline" count={3} />
```

### Failed, with a retry

```tsx
<SyncStatus state="failed" reason="No signal" onRetry={() => save()} />
```
