Rental
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.
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
Section titled “Preview”The default, audit. The other shapes follow below.
<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
Section titled “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
Section titled “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
Section titled “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.
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.
<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
Section titled “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.
<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
Section titled “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.
<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> <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.
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:
<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
Section titled “Installation”npm install @nana-tec/ui-componentsOr copy the source in and own it:
npx @nana-tec/ui add timelineimport "@nana-tec/ui-components/timeline";<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>const el = document.querySelector("nana-timeline");el.addEventListener("nana-load-more", (e) => console.log(e.detail));Properties
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
current | current | string | '' | The id of the step under way; without it, the latest step whose time has come |
entries | entries | TimelineEntry[] | [] | The entries, each with an id and an ISO at. An audit entry adds an actor and an action; a step or stop adds a title and description. |
hasMore | has-more | boolean | false | There is earlier activity to load |
headingLevel | heading-level | number | 3 | Level of the day headings in the page's outline |
loading | loading | boolean | false | Earlier activity is on its way |
locale | locale | string | '' | BCP 47 locale for dates and times; the reader's own when empty |
moreLabel | more-label | string | 'Show earlier activity' | What the load button says |
orientation | orientation | TimelineOrientation | 'vertical' | Run down the page or across it; audit entries always run down |
variant | variant | TimelineVariant | 'audit' | audit for a record of changes, steps for milestones, tracking for one thing's stops |
Events
| Event | Description |
|---|---|
nana-load-more | The reader asked for earlier activity |
Slots
| Slot | Description |
|---|---|
empty | Shown when there is no activity |
icon-<id> | A glyph for the entry with that id, in place of its icon |
CSS parts
| Part | Description |
|---|---|
::part(base) | The container |
::part(day) | One day's heading |
::part(list) | One day's entries |
::part(entry) | One entry |
::part(marker) | The entry's dot or icon on the rail |
::part(connector) | The stretch of rail joining an entry to the next |
::part(title) | A step or stop's name |
::part(description) | The line under a step or stop's name |
::part(line) | The who-did-what sentence |
::part(time) | The entry's time |
::part(source) | The chip naming a non-human source |
::part(changes) | The changed fields |
::part(note) | The note left with the entry |
::part(more) | The button that loads earlier activity |
CSS custom properties
| Property | Description |
|---|---|
--nana-timeline-rail | Colour of the line joining the entries |
--nana-timeline-accent | Colour of finished steps and the latest stop |
--nana-timeline-marker-size | Size of an icon marker |
--nana-timeline-step-min | Narrowest a step may get across the page before it scrolls |