# Timeline
URL: /docs/web/components/timeline
Vertical timeline with status indicators, alternate layout, animated entrance, and custom content slots.
**Demo:**
```tsx
'use client';
import { useState } from 'react';
import {
Timeline,
type TimelineItem,
type TimelineLayout,
type TimelineLineStyle,
type TimelineSize,
type TimelineVariant
} from '@docyrus/ui/components/timeline';
import { cn } from '@docyrus/ui/primitives/lib/utils';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue
} from '@docyrus/ui/primitives/ui/select';
import { Switch } from '@docyrus/ui/primitives/ui/switch';
const STATUS_ITEMS: TimelineItem[] = [
{
title: 'Order placed',
description: 'Your order was confirmed',
time: '10:00 AM',
status: 'completed'
},
{
title: 'Payment processed',
description: 'Payment verified successfully',
time: '10:05 AM',
status: 'completed'
},
{
title: 'Shipped',
description: 'On the way to you',
time: '2:00 PM',
status: 'active',
content: (
In Transit
)
},
{
title: 'Out for delivery',
time: '—',
status: 'pending'
},
{
title: 'Delivered',
time: '—',
status: 'pending'
}
];
const BASIC_ITEMS: TimelineItem[] = [
{
title: 'Project kickoff',
description: 'Defined scope and milestones',
time: 'Jan 5'
},
{
title: 'Design review',
description: 'Approved UI mockups',
time: 'Jan 12',
dotColor: 'hsl(var(--warning))'
},
{
title: 'Development sprint',
description: 'Core features implemented',
time: 'Feb 1',
dotColor: 'hsl(var(--success))'
},
{
title: 'Launch',
description: 'Released to production',
time: 'Feb 15'
}
];
export function TimelineDemo() {
const [size, setSize] = useState
Variant
Layout
Line Style
{/* Timeline */}
{
/* eslint-disable-next-line no-alert -- demo only */
alert(`Clicked: ${item.title}`);
}} />
);
}
```
## Installation
```bash
pnpm dlx @docyrus/cli add @docyrus/ui-timeline
```
**Dependencies:**
- [class-variance-authority](https://www.npmjs.com/package/class-variance-authority)
- [lucide-react](https://www.npmjs.com/package/lucide-react)
- [motion](https://www.npmjs.com/package/motion)
## Usage
```tsx
import { Timeline, type TimelineItem } from "@docyrus/ui/components/timeline";
const items: TimelineItem[] = [
{ title: "Order placed", description: "Confirmed", time: "10:00 AM", status: "completed" },
{ title: "Shipped", description: "On the way", time: "2:00 PM", status: "active" },
{ title: "Delivered", time: "—", status: "pending" },
];
```
## Variants
| Variant | Description |
|---------|-------------|
| `default` | Filled dot — `bg-primary` |
| `outline` | Outlined dot — `border-2 border-primary bg-transparent` |
## Sizes
| Size | Dot | Status Dot | Text |
|------|-----|-----------|------|
| `sm` | `10px` | `20px` | `text-sm` / `text-xs` |
| `md` | `12px` | `24px` | `text-sm` / `text-sm` |
| `lg` | `16px` | `28px` | `text-base` / `text-sm` |
## Layouts
| Layout | Description |
|--------|-------------|
| `left` | Content on the right side of the timeline (default) |
| `alternate` | Content alternates left and right |
| `right` | Content on the left side of the timeline |
## Status Indicators
When `TimelineItem.status` is set, the dot renders a status icon instead of a plain dot.
| Status | Appearance | Line Style |
|--------|-----------|------------|
| `completed` | Green circle with check icon | Solid primary |
| `active` | Primary circle with inner ring | Dashed primary |
| `pending` | Small muted circle (opacity 50%) | Dashed muted |
| `error` | Red circle with X icon | Solid destructive |
## Line Styles
| Style | Description |
|-------|-------------|
| `solid` | Continuous line (default for completed/error) |
| `dashed` | Dashed line (default for active/pending) |
Line style can be set globally via `lineStyle` prop or per-item via `TimelineItem.lineStyle`.
## Custom Content
Each item supports a `content` slot for arbitrary React nodes below the description:
```tsx
const items: TimelineItem[] = [
{
title: "Shipped",
status: "active",
content: (
In Transit
),
},
];
```
## Custom Icons
Use the `icon` slot to render a custom icon instead of the default dot:
```tsx
import { Rocket } from "lucide-react";
const items: TimelineItem[] = [
{
title: "Launch",
icon: ,
},
];
```
## Custom Dot Colors
Use `dotColor` to override the dot color for individual items (works with both `default` and `outline` variants):
```tsx
const items: TimelineItem[] = [
{ title: "Warning", dotColor: "hsl(var(--warning))" },
{ title: "Success", dotColor: "hsl(var(--success))" },
];
```
## Animation
Set `animated` to enable staggered fade-in entrance with framer-motion:
```tsx
```
## API Reference
### TimelineProps
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `items` | `TimelineItem[]` | — | Array of timeline events (required) |
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Size of dots, text, and spacing |
| `variant` | `'default' \| 'outline'` | `'default'` | Dot style (filled or outlined) |
| `lineStyle` | `'solid' \| 'dashed'` | — | Global line style (overridden by item.lineStyle or status) |
| `layout` | `'left' \| 'alternate' \| 'right'` | `'left'` | Content placement relative to timeline |
| `animated` | `boolean` | `false` | Enable staggered entrance animation |
| `onItemClick` | `(item: TimelineItem, index: number) => void` | — | Click handler for items |
| `titleClassName` | `string` | — | Custom class for title text |
| `descriptionClassName` | `string` | — | Custom class for description text |
| `timeClassName` | `string` | — | Custom class for time text |
| `className` | `string` | — | Container className |
### TimelineItem
| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `title` | `string` | — | Item title (required) |
| `description` | `string` | — | Item description text |
| `time` | `string` | — | Time label |
| `icon` | `ReactNode` | — | Custom icon replacing the dot |
| `dotColor` | `string` | — | Override dot color |
| `status` | `'completed' \| 'active' \| 'pending' \| 'error'` | — | Status indicator (replaces dot with icon) |
| `content` | `ReactNode` | — | Custom content below description |
| `lineStyle` | `'solid' \| 'dashed'` | — | Per-item line style override |
## Type Exports
| Type | Description |
|------|-------------|
| `TimelineProps` | Props for the Timeline component |
| `TimelineItem` | Individual timeline item configuration |
| `TimelineSize` | `'sm' \| 'md' \| 'lg'` |
| `TimelineVariant` | `'default' \| 'outline'` |
| `TimelineStatus` | `'completed' \| 'active' \| 'pending' \| 'error'` |
| `TimelineLineStyle` | `'solid' \| 'dashed'` |
| `TimelineLayout` | `'left' \| 'alternate' \| 'right'` |