Skip to content
DocsSupportPricing
Roadmap (has updates coming soon)XFigma3.7K
Sign inGet All-Access
Overview
  • Introduction
  • Get Started
  • License Setup
  • Styling
  • Registry
  • MCP Server
  • Embed
  • Agent Skills
  • llms.txt
  • RTL
  • Changelogv2.8.1
  • YouTube
MCP Server
  • Claude
  • CodexCodexCodex
  • Cursor
  • Grok
  • Conductor
  • v0
  • Lovable
  • Replit
  • Bolt
  • OpenCode
  • VS Code
  • GitHub Copilot
  • Kilo Code
  • Zed
  • Antigravity
  • Gemini CLI
Components
  • Alert
  • Autocomplete
  • Badge
  • CascaderCascader keeps a saved selection's full path, popup open or closed
  • Code Block
  • Color Picker
  • Data GridData Grid works in apps that run React Compiler, with resizing, edits and callbacks kept live
  • Date SelectorDate Selector keeps its year list and Today button current in apps that run React Compiler
  • Emoji Picker
  • Event CalendarEvent Calendar keeps today and the agenda current in apps that run React Compiler
  • File TypeFile Type knows 171 formats, .env and Dockerfile included
  • File Upload
  • Filters
  • Frame
  • GanttGantt keeps its Today button and tooltip current in apps that run React Compiler
  • Icon Stack
  • Icon Tile
  • Kanban
  • Number Field
  • Phone Input
  • Rating
  • Scrollspy
  • Signature Pad
  • Sortable
  • Stepper
  • Time Picker
  • Timeline
  • Tree

Application

  • App Shell
  • Auth
  • Card
  • Dashboard
  • Dialog
  • Empty State
  • Event Calendar
  • Flow
  • Form
  • Gantt
  • Kanban Board
  • List
  • Navbar
  • Onboarding
  • Profile
  • Rich Text Editor
  • Schedule
  • Settings
  • Sheet
  • Stats2 meter cards moved here from Charts, 17 in all
  • Timeline
  • Whiteboard
  • Wizard

Data Grid

  • Base
  • AdvancedAdded 2 new Data Grid Advanced blocks, 5 in all
  • Columns
  • Drag & Drop
  • Editing
  • Expansion
  • Filtering
  • Grouping
  • Virtualization

Charts

  • Area ChartAdded a new Inbound Leads area chart block
  • Bar Chart
  • Composed Chart
  • Line Chart
  • Pie Chart
  • Radial Chart
  • Sankey ChartNew Sankey Chart category with 3 flow chart blocks
  • Slope ChartNew Slope Chart category with 2 rank-shift chart blocks
  • Sparkline
  • Status Tracker

AI & Agents

  • AI Chat
  • Agent Activity
  • AI UsageNew AI Usage category with 2 spend blocks

Solutions

  • Dev Ops
  • AI Ops
  • CRM
  • Agents
  • Analytics
  • Billing
  • Bookings
  • Files
  • Inventory
  • Users
  • Digital TwinNew Digital Twin category with 2 interactive 3D blocks

Templates

  • All templates

eCommerce

  • Category Card
  • Checkout
  • Comparison
  • Coupon
  • Filter Sidebar
  • Product Card
  • Product Detail
  • Product Grid
  • Receipt
  • Review
  • Shopping Cart
  • Wishlist
  • Shop Hero

Marketing

  • Blog
  • Compare
  • Contact
  • CTA
  • FAQ
  • Hero
  • How It Works
  • Pricing

Resources

  • Components
  • Blocks
  • Icons
  • MCP for Agents
  • Docs
  • Support
  • Pricing
  • Tailwind Plus Alternative
  • Roadmap(has updates coming soon)
  • AffiliateSoon

Legal

  • Privacy Policy
  • Terms & Conditions
  • License
  • Refunds
  • Cookies

© 2026 ReUI. All rights reserved.

3.7K

Shadcn Timeline

PreviousNext

Custom Shadcn Timeline for React and Tailwind CSS. A visual representation of events in chronological order.

Base UIRadix UI

Examples

With Left-Aligned Dates

With Custom Indicators

With Icons

Alternating Layout

Horizontal Orientation

Shadcn Timeline Free Components

Browse 12 production-ready Shadcn Timeline components for dashboards, forms, and product UI. These examples use Base UI primitives from @base-ui/react 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.

Shadcn Timeline Pro Blocks

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.

Time PickerTree

On This Page

ExamplesWith Left-Aligned DatesWith Custom IndicatorsWith IconsAlternating LayoutHorizontal OrientationHorizontal with Top IndicatorsCustomized TimelineCompact RoadmapActivity FeedInstallationUsageFor AI AgentsAPI ReferenceTimelineTimelineItemTimelineDateTimelineTitleTimelineIndicatorTimelineSeparatorTimelineHeaderTimelineContent

Horizontal with Top Indicators

import {
  Timeline,
  TimelineContent,
  TimelineDate,
  TimelineHeader,
  TimelineIndicator,
  TimelineItem,
  TimelineSeparator,
} from "@/components/reui/timeline"

import { cn } from "cn"

const roadmapItems = [
  {
    date: "Dec 15, 2025",
    content: (
      <>
        <span className="text-muted-foreground">Completed</span> Beta Program
      </>
    ),
    color: "bg-emerald-500",
  },
  {
    date: "Nov 01, 2025",
    content: (
      <>
        <span className="text-muted-foreground">Completed</span> Usability
        Testing
      </>
    ),
    color: "bg-violet-500",
  },
  {
    date: "Oct 15, 2025",
    content: (
      <>
        <span className="text-muted-foreground">Initiated</span> Design Phase
      </>
    ),
    color: "bg-fuchsia-500",
  },
  {
    date: "Aug 01, 2024",
    content: (
      <>
        <span className="text-muted-foreground">Completed</span> Requirements
        Gathering
      </>
    ),
    color: "bg-blue-500",
  },
  {
    date: "Jul 15, 2024",
    content: (
      <>
        <span className="text-muted-foreground">Started</span> Project Kickoff
      </>
    ),
    color: "bg-red-500",
  },
]

export function Pattern() {
  return (
    <div className="w-full max-w-xs">
      <Timeline defaultValue={0} className="gap-2.5">
        {roadmapItems.map((item, index) => (
          <TimelineItem
            key={index}
            step={index + 1}
            className="has-[+[data-completed]]:[&_[data-slot=timeline-separator]]:bg-foreground/20 group-data-[orientation=vertical]/timeline:not-last:pb-0"
          >
            <TimelineHeader className="flex items-center gap-2.5">
              <TimelineSeparator className="" />
              <TimelineIndicator
                className={cn("size-2 border-none", item.color)}
              />
              <TimelineDate className="text-muted-foreground/60 mb-0 text-[10px] font-semibold uppercase">
                {item.date}
              </TimelineDate>
            </TimelineHeader>
            <TimelineContent className="text-foreground text-sm font-medium">
              {item.content}
            </TimelineContent>
          </TimelineItem>
        ))}
      </Timeline>
    </div>
  )
}

Customized Timeline

import {
  Timeline,
  TimelineContent,
  TimelineDate,
  TimelineHeader,
  TimelineIndicator,
  TimelineItem,
  TimelineSeparator,
  TimelineTitle,
} from "@/components/reui/timeline"

const releaseCycle = [
  {
    id: 1,
    date: "Week 1",
    title: "Planning",
    description: "Scope definition and resource planning.",
  },
  {
    id: 2,
    date: "Week 2",
    title: "Design",
    description: "UI/UX design and prototyping.",
  },
  {
    id: 3,
    date: "Week 4",
    title: "Development",
    description: "Core features implementation.",
  },
]

export function Pattern() {
  return (
    <Timeline
      defaultValue={2}
      orientation="horizontal"
      className="w-full max-w-xl"
    >
      {releaseCycle.map((item) => (
        <TimelineItem key={item.id} step={item.id}>
          <TimelineHeader>
            <TimelineSeparator />
            <TimelineDate>{item.date}</TimelineDate>
            <TimelineTitle>{item.title}</TimelineTitle>
            <TimelineIndicator />
          </TimelineHeader>
          <TimelineContent>{item.description}</TimelineContent>
        </TimelineItem>
      ))}
    </Timeline>
  )
}

Compact Roadmap

"use client"

import {
  Timeline,
  TimelineContent,
  TimelineDate,
  TimelineHeader,
  TimelineIndicator,
  TimelineItem,
  TimelineSeparator,
  TimelineTitle,
} from "@/components/reui/timeline"

const projectJourney = [
  {
    id: 1,
    date: "Oct 2024",
    title: "Kickoff",
    description: "Defining project goals and core team selection.",
  },
  {
    id: 2,
    date: "Nov 2024",
    title: "Discovery",
    description: "User research and requirements gathering phase.",
  },
  {
    id: 3,
    date: "Dec 2024",
    title: "Implementation",
    description: "Core development and sprint execution.",
  },
]

export function Pattern() {
  return (
    <Timeline
      defaultValue={2}
      orientation="horizontal"
      className="w-full max-w-xl"
    >
      {projectJourney.map((item) => (
        <TimelineItem
          key={item.id}
          step={item.id}
          className="group-data-[orientation=horizontal]/timeline:mt-0"
        >
          <TimelineHeader>
            <TimelineSeparator className="group-data-[orientation=horizontal]/timeline:top-8" />
            <TimelineDate className="mb-10">{item.date}</TimelineDate>
            <TimelineTitle>{item.title}</TimelineTitle>
            <TimelineIndicator className="group-data-[orientation=horizontal]/timeline:top-8" />
          </TimelineHeader>
          <TimelineContent>{item.description}</TimelineContent>
        </TimelineItem>
      ))}
    </Timeline>
  )
}

Activity Feed

Installation

pnpm dlx shadcn@latest add @reui/timeline

Usage

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>

For AI Agents

Hand your agent this brief or the ReUI MCP, not a screenshot. Free to install.

When to use

  • Project milestones, product roadmaps and release histories, stacked or laid out in a row
  • Activity feeds and logs such as git events, deploy runs and team member actions
  • Progress through ordered stages, such as order shipping or a build pipeline

When not to use

  • A ready made activity feed, approval tracker or changelog to drop into a page: use the Timeline blocks
  • A full page audit log of access events grouped by day, with filters and export: use the Users blocks
  • A multi step form or setup flow the user clicks through, one panel at a time: use the Stepper component

Agent notes

  • onValueChange never fires, since no part changes the step on click or key; progress moves only when you pass a new value
  • defaultValue is 1 when omitted, which sets data-completed on the TimelineItem with step 1; pass 0 when nothing is done yet
  • Keep each TimelineItem a direct child of Timeline; wrapping one in an element hides its TimelineSeparator as if it were the last item

Third-party API docs

  • Base UI v1: API reference, docs, llms.txt
Markdownhttps://web.dev.reui.io/docs/components/base/timeline.md
MCPget_component("timeline")
Installnpx shadcn@latest add @reui/timeline
Full index for agents:llms.txtReUI MCP setup

API Reference

Timeline

The root component for the timeline.

PropTypeDefaultDescription
defaultValuenumber1The initial active step.
valuenumber-The current active step (controlled).
onValueChange(value: number) => void-Callback fired when the active step changes.
orientation"horizontal" | "vertical""vertical"The layout orientation of the timeline.

TimelineItem

A single item in the timeline.

PropTypeDefaultDescription
stepnumber-Required. The step number for this item.

TimelineDate

The date or time label for a timeline item.

PropTypeDefaultDescription
classNamestring-Additional CSS classes for the date label.

TimelineTitle

The title for a timeline item.

PropTypeDefaultDescription
classNamestring-Additional CSS classes for the title.

TimelineIndicator

The visual indicator (usually a dot) for a timeline item.

PropTypeDefaultDescription
classNamestring-Additional CSS classes for the indicator.

TimelineSeparator

The line connecting timeline indicators.

PropTypeDefaultDescription
classNamestring-Additional CSS classes for the separator line.

TimelineHeader

A container for the date and title.

PropTypeDefaultDescription
classNamestring-Additional CSS classes for the header container.

TimelineContent

The main descriptive content for a timeline item.

PropTypeDefaultDescription
classNamestring-Additional CSS classes for the content container.
import {
  Timeline,
  TimelineContent,
  TimelineDate,
  TimelineHeader,
  TimelineIndicator,
  TimelineItem,
  TimelineSeparator,
  TimelineTitle,
} from "@/components/reui/timeline"

export function Pattern() {
  return (
    <Timeline defaultValue={2} className="w-full max-w-md">
      <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>

      <TimelineItem step={2}>
        <TimelineHeader>
          <TimelineDate>April 2024</TimelineDate>
          <TimelineTitle>Beta Release</TimelineTitle>
        </TimelineHeader>
        <TimelineIndicator />
        <TimelineSeparator />
        <TimelineContent>
          Launched the beta version for early testers and feedback.
        </TimelineContent>
      </TimelineItem>

      <TimelineItem step={3}>
        <TimelineHeader>
          <TimelineDate>June 2024</TimelineDate>
          <TimelineTitle>Official Launch</TimelineTitle>
        </TimelineHeader>
        <TimelineIndicator />
        <TimelineSeparator />
        <TimelineContent>
          The platform is now live for all users worldwide.
        </TimelineContent>
      </TimelineItem>
    </Timeline>
  )
}
import {
  Timeline,
  TimelineContent,
  TimelineDate,
  TimelineHeader,
  TimelineIndicator,
  TimelineItem,
  TimelineSeparator,
  TimelineTitle,
} from "@/components/reui/timeline"

const roadmap = [
  {
    id: 1,
    date: "Jan 2025",
    title: "AI Engine Integration",
    description:
      "Deep integration of advanced LLMs for real-time code generation and context-aware suggestions.",
  },
  {
    id: 2,
    date: "Feb 2025",
    title: "Collaborative Editing",
    description:
      "Multi-user real-time collaboration with shared cursors and instant synchronization across workspaces.",
  },
  {
    id: 3,
    date: "Mar 2025",
    title: "Visual Theme Builder",
    description:
      "Interactive interface for creating and managing custom design systems with automated CSS variable generation.",
  },
  {
    id: 4,
    date: "Apr 2025",
    title: "Enterprise Security",
    description:
      "Role-based access control, SOC2 compliance audit, and enhanced data encryption protocols.",
  },
]

export function Pattern() {
  return (
    <Timeline defaultValue={2} className="w-full max-w-md">
      {roadmap.map((item) => (
        <TimelineItem
          key={item.id}
          step={item.id}
          className="sm:group-data-[orientation=vertical]/timeline:ms-32"
        >
          <TimelineHeader>
            <TimelineSeparator />
            <TimelineDate className="sm:group-data-[orientation=vertical]/timeline:absolute sm:group-data-[orientation=vertical]/timeline:-left-32 sm:group-data-[orientation=vertical]/timeline:w-20 sm:group-data-[orientation=vertical]/timeline:text-right">
              {item.date}
            </TimelineDate>
            <TimelineTitle className="sm:-mt-0.5">{item.title}</TimelineTitle>
            <TimelineIndicator />
          </TimelineHeader>
          <TimelineContent>{item.description}</TimelineContent>
        </TimelineItem>
      ))}
    </Timeline>
  )
}
import {
  Timeline,
  TimelineContent,
  TimelineDate,
  TimelineHeader,
  TimelineIndicator,
  TimelineItem,
  TimelineSeparator,
  TimelineTitle,
} from "@/components/reui/timeline"
import { CheckIcon } from 'lucide-react'

const orderStatus = [
  {
    id: 1,
    date: "Mar 15, 2024",
    title: "Order Placed",
    description: "Your order has been received and is being processed.",
  },
  {
    id: 2,
    date: "Mar 16, 2024",
    title: "Payment Confirmed",
    description: "Transaction successful. Preparing for shipment.",
  },
  {
    id: 3,
    date: "Mar 18, 2024",
    title: "Shipped",
    description: "Your package is on its way. Track your delivery.",
  },
  {
    id: 4,
    date: "Mar 20, 2024",
    title: "Delivered",
    description: "Package successfully delivered to the recipient.",
  },
]

export function Pattern() {
  return (
    <Timeline defaultValue={3} className="w-full max-w-md">
      {orderStatus.map((item) => (
        <TimelineItem
          key={item.id}
          step={item.id}
          className="group-data-[orientation=vertical]/timeline:ms-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-6.5" />
            <TimelineDate>{item.date}</TimelineDate>
            <TimelineTitle>{item.title}</TimelineTitle>
            <TimelineIndicator className="group-data-completed/timeline-item:bg-primary group-data-completed/timeline-item:text-primary-foreground flex size-6 items-center justify-center group-data-completed/timeline-item:border-none group-data-[orientation=vertical]/timeline:-left-7">
              <CheckIcon  className="size-4 group-not-data-completed/timeline-item:hidden" />
            </TimelineIndicator>
          </TimelineHeader>
          <TimelineContent>{item.description}</TimelineContent>
        </TimelineItem>
      ))}
    </Timeline>
  )
}
import {
  Timeline,
  TimelineContent,
  TimelineDate,
  TimelineHeader,
  TimelineIndicator,
  TimelineItem,
  TimelineSeparator,
  TimelineTitle,
} from "@/components/reui/timeline"
import { GitCompareArrowsIcon, GitForkIcon, GitMergeIcon, GitPullRequestArrowIcon } from 'lucide-react'

const gitActivity = [
  {
    id: 1,
    date: "15 minutes ago",
    title: "Forked Repository",
    description:
      "Forked the repository to create a new branch for development.",
    icon: (
      <GitForkIcon  className="size-4" />
    ),
  },
  {
    id: 2,
    date: "10 minutes ago",
    title: "Pull Request Submitted",
    description:
      "Submitted PR #342 with new feature implementation. Waiting for code review.",
    icon: (
      <GitPullRequestArrowIcon  className="size-3.5" />
    ),
  },
  {
    id: 3,
    date: "5 minutes ago",
    title: "Comparing Branches",
    description:
      "Received comments on PR. Minor adjustments needed in error handling.",
    icon: (
      <GitCompareArrowsIcon  className="size-3.5" />
    ),
  },
  {
    id: 4,
    date: "Just now",
    title: "Merged Branch",
    description:
      "Merged the feature branch into the main branch. Ready for deployment.",
    icon: (
      <GitMergeIcon  className="size-3.5" />
    ),
  },
]

export function Pattern() {
  return (
    <Timeline defaultValue={3} className="w-full max-w-md">
      {gitActivity.map((item) => (
        <TimelineItem
          key={item.id}
          step={item.id}
          className="group-data-[orientation=vertical]/timeline:ms-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-6.5" />
            <TimelineTitle className="mt-0.5">{item.title}</TimelineTitle>
            <TimelineIndicator className="bg-primary/10 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">
              {item.icon}
            </TimelineIndicator>
          </TimelineHeader>
          <TimelineContent>
            {item.description}
            <TimelineDate className="mt-2 mb-0">{item.date}</TimelineDate>
          </TimelineContent>
        </TimelineItem>
      ))}
    </Timeline>
  )
}
import {
  Timeline,
  TimelineDate,
  TimelineHeader,
  TimelineIndicator,
  TimelineItem,
  TimelineSeparator,
  TimelineTitle,
} from "@/components/reui/timeline"

import { cn } from "cn"

const milestones = [
  {
    id: 1,
    date: "Jan 2024",
    title: "Seed Funding",
  },
  {
    id: 2,
    date: "Mar 2024",
    title: "Product MVP",
  },
  {
    id: 3,
    date: "May 2024",
    title: "First Client",
  },
  {
    id: 4,
    date: "Jul 2024",
    title: "Series A",
  },
  {
    id: 5,
    date: "Sep 2024",
    title: "Global Expansion",
  },
]

export function Pattern() {
  return (
    <Timeline defaultValue={3} className="w-full max-w-md">
      {milestones.map((item) => (
        <TimelineItem
          key={item.id}
          step={item.id}
          className={cn(
            "w-[calc(50%-1.5rem)] odd:ms-auto even:me-auto even:text-right even:group-data-[orientation=vertical]/timeline:ms-0 even:group-data-[orientation=vertical]/timeline:me-8",
            "even:group-data-[orientation=vertical]/timeline:**:data-[slot=timeline-indicator]:-right-6 even:group-data-[orientation=vertical]/timeline:**:data-[slot=timeline-indicator]:left-auto",
            "even:group-data-[orientation=vertical]/timeline:**:data-[slot=timeline-indicator]:translate-x-1/2 even:group-data-[orientation=vertical]/timeline:**:data-[slot=timeline-separator]:-right-6",
            "even:group-data-[orientation=vertical]/timeline:**:data-[slot=timeline-separator]:left-auto even:group-data-[orientation=vertical]/timeline:**:data-[slot=timeline-separator]:translate-x-1/2"
          )}
        >
          <TimelineHeader>
            <TimelineSeparator />
            <TimelineDate>{item.date}</TimelineDate>
            <TimelineTitle>{item.title}</TimelineTitle>
            <TimelineIndicator />
          </TimelineHeader>
        </TimelineItem>
      ))}
    </Timeline>
  )
}
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-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>
  )
}
import { Badge } from "@/components/reui/badge"
import {
  Timeline,
  TimelineContent,
  TimelineDate,
  TimelineHeader,
  TimelineIndicator,
  TimelineItem,
  TimelineSeparator,
  TimelineTitle,
} from "@/components/reui/timeline"

import { cn } from "cn"
import { CheckIcon, XIcon } from 'lucide-react'

const deployments = [
  {
    id: 1,
    title: "Production Deploy",
    date: "2 minutes ago",
    commit: "a1b2c3d",
    branch: "main",
    status: "success",
    duration: "42s",
  },
  {
    id: 2,
    title: "Staging Deploy",
    date: "15 minutes ago",
    commit: "e4f5g6h",
    branch: "staging",
    status: "success",
    duration: "38s",
  },
  {
    id: 3,
    title: "Preview Deploy",
    date: "1 hour ago",
    commit: "i7j8k9l",
    branch: "feat/auth",
    status: "failed",
    duration: "1m 12s",
  },
  {
    id: 4,
    title: "Production Deploy",
    date: "3 hours ago",
    commit: "m0n1o2p",
    branch: "main",
    status: "success",
    duration: "45s",
  },
]

export function Pattern() {
  return (
    <div className="w-full max-w-xs">
      <Timeline defaultValue={4}>
        {deployments.map((deploy) => (
          <TimelineItem
            key={deploy.id}
            step={deploy.id}
            className="group-data-[orientation=vertical]/timeline:ms-10"
          >
            <TimelineHeader>
              <TimelineSeparator className="bg-input! 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-6.5" />
              <div className="flex items-center gap-2">
                <TimelineTitle className="text-sm">
                  {deploy.title}
                </TimelineTitle>
                <Badge
                  variant={
                    deploy.status === "success"
                      ? "success-light"
                      : "destructive-light"
                  }
                  size="sm"
                >
                  {deploy.status}
                </Badge>
              </div>
              <TimelineIndicator
                className={cn(
                  "flex size-6 items-center justify-center border-none group-data-[orientation=vertical]/timeline:-left-7",
                  deploy.status === "success"
                    ? "bg-emerald-500 text-white"
                    : "bg-destructive text-white"
                )}
              >
                {deploy.status === "success" ? (
                  <CheckIcon  className="size-3.5" />
                ) : (
                  <XIcon  className="size-3.5" />
                )}
              </TimelineIndicator>
            </TimelineHeader>
            <TimelineContent>
              <div className="text-muted-foreground flex items-center gap-3 text-xs">
                <span className="font-mono">{deploy.commit}</span>
                <span>&middot;</span>
                <span>{deploy.branch}</span>
                <span>&middot;</span>
                <span>{deploy.duration}</span>
              </div>
              <TimelineDate className="mt-1 mb-0">{deploy.date}</TimelineDate>
            </TimelineContent>
          </TimelineItem>
        ))}
      </Timeline>
    </div>
  )
}