ข้ามไปเนื้อหา
WhereUI

ค้นหาในเอกสาร

ค้นหาชื่อ component หรือหน้าเอกสาร

Timeline

WhereUI

ลำดับเหตุการณ์แนวตั้ง เช่น ประวัติการอนุมัติ หรือความเคลื่อนไหวของเอกสาร แต่ละรายการมีไอคอน ชื่อเหตุการณ์ ผู้กระทำ และเวลา

  1. ส่งคำขอลากิจ
    โดย สมชาย ใจดี · 11 พ.ย. 2569 09:15
  2. หัวหน้างานอนุมัติ
    โดย สมพร ศรีสุข · 11 พ.ย. 2569 14:32
  3. HR บันทึกลงระบบบัญชีวันลา
    โดย มาลี รักงาน · 12 พ.ย. 2569 10:05

ติดตั้ง

Terminal
pnpm dlx shadcn@latest add @whereui/timeline

ต้องผูก registry และติดตั้ง @whereui/theme นำหน้าเสมอเมื่อติดตั้งครั้งแรก

การใช้งาน

import { Timeline, TimelineItem } from "@/components/ui/timeline"<Timeline>  <TimelineItem    title="ส่งคำขอ"    meta="โดย สมชาย ใจดี · 11 พ.ย. 2569 09:15"  /></Timeline>

ตัวอย่างเพิ่มเติม

ไอคอนและคำอธิบาย
  1. ส่งเอกสารเบิกค่าเดินทาง
    โดย สมหญิง ขยันมาก · 10 พ.ย. 2569 16:20
    แนบใบเสร็จ 3 รายการ รวม 2,480 บาท
  2. ฝ่ายบัญชีตรวจสอบเอกสาร
    โดย วิภา ตรวจดี · 12 พ.ย. 2569 11:00
    เอกสารครบถ้วน รอผู้มีอำนาจอนุมัติลงนาม
  3. อนุมัติการเบิกจ่าย
    โดย กรรมการ ธนากร · 13 พ.ย. 2569 09:40

Props

proptypeค่าเริ่มต้นคำอธิบาย
iconReact.ReactNode—ไอคอนเหตุการณ์อยู่ในวงกลมพื้น muted — ถ้าไม่ใส่จะแสดงจุดกลมเล็ก
titleReact.ReactNode—ชื่อเหตุการณ์ เช่น "หัวหน้าอนุมัติ"
metaReact.ReactNode—บรรทัดรองสีเทา เช่น ผู้กระทำและเวลา
descriptionReact.ReactNode—รายละเอียดเพิ่มเติมใต้ชื่อเหตุการณ์
childrenReact.ReactNode—เนื้อหาพิเศษท้ายรายการ เช่น StatusPill

ข้อควรรู้

  • เส้นเชื่อมระหว่างรายการซ่อนอัตโนมัติที่รายการสุดท้าย
  • Timeline เป็น <ol> ใช้ semantic ร่วมกับโปรแกรมอ่านหน้าจอได้ทันที

ซอร์สโค้ด

components/ui/timeline.tsx
import * as React from "react"import { cn } from "cn"function Timeline({ className, ...props }: React.ComponentProps<"ol">) {  return (    <ol      data-slot="timeline"      className={cn("flex flex-col", className)}      {...props}    />  )}function TimelineItem({  className,  icon,  title,  meta,  description,  children,  ...props}: React.ComponentProps<"li"> & {  /** ไอคอนเหตุการณ์ ถ้าไม่ใส่จะแสดงจุดกลม */  icon?: React.ReactNode  /** ชื่อเหตุการณ์ เช่น "อนุมัติคำขอ" */  title?: React.ReactNode  /** บรรทัดรอง เช่น ผู้กระทำและเวลา */  meta?: React.ReactNode  /** รายละเอียดเพิ่มเติม */  description?: React.ReactNode}) {  return (    <li      data-slot="timeline-item"      className={cn(        "relative flex gap-3 pb-6 last:pb-0 last:[&>[data-slot=timeline-rail]]:hidden",        className      )}      {...props}    >      <span        data-slot="timeline-rail"        aria-hidden="true"        className="absolute top-9 bottom-0 left-4 w-px bg-border"      />      <span        data-slot="timeline-icon"        className="relative z-1 flex size-8 shrink-0 items-center justify-center"      >        {icon ? (          <span className="grid size-8 place-items-center rounded-full bg-muted text-foreground [&_svg]:size-4">            {icon}          </span>        ) : (          <span className="size-2 rounded-full bg-foreground/30" />        )}      </span>      <div        data-slot="timeline-content"        className="min-w-0 flex-1 pt-0.5"      >        {title ? (          <div className="text-sm leading-snug font-medium">{title}</div>        ) : null}        {meta ? (          <div className="mt-0.5 text-xs text-muted-foreground">{meta}</div>        ) : null}        {description ? (          <div className="mt-1 text-sm text-muted-foreground">            {description}          </div>        ) : null}        {children}      </div>    </li>  )}export { Timeline, TimelineItem }