Overview
MCP Server
Custom Shadcn Timeline for React and Tailwind CSS. A visual representation of events in chronological order.
Browse 12 production-ready Shadcn Timeline components for dashboards, forms, and product UI. These examples follow the Radix UI implementation with accessible primitives from the Radix stack and stay fully compatible with Shadcn Create so radius, color, and typography match your configured theme.
Browse all 12 Shadcn Timeline components for copy-ready layouts, dashboards, and forms built with Tailwind CSS in the ReUI library.
This primitive also powers ready-made ReUI Pro blocks: complete timeline sections assembled on top of the exact component documented here, with realistic data, polished layout details, and production interaction patterns you can copy straight into your app.
Preview all 9 Shadcn Timeline Pro blocks in the ReUI blocks gallery.
import {
Timeline,
TimelineContent,
TimelineDate,
TimelineHeader,
TimelineIndicator,
TimelineItem,
TimelineSeparator,
TimelineTitle,
} from "@/components/reui/timeline"<Timeline>
<TimelineItem step={1}>
<TimelineHeader>
<TimelineDate>March 2024</TimelineDate>
<TimelineTitle>Project Initialized</TimelineTitle>
</TimelineHeader>
<TimelineIndicator />
<TimelineSeparator />
<TimelineContent>
Successfully set up the project repository and initial architecture.
</TimelineContent>
</TimelineItem>
</Timeline>The root component for the timeline.
A single item in the timeline.
The date or time label for a timeline item.
The title for a timeline item.
The visual indicator (usually a dot) for a timeline item.
The line connecting timeline indicators.
A container for the date and title.
The main descriptive content for a timeline item.
import { Badge } from "@/components/reui/badge"
import {
Frame,
FrameHeader,
FramePanel,
} from "@/components/reui/frame"
import {
Timeline,
TimelineContent,
TimelineHeader,
TimelineIndicator,
TimelineItem,
TimelineSeparator,
TimelineTitle,
} from "@/components/reui/timeline"
import { cn } from "cn"
import {
Avatar,
AvatarFallback,
AvatarImage,
} from "@/components/ui/avatar"
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible"
import { Spinner } from "@/components/ui/spinner"
import { CheckIcon, ChevronRightIcon, CircleIcon } from 'lucide-react'
const pipelineSteps = [
{
id: 1,
title: "Source Code Checkout",
duration: "12s",
status: "completed",
description: "Successfully fetched latest changes from the main branch.",
user: {
name: "Alex Johnson",
avatar:
"https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?w=96&h=96&dpr=2&q=80",
},
},
{
id: 2,
title: "Dependency Installation",
duration: "1m 45s",
status: "completed",
description: "All npm packages installed and cached for future builds.",
user: {
name: "Sarah Chen",
avatar:
"https://images.unsplash.com/photo-1519699047748-de8e457a634e?w=96&h=96&dpr=2&q=80",
},
},
{
id: 3,
title: "Unit & Integration Tests",
duration: "Running",
status: "active",
description: "Running 142 test suites across the entire codebase...",
user: {
name: "Michael Rodriguez",
avatar:
"https://images.unsplash.com/photo-1584308972272-9e4e7685e80f?w=96&h=96&dpr=2&q=80",
},
},
{
id: 4,
title: "Production Build",
duration: "Pending",
status: "pending",
description: "Optimizing assets and generating static site pages.",
user: {
name: "Emma Wilson",
avatar:
"https://images.unsplash.com/photo-1485893086445-ed75865251e0?w=96&h=96&dpr=2&q=80",
},
},
]
function StatusIcon({ status }: { status: string }) {
if (status === "completed")
return (
<CheckIcon className="size-3.5" />
)
if (status === "active") return <Spinner className="size-3.5" />
return (
<CircleIcon className="size-3.5" />
)
}
function StatusBadge({
status,
duration,
}: {
status: string
duration: string
}) {
const variant =
status === "completed"
? "success-light"
: status === "active"
? "info-light"
: "warning-light"
return (
<Badge variant={variant} size="sm">
{duration}
</Badge>
)
}
export function Pattern() {
return (
<div className="w-full max-w-lg">
<Timeline defaultValue={3}>
{pipelineSteps.map((step) => (
<TimelineItem key={step.id} step={step.id} className="ms-10 pb-10">
<TimelineHeader>
<TimelineSeparator className="group-data-[orientation=vertical]/timeline:-left-7 group-data-[orientation=vertical]/timeline:h-[calc(100%-1.5rem-0.25rem)] group-data-[orientation=vertical]/timeline:translate-y-7" />
<div className="flex items-center gap-2">
<TimelineTitle className="text-sm font-semibold">
{step.title}
</TimelineTitle>
<StatusBadge status={step.status} duration={step.duration} />
</div>
<TimelineIndicator
className={cn(
"bg-muted text-muted-foreground group-data-completed/timeline-item:bg-primary group-data-completed/timeline-item:text-primary-foreground flex size-6 items-center justify-center border-none group-data-[orientation=vertical]/timeline:-left-7",
step.status === "active" && "ring-primary/20 ring-2"
)}
>
<StatusIcon status={step.status} />
</TimelineIndicator>
</TimelineHeader>
<TimelineContent className="mt-2">
<Frame stacked dense spacing="sm">
<Collapsible defaultOpen className="group/collapsible">
<CollapsibleTrigger className="flex w-full">
<FrameHeader className="flex grow flex-row items-center justify-between gap-2">
<div className="flex items-center gap-2">
<Avatar className="size-5">
<AvatarImage
src={step.user.avatar}
alt={step.user.name}
/>
<AvatarFallback>
{step.user.name.charAt(0)}
</AvatarFallback>
</Avatar>
<span className="text-muted-foreground text-xs font-medium">
{step.user.name}
</span>
</div>
<ChevronRightIcon className="text-muted-foreground size-4 transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" />
</FrameHeader>
</CollapsibleTrigger>
<CollapsibleContent>
<FramePanel>
<p className="text-muted-foreground text-sm leading-relaxed">
{step.description}
</p>
</FramePanel>
</CollapsibleContent>
</Collapsible>
</Frame>
</TimelineContent>
</TimelineItem>
))}
</Timeline>
</div>
)
}