When to use Timeline, what each of its props is for, and the choices it leaves to you.
When to use
A timeline is a record: events that already happened, in the order they happened, on a line the reader scans instead of acting on. Each event gets a dot that can carry its own color or icon, and a body that can carry anything.
An activity or audit log: who changed what, when, with the change itself in the row.
A run trace: a job, a deployment, an agent's tool calls, where a failed step and its retry sit next to each other.
Delivery or fulfillment tracking, where the last entry is the current state and everything above it is history.
A postmortem or a changelog, where the reader is piecing a sequence back together instead of moving through one.
Use something else when
The reader is working through the sequence. A checkout, an onboarding flow, a multi-part form: that is Steps, which has a current step, a next one and a sense of progress. Timeline has no “you are here”: every row is finished.
The order carries no meaning. If the rows could be sorted by name or by size without losing anything, the line and the dots are decoration. Use a List, or a table.
The sequence branches. A timeline is one line. A tree of causes and effects is a diagram, not a list.
items is the API
Pass items. Timeline.Item is deprecated, and the kit leaves it out.
Every item field was renamed in Ant Design 6. The old names still work, but each one warns in development.
children is now content: the body of the row.
dot is now icon: what is drawn on the line.
label is now title: the gutter text, usually the timestamp.
position is now placement, and takes only start or end.
Give each item a stable key when the list can grow. A timeline that gains a row at the top is where an index key makes React reuse the wrong row.
Which side the rows sit on
mode places the whole list against the line. start is the default and the one to use: one column, the line on the leading edge, everything reading top to bottom at one indent. end mirrors it. An unknown value falls back to start without a warning.
mode="left" and mode="right" still work but are deprecated and warn. Write start and end, which flip on their own in a right-to-left layout.
alternate puts the line down the middle and sends odd rows one way and even rows the other. Use it when the items have a title and the two sides mean something: two speakers, two systems, plan against actual. placement on one item moves just that row, so a mixed timeline stays one component.
Alternate is hard to read once rows are uneven or long. The eye has to cross the line for every entry, and a tall row on one side leaves a gap on the other. On a phone-width screen it becomes one column anyway. Use alternate for a dozen short, paired rows, and start for a log.
An open-ended end
A timeline of something still running needs a last row that says so. There are two ways to add one.
pending and pendingDot on the root add a trailing item. Both are deprecated: put the row in items like any other.
loading: true on an item is the current way. It marks that row as in progress instead of finished.
Both draw a default spinner when the row has no icon of its own, and that spinner ignores your icon pack. Pass your own icon alongside loading: true to keep the in-progress styling with your glyph, and add motion-safe:animate-spin, since an icon from your pack does not spin by itself.
Keep one pending row, at the end. Two of them stop reading as “what is happening now” and start reading as a queue, which is a different component.
The dot and its color
The dot is the only thing every row has. Keep it plain unless the row is a different kind of event, because a timeline where every dot is a different glyph has no baseline left to read against.
icon replaces the dot for one row. Use it for the exceptions: a failure, a deploy, a human approval, the row that is still running.
color takes blue, red, green or gray as presets, or any other CSS color.
For a custom color, use a theme variable like color="var(--ant-magenta-6)" instead of a hex, so the dot follows the theme into dark mode.
Pick a meaning per color and keep it across the product. Red for the failed step everywhere, not red for “important” on one screen and “deleted” on the next.
Color is never the only thing saying what a row is. The row's own text has to say it too, which is also the Accessibility tab's first rule.
Where the timestamp goes
A time can go in two places, and they are different choices. title puts it in its own gutter, aligned down the whole list. Putting it inside content makes it part of the sentence.
Use title when the reader scans by time: an audit log, a delivery, anything where “what happened at 09:14” is the question. An aligned column of timestamps is easy to scan, and a column of prose is not.
Put it in content when the time is context, not an index: “Retried 40 seconds later”, a relative time, a duration. Those read as part of the event.
titleSpan sets the gutter's width. A number is a column count out of 24 (the default is 12, so half), and a string is a CSS width. A number sized like pixels, say 110, squeezes the content into a sliver, so pass "110px" instead. It has no effect with alternate.
Do not put it in both. A time in the gutter and a time in the body is the same fact twice, and screen readers read both.
Giving any item a title changes the layout of the whole vertical timeline: it switches to two columns as soon as one item has one. Add a title to a single row of a long log and every other row moves.
Newest first, or newest last
reverse flips the order items are shown in. Decide which end the reader starts at once per surface, and keep it.
Newest last when the reader follows a chain of causes: an incident postmortem, a build log, a run trace. The story reads forward, and the still-running row is at the bottom where the pending item belongs.
Newest first when the reader is checking on something: a notification feed, an activity stream, an audit log they open to see what just happened. Nobody scrolls to the bottom of a year of history.
reverse reverses the page order, not only the paint, so the reading order and the visual order agree. Use it instead of reversing the array yourself in a render.
Do not flip the order in response to a filter or a sort control elsewhere on the page. A list that changes direction under the reader costs more than the sort saved.