Timeline
A sequence where the order is the content, and a progress stepper when you need one.
import { ... } from '@corndev/ui' - POST/sessionSign in, and keep the token.
- POST/ordersPlace the order.
- GET/orders/{id}
Poll until it ships.
- Account
- Billing
- Confirm
HTML
No JavaScript required — these classes are the whole component.
<ol class="corn-timeline" data-variant="sequence">
<li class="corn-timeline-item">
<span class="corn-timeline-bullet" aria-hidden="true">1</span>
<div class="corn-timeline-title">Sign in</div>
<div class="corn-timeline-body">Exchange credentials for a token.</div>
</li>
<li class="corn-timeline-item">
<span class="corn-timeline-bullet" aria-hidden="true">2</span>
<div class="corn-timeline-title">Place the order</div>
</li>
</ol>
<!-- Progress: write the state on each item; the current one is aria-current="step". -->
<ol class="corn-timeline" data-variant="progress">
<li class="corn-timeline-item" data-state="complete"><span class="corn-timeline-bullet" aria-hidden="true"></span><div class="corn-timeline-title">Account</div></li>
<li class="corn-timeline-item" data-state="active" aria-current="step"><span class="corn-timeline-bullet" aria-hidden="true"></span><div class="corn-timeline-title">Billing</div></li>
<li class="corn-timeline-item" data-state="pending"><span class="corn-timeline-bullet" aria-hidden="true"></span><div class="corn-timeline-title">Confirm</div></li>
</ol>
Classes
| Class |
|---|
.corn-timeline |
.corn-timeline-item |
.corn-timeline-bullet |
.corn-timeline-title |
.corn-timeline-body |
Attributes
| On | Attribute | Values |
|---|---|---|
.corn-timeline | data-variant | progress |
.corn-timeline-item | data-state | complete|active |
CSS variables
| Variable | Default | Description |
|---|---|---|
--corn-timeline-bullet-size | 22px | Bullet diameter |
--corn-timeline-line-width | 2px | Connector and bullet border width |
Vanilla JS
Optional. createTimeline only adds and removes the classes and attributes above, so the HTML is equivalent. Reach for it when you need to change options at runtime.
import { createTimeline } from '@corndev/ui';
import '@corndev/ui/theme';
const el = document.querySelector('#target');
const instance = createTimeline(el, { /* options */ });
Options
| Option | Type | Default | Description |
|---|---|---|---|
variant | 'sequence'|'progress' | 'sequence' | sequence: every item equal — a documented workflow, where nothing is running. progress: items before active are complete, active is current, the rest are pending. |
active | number | undefined | Index of the current item, for progress. Items before it read as complete; pass the item count to complete them all. |
bulletSize | number|string | undefined | Bullet diameter — a number is pixels. Sets --corn-timeline-bullet-size; the stylesheet default is 22px. |
lineWidth | number|string | undefined | Connector width — a number is pixels. Sets --corn-timeline-line-width; the stylesheet default is 2px. |
React
Timeline, TimelineItem — from @corndev/ui-react.
The props are the same as the options above, plus className.
<Timeline.Item> props
One step, with title and bullet slots and the body as children.
| Prop | Type | Default | Description |
|---|---|---|---|
title | React.ReactNode | undefined | Heading beside the bullet. |
bullet | React.ReactNode | undefined | Inside the bullet: a number, an icon. Decoration — it is hidden from assistive technology, so do not put meaning only here. |
children | React.ReactNode | undefined | The body. |
className | string | undefined |
React usage
import { Timeline } from '@corndev/ui-react';
<Timeline>
<Timeline.Item bullet="1" title="Sign in">Exchange credentials for a token.</Timeline.Item>
<Timeline.Item bullet="2" title="Place the order" />
<Timeline.Item bullet="3" title="Poll until it ships" />
</Timeline>
A timeline rather than a list of headings because a list does not say that step 2
happens after step 1 rather than instead of it. It renders an <ol> for the same
reason: the order is the meaning.
Sequence, the default
A documented workflow has no current step — nothing is running — so every item is
equal and the line between them is only structure. That is variant="sequence",
and it is the default.
Progress
For a stepper — onboarding, checkout — variant="progress" with active, the index
of the current item:
<Timeline variant="progress" active={1}>
<Timeline.Item title="Account" />
<Timeline.Item title="Billing" />
<Timeline.Item title="Confirm" />
</Timeline>
Items before active are complete: a filled bullet and a coloured line. The current
one has a ringed bullet, a bold title and aria-current="step", so a screen reader
says which step you are on. Pass the number of items to mark every one complete.
Slots
title and bullet take any node. The title wraps, so a row of badges fits in it.
The bullet is aria-hidden — it is decoration — so a number or an icon there must
not be the only place that information lives.
If you colour a bullet by meaning, do it from your own content: the component never maps colour to status, so a bullet you style stays yours.
Density
Sized for documentation set at 14px inside a card: 22px bullets and a 2px line.
bulletSize and lineWidth change them, a number meaning pixels — or set
--corn-timeline-bullet-size and --corn-timeline-line-width in CSS.