Scroll Timeline
滾動驅動的時間軸,主軸生長線隨捲動延伸,抵達的節點同步亮起並揭示內容。
把這個效果裝進你的專案
在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。
npx webberui@latest add scroll-timelineScroll Timeline 是用 React、Tailwind CSS 與 Motion 的 useScroll 做的捲動時間軸(scroll timeline/滾動進度時間軸)元件:左側主軸的線條隨捲動往下延伸,到達的節點同步亮起,內容由淡轉亮;結構是語意化的 ol 清單。
Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
<ScrollTimeline/>
完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。
適用情境
- 公司「關於我們」頁的發展歷程或里程碑。
- 產品 roadmap 或更新日誌,依季度或版本列出。
- 導入流程、申請步驟這類需要依序閱讀的說明頁。
- 個人履歷或作品集的經歷區塊。
安裝
npx webberui@latest add https://webberui.com/r/scroll-timeline.json或在 components.json 設定 registries 後,改用 @webberui/scroll-timeline 安裝。
使用
以 ScrollTimeline 包裹一組 ScrollTimelineItem。捲動時中央主軸的生長線會由上往下延伸,抵達的節點同步亮起。
import { Flag, Rocket } from "lucide-react";
import {
ScrollTimeline,
ScrollTimelineItem,
} from "@/components/ui/scroll-timeline";
<ScrollTimeline>
<ScrollTimelineItem icon={<Flag />} date="2024 · Q1" title="專案啟動">
確立動畫優先的設計原則。
</ScrollTimelineItem>
<ScrollTimelineItem icon={<Rocket />} date="2025 · Q1" title="正式上線">
捲動至此,節點隨生長線一同亮起。
</ScrollTimelineItem>
</ScrollTimeline>;若時間軸放在固定高度的巢狀捲動容器內,將該容器的 ref 傳入 container:
const scrollerRef = React.useRef<HTMLDivElement>(null);
<div ref={scrollerRef} className="h-[300px] overflow-y-auto">
<ScrollTimeline container={scrollerRef}>{/* ... */}</ScrollTimeline>
</div>;範例
從資料陣列產生節點
節點資料通常來自 CMS 或常數檔,用 map 產生 ScrollTimelineItem 即可;icon 與 date 都是選填。
import {
ScrollTimeline,
ScrollTimelineItem,
} from "@/components/ui/scroll-timeline";
const releases = [
{ version: "v1.0", date: "2024 年 3 月", note: "第一個公開版本,支援專案與任務管理。" },
{ version: "v1.4", date: "2024 年 9 月", note: "新增甘特圖與 CSV 匯出。" },
{ version: "v2.0", date: "2025 年 4 月", note: "改寫權限系統,支援自訂角色。" },
];
export function Changelog() {
return (
<ScrollTimeline className="mx-auto max-w-xl">
{releases.map((r) => (
<ScrollTimelineItem key={r.version} date={r.date} title={r.version}>
{r.note}
</ScrollTimelineItem>
))}
</ScrollTimeline>
);
}讓節點更早亮起
activationLine 是觸發線在視區中的位置,預設 0.5(正中央)。往下移到 0.75,節點捲到畫面下方四分之一處就會亮起,適合節點內容較短的時間軸。
<ScrollTimeline activationLine={0.75}>
{/* ScrollTimelineItem… */}
</ScrollTimeline>放在可用鍵盤捲動的固定高度區塊
時間軸放在側欄或對話框等固定高度區塊時,把捲動容器的 ref 傳給 container,並加上 tabIndex 與 aria-label,讓鍵盤使用者能聚焦後用方向鍵捲動。
const scrollerRef = React.useRef<HTMLDivElement>(null);
<div
ref={scrollerRef}
tabIndex={0}
aria-label="專案歷程"
className="h-[360px] overflow-y-auto rounded-xl border p-6"
>
<ScrollTimeline container={scrollerRef}>{/* ScrollTimelineItem… */}</ScrollTimeline>
</div>Props
ScrollTimeline
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
children | React.ReactNode | — | 放入一組 ScrollTimelineItem |
container | React.RefObject<HTMLElement | null> | — | 巢狀 overflow 捲動容器的 ref;未提供時以視窗為捲動容器 |
activationLine | number | 0.5 | 觸發線在捲動視區中的位置(0=頂端、1=底端),生長線末端與節點點亮皆以此為基準 |
className | string | — | 附加在最外層容器的 class |
ScrollTimelineItem
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
title | React.ReactNode | — | 節點標題 |
date | React.ReactNode | — | 時間或階段標籤,顯示在標題上方 |
icon | React.ReactNode | — | 節點圖示(建議傳入 lucide-react 圖示),點亮後顯示於節點內 |
children | React.ReactNode | — | 節點說明內文 |
className | string | — | 附加在節點 li 上的 class |
細節
- 生長線的末端位置與各節點的點亮時機都以同一條「觸發線」(
activationLine)為基準,因此無論每個節點的高度是否不同,節點永遠在生長線抵達的瞬間亮起,兩者精準同步。 - 主軸末端帶有一顆「彗尾光點」,跟隨生長線前緣移動,強化捲動的方向感。
- 節點與內容會隨捲動進度平滑地由淡轉亮;尚未抵達的節點維持淡色描邊的空心狀態。
可及性
- 使用者系統開啟「減少動態效果」時,直接呈現整條點亮、內容全顯的靜態時間軸,不隨捲動變化。
- 主軸、生長線、節點與光點皆為純裝飾,標記
aria-hidden;時間軸內容以語意化的ol/li結構承載,輔助科技朗讀時為完整清單。 - 巢狀捲動容器範例加上
tabIndex與aria-label,讓鍵盤使用者可聚焦並以方向鍵捲動。
常見問題
可以在 Next.js App Router 使用嗎?
可以。檔案開頭已有 "use client",在 Server Component 頁面中照常 import,並把資料當作 props 與 children 傳入。
時間軸放在有捲軸的容器裡,線條不會動?
未傳 container 時,元件以整個視窗作為捲動來源。如果實際捲動的是某個 overflow-y-auto 的元素,要把那個元素的 ref 傳給 container。
節點高度不一樣,會不會對不齊?
不會。生長線的末端與每個節點的點亮時機都以同一條 activationLine 為基準,與節點高度無關,節點會在線條抵達時亮起。
怎麼改顏色?
主軸、節點與光點使用固定的 neutral 色系 Tailwind class,並附 dark: 變體。要換成品牌色,直接修改原始碼裡對應的 class;外層間距與寬度則用 className。
開啟「減少動態效果」會怎樣?
時間軸會直接以全部點亮、內容全顯的靜態樣子呈現,不隨捲動變化,也不顯示跟隨線條的光點。