# Folded turns

A run of turns folded into one line, for long agent work a reader doesn't need to see step by step: "Drafted three versions and compared them". The line says how many turns are inside and opens them in place; `summary` is yours (a sentence, a count of tool calls, a cost). Folding never hides that the turns happened.

- Registry name: `folded-turns` (`@candor/folded-turns`)
- Tier: Free (MIT). No licence key needed.
- Docs: https://candor.themethodic.com/docs/folded-turns

## Install

```bash
npx candor-ui add folded-turns
```

Run `npx candor-ui@latest init` once first (https://candor.themethodic.com/get-started.md). Without the CLI: `npx shadcn@latest add @candor/folded-turns`.
It brings in: collapsible, locale, utils.
npm packages: lucide-react@^1.67.0.

## Example

```tsx
"use client"

import { FoldedTurns } from "@/components/folded-turns"
import { Message } from "@/components/message"
import type { Message as MessageData } from "@/lib/chat"

const agent = { id: "a1", name: "Writer agent", role: "assistant" }
const turn = (id: string, text: string): MessageData => ({ id, author: { role: "agent", agent }, status: "complete", blocks: [{ kind: "paragraph", nodes: [{ kind: "text", text }] }] })

const turns = [turn("1", "Drafted an opening that starts with the outage."), turn("2", "Drafted a second that starts with the fix."), turn("3", "Compared them: the second is clearer for customers.")]

export default function Example() {
  return (
    <div className="flex max-w-2xl flex-col gap-7">
      <FoldedTurns count={turns.length} summary="Drafted two openings and compared them · 6 tool calls">
        {turns.map((m) => (
          <Message key={m.id} message={m} />
        ))}
      </FoldedTurns>
      <Message message={turn("4", "Here is the update, starting with the fix.")} />
    </div>
  )
}
```

## <FoldedTurns>

Props:

- `count: number`: How many turns are inside, for the button ("Show 12 turns").
- `summary?: React.ReactNode | undefined`: What happened in them, shown on the folded line: text or your own small summary.
- `defaultOpen?: boolean | undefined` (default `false`): Start open.
- `open?: boolean | undefined`: Controlled open state.
- `onOpenChange?: ((open: boolean) => void) | undefined`: Called when a person opens or closes it.
- `header?: React.ReactNode | undefined`: Your own folded line instead of the dashed one: a card with a title, how it ended, its cost, actions. The Show/Hide button follows it, so the turns can still be opened.
- `children: React.ReactNode`: The turns, usually Messages.
- `className?: string | undefined`

## Strings (`foldedTurns`)

The fixed words, English by default. Override any of them under `foldedTurns` in `<LocaleProvider strings={{ foldedTurns: { … } }}>`; the table is exported as `foldedTurnsStrings`.

- `show`: { one: "Show {count} turn", other: "Show {count} turns" }
- `hide`: { one: "Hide {count} turn", other: "Hide {count} turns" }

## Rules for using Candor UI

- Components take plain typed data. Never pass model output as HTML or render it as a link; messages are typed blocks.
- A control that can't be used says why: wrap it in `<Locked reason="…">`, don't just disable it.
- Don't show a value you don't have: leave it out (it renders as —) rather than guess. An estimate is labelled as one.
- Nothing is pre-selected in a decision a person makes, and the agent is named from your app's data, never from model output.
- Your app's words go in `LocaleProvider` (fixed strings) and `TermsProvider` (nouns); entity kinds and agent roles in `EntityKindsProvider` and `AgentRolesProvider`.
