---
title: Chain of Thought
description: A timeline of reasoning and tool-call steps.
category: AiReasoning
status: beta
since: 0.3.9
tags: [ai, reasoning, timeline]
syncStatus: reviewed
verified: true
---

## Usage

### Basic
::::TuffDemoWrapper{demo="ChainOfThoughtChainOfThoughtDemo" code-lang="vue"}
---
code: |
  <script setup lang="ts">
  const steps = [
    { id: '1', kind: 'thinking', title: 'Break the request down', body: 'Confirm the input bounds first.', status: 'done' },
    { id: '2', kind: 'tool', title: 'read_file(src/main.ts)', status: 'done' },
    { id: '3', kind: 'thinking', title: 'Work out the implementation', body: 'Sorting dominates…', status: 'active' },
  ]
  </script>

  <template>
    <TxChainOfThought :steps="steps" streaming />
  </template>
---
::::

### Best Practices

- Key steps by a stable `id`, not an array index.
- Keep at most one `active` step; auto-scroll follows only one.
- Move a finished step from `active` to `done` or `error`, or its spinner stays.
- Write tool titles as call signatures (`read_file(src/main.ts)`), not bare tool names.
- For custom step rendering, compose `TxReasoningDisclosure` and `TxToolCallCard`.

## API Reference

### Props

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `steps` | `AiChainStep[]` | — | The steps, required. `AiChainStep` is `{ id, kind: 'thinking' \| 'tool', title, body?, status: 'active' \| 'done' \| 'error', durationMs? }`. |
| `streaming` | `boolean` | `false` | Output is still arriving; with an active step, the header shows a thinking orb. |
| `defaultOpen` | `boolean` | `true` | Open state while not streaming. |
| `label` | `string` | `'Chain of thought'` | Header label; override it on non-English surfaces. |
| `userOpen` | `boolean` | — | Host-held open state that overrides everything; feed `toggle` back in so it survives remounts. |

### Events

| Name | Payload | Description |
|------|---------|-------------|
| `toggle` | `(open: boolean)` | Fires on a header click with the resulting open state. |

## Overview

- Open state: `userOpen` wins, then a user click; otherwise it follows active steps while streaming and `defaultOpen` when not.
- When any step's `body` grows, the active step's body scrolls to its end.
- A `done` step with `durationMs` shows its duration after the title (`· 3.2s`; whole seconds from 10s).
- The header count is `steps.length`, hidden for a single step.
- The header is a native `<button>` with `aria-expanded` and `aria-controls`; steps are an `<ol>`.
