ChainOfThought
Collapsible reasoning chain showing numbered steps with done/active/pending status indicators.
Use and inspectUse this as a presentational interface around your own submit, stream, or state handlers. Reset preview only remounts the local example; it does not send a request or connect to a model.Next: inspect the source and wire its callback to a bounded backend action.
ChainOfThoughtCollapsible reasoning chain showing numbered steps with done/active/pending status indicators.
"use client";
import { useState } from "react";
type ChainStep = {
label: string;
status: "done" | "active" | "pending";
content?: string;
};
type ChainOfThoughtProps = {
steps: ChainStep[];
defaultOpen?: boolean;
};
function stepIcon(s: ChainStep["status"]) {
if (s === "done") return "✓";
if (s === "active") return "●";
return "○";
}
export function ChainOfThought({ steps, defaultOpen = false }: ChainOfThoughtProps) {
const [open, setOpen] = useState(defaultOpen);
return (
<div className="pk-cot">
<button className="pk-cot-toggle" onClick={() => setOpen(!open)}>
<span className="pk-cot-chevron">{open ? "▾" : "▸"}</span>
<span className="pk-cot-summary">
{open ? "Reasoning" : `${steps.length} reasoning steps`}
</span>
</button>
{open && (
<div className="pk-cot-steps">
{steps.map((step, i) => (
<div key={i} className={`pk-cot-step pk-cot-step--${step.status}`}>
<div className="pk-cot-step-header">
<span className="pk-cot-step-num">{i + 1}</span>
<span className="pk-cot-step-icon">{stepIcon(step.status)}</span>
<span className="pk-cot-step-label">{step.label}</span>
</div>
{step.content && (
<div className="pk-cot-step-content">{step.content}</div>
)}
</div>
))}
</div>
)}
</div>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
steps* | {label:string, status:"done"|"active"|"pending", content?:string}[] | — | Array of reasoning steps |
defaultOpen | boolean | false | Whether the chain is expanded by default |