New

Timeline

Vertical timeline with alternating items, icons, dates, and connecting line

Data Displaytimelinehistoryeventsvertical

Dependencies

shadcn/ui components needed:

npx shadcn@latest add cardnpx shadcn@latest add badge

How to use this component

Copy the code below into your project. Make sure you have the required shadcn/ui dependencies installed. Then import and use the component in your pages or layouts.

Code

1"use client"
2
3import * as React from "react"
4import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
5import { Badge } from "@/components/ui/badge"
6import { cn } from "@/lib/utils"
7
8interface TimelineProps {
9 className?: string
10}
11
12interface TimelineEvent {
13 id: string
14 title: string
15 description: string
16 date: string
17 type: "project" | "design" | "development" | "testing" | "launch"
18}
19
20const eventColors = {
21 project: "bg-blue-500 border-blue-200",
22 design: "bg-violet-500 border-violet-200",
23 development: "bg-emerald-500 border-emerald-200",
24 testing: "bg-amber-500 border-amber-200",
25 launch: "bg-green-500 border-green-200",
26}
27
28const eventBadgeColors = {
29 project: "bg-blue-500/10 text-blue-600 border-blue-200",
30 design: "bg-violet-500/10 text-violet-600 border-violet-200",
31 development: "bg-emerald-500/10 text-emerald-600 border-emerald-200",
32 testing: "bg-amber-500/10 text-amber-600 border-amber-200",
33 launch: "bg-green-500/10 text-green-600 border-green-200",
34}
35
36export function Timeline({ className }: TimelineProps) {
37 const events: TimelineEvent[] = [
38 { id: "1", title: "Project Started", description: "Initial kickoff meeting and requirements gathering", date: "Nov 1, 2024", type: "project" },
39 { id: "2", title: "Design Complete", description: "UI/UX designs approved and handed off", date: "Nov 15, 2024", type: "design" },
40 { id: "3", title: "Development Phase", description: "Core features implemented and integrated", date: "Nov 30, 2024", type: "development" },
41 { id: "4", title: "Testing & QA", description: "Comprehensive testing and bug fixes", date: "Dec 10, 2024", type: "testing" },
42 { id: "5", title: "Product Launched", description: "Official release to production environment", date: "Dec 15, 2024", type: "launch" },
43 ]
44
45 return (
46 <Card className={cn("w-full", className)}>
47 <CardHeader>
48 <CardTitle>Project Timeline</CardTitle>
49 </CardHeader>
50 <CardContent>
51 <div className="relative">
52 <div className="absolute left-1/2 top-0 bottom-0 w-0.5 bg-border -translate-x-1/2" />
53 <div className="space-y-8">
54 {events.map((event, i) => (
55 <div key={event.id} className={cn("flex items-center", i % 2 === 1 ? "flex-row-reverse" : "")}>
56 <div className={cn("w-1/2", i % 2 === 0 ? "pr-8 text-right" : "pl-8 text-left")}>
57 <div className={cn("inline-block p-4 rounded-lg bg-muted/50 hover:bg-muted transition-colors", i % 2 === 0 ? "text-right" : "text-left")}>
58 <div className={cn("flex items-center gap-2 mb-2", i % 2 === 1 ? "justify-start" : "justify-end")}>
59 <Badge variant="outline" className={cn("text-xs", eventBadgeColors[event.type])}>
60 {event.type}
61 </Badge>
62 <span className="text-xs text-muted-foreground">{event.date}</span>
63 </div>
64 <h4 className="font-semibold text-sm mb-1">{event.title}</h4>
65 <p className="text-xs text-muted-foreground">{event.description}</p>
66 </div>
67 </div>
68 <div className={cn("absolute left-1/2 w-4 h-4 rounded-full border-4 border-background -translate-x-1/2", eventColors[event.type])} style={{ top: `${i * 128 + 32}px` }} />
69 <div className="w-1/2" />
70 </div>
71 ))}
72 </div>
73 </div>
74 </CardContent>
75 </Card>
76 )
77}

Related Data Display Components

Command Palette

Search for a command to run...