AppTimeline
Two variants on one rail — a feed (audit trail) and a progress status tracker.
<app-timeline><app-timeline-item title="…" /></app-timeline><app-timeline> puts a sequence of dots on a single vertical rail. It ships in two variants, chosen with the variant attribute and sharing the same anatomy — a dot, a title, and supporting text:
- Feed
(default)— an audit trail, a sign-off history, an activity log: what happened, when, and who did it. - Progress — a status tracker for a fixed set of steps (an order, a loan, an onboarding): where the process is now, with a status on every step.
The rail never breaks into disconnected segments when an entry wraps to two lines — the failure that makes most hand-rolled timelines look broken with real data.
The two variants at a glance
Same component, two looks. Feed reads top-down as history (newest first); progress reads top-down as a pipeline (first step first) with a live status on every step.
variant="feed" (default) — an audit trail / activity log
- Report approved
- Submitted for sign-off
- Returned for revision
variant="progress" — a status tracker for a fixed set of steps
- Initiated25 Jul 202609:12Loan application process started
- Submitted26 Jul 202614:40File shared with the lender.
- Approved / Rejected
- Sanctioned
- Disbursed
Playground
Every attribute of a single feed entry, live. Each change re-renders the real tag helper on the server, so the markup underneath is the exact call that produced the entry above it.
Feed · basics
The default variant. Write items newest first — a reader scanning an audit trail expects the latest event at the top; the tag helper does not sort for you, because only you know which field is authoritative.
- Report approved
- Submitted for sign-off
Show code
<app-timeline>
<app-timeline-item tone="success" icon="check-circle" title="Report approved"
at="24-Jul-2026" time="14:05" by="Priya Sharma" />
<app-timeline-item icon="send" title="Submitted for sign-off"
at="24-Jul-2026" time="11:20" by="Ravi Kumar" />
</app-timeline>
Asia/Kolkata the rendered dates are simply wrong off-IST — a bug that looks fine in local testing. Pass the date as at and, when you want a time-of-day beside it, time (e.g. at="24-Jul-2026" time="14:05").Feed · tones
A tone tints the dot so an outcome is visible while scanning: success for an approval, danger for a rejection, warning for something needing attention. Leave it off for a neutral, factual event.
- Approved
- Rejected
- Overdue
- Reminder sent
- Draft created
Show code
<app-timeline-item tone="success" icon="check-circle" title="Approved" at="14:05" /> <app-timeline-item tone="danger" icon="alert-circle" title="Rejected" at="13:40" />
Feed · notes
A note carries free text the actor wrote — a rejection reason, a comment. It preserves the author's line breaks and breaks long unspaced strings rather than overflowing the panel.
- Report approved
- Submitted for sign-off
- Returned for revision
Zone 3 lightning density looks off against the site coordinates — please re-check before resubmitting.
- Draft created
Show code
<app-timeline-item tone="danger" icon="alert-circle" title="Returned for revision"
at="22-Jul-2026 16:42" by="Priya Sharma"
note="Zone 3 lightning density looks off…" />
Progress · a status tracker
Add variant="progress" on <app-timeline> to turn the feed into a status tracker for a fixed sequence of stages. Each item carries a status (see the full status vocabulary below); the rail fills green only between two completed steps. Use description for the subtext and at for the top-right date.
Just initiated
- Initiated25 Jul 202609:12Loan application process started
- Submitted
- Approved / Rejected
- Sanctioned
- Disbursed
Under review — current: In progress
- Initiated25 Jul 202609:12Loan application process started
- Submitted26 Jul 202614:40File shared with the lender.
- Approved / Rejected
- Sanctioned
- Disbursed
Approved
- Initiated25 Jul 202609:12Loan application process started
- Submitted26 Jul 202614:40All documents finalised.
- Approved30 Jul 202611:05Approved with 3 scheme options
- Sanctioned
- Disbursed
Rejected — the terminal error state
- Initiated25 Jul 202609:12Loan application process started
- Submitted26 Jul 202614:40All documents finalised.
- Rejected30 Jul 2026Declined: exposure to the sector is at their internal cap this quarter.
- Sanctioned
- Disbursed
Sanctioned
- Initiated25 Jul 202609:12Loan application process started
- Submitted26 Jul 202614:40All documents finalised.
- Approved30 Jul 202611:05Approved with 3 scheme options
- Sanctioned30 Jul 202616:20Sanction letter issued to you.
- Disbursed
Disbursed — complete
- Initiated25 Jul 202609:12Loan application process started
- Submitted26 Jul 202614:40All documents finalised.
- Approved30 Jul 202611:05Approved with 3 scheme options
- Sanctioned30 Jul 202616:20Sanction letter issued to you.
- Disbursed31 Jul 202610:30Money in your account.
Show code
<app-timeline variant="progress">
<app-timeline-item status="done" title="Initiated"
description="Loan application process started" at="25 Jul 2026" />
<app-timeline-item status="done" title="Submitted"
description="All documents finalised." at="26 Jul 2026" />
<app-timeline-item status="current" title="Approved / Rejected" />
<app-timeline-item status="upcoming" title="Sanctioned" />
<app-timeline-item status="upcoming" title="Disbursed" />
</app-timeline>
Progress · status vocabulary
Every status a progress step can be in, in one place. The first three are the lifecycle (upcoming → current → done); the rest cover the exception paths. Each maps to its own colour, glyph and halo — keep the status name, and write your own copy.
done, current, on-hold and rejected carry a coloured halo; cancelled/skipped read as muted slate; upcoming is a hollow ring.- Upcomingstatus="upcoming"Not started yet — a future step.
- In progressstatus="current"Being worked on right now.
- Completedstatus="done"Finished successfully.
- On holdstatus="on-hold"Blocked — waiting on an external action.
- Rejectedstatus="rejected"Declined or failed — a terminal error.
- Cancelledstatus="cancelled"Aborted — the plan changed.
- Skippedstatus="skipped"Intentionally bypassed.
Show code
<app-timeline variant="progress">
<app-timeline-item status="upcoming" title="Upcoming" description="Not started yet — a future step." />
<app-timeline-item status="current" title="In progress" description="Being worked on right now." />
<app-timeline-item status="done" title="Completed" description="Finished successfully." />
<app-timeline-item status="on-hold" title="On hold" description="Blocked — waiting on an external action." />
<app-timeline-item status="rejected" title="Rejected" description="Declined or failed — a terminal error." />
<app-timeline-item status="cancelled" title="Cancelled" description="Aborted — the plan changed." />
<app-timeline-item status="skipped" title="Skipped" description="Intentionally bypassed." />
</app-timeline>
Horizontal
orientation="horizontal" lays the dots in a row with the body stacked beneath each — a compact stepper across the top of a page. It is orthogonal to variant, so both feed and progress can run horizontally.
- Submitted
- Reviewed
- Approval
- Sanctioned
- Disbursed
Show code
<app-timeline variant="progress" orientation="horizontal">
<app-timeline-item status="done" title="Submitted" />
<app-timeline-item status="done" title="Reviewed" />
<app-timeline-item status="current" title="Approval" />
<app-timeline-item status="upcoming" title="Sanctioned" />
<app-timeline-item status="upcoming" title="Disbursed" />
</app-timeline>
When to use
Use it when
- A sequence of events or steps where the order matters.
- Feed: an audit trail / sign-off history — what happened, when, and who did it.
- Progress: a live status tracker — an order, a loan, an onboarding — with a state on every step.
Reach for something else when
- The rows are records to sort, filter or page. → app-data-table
- It is a form wizard's position indicator with no per-step history or status. → app-stepper
- They are label/value facts with no time or step dimension. → app-info-list
- There is nothing to show yet. → app-empty-state
Best practices
- Report approved
- Status changed
Every option
The whole surface of the component, one cell per value — grouped by variant: the feed's tones / icons / meta line / notes, then the progress statuses, then what both share.
Feed · tone — all five, paired with a matching icon
tone="neutral"
- Draft created
tone="success"
- Event success
tone="warning"
- Event warning
tone="danger"
- Event danger
tone="info"
- Event info
Feed · icon
(default) — circle
- No icon given
icon="send"
- Submitted
Feed · at / by — the meta line
neither at nor by
- Draft created
at only
- Draft created
by only
- Draft created
at and by
- Draft created
Feed · note
no note
- Submitted for sign-off
with a note
- Returned for revision
Zone 3 lightning density looks off against the site coordinates.
Progress · status — every state (variant="progress")
status="upcoming"
- UpcomingNot started yet — a future step.
status="current"
- In progressBeing worked on right now.
status="done"
- CompletedFinished successfully.
status="on-hold"
- On holdBlocked — waiting on an external action.
status="rejected"
- RejectedDeclined or failed — a terminal error.
status="cancelled"
- CancelledAborted — the plan changed.
status="skipped"
- SkippedIntentionally bypassed.
Both · description — inline subtext
no description
- Submitted
with a description
- SubmittedFile shared with the lender.
Both · size (px) — the dot, glyph, rail and halo scale together
size="20"
- Approved
- In review
- Payout
size="24" (default)
- Approved
- In review
- Payout
size="32"
- Approved
- In review
- Payout
size="44"
- Approved
- In review
- Payout
Edge cases
no app-timeline-item children — empty list, still a valid <ol>
variant="progress" with no status — an empty ring
- No status given25 Jul 2026
a long, unbroken title and note wrap without overflowing the rail
- Averyveryverylongsingletokenstitlethatmustwrapinsteadofoverflowingthetimelinerail
Anexceptionallylongunspacedreasonstringthatshouldbreakratherthanpushthepanelwider.
multiple entries — the rail stays continuous across wraps
- Report approved
- Submitted for sign-off
- Returned for revision
Zone 3 lightning density looks off against the site coordinates — please re-check before resubmitting.
- Draft created
Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
| title * | string | — | The step / event label. |
| status | upcoming | current | done | on-hold | rejected | cancelled | skipped | — | Step state in the progress variant — drives the dot colour/glyph/halo and the rail segment. See the status vocabulary. |
| tone | neutral | success | warning | danger | info | neutral | Tints the dot (feed variant). |
| icon | string | circle | Glyph inside the dot. Overrides the status glyph. Should say the same thing as the tone. |
| description | string | — | Plain inline subtext under the title (distinct from the boxed note). |
| at | string | — | Formatted timestamp. Absolute, not relative. |
| by | string | — | Who did it (feed variant). |
| note | string | — | Free text boxed block. Line breaks are preserved. |
The attributes above are on <app-timeline-item>. The wrapper <app-timeline> itself takes:
| Attribute | Type | Default | Description |
|---|---|---|---|
| variant | feed | progress | feed | Layout mode — the audit-trail feed or the status tracker. |
| orientation | vertical | horizontal | vertical | Rail direction. horizontal lays the dots in a row with the body beneath each; orthogonal to variant. |
| size | int (px) | 24 | Dot diameter in px. The glyph, rail and halo all scale from it; the glyph auto-sizes to ~54% of the dot. |