Basic Vertical Timeline
A plain vertical rail with a dot, time, title and description per entry - the default timeline.
3 frameworksBeginner
A status-driven roadmap where every item pairs a coloured dot with a worded state badge.
<!--
Status drives colour, and colour never carries the meaning alone: every dot is
paired with a text badge ("Shipped", "In progress", "Planned"), so the state
is legible to anyone who cannot tell emerald from blue. The connector is the
flex-grow spacer under each marker and is simply omitted on the last row.
-->
<ol class="mx-auto w-full max-w-xl">
<li class="relative flex gap-4 pb-8">
<div class="flex flex-col items-center">
<span class="mt-1 h-3 w-3 shrink-0 rounded-full bg-emerald-500 ring-4 ring-white dark:ring-gray-950" aria-hidden="true"></span>
<span class="mt-1 w-px grow bg-gray-200 dark:bg-gray-800" aria-hidden="true"></span>
</div>
<div class="-mt-0.5 flex-1 pb-1">
<div class="flex flex-wrap items-center gap-2">
<h3 class="text-sm font-semibold text-gray-900 dark:text-gray-100">Public API</h3>
<span class="inline-flex items-center rounded-full bg-emerald-50 px-2 py-0.5 text-xs font-medium text-emerald-700 dark:bg-emerald-500/10 dark:text-emerald-300">Shipped</span>
</div>
<time class="mt-0.5 block text-xs text-gray-500 dark:text-gray-400">Q1 2026</time>
<p class="mt-1 text-sm leading-relaxed text-gray-600 dark:text-gray-400">REST and webhooks, versioned and documented.</p>
</div>
</li>
<li class="relative flex gap-4 pb-8">
<div class="flex flex-col items-center">
<span class="mt-1 h-3 w-3 shrink-0 rounded-full bg-blue-500 ring-4 ring-white dark:ring-gray-950" aria-hidden="true"></span>
<span class="mt-1 w-px grow bg-gray-200 dark:bg-gray-800" aria-hidden="true"></span>
</div>
<div class="-mt-0.5 flex-1 pb-1">
<div class="flex flex-wrap items-center gap-2">
<h3 class="text-sm font-semibold text-gray-900 dark:text-gray-100">Mobile app</h3>
<span class="inline-flex items-center rounded-full bg-blue-50 px-2 py-0.5 text-xs font-medium text-blue-700 dark:bg-blue-500/10 dark:text-blue-300">In progress</span>
</div>
<time class="mt-0.5 block text-xs text-gray-500 dark:text-gray-400">Q3 2026</time>
<p class="mt-1 text-sm leading-relaxed text-gray-600 dark:text-gray-400">iOS first, Android close behind.</p>
</div>
</li>
<li class="relative flex gap-4">
<div class="flex flex-col items-center">
<span class="mt-1 h-3 w-3 shrink-0 rounded-full bg-gray-300 ring-4 ring-white dark:bg-gray-600 dark:ring-gray-950" aria-hidden="true"></span>
</div>
<div class="-mt-0.5 flex-1">
<div class="flex flex-wrap items-center gap-2">
<h3 class="text-sm font-semibold text-gray-900 dark:text-gray-100">Offline mode</h3>
<span class="inline-flex items-center rounded-full bg-gray-100 px-2 py-0.5 text-xs font-medium text-gray-600 dark:bg-gray-800 dark:text-gray-300">Planned</span>
</div>
<time class="mt-0.5 block text-xs text-gray-500 dark:text-gray-400">Q4 2026</time>
<p class="mt-1 text-sm leading-relaxed text-gray-600 dark:text-gray-400">Local-first sync for flaky connections.</p>
</div>
</li>
</ol>| Prop | Type | Default | Description |
|---|---|---|---|
itemsrequired | RoadmapItem[] | - | The array of items to render. |
labels | Record<RoadmapStatus, string> | - | Labels |
className | string | - | Additional classes merged onto the root element. |
Colour is only a hint: each `status` renders a dot and a matching text badge, so state survives colour-blindness and greyscale. Pass `labels` to rename or translate the three states without touching the palette map.