← All proposals

Chain of Thought

A collapsible list.

Net-new componentOpen in Storybook

proposals/ChainOfThought/decisions.md25 lines · View on GitHub

Decisions

  • Renamed from ChainOfThought to ChainOfThought (2026-10-12), at Erika's call. An earlier note argued for ChainOfThought because two references were tool logs; the new variants (below) are how ChainOfThought now covers both reasoning and tool use. Docs should still mention "agent steps" and "tool calls" so either search finds it.

  • variant: steps (default) | reasoning | search | coding. It sets the body: steps is rows with status icons; reasoning is running text (paragraphs, secondary color, a div instead of an ol); search is a quiet query row (magnifying glass), result rows with a bold title and the domain as secondary text, and a quiet "+N more" row; coding is rows with a bold verb and code-font secondary text, with +/- diff counts in success and critical colors (pds-agent-step__added, __removed). Rows are still AgentStep; the variant only adds styling, so the body is still the consumer's content.

  • Name: ChainOfThought, not ChainOfThought. Two of three references are tool logs, and "chain of thought" implies the steps are the model's real reasoning. Mention both terms in the docs so either search finds it.

  • Separate pattern, ThinkingState stays the primitive. The summary line is a ThinkingState passed in the summary slot, so the finished wording ("Thought for 4 seconds") is just a ThinkingState with state='completed'. ThinkingState stays non-interactive and usable alone while there are no steps yet.

  • Built on native <details>, not ExpansionPanel. ExpansionPanel is a bordered card with a space-between chevron and a divider when open. The references have a borderless, left-aligned summary with the chevron beside the label and a rule down the left of the steps. Same markup approach (details/summary, state mirrored in React so the chevron rotates), different look.

  • AgentStep is its own primitive (proposals/AgentStep/), and ChainOfThought composes it. ChainOfThought wraps each child in an <li>, so list semantics belong to the list and the step renders a div that also works inline. Steps are children, not a data array.

  • Uses the local Spinner (for agentic) and Icon wrapper; the port swaps in the real ones. Storybook: Proposals/Chain of Thought, tagged new-pattern.

  • Open: reasoning text. Reference 2 puts italic model reasoning between tool calls. Not designed; likely a step type with no status icon.

  • Open: diff counts (+74 -41 in the Edit row) are plain text now; green and red would need a small part or tokens-only spans.

  • Open: motion. Steps appear instantly when added. Does a new step animate in? Does the list auto-open while working and collapse when done?

  • Open: nested spacing and long lists. No max-height or scroll; decide when steps can run to dozens.

  • Open: keyboard. Summary toggles with Enter and Space (native); not yet checked by eye.

  • Step status, secondary text, detail and the configurable icon are decided in ../AgentStep/decisions.md.

  • Open: result favicons. Search results use a globe icon; the reference shows each site's colored favicon. A leading slot on AgentStep would take an image.

  • Open: "+7 more" is a plain quiet row; should it be a link or button that expands the rest?

  • Open: row name. The row is still AgentStep; rename to ChainOfThoughtStep for consistency?

  • Open: reasoning variant is plain text; italic, links and markdown aren't handled.

  • size prop: s (default) | m, for the whole block. s is a 14px summary over 12px rows and reasoning text; m is 16px over 14px. Row icons follow the text size (1em); the active spinner stays at its smallest size. 12px is small for reasoning paragraphs and result titles, so m is the readable option.

  • The summary is rendered by Chain of Thought, not passed in. It takes label, isActive, time, showTimer and iconName and renders a ThinkingState at the same size, so the size hierarchy is enforced. The cost: no custom summary. isActive defaults to false here (a record is usually finished), unlike ThinkingState's true; set it while the agent works. Rows read the size through the --agent-step-font-size variable set by the container; a standalone Agent Step defaults to xs.

  • expandWhenActive (default false): opens the list while isActive is true and closes it when the agent finishes. The first time the user opens or closes it themselves, the automatic behavior stops for that instance, so it never fights them. isOpen is still the initial state only. The Working story turns it on; flip isActive in the controls to see it collapse.

  • ThinkingState now takes state, not isActive. Chain of Thought keeps its own isActive boolean and maps it to active / completed. Open: should a stopped run show here too (stopped state passed through)?