Skip to content
TopClass UI

Timeline

A rail of dated events, each with a marker in its tone. It renders on the server and mirrors by itself in right-to-left layouts.

server - 0 KB

Timeline

server - 0 KB

A rail of dated events, each with a marker in its tone. It renders on the server and mirrors by itself in right-to-left layouts.

Install
  1. Done
    Project created
  2. Done
    First deploy
  3. Current
    In review
    Today
  4. Not started
    Launch
    Not scheduled

The code

timeline.tsx
import { Timeline } from 'topclassui/timeline'

const EVENTS = [
  { id: 'created', title: 'Project created', time: <time dateTime="2026-10-02T09:12">2 October, 09:12</time>, status: 'done' },
  { id: 'deployed', title: 'First deploy', time: <time dateTime="2026-10-04T16:40">4 October, 16:40</time>, status: 'done' },
  { id: 'review', title: 'In review', time: 'Today', status: 'current' },
  { id: 'launch', title: 'Launch', time: 'Not scheduled', status: 'todo' },
] as const

/** The drawn rail: done filled in success, the current step a dot in a ring, and a hollow todo.
 * A `<time>` gives a date a machine can read; each status is also said in hidden text. */
export default function Demo() {
  return <Timeline items={EVENTS} getKey={(event) => event.id} />
}

An item's icon is an element, such as <Svg icon={check} size="xs" />, not an icon name: no icon loader ships.

Every state

6 states
  1. Done
    Done
    A filled dot in success
  1. Current
    Current
    A dot in a ring, read as the current step
  1. Not started
    To do
    A hollow dot
  1. A tone of its own
    No status, the danger tone
  1. Done
    An icon
    Takes the tone of its status
  1. Not started
    An icon to do

Import from the package

topclassui/timeline
import { Timeline } from 'topclassui/timeline'

Install once:npm i topclassui@beta zod

Examples

  • An item is { title, time?, status?, tone?, icon? }, plus any field of your own, such as an id for getKey.
  • Pass a <time dateTime="..."> as time for a date a machine can read; it shows muted under the title.
  • A done item is a filled dot, current a dot in a ring and todo a hollow dot. With no tone, done is success and the rest are primary; a todo marker stays hollow whatever the tone.
  • Timeline renders the items it is given, in that order: it never sorts, fetches or pages.
  • No items renders emptyFallback on its own, or nothing without one.
basic
  1. Done
    Project created
  2. Done
    First deploy
  3. Current
    In review
    Today
  4. Not started
    Launch
    Not scheduled
tones
  1. Primary
    A new version is ready.
  2. Neutral
    Nothing has changed since Monday.
  3. Success
    The invoice was paid.
  4. Warning
    The trial ends in three days.
  5. Danger
    The last deploy failed.
  6. Info
    Maintenance starts at 22:00.
icons
  1. Invoice created
    09:12
  2. Payment received
    11:30
  3. Receipt delayed
    11:31
  4. Not started
    Receipt sent
long-text
  1. The deploy failed while uploading the static assets to the edge network
    Friday 9 October 2026 at 16:40, Central European Summer Time
  2. https://example.com/projects/topclassui/deployments/2026-10-09/logs/build-step-four-of-six.txt
    Kept for thirty days
  3. Not started
    Retry
empty

No activity yet.

In Arabic, right to left
  1. مكتمل
    أُنشئ المشروع
    ٢ أكتوبر، ٠٩:١٢
  2. مكتمل
    وصلت الدفعة
    ٤ أكتوبر، ١٦:٤٠
  3. الحالي
    قيد المراجعة
    اليوم
  4. لم يبدأ
    الإطلاق
    لم يُحدَّد موعده

Props

The props of Timeline
PropTypeDefaultLimitsDescription
getKey*(item: T) => string--A stable identity for each item, which becomes its React key.
items*readonly T[]--The events, first to last. The connector runs from each marker to the next.
emptyFallbackReactNode--Rendered in place of the list while items is empty. Without it, nothing renders.
labelsLabels--The built-in strings, which name each status. Defaults to English; pass getLabels(locale).labels for another.
localestring--Accepted so {...getLabels(locale)} spreads cleanly. Nothing here formats a number, so it is not used and never reaches the element.

Keyboard and accessibility

Nothing to operate: it is not interactive on its own.

  • An ordered list, with role="list" written so Safari with VoiceOver keeps it.
  • The marker is a shape and a colour, so each status is also said in hidden words from labels; the current item carries aria-current="step".
  • Nothing in it takes focus: it is page content, not a control.

Right to left

The rail sits at the inline start, on the right in Arabic, with no direction prop. Pass labels for the status words in Arabic.

Server and client

Renders on the server and ships no JavaScript.

Files: index.tsx.

On the chip: server - 0 KB.