Reasoning
Shows the model's reasoning as it streams, then folds it away behind a short “Thought for 12s” line.
Loading preview…
Install
- 1
Run this command in your Tailwind CSS project. It adds
components/ai/reasoning-collapsible.tsxand installs its dependencies.$ npx shadcn@latest add https://gradientdeck.com/ai-components/r/reasoning-collapsible.json
Usage & API
Example
import { Reasoning } from "@/components/ai/reasoning-collapsible"
<Reasoning
text="…"
streaming={true}
/>Props Reasoning
| Prop | Type & description | Required |
|---|---|---|
text | stringThe reasoning text so far. Grows while streaming. | Required |
streaming | boolean | Required |
seconds | numberHow long the model thought, shown once streaming ends. | Optional |
autoCollapse | number | falseClose the panel this many ms after streaming ends. Set to false to keep it open. | Optional |
Dependencies
- React
- Tailwind CSS
- motion
- lucide-react
Implementation notes
Collapsible exports Reasoning. While streaming is true the trigger reads Thinking… with a moving shine, and the panel is open. When streaming ends, the label becomes Thought for {seconds}s, or Thought for a moment if seconds is omitted. A timer then calls setOpen(false) after autoCollapse, unless that prop is false. Clicking the button toggles the panel at any time, and aria-expanded follows the open state. The sample walks a weekend in Lisbon for two under €600: easyJet out, TAP back, two nights in Baixa, about €540. The Replay control under the answer is demo chrome, not part of Reasoning.
Example
import { ReasoningRail } from "@/components/ai/reasoning-rail"
<ReasoningRail
text="…"
streaming={true}
/>Props ReasoningRail
| Prop | Type & description | Required |
|---|---|---|
text | string | Required |
streaming | boolean | Required |
seconds | number | Optional |
previewHeight | numberHeight of the folded preview, in px. | Optional |
Dependencies
- React
- Tailwind CSS
- motion
- lucide-react
Implementation notes
Rail exports ReasoningRail. The label reads Reasoning while streaming is true. Once streaming is false it reads Reasoned for {seconds}s when seconds is set, and Reasoning again when it is not. A ResizeObserver measures the text. The animated height is previewHeight while folded, or the full height when open or when the text already fits. Folded text is positioned at the bottom of the clip, with a mask that fades the top. The sample is a CI-only date failure: the fixture 2026-03-29 01:30 lands on an hour Europe skips, and CI runs in UTC. Clicking expands the note; the answer about an explicit offset is rendered beside the rail, not inside it.
Choosing a layout
Use it when the wait is long enough that a blank gap feels stuck, and the notes are something a person might actually read. Collapsible fits a normal chat: the thinking is there, then it gets out of the way so the answer can sit underneath. Rail fits a trace you want to watch, such as a debugging note, because the folded state already shows the newest lines instead of hiding everything.
Skip it when there is no separate reasoning channel, or when the thinking is a list of named steps, searches, or rejected options. That is Chain of thought. A wait with no text yet is Loader: an orb, dots, bars, or a spinner, optionally with a label. Do not put the finished answer inside text. In both previews the answer is a sibling that appears once streaming is false.
Does the panel close on its own?
Only Collapsible does. Reasoning starts open while streaming is true, then waits autoCollapse milliseconds, 800 by default, and closes. Set autoCollapse to false to leave it open. ReasoningRail never starts a timer. It stays at previewHeight until the person clicks, and it stays fully open after that click until they click again. Both components keep that open flag in local state. There is no open prop to control from outside.
What is shown if I leave seconds unset?
Reasoning uses Thought for a moment once streaming is false and seconds is missing. While streaming it always shows Thinking…, even if you passed seconds for later. ReasoningRail uses the word Reasoning in both of those cases. It only switches to Reasoned for {seconds}s after streaming ends and seconds is a number. The Lisbon demo passes 12. The CI demo passes 9. The number is display text, not a clock the component runs.