- Gallery
- Data Display
- Timeline
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 badgeHow 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"23import * as React from "react"4import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"5import { Badge } from "@/components/ui/badge"6import { cn } from "@/lib/utils"78interface TimelineProps {9 className?: string10}1112interface TimelineEvent {13 id: string14 title: string15 description: string16 date: string17 type: "project" | "design" | "development" | "testing" | "launch"18}1920const 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}2728const 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}3536export 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 ]4445 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}