# Thinking State

> What an agent is doing, step by step. The list grows while it works, then folds into one line, like Thought for 34s, 5 steps.

- Name: `thinking-state`
- Status: beta
- Categories: ai, feedback
- File: the install writes `thinking-state.tsx` to your `ui` alias, `@/components/ui` by default.
- npm packages: `@base-ui/react`, `class-variance-authority`. The install adds them.
- Other registry items: `@arbokui/spinner`, `@arbokui/timeline`. The install adds them.
- Gallery: https://arbokui.com/components/thinking-state
- Registry item: https://arbokui.com/r/thinking-state.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/thinking-state
   ```

## Use it for

- Above an agent's answer, to show the steps it took: Read 12 files, Ran the tests.
- Pass loading while the agent works. Add each step to the end of steps as it starts. The last one spins.
- Set loading to false when it is done. The list folds into one line that opens again.
- Pass duration, like 34s, and keep it current while loading for a live timer. The folded line uses it.
- Give each step an id, so a new one fades in and the rest stay still.
- Put the files or sources a step used in detail, as a quiet second line.

## Avoid it for

- A single wait with no steps. Use Spinner.
- One tool call with its inputs and result. Use ToolCallCard.
- Progress with a known end, like 3 of 5 files sent. Use Progress.

## Props

- `steps`: `{ id?: string; label: ReactNode; detail?: ReactNode; time?: string }[]`. Required. The steps so far, oldest first. While loading, the last one is under way.
- `loading`: `boolean`. Default `false`. The agent is still working. The list stays open and grows. When it turns false, the list folds into one line.
- `duration`: `string`. How long the agent has worked, or worked in all, like "34s".
- `label`: `ReactNode`. Default `"Thinking"`. The line while loading. It pulses slowly.
- `summary`: `ReactNode`. The folded line once done. Default "Thought for 34s, 5 steps", from duration and the step count.
- `defaultOpen`: `boolean`. Starts open or folded. Default: open while loading, folded when done.
- `open`: `boolean`. Controls whether it is open. Pair it with onOpenChange. Then it no longer folds itself.
- `onOpenChange`: `(open: boolean) => void`. Called when it opens or folds.
- `className`: `string`. Extra classes on the root. Later classes win.

## Accessibility

- The line is one button that opens and folds the steps, and it tells screen readers if it is open.
- The steps are an ordered list named Steps. The one under way says (working) to screen readers.
- Each new step is said politely in a hidden status region, and so is the summary when the agent is done.
- The spinners and the pulse stop when the theme turns motion off, and for reduced motion. The list then opens and folds at once.

## Examples

### While working

```tsx
<ThinkingState
  loading
  duration="12s"
  steps={[
    { id: "read", label: "Read 12 files", detail: "app/, lib/, registry/" },
    { id: "test", label: "Ran the tests" },
  ]}
/>
```

### Done

```tsx
<ThinkingState
  duration="34s"
  steps={[
    { id: "read", label: "Read 12 files" },
    { id: "test", label: "Ran the tests" },
    { id: "fix", label: "Fixed the failing test" },
  ]}
/>
```
