# Timeline

> Source: https://design.nanatec.co.ke/components/timeline/
> What happened to something, in order — an audit record of changes, a sequence of milestones, or one thing tracked through its stops — down the page or across it, with an icon on any entry.
> Status: beta
> Since: v0.0.36

One element, three shapes, picked with `variant`:

| Variant | For | Reads as |
|---|---|---|
| `audit` (default) | The record of changes to a tenancy, invoice or unit | Grouped by day, newest first; who did what, to what, with old values struck through |
| `steps` | Milestones in order — application to move-in, a repair from report to sign-off | Each step complete, current or upcoming; the rail fills as far as the work has got |
| `tracking` | One thing followed through its stops — a payment from phone to ledger | Newest first, date and time beside each stop; the latest picked out, the history dashed |

`steps` and `tracking` also run across the page with
`orientation="horizontal"`. Any entry, in any variant, can carry an icon.

The audit shape is not a feed. Every entry names its actor, carries an exact
time, and shows a changed field as the old value struck through beside the new
one, so the question "who changed the rent, and from what?" has its answer on
the line.

## Preview

The default, `audit`. The [other shapes](#three-shapes) follow below.

```html
<nana-timeline
  entries='[{"id":"5","at":"2026-10-08T09:12:00+03:00","actor":"Wanjiru K.","action":"changed the rent on","subject":"Unit 4B","changes":[{"field":"Monthly rent","from":"KES 25,000","to":"KES 28,000"},{"field":"Effective from","from":"","to":"1 Nov 2026"}]},{"id":"4","at":"2026-10-08T08:02:00+03:00","actor":"M-Pesa","source":"integration","action":"matched a payment to","subject":"INV-2041","tone":"success"},{"id":"3","at":"2026-10-07T16:40:00+03:00","actor":"Kamau J.","source":"tenant","action":"gave notice on","subject":"Unit 4B","tone":"warning","note":"Moving to Nakuru for work. Will leave by 30 November."},{"id":"2","at":"2026-10-07T06:00:00+03:00","actor":"Nana","source":"system","action":"marked overdue","subject":"INV-2033","tone":"danger"}]'
  has-more
  style="max-width:40rem"
></nana-timeline>
```

## Entry shape

Which fields an entry uses depends on the variant: `audit` reads `actor`,
`action`, `subject`, `changes` and `note`; `steps` and `tracking` read `title`
and `description`. `id`, `at`, `tone` and `icon` work in all three.

| Field | Meaning |
|---|---|
| `id` | Your key for the entry |
| `at` | ISO time; sets the order and the day it is grouped under |
| `actor` | Who did it — a person, or the system or service that did |
| `action` | What they did, as the middle of a sentence: "changed the rent on" |
| `subject` | What they did it to |
| `source` | `user` (the default), `system`, `tenant` or `integration`, shown as a chip when not a user |
| `tone` | `neutral`, `info`, `success`, `warning` or `danger` — colours the marker |
| `changes` | Fields as `{ field, from, to }`; the old value is struck through beside the new one |
| `note` | What the actor wrote, kept as they wrote it |
| `title` | A step or stop's name, for `steps` and `tracking` |
| `description` | The line under the name |
| `icon` | The name of a bundled icon for the marker |
| `state` | `complete`, `current` or `upcoming`, for a step that should not follow `current` |

The time shown is the clock time; the full date and time are in the tooltip
and in the `datetime` attribute, for anyone reading the record exactly.

## Loading earlier activity

`has-more` adds a button that fires `nana-load-more`. Set `loading` while the
request is in flight and append to `entries` when it lands; the grouping is
worked out again from whatever the list holds.

## Three shapes

`variant` picks the shape. `audit`, the default, is the record above. The
other two use `title` and `description` instead of `actor` and `action`.

### Steps

Milestones in order — a tenancy from application to move-in. Done steps are
filled with a check, the step under way has an outlined clock, and the rail
fills as far as the work has got. Name the step under way with `current`;
leave it out and the latest step whose time has come is the current one.

```html
<nana-timeline
  variant="steps"
  current="viewing"
  entries='[{"id":"applied","at":"2026-09-02T09:00:00+03:00","title":"Application received","description":"Documents and ID checked"},{"id":"viewing","at":"2026-09-05T10:30:00+03:00","title":"Viewing","description":"Unit 4B with the caretaker"},{"id":"lease","at":"2026-09-12T14:00:00+03:00","title":"Lease signed","description":"Deposit and first month due"},{"id":"move","at":"2026-10-01T16:00:00+03:00","title":"Move-in","description":"Keys and meter readings handed over","icon":"key"}]'
  style="max-width:32rem"
></nana-timeline>
```

### Tracking

One thing followed through its stops — a payment from the phone to the
ledger. Newest first, with the date and time on the left and the stop on the
right. The latest stop is picked out in its `tone`, joined to the one before by
a solid line; the history behind it is dashed.

```html
<nana-timeline
  variant="tracking"
  entries='[{"id":"1","at":"2026-10-07T12:18:00+03:00","title":"Payment sent","description":"M-Pesa · 0722 *** 418","icon":"smartphone"},{"id":"2","at":"2026-10-07T12:19:00+03:00","title":"Received by paybill","description":"Paybill 522533","icon":"payments"},{"id":"3","at":"2026-10-07T17:04:00+03:00","title":"Matched to invoice","description":"INV-2041 · Unit 4B","icon":"assignment"},{"id":"4","at":"2026-10-08T09:15:00+03:00","title":"Posted to ledger","description":"Balance now KES 0","icon":"verified","tone":"success"}]'
  style="max-width:36rem"
></nana-timeline>
```

## Across the page

`orientation="horizontal"` runs steps and tracking from left to right. Tracking
turns round to read oldest to newest, so time runs the way the eye does and the
latest stop ends the line. On a narrow screen the row scrolls rather than
squeezing; `--nana-timeline-step-min` sets how narrow a step may get first.

```html
<nana-timeline
  variant="steps"
  orientation="horizontal"
  current="viewing"
  entries='[{"id":"applied","at":"2026-09-02T09:00:00+03:00","title":"Application received","description":"Documents and ID checked"},{"id":"viewing","at":"2026-09-05T10:30:00+03:00","title":"Viewing","description":"Unit 4B with the caretaker"},{"id":"lease","at":"2026-09-12T14:00:00+03:00","title":"Lease signed","description":"Deposit and first month due"},{"id":"move","at":"2026-10-01T16:00:00+03:00","title":"Move-in","description":"Keys and meter readings handed over","icon":"key"}]'
></nana-timeline>
```

```html
<nana-timeline
  variant="tracking"
  orientation="horizontal"
  entries='[{"id":"1","at":"2026-10-07T12:18:00+03:00","title":"Payment sent","description":"M-Pesa · 0722 *** 418","icon":"smartphone"},{"id":"2","at":"2026-10-07T12:19:00+03:00","title":"Received by paybill","description":"Paybill 522533","icon":"payments"},{"id":"3","at":"2026-10-07T17:04:00+03:00","title":"Matched to invoice","description":"INV-2041 · Unit 4B","icon":"assignment"},{"id":"4","at":"2026-10-08T09:15:00+03:00","title":"Posted to ledger","description":"Balance now KES 0","icon":"verified","tone":"success"}]'
></nana-timeline>
```

Audit entries always run down the page: the changed fields need the width.

## Icons

Give an entry an `icon` with the name of any bundled icon — `key`, `payments`,
`build`, `home`, `verified` — and its marker draws it, in every variant. Steps
without one get a check when done and a clock otherwise.

For a glyph of your own, put it in the slot named after the entry's id:

```html
<nana-timeline variant="tracking">
  <svg slot="icon-posted" viewBox="0 0 24 24"><path d="…" /></svg>
</nana-timeline>
```

`--nana-timeline-marker-size` sets the size of the markers, and
`--nana-timeline-accent` the colour of finished steps.

## Installation

```bash
npm install @nana-tec/ui-components
```

Or copy the source in and own it:

```bash
npx @nana-tec/ui add timeline
```

## Usage

```js
import "@nana-tec/ui-components/timeline";
```

```html
<nana-timeline
  entries='[{"id":"1","at":"2026-10-08T09:12:00Z","actor":"Wanjiru K.","action":"changed the rent on","subject":"Unit 4B","changes":[{"field":"Monthly rent","from":"KES 25,000","to":"KES 28,000"}]}]'
></nana-timeline>
```

```js
const el = document.querySelector("nana-timeline");
el.addEventListener("nana-load-more", (e) => console.log(e.detail));
```

## API

## Storybook

See every state and prop interactively in Storybook: https://storybook.nanatec.co.ke/?path=/docs/components-timeline--docs
