Basic Vertical Timeline
A plain vertical rail with a dot, time, title and description per entry - the default timeline.
3 个框架初级
A horizontal strip of milestone cards on a rail that scroll-snaps instead of wrapping.
<!--
A horizontal rail cannot wrap, so it scrolls: the inner list is min-w-max and
the wrapper owns overflow-x-auto with scroll snapping. Fixed-width cards keep
the row from collapsing at 320px - the page never scrolls sideways, only this
strip does. The connector line is inset-x so it stops at the first and last
card rather than bleeding to the scroll edges.
-->
<div class="w-full overflow-x-auto pb-4">
<ol class="relative flex min-w-max snap-x snap-mandatory gap-4 px-1">
<span class="pointer-events-none absolute inset-x-4 top-2 h-px bg-gray-200 dark:bg-gray-800" aria-hidden="true"></span>
<li class="relative w-60 shrink-0 snap-start pt-6">
<span class="absolute left-4 top-2 h-3 w-3 -translate-y-1/2 rounded-full border-2 border-white bg-blue-600 dark:border-gray-950 dark:bg-blue-500" aria-hidden="true"></span>
<div class="rounded-lg border border-gray-200 bg-white p-4 shadow-sm dark:border-gray-800 dark:bg-gray-900">
<time class="text-xs font-medium uppercase tracking-wide text-gray-500 dark:text-gray-400">Q1</time>
<h3 class="mt-1 text-sm font-semibold text-gray-900 dark:text-gray-100">Discovery</h3>
<p class="mt-1 text-sm leading-relaxed text-gray-600 dark:text-gray-400">Interviews, research and a very messy whiteboard.</p>
</div>
</li>
<li class="relative w-60 shrink-0 snap-start pt-6">
<span class="absolute left-4 top-2 h-3 w-3 -translate-y-1/2 rounded-full border-2 border-white bg-blue-600 dark:border-gray-950 dark:bg-blue-500" aria-hidden="true"></span>
<div class="rounded-lg border border-gray-200 bg-white p-4 shadow-sm dark:border-gray-800 dark:bg-gray-900">
<time class="text-xs font-medium uppercase tracking-wide text-gray-500 dark:text-gray-400">Q2</time>
<h3 class="mt-1 text-sm font-semibold text-gray-900 dark:text-gray-100">Prototype</h3>
<p class="mt-1 text-sm leading-relaxed text-gray-600 dark:text-gray-400">The first thing you could actually click.</p>
</div>
</li>
<li class="relative w-60 shrink-0 snap-start pt-6">
<span class="absolute left-4 top-2 h-3 w-3 -translate-y-1/2 rounded-full border-2 border-white bg-blue-600 dark:border-gray-950 dark:bg-blue-500" aria-hidden="true"></span>
<div class="rounded-lg border border-gray-200 bg-white p-4 shadow-sm dark:border-gray-800 dark:bg-gray-900">
<time class="text-xs font-medium uppercase tracking-wide text-gray-500 dark:text-gray-400">Q3</time>
<h3 class="mt-1 text-sm font-semibold text-gray-900 dark:text-gray-100">Beta</h3>
<p class="mt-1 text-sm leading-relaxed text-gray-600 dark:text-gray-400">Fifty teams, endless feedback, zero regrets.</p>
</div>
</li>
<li class="relative w-60 shrink-0 snap-start pt-6">
<span class="absolute left-4 top-2 h-3 w-3 -translate-y-1/2 rounded-full border-2 border-white bg-blue-600 dark:border-gray-950 dark:bg-blue-500" aria-hidden="true"></span>
<div class="rounded-lg border border-gray-200 bg-white p-4 shadow-sm dark:border-gray-800 dark:bg-gray-900">
<time class="text-xs font-medium uppercase tracking-wide text-gray-500 dark:text-gray-400">Q4</time>
<h3 class="mt-1 text-sm font-semibold text-gray-900 dark:text-gray-100">Launch</h3>
<p class="mt-1 text-sm leading-relaxed text-gray-600 dark:text-gray-400">Doors open, coffee cold, dashboards green.</p>
</div>
</li>
</ol>
</div>| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
items必填 | HScrollItem[] | - | 要渲染的项目数组。 |
className | string | - | 合并到根元素上的额外类名。 |
The inner list is `min-w-max` and the wrapper owns `overflow-x-auto`, so only the strip scrolls sideways, never the page. Adjust card width with `w-60` and the snap feel with `snap-mandatory`.