Chuyển tới nội dung

Pro đang mở bán trước. Cài đặt mở từ tháng 1/2027. Xem Pro

Component

Timeline

Một danh sách sự kiện có thứ tự, như các bước của một lượt chạy agent hay lịch sử một đơn hàng: mỗi sự kiện có điểm đánh dấu (chấm, icon hoặc avatar) tô theo trạng thái, đường nối tới sự kiện sau, tiêu đề, thời gian, mô tả và nội dung tùy ý. Mặc định dọc, hoặc ngang thành một hàng.

  • npm: 0 trực tiếp, 1 tổng
  • registry: 2 trực tiếp, 2 tổng

Xem trước

  1. Đã tìm trong tài liệu
    xong

    Tìm thấy 4 trang về token.

  2. Đã đọc tokens.css
    xong

    312 dòng, 48 token màu.

  3. Đang viết câu trả lời
    đang chạy

    Bước hiện tại.

Props

  • orientation
  • size
  • scrollLabel
  • marker
  • descriptions
import { IconFileText, IconLoader2, IconSearch } from "@tabler/icons-react"
import { Timeline, TimelineItem } from "@/components/ui/timeline"

<Timeline statusLabels={{ success: "xong", warning: "cần chú ý", danger: "thất bại", info: "đang chạy" }}>
  <TimelineItem status="success" icon={<IconSearch />} title="Đã tìm trong tài liệu" time="10:42" dateTime="2026-10-24T10:42" description="Tìm thấy 4 trang về token." />
  <TimelineItem status="success" icon={<IconFileText />} title="Đã đọc tokens.css" time="10:43" dateTime="2026-10-24T10:43" description="312 dòng, 48 token màu." />
  <TimelineItem status="info" icon={<IconLoader2 />} title="Đang viết câu trả lời" time="10:43" dateTime="2026-10-24T10:43" description="Bước hiện tại." current />
</Timeline>

Cách dùng

Khi nào dùng

  • Hiện các sự kiện theo thứ tự đã xảy ra, như các bước của một lượt chạy agent, một lần deploy hay lịch sử đơn hàng.
  • Một luồng hoạt động, mỗi mục nói ai đã làm gì và khi nào.

Khi nào không dùng

  • Các bước của một luồng người dùng đi qua. Dùng Stepper.
  • Danh sách không có thứ tự thời gian. Dùng danh sách hoặc Table.
  • Một trạng thái đơn lẻ. Dùng Badge hoặc Alert.

Biến thể

orientation

vertical xếp sự kiện từ trên xuống; horizontal đặt chúng thành các cột đều nhau, cuộn ngang khi hẹp.

    1. Đã tìm trong tài liệu
      xong

      Tìm thấy 4 trang về token.

    2. Đã đọc tokens.css
      xong

      312 dòng, 48 token màu.

    3. Đang viết câu trả lời
      đang chạy

      Bước hiện tại.

    verticalmặc định

    1. Đã tìm trong tài liệu
      xong

      Tìm thấy 4 trang về token.

    2. Đã đọc tokens.css
      xong

      312 dòng, 48 token màu.

    3. Đang viết câu trả lời
      đang chạy

      Bước hiện tại.

    horizontal

import { IconFileText, IconLoader2, IconSearch } from "@tabler/icons-react"
import { Timeline, TimelineItem } from "@/components/ui/timeline"

<Timeline statusLabels={{ success: "xong", warning: "cần chú ý", danger: "thất bại", info: "đang chạy" }}>
  <TimelineItem status="success" icon={<IconSearch />} title="Đã tìm trong tài liệu" time="10:42" dateTime="2026-10-24T10:42" description="Tìm thấy 4 trang về token." />
  <TimelineItem status="success" icon={<IconFileText />} title="Đã đọc tokens.css" time="10:43" dateTime="2026-10-24T10:43" description="312 dòng, 48 token màu." />
  <TimelineItem status="info" icon={<IconLoader2 />} title="Đang viết câu trả lời" time="10:43" dateTime="2026-10-24T10:43" description="Bước hiện tại." current />
</Timeline>
<Timeline orientation="horizontal" statusLabels={{ success: "xong", warning: "cần chú ý", danger: "thất bại", info: "đang chạy" }}>
  <TimelineItem status="success" icon={<IconSearch />} title="Đã tìm trong tài liệu" time="10:42" dateTime="2026-10-24T10:42" description="Tìm thấy 4 trang về token." />
  <TimelineItem status="success" icon={<IconFileText />} title="Đã đọc tokens.css" time="10:43" dateTime="2026-10-24T10:43" description="312 dòng, 48 token màu." />
  <TimelineItem status="info" icon={<IconLoader2 />} title="Đang viết câu trả lời" time="10:43" dateTime="2026-10-24T10:43" description="Bước hiện tại." current />
</Timeline>

size

Cỡ ô đánh dấu, chữ và khoảng cách: điểm đánh dấu 24, 32 hoặc 40px.

    1. Đã tìm trong tài liệu
      xong

      Tìm thấy 4 trang về token.

    2. Đã đọc tokens.css
      xong

      312 dòng, 48 token màu.

    3. Đang viết câu trả lời
      đang chạy

      Bước hiện tại.

    sm

    1. Đã tìm trong tài liệu
      xong

      Tìm thấy 4 trang về token.

    2. Đã đọc tokens.css
      xong

      312 dòng, 48 token màu.

    3. Đang viết câu trả lời
      đang chạy

      Bước hiện tại.

    mdmặc định

    1. Đã tìm trong tài liệu
      xong

      Tìm thấy 4 trang về token.

    2. Đã đọc tokens.css
      xong

      312 dòng, 48 token màu.

    3. Đang viết câu trả lời
      đang chạy

      Bước hiện tại.

    lg

import { IconFileText, IconLoader2, IconSearch } from "@tabler/icons-react"
import { Timeline, TimelineItem } from "@/components/ui/timeline"

<Timeline size="sm" statusLabels={{ success: "xong", warning: "cần chú ý", danger: "thất bại", info: "đang chạy" }}>
  <TimelineItem status="success" icon={<IconSearch />} title="Đã tìm trong tài liệu" time="10:42" dateTime="2026-10-24T10:42" description="Tìm thấy 4 trang về token." />
  <TimelineItem status="success" icon={<IconFileText />} title="Đã đọc tokens.css" time="10:43" dateTime="2026-10-24T10:43" description="312 dòng, 48 token màu." />
  <TimelineItem status="info" icon={<IconLoader2 />} title="Đang viết câu trả lời" time="10:43" dateTime="2026-10-24T10:43" description="Bước hiện tại." current />
</Timeline>
<Timeline statusLabels={{ success: "xong", warning: "cần chú ý", danger: "thất bại", info: "đang chạy" }}>
  <TimelineItem status="success" icon={<IconSearch />} title="Đã tìm trong tài liệu" time="10:42" dateTime="2026-10-24T10:42" description="Tìm thấy 4 trang về token." />
  <TimelineItem status="success" icon={<IconFileText />} title="Đã đọc tokens.css" time="10:43" dateTime="2026-10-24T10:43" description="312 dòng, 48 token màu." />
  <TimelineItem status="info" icon={<IconLoader2 />} title="Đang viết câu trả lời" time="10:43" dateTime="2026-10-24T10:43" description="Bước hiện tại." current />
</Timeline>
<Timeline size="lg" statusLabels={{ success: "xong", warning: "cần chú ý", danger: "thất bại", info: "đang chạy" }}>
  <TimelineItem status="success" icon={<IconSearch />} title="Đã tìm trong tài liệu" time="10:42" dateTime="2026-10-24T10:42" description="Tìm thấy 4 trang về token." />
  <TimelineItem status="success" icon={<IconFileText />} title="Đã đọc tokens.css" time="10:43" dateTime="2026-10-24T10:43" description="312 dòng, 48 token màu." />
  <TimelineItem status="info" icon={<IconLoader2 />} title="Đang viết câu trả lời" time="10:43" dateTime="2026-10-24T10:43" description="Bước hiện tại." current />
</Timeline>

status

Trên TimelineItem. Tô điểm đánh dấu bằng token trạng thái.

    1. Đã tìm trong tài liệu
      xong

      Tìm thấy 4 trang về token.

    2. Đã đọc tokens.css
      xong

      312 dòng, 48 token màu.

    3. Đang viết câu trả lời
      đang chạy

      Bước hiện tại.

    defaultmặc định

    1. Đã tìm trong tài liệu
      xong

      Tìm thấy 4 trang về token.

    2. Đã đọc tokens.css
      xong

      312 dòng, 48 token màu.

    3. Đang viết câu trả lời
      đang chạy

      Bước hiện tại.

    success

    1. Đã tìm trong tài liệu
      xong

      Tìm thấy 4 trang về token.

    2. Đã đọc tokens.css
      xong

      312 dòng, 48 token màu.

    3. Đang viết câu trả lời
      đang chạy

      Bước hiện tại.

    warning

    1. Đã tìm trong tài liệu
      xong

      Tìm thấy 4 trang về token.

    2. Đã đọc tokens.css
      xong

      312 dòng, 48 token màu.

    3. Đang viết câu trả lời
      đang chạy

      Bước hiện tại.

    danger

    1. Đã tìm trong tài liệu
      xong

      Tìm thấy 4 trang về token.

    2. Đã đọc tokens.css
      xong

      312 dòng, 48 token màu.

    3. Đang viết câu trả lời
      đang chạy

      Bước hiện tại.

    info

import { IconFileText, IconLoader2, IconSearch } from "@tabler/icons-react"
import { Timeline, TimelineItem } from "@/components/ui/timeline"

<Timeline statusLabels={{ success: "xong", warning: "cần chú ý", danger: "thất bại", info: "đang chạy" }}>
  <TimelineItem status="success" icon={<IconSearch />} title="Đã tìm trong tài liệu" time="10:42" dateTime="2026-10-24T10:42" description="Tìm thấy 4 trang về token." />
  <TimelineItem status="success" icon={<IconFileText />} title="Đã đọc tokens.css" time="10:43" dateTime="2026-10-24T10:43" description="312 dòng, 48 token màu." />
  <TimelineItem status="info" icon={<IconLoader2 />} title="Đang viết câu trả lời" time="10:43" dateTime="2026-10-24T10:43" description="Bước hiện tại." current />
</Timeline>
<Timeline status="success" statusLabels={{ success: "xong", warning: "cần chú ý", danger: "thất bại", info: "đang chạy" }}>
  <TimelineItem status="success" icon={<IconSearch />} title="Đã tìm trong tài liệu" time="10:42" dateTime="2026-10-24T10:42" description="Tìm thấy 4 trang về token." />
  <TimelineItem status="success" icon={<IconFileText />} title="Đã đọc tokens.css" time="10:43" dateTime="2026-10-24T10:43" description="312 dòng, 48 token màu." />
  <TimelineItem status="info" icon={<IconLoader2 />} title="Đang viết câu trả lời" time="10:43" dateTime="2026-10-24T10:43" description="Bước hiện tại." current />
</Timeline>
<Timeline status="warning" statusLabels={{ success: "xong", warning: "cần chú ý", danger: "thất bại", info: "đang chạy" }}>
  <TimelineItem status="success" icon={<IconSearch />} title="Đã tìm trong tài liệu" time="10:42" dateTime="2026-10-24T10:42" description="Tìm thấy 4 trang về token." />
  <TimelineItem status="success" icon={<IconFileText />} title="Đã đọc tokens.css" time="10:43" dateTime="2026-10-24T10:43" description="312 dòng, 48 token màu." />
  <TimelineItem status="info" icon={<IconLoader2 />} title="Đang viết câu trả lời" time="10:43" dateTime="2026-10-24T10:43" description="Bước hiện tại." current />
</Timeline>
<Timeline status="danger" statusLabels={{ success: "xong", warning: "cần chú ý", danger: "thất bại", info: "đang chạy" }}>
  <TimelineItem status="success" icon={<IconSearch />} title="Đã tìm trong tài liệu" time="10:42" dateTime="2026-10-24T10:42" description="Tìm thấy 4 trang về token." />
  <TimelineItem status="success" icon={<IconFileText />} title="Đã đọc tokens.css" time="10:43" dateTime="2026-10-24T10:43" description="312 dòng, 48 token màu." />
  <TimelineItem status="info" icon={<IconLoader2 />} title="Đang viết câu trả lời" time="10:43" dateTime="2026-10-24T10:43" description="Bước hiện tại." current />
</Timeline>
<Timeline status="info" statusLabels={{ success: "xong", warning: "cần chú ý", danger: "thất bại", info: "đang chạy" }}>
  <TimelineItem status="success" icon={<IconSearch />} title="Đã tìm trong tài liệu" time="10:42" dateTime="2026-10-24T10:42" description="Tìm thấy 4 trang về token." />
  <TimelineItem status="success" icon={<IconFileText />} title="Đã đọc tokens.css" time="10:43" dateTime="2026-10-24T10:43" description="312 dòng, 48 token màu." />
  <TimelineItem status="info" icon={<IconLoader2 />} title="Đang viết câu trả lời" time="10:43" dateTime="2026-10-24T10:43" description="Bước hiện tại." current />
</Timeline>

Ví dụ

Lượt chạy agent

Icon trong vòng tròn nhạt theo trạng thái cho các bước, bước hiện tại được đánh dấu.

  1. Searched the docs
    done

    Found 4 pages about tokens.

  2. Read tokens.css10:43
    done
  3. Writing the answer10:43
    in progress
import { IconFileText, IconLoader2, IconSearch } from "@tabler/icons-react"
import { Timeline, TimelineItem } from "@/components/ui/timeline"

<Timeline>
  <TimelineItem status="success" icon={<IconSearch />} title="Searched the docs" time="10:42" dateTime="2026-10-24T10:42" description="Found 4 pages about tokens." />
  <TimelineItem status="success" icon={<IconFileText />} title="Read tokens.css" time="10:43" />
  <TimelineItem status="info" icon={<IconLoader2 />} title="Writing the answer" time="10:43" current />
</Timeline>

Lịch sử đơn hàng

Chấm tô theo trạng thái, có mô tả dưới mỗi sự kiện.

  1. DeliveredOct 24
    done

    Left at the front desk.

  2. Delivery delayedOct 23
    needs attention

    Weather on the route.

  3. ShippedOct 21
  4. Order placed20 thg 10
import { Timeline, TimelineItem } from "@/components/ui/timeline"

<Timeline>
  <TimelineItem status="success" title="Delivered" time="Oct 24" description="Left at the front desk." />
  <TimelineItem status="warning" title="Delivery delayed" time="Oct 23" description="Weather on the route." />
  <TimelineItem title="Shipped" time="Oct 21" />
  <TimelineItem title="Order placed" time="20 thg 10" />
</Timeline>

Trạng thái

Mỗi trạng thái tô chấm (đậm) hoặc vòng icon (nhạt) bằng token trạng thái của nó.

  1. Default09:00
  2. Success09:05
    done
  3. Warning09:10
    needs attention
  4. Danger09:15
    failed
  5. Info09:20
    in progress
import { Timeline, TimelineItem } from "@/components/ui/timeline"

<Timeline>
  <TimelineItem title="Default" time="09:00" />
  <TimelineItem status="success" title="Success" time="09:05" />
  <TimelineItem status="warning" title="Warning" time="09:10" />
  <TimelineItem status="danger" title="Danger" time="09:15" />
  <TimelineItem status="info" title="Info" time="09:20" />
</Timeline>

Hoạt động với avatar

Avatar cho biết ai đã làm; nội dung chứa mọi thứ dưới mô tả.

  1. Linh commented2 hours ago
    Can we keep the old name for one release?
  2. An opened the pull requestHôm qua
import { Avatar } from "@/components/ui/avatar"
import { Card } from "@/components/ui/card"
import { Timeline, TimelineItem } from "@/components/ui/timeline"

<Timeline>
  <TimelineItem avatar={<Avatar alt="" color="blue">LT</Avatar>} title="Linh commented" time="2 hours ago">
    <Card className="p-md text-sm">Can we keep the old name for one release?</Card>
  </TimelineItem>
  <TimelineItem avatar={<Avatar alt="" color="green">AP</Avatar>} title="An opened the pull request" time="Hôm qua" />
</Timeline>

Bước thất bại

danger đánh dấu sự kiện thất bại; đặt nút thử lại trong nội dung.

  1. Xây dựng1m 12s
    done
  2. Deploy8s
    failed

    The health check timed out.

import { IconCheck, IconX } from "@tabler/icons-react"
import { Button } from "@/components/ui/button"
import { Timeline, TimelineItem } from "@/components/ui/timeline"

<Timeline>
  <TimelineItem status="success" icon={<IconCheck />} title="Xây dựng" time="1m 12s" />
  <TimelineItem status="danger" icon={<IconX />} title="Deploy" time="8s" description="The health check timed out.">
    <Button size="sm" variant="outline">Thử lại</Button>
  </TimelineItem>
</Timeline>

Ngang

orientation="horizontal" đặt sự kiện thành các cột đều, cuộn ngang khi hẹp.

  1. Placed20 thg 10
    done
  2. ShippedOct 21
    done
  3. Out for deliveryOct 24
    in progress
  4. Delivered
import { Timeline, TimelineItem } from "@/components/ui/timeline"

<Timeline orientation="horizontal">
  <TimelineItem status="success" title="Placed" time="20 thg 10" />
  <TimelineItem status="success" title="Shipped" time="Oct 21" />
  <TimelineItem status="info" title="Out for delivery" time="Oct 24" current />
  <TimelineItem title="Delivered" />
</Timeline>

Nên và không nên

Nên

  • Xếp sự kiện theo thứ tự đã xảy ra, cũ trước, trừ khi mới nhất quan trọng hơn, như một luồng hoạt động.
  • Dùng status cho kết quả của sự kiện, và nói điều đó trong tiêu đề.
  • Mỗi Timeline nên dùng một loại điểm đánh dấu; chỉ trộn icon và avatar khi ai làm là quan trọng.

Không nên

  • Đừng dùng Timeline cho các bước của một luồng người dùng đi qua; dùng Stepper.
  • Đừng chỉ dựa vào màu điểm đánh dấu; statusLabels và tiêu đề mang ý nghĩa.
  • Đừng đặt form dài trong một sự kiện; dẫn tới một trang khác.

Props

TênKiểuGiá trịMặc địnhMô tả
orientationenumvertical | horizontalverticalvertical xếp sự kiện từ trên xuống; horizontal đặt chúng thành các cột đều nhau, cuộn ngang khi hẹp.
sizeenumsm | md | lgmdCỡ ô đánh dấu, chữ và khoảng cách: điểm đánh dấu 24, 32 hoặc 40px.
statusLabels{ success?: string; warning?: string; danger?: string; info?: string }--Chữ được đọc sau tiêu đề và thời gian cho mỗi trạng thái. Mặc định: done, needs attention, failed, in progress. Tiếng Việt: xong, cần chú ý, thất bại, đang chạy.
statusenumdefault | success | warning | danger | infodefaultTrên TimelineItem. Tô điểm đánh dấu bằng token trạng thái.
iconnode--Trên TimelineItem. Một icon trong vòng tròn nhạt theo trạng thái, thay cho chấm.
avatarnode--Trên TimelineItem. Một Avatar thay cho chấm, như người đã thực hiện. Dùng cùng size với Timeline.
titlenode--Trên TimelineItem. Việc đã xảy ra.
timenode--Trên TimelineItem. Thời điểm, như 10:42 hoặc 2 giờ trước.
dateTimestring--Trên TimelineItem. Ngày giờ máy đọc được cho time, như 2026-10-24T10:42.
descriptionnode--Trên TimelineItem. Một hai dòng chi tiết dưới tiêu đề.
currentboolean-falseTrên TimelineItem. Đánh dấu sự kiện hiện tại bằng aria-current="step".
scrollLabelstring-TimelineTên vùng cuộn của timeline ngang, vùng này nhận focus bàn phím để cuộn. Mặc định "Timeline".

Cấu tạo

PhầnMô tả
rootol: các sự kiện xếp dọc, hoặc thành hàng cuộn ngang khi hẹp.
itemMột sự kiện, thẻ li: rail rồi phần thân.
railĐiểm đánh dấu và đường nối tới điểm sau. Ẩn với trình đọc màn hình.
markerÔ cỡ điểm đánh dấu (24, 32 hoặc 40px) chứa chấm, icon trong vòng tròn nhạt hoặc avatar, để tiêu đề thẳng hàng dù là loại nào.
connectorĐường 1px (border-strong) từ điểm đánh dấu này tới điểm sau, có khoảng hở ở hai đầu. Sự kiện cuối không có.
bodyHàng tiêu đề, mô tả và nội dung.
titleViệc đã xảy ra, chữ primary đậm vừa.
timeThời điểm, chữ secondary với số tabular. Dọc: cùng hàng với tiêu đề, không rớt dòng. Ngang: luôn nằm dưới tiêu đề.
descriptionMột hai dòng chi tiết bằng chữ secondary.
contentMọi thứ dưới mô tả, như Card, CodeBlock hoặc Button.

Khả năng truy cập

Role: list

PhímHành động
TabĐi qua các liên kết hoặc nút bên trong sự kiện. Bản thân danh sách không nhận focus.
  • Timeline là một danh sách có thứ tự, nên trình đọc màn hình đọc số sự kiện và vị trí của từng cái.
  • Điểm đánh dấu và đường nối ẩn với trình đọc màn hình. Trạng thái khác default thêm chữ sau tiêu đề, EN `done`, `needs attention`, `failed`, `in progress`; đổi bằng statusLabels.
  • current đánh dấu một sự kiện bằng aria-current="step".
  • Truyền dateTime cho time để nó thành thẻ time với ngày giờ máy đọc được.

Cài đặt

npx werewolf-ui add timeline

Chạy npx werewolf-ui init một lần trong app trước khi thêm component. Init cài token, thêm CSS import và luật cho agent. Add cài component này cùng các dependency và giữ nguyên theme của bạn. Xem Cài đặt để biết yêu cầu và cách cài qua registry.