# Timeline item

A list of things that happened, in order, on an icon rail: each item's icon in a ring on a line that joins them, on the inline-start side. The rail and rings are borders, so they stay drawn in forced colours.

For events inside a chat thread use `ThreadEvent`; for a document's saved versions, `VersionHistory`. `Timeline` is for any other history: a record's activity, an incident's steps, an order's progress.

- Registry name: `timeline-item` (`@candor/timeline-item`)
- Tier: Pro. Installing it needs a Pro, Premium or Team licence key: the person runs `npx candor-ui key <key>` themselves; never ask for the key in chat or write it to a file.
- Docs: https://candor.themethodic.com/docs/timeline-item

## Install

```bash
npx candor-ui add timeline-item
```

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

## Example

```tsx
"use client"

import { Bot, MessageSquare } from "lucide-react"
import { Timeline, TimelineItem } from "@/components/candor/timeline-item"

const minutes = (n: number) => new Date(Date.now() - n * 60_000)

export default function Example() {
  return (
    <div className="max-w-md rounded-xl border bg-card p-4">
      <Timeline label="Activity on refund R-2041">
        <TimelineItem title="Asked for a refund" icon={MessageSquare} actor="Dana Reyes" time={minutes(95)}>
          The order arrived damaged.
        </TimelineItem>
        <TimelineItem title="Checked the order against the refund policy" icon={Bot} actor="Billing agent" time={minutes(94)} />
        <TimelineItem title="Refund over the agent's limit" tone="warning" actor="Billing agent" time={minutes(94)}>
          Sent to a person to approve.
        </TimelineItem>
        <TimelineItem title="Approved the refund" tone="success" actor="Sam Okafor" time={minutes(12)} />
        <TimelineItem title="Card network confirmation" tone="muted" time={null} />
      </Timeline>
    </div>
  )
}
```

## <Timeline>

Props:

- `label?: string | undefined`: The list's accessible name ("Activity on Q3 report").
- `className?: string | undefined`: Classes for the list, merged with Candor's.
- `children?: React.ReactNode | undefined`: The `TimelineItem`s, in the order they happened (or newest first, as the app chooses).

## <TimelineItem>

One thing that happened in a `Timeline`: an icon in a ring, a title, who did it and when, and a body. The tone's icon carries its meaning (a tick, a warning sign, a cross) and the colour repeats it, never alone; screen readers hear it as a word before the title ("Done", "Warning", "Failed", from `timelineItem` in LocaleProvider's `strings`). `icon` replaces the tone's icon, not its word. "default" and "muted" have no word. `title` can be an agent's words, so it is drawn as text in its own isolate. `actor` is named by the app. A `time` of null says "Time not recorded" rather than leaving the reader to guess.

Props:

- `icon?: LucideIcon | undefined`: The item's icon, in place of the tone's own. Shape, not colour, should say what it is.
- `tone?: TimelineTone | undefined` (default `"default"`): How it reads: "default", "success", "warning", "destructive" or "muted". Colours the ring and the icon.
- `title: string`: What happened ("Approved the refund"). Drawn as text, so it can be an agent's words.
- `time?: string | Date | null | undefined`: When it happened, relative with the full date on hover; `null` says "Time not recorded". Left out, no time is shown.
- `actor?: string | undefined`: Who did it, named by the app (a person, or the agent by its app-given name).
- `children?: React.ReactNode | undefined`: The body: details, a quote, a link to the record.
- `className?: string | undefined`: Classes for the item, merged with Candor's.

## Strings (`timelineItem`)

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

- `noTime`: Time not recorded
- `success`: Done
- `warning`: Warning
- `destructive`: Failed

## Types

### TimelineTone

How an item reads at a glance; the icon carries it, the colour only repeats it.

```ts
"default" | "success" | "warning" | "destructive" | "muted"
```

## 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`: its fixed strings in `strings`, its nouns in `nouns`; entity kinds and agent roles in `EntityKindsProvider` and `AgentRolesProvider`.
