Data & display

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
  1. Report approved
    24-Jul-202614:05Priya Sharma
  2. Submitted for sign-off
    24-Jul-202611:20Ravi Kumar
  3. Returned for revision
    22-Jul-202616:42Priya Sharma
variant="progress" — a status tracker for a fixed set of steps
  1. Initiated
    25 Jul 202609:12
    Loan application process started
  2. Submitted
    26 Jul 202614:40
    File shared with the lender.
  3. Approved / Rejected
  4. Sanctioned
  5. 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.

  1. Report approved
    24-Jul-2026 14:05Priya Sharma
<app-timeline-item title="Report approved" at="24-Jul-2026 14:05" by="Priya Sharma" />

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.

A sign-off history
Timestamps are formatted by the caller — pin the timezone to IST rather than the server's.
  1. Report approved
    24-Jul-2026 14:05Priya Sharma
  2. Submitted for sign-off
    24-Jul-2026 11:20Ravi Kumar
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>
Format the timestamp before passing itThe backend stores UTC; without pinning 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.

The five tones
Pair the tone with an icon that says the same thing — the dot's colour alone is not enough.
  1. Approved
    14:0511:05
  2. Rejected
    13:40
  3. Overdue
    12:00
  4. Reminder sent
    11:30
  5. Draft created
    09:15
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.

An entry with a reason
The whole history, including a returned-for-revision entry and its reason.
  1. Report approved
    24-Jul-2026 14:05Priya Sharma
  2. Submitted for sign-off
    24-Jul-2026 11:20Ravi Kumar
  3. Returned for revision
    22-Jul-2026 16:42Priya Sharma

    Zone 3 lightning density looks off against the site coordinates — please re-check before resubmitting.

  4. Draft created
    21-Jul-2026 09:15Ravi Kumar
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.

A loan application, step by step
The same tracker at six points in its life — the states a customer sees as the application moves from Initiated to Disbursed. Upcoming steps stay hollow and greyed until they happen.
Just initiated
  1. Initiated
    25 Jul 202609:12
    Loan application process started
  2. Submitted
  3. Approved / Rejected
  4. Sanctioned
  5. Disbursed
Under review — current: In progress
  1. Initiated
    25 Jul 202609:12
    Loan application process started
  2. Submitted
    26 Jul 202614:40
    File shared with the lender.
  3. Approved / Rejected
  4. Sanctioned
  5. Disbursed
Approved
  1. Initiated
    25 Jul 202609:12
    Loan application process started
  2. Submitted
    26 Jul 202614:40
    All documents finalised.
  3. Approved
    30 Jul 202611:05
    Approved with 3 scheme options
  4. Sanctioned
  5. Disbursed
Rejected — the terminal error state
  1. Initiated
    25 Jul 202609:12
    Loan application process started
  2. Submitted
    26 Jul 202614:40
    All documents finalised.
  3. Rejected
    30 Jul 2026
    Declined: exposure to the sector is at their internal cap this quarter.
  4. Sanctioned
  5. Disbursed
Sanctioned
  1. Initiated
    25 Jul 202609:12
    Loan application process started
  2. Submitted
    26 Jul 202614:40
    All documents finalised.
  3. Approved
    30 Jul 202611:05
    Approved with 3 scheme options
  4. Sanctioned
    30 Jul 202616:20
    Sanction letter issued to you.
  5. Disbursed
Disbursed — complete
  1. Initiated
    25 Jul 202609:12
    Loan application process started
  2. Submitted
    26 Jul 202614:40
    All documents finalised.
  3. Approved
    30 Jul 202611:05
    Approved with 3 scheme options
  4. Sanctioned
    30 Jul 202616:20
    Sanction letter issued to you.
  5. Disbursed
    31 Jul 202610:30
    Money 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.

All statuses
One dot per status, with the value you pass and what it means. done, current, on-hold and rejected carry a coloured halo; cancelled/skipped read as muted slate; upcoming is a hollow ring.
  1. Upcoming
    status="upcoming"
    Not started yet — a future step.
  2. In progress
    status="current"
    Being worked on right now.
  3. Completed
    status="done"
    Finished successfully.
  4. On hold
    status="on-hold"
    Blocked — waiting on an external action.
  5. Rejected
    status="rejected"
    Declined or failed — a terminal error.
  6. Cancelled
    status="cancelled"
    Aborted — the plan changed.
  7. Skipped
    status="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.

Horizontal progress stepper
The same statuses and rail, turned on their side. Best for a short, fixed sequence where a left-to-right read matches the flow.
  1. Submitted
  2. Reviewed
  3. Approval
  4. Sanctioned
  5. 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

Do
  1. Report approved
    24-Jul-2026 14:05Priya Sharma
Title in the past tense saying what happened, plus the actor and an absolute timestamp — the three things an audit reader is looking for.
Don't
  1. Status changed
    2 days ago
“Status changed” to what, by whom? And “2 days ago” cannot be cross-referenced against anything — an audit trail needs absolute times.

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"
  1. Draft created
tone="success"
  1. Event success
tone="warning"
  1. Event warning
tone="danger"
  1. Event danger
tone="info"
  1. Event info

Feed · icon

(default) — circle
  1. No icon given
icon="send"
  1. Submitted

Feed · at / by — the meta line

neither at nor by
  1. Draft created
at only
  1. Draft created
    21-Jul-2026 09:15
by only
  1. Draft created
    Ravi Kumar
at and by
  1. Draft created
    21-Jul-2026 09:15Ravi Kumar

Feed · note

no note
  1. Submitted for sign-off
with a note
  1. Returned for revision

    Zone 3 lightning density looks off against the site coordinates.

Progress · status — every state (variant="progress")

status="upcoming"
  1. Upcoming
    Not started yet — a future step.
status="current"
  1. In progress
    Being worked on right now.
status="done"
  1. Completed
    Finished successfully.
status="on-hold"
  1. On hold
    Blocked — waiting on an external action.
status="rejected"
  1. Rejected
    Declined or failed — a terminal error.
status="cancelled"
  1. Cancelled
    Aborted — the plan changed.
status="skipped"
  1. Skipped
    Intentionally bypassed.

Both · description — inline subtext

no description
  1. Submitted
with a description
  1. Submitted
    File shared with the lender.

Both · size (px) — the dot, glyph, rail and halo scale together

size="20"
  1. Approved
  2. In review
  3. Payout
size="24" (default)
  1. Approved
  2. In review
  3. Payout
size="32"
  1. Approved
  2. In review
  3. Payout
size="44"
  1. Approved
  2. In review
  3. Payout

Edge cases

no app-timeline-item children — empty list, still a valid <ol>
    variant="progress" with no status — an empty ring
    1. No status given
      25 Jul 2026
    a long, unbroken title and note wrap without overflowing the rail
    1. Averyveryverylongsingletokenstitlethatmustwrapinsteadofoverflowingthetimelinerail
      24-Jul-2026 14:05Priya Sharma

      Anexceptionallylongunspacedreasonstringthatshouldbreakratherthanpushthepanelwider.

    multiple entries — the rail stays continuous across wraps
    1. Report approved
      24-Jul-2026 14:05Priya Sharma
    2. Submitted for sign-off
      24-Jul-2026 11:20Ravi Kumar
    3. Returned for revision
      22-Jul-2026 16:42Priya Sharma

      Zone 3 lightning density looks off against the site coordinates — please re-check before resubmitting.

    4. Draft created
      21-Jul-2026 09:15Ravi Kumar

    Attributes

    AttributeTypeDefaultDescription
    title *string—The step / event label.
    statusupcoming | 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.
    toneneutral | success | warning | danger | infoneutralTints the dot (feed variant).
    iconstringcircleGlyph inside the dot. Overrides the status glyph. Should say the same thing as the tone.
    descriptionstring—Plain inline subtext under the title (distinct from the boxed note).
    atstring—Formatted timestamp. Absolute, not relative.
    bystring—Who did it (feed variant).
    notestring—Free text boxed block. Line breaks are preserved.

    The attributes above are on <app-timeline-item>. The wrapper <app-timeline> itself takes:

    AttributeTypeDefaultDescription
    variantfeed | progressfeedLayout mode — the audit-trail feed or the status tracker.
    orientationvertical | horizontalverticalRail direction. horizontal lays the dots in a row with the body beneath each; orthogonal to variant.
    sizeint (px)24Dot diameter in px. The glyph, rail and halo all scale from it; the glyph auto-sizes to ~54% of the dot.