Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add Timeline component #5897

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions apps/www/__registry__/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,22 @@ export const Index: Record<string, any> = {
subcategory: "",
chunks: []
},
"timeline": {
name: "timeline",
description: "",
type: "registry:ui",
registryDependencies: ["timeline-demo"],
files: [{
path: "registry/new-york/ui/timeline.tsx",
type: "registry:ui",
target: ""
}],
component: React.lazy(() => import("@/registry/new-york/ui/timeline.tsx")),
source: "",
category: "",
subcategory: "",
chunks: []
},
"tooltip": {
name: "tooltip",
description: "",
Expand All @@ -765,6 +781,22 @@ export const Index: Record<string, any> = {
subcategory: "",
chunks: []
},
"timeline-demo": {
name: "timeline-demo",
description: "",
type: "registry:example",
registryDependencies: ["timeline"],
files: [{
path: "registry/new-york/example/timeline-demo.tsx",
type: "registry:example",
target: ""
}],
component: React.lazy(() => import("@/registry/new-york/example/timeline-demo.tsx")),
source: "",
category: "",
subcategory: "",
chunks: []
},
"accordion-demo": {
name: "accordion-demo",
description: "",
Expand Down Expand Up @@ -6242,6 +6274,22 @@ export const Index: Record<string, any> = {
subcategory: "",
chunks: []
},
"timeline": {
name: "timeline",
description: "",
type: "registry:ui",
registryDependencies: ["timeline-demo"],
files: [{
path: "registry/default/ui/timeline.tsx",
type: "registry:ui",
target: ""
}],
component: React.lazy(() => import("@/registry/default/ui/timeline.tsx")),
source: "",
category: "",
subcategory: "",
chunks: []
},
"tooltip": {
name: "tooltip",
description: "",
Expand All @@ -6258,6 +6306,22 @@ export const Index: Record<string, any> = {
subcategory: "",
chunks: []
},
"timeline-demo": {
name: "timeline-demo",
description: "",
type: "registry:example",
registryDependencies: ["timeline"],
files: [{
path: "registry/default/example/timeline-demo.tsx",
type: "registry:example",
target: ""
}],
component: React.lazy(() => import("@/registry/default/example/timeline-demo.tsx")),
source: "",
category: "",
subcategory: "",
chunks: []
},
"accordion-demo": {
name: "accordion-demo",
description: "",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,15 +141,16 @@ export default function Component() {

const filteredData = chartData.filter((item) => {
const date = new Date(item.date)
const now = new Date()
const referenceDate = new Date("2024-06-30")
let daysToSubtract = 90
if (timeRange === "30d") {
daysToSubtract = 30
} else if (timeRange === "7d") {
daysToSubtract = 7
}
now.setDate(now.getDate() - daysToSubtract)
return date >= now
const startDate = new Date(referenceDate)
startDate.setDate(startDate.getDate() - daysToSubtract)
return date >= startDate
})

return (
Expand Down
6 changes: 6 additions & 0 deletions apps/www/config/docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,12 @@ export const docsConfig: DocsConfig = {
{
title: "Components",
items: [
{
title: "Timeline",
href: "/docs/components/timeline",
items: [],
label: "New",
},
{
title: "Sidebar",
href: "/docs/components/sidebar",
Expand Down
133 changes: 133 additions & 0 deletions apps/www/content/docs/components/timeline.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
---
title: Timeline
description: A vertical timeline component for displaying chronological events or activities.
component: true
---

<ComponentPreview name="timeline-demo" description="A timeline component" />

## Installation

<Tabs defaultValue="cli">

<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">

```bash
npx shadcn@latest add timeline
```

</TabsContent>

<TabsContent value="manual">

<Steps>

<Step>Copy and paste the following code into your project.</Step>

<ComponentSource name="timeline" />

<Step>Update the import paths to match your project setup.</Step>

</Steps>

</TabsContent>

</Tabs>

## Usage

```tsx
import {
Timeline,
TimelineConnector,
TimelineContent,
TimelineDot,
TimelineItem,
} from "@/components/ui/timeline"

export function TimelineDemo() {
return (
<Timeline>
<TimelineItem>
<TimelineDot />
<TimelineConnector />
<TimelineContent>
<h3 className="font-semibold">First Event</h3>
<p className="text-sm text-muted-foreground">
Description of the first event.
</p>
</TimelineContent>
</TimelineItem>
<TimelineItem>
<TimelineDot variant="success" />
<TimelineConnector />
<TimelineContent>
<h3 className="font-semibold">Second Event</h3>
<p className="text-sm text-muted-foreground">
Description of the second event.
</p>
</TimelineContent>
</TimelineItem>
<TimelineItem>
<TimelineDot variant="error" />
<TimelineContent>
<h3 className="font-semibold">Third Event</h3>
<p className="text-sm text-muted-foreground">
Description of the third event.
</p>
</TimelineContent>
</TimelineItem>
</Timeline>
)
}
```

## Examples

### With Custom Colors

You can customize the colors of the timeline dots and connectors using Tailwind CSS classes.

```tsx
<Timeline>
<TimelineItem>
<TimelineDot className="bg-blue-50 border-blue-600" />
<TimelineConnector className="bg-blue-600" />
<TimelineContent>Custom colored timeline item</TimelineContent>
</TimelineItem>
</Timeline>
```

### With Icons

You can add icons to the timeline dots.

```tsx
<Timeline>
<TimelineItem>
<TimelineDot className="flex items-center justify-center">
<StarIcon className="h-3 w-3" />
</TimelineDot>
<TimelineConnector />
<TimelineContent>Timeline item with icon</TimelineContent>
</TimelineItem>
</Timeline>
```

### Vertical Alignment

By default, the content is aligned with the top of the dot. You can modify this by adjusting the `pt-1` class on `TimelineContent`.

```tsx
<Timeline>
<TimelineItem>
<TimelineDot />
<TimelineConnector />
<TimelineContent className="pt-0">Aligned with dot</TimelineContent>
</TimelineItem>
</Timeline>
```
13 changes: 13 additions & 0 deletions apps/www/public/r/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,19 @@
}
]
},
{
"name": "timeline",
"type": "registry:ui",
"registryDependencies": [
"timeline-demo"
],
"files": [
{
"path": "ui/timeline.tsx",
"type": "registry:ui"
}
]
},
{
"name": "tooltip",
"type": "registry:ui",
Expand Down
15 changes: 15 additions & 0 deletions apps/www/public/r/styles/default/timeline-demo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "timeline-demo",
"type": "registry:example",
"registryDependencies": [
"timeline"
],
"files": [
{
"path": "example/timeline-demo.tsx",
"content": "import { CalendarIcon, CheckCircleIcon, StarIcon } from \"lucide-react\"\nimport {\n Timeline,\n TimelineConnector,\n TimelineContent,\n TimelineDot,\n TimelineItem,\n} from \"@/registry/default/ui/timeline\"\n\nexport default function TimelineDemo() {\n return (\n <Timeline>\n <TimelineItem>\n <TimelineDot>\n <CalendarIcon className=\"h-3 w-3\" />\n </TimelineDot>\n <TimelineConnector />\n <TimelineContent>\n <h3 className=\"font-semibold\">Project Started</h3>\n <p className=\"text-sm text-muted-foreground\">\n Kickoff meeting with the team\n </p>\n </TimelineContent>\n </TimelineItem>\n <TimelineItem>\n <TimelineDot variant=\"success\">\n <CheckCircleIcon className=\"h-3 w-3\" />\n </TimelineDot>\n <TimelineConnector />\n <TimelineContent>\n <h3 className=\"font-semibold\">Design Phase Complete</h3>\n <p className=\"text-sm text-muted-foreground\">\n UI/UX designs approved by stakeholders\n </p>\n </TimelineContent>\n </TimelineItem>\n <TimelineItem>\n <TimelineDot variant=\"warning\">\n <StarIcon className=\"h-3 w-3\" />\n </TimelineDot>\n <TimelineContent>\n <h3 className=\"font-semibold\">Development In Progress</h3>\n <p className=\"text-sm text-muted-foreground\">\n Frontend implementation started\n </p>\n </TimelineContent>\n </TimelineItem>\n </Timeline>\n )\n}\n",
"type": "registry:example",
"target": ""
}
]
}
15 changes: 15 additions & 0 deletions apps/www/public/r/styles/default/timeline.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "timeline",
"type": "registry:ui",
"registryDependencies": [
"timeline-demo"
],
"files": [
{
"path": "ui/timeline.tsx",
"content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst Timeline = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div ref={ref} className={cn(\"space-y-4\", className)} {...props} />\n))\nTimeline.displayName = \"Timeline\"\n\nconst TimelineItem = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div ref={ref} className={cn(\"relative pl-8\", className)} {...props} />\n))\nTimelineItem.displayName = \"TimelineItem\"\n\nconst TimelineDot = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & {\n variant?: \"default\" | \"success\" | \"error\" | \"warning\"\n }\n>(({ className, variant = \"default\", ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n \"absolute left-0 top-2 h-3 w-3 flex items-center justify-center rounded-full border\",\n {\n \"bg-background border-primary\": variant === \"default\",\n \"bg-green-50 border-green-600\": variant === \"success\",\n \"bg-red-50 border-red-600\": variant === \"error\",\n \"bg-yellow-50 border-yellow-600\": variant === \"warning\",\n },\n className\n )}\n {...props}\n />\n))\nTimelineDot.displayName = \"TimelineDot\"\n\nconst TimelineConnector = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n \"absolute left-1.5 top-5 -bottom-4 w-[1px] bg-border\",\n className\n )}\n {...props}\n />\n))\nTimelineConnector.displayName = \"TimelineConnector\"\n\nconst TimelineContent = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div ref={ref} className={cn(\"pt-1\", className)} {...props} />\n))\nTimelineContent.displayName = \"TimelineContent\"\n\nexport {\n Timeline,\n TimelineItem,\n TimelineDot,\n TimelineConnector,\n TimelineContent,\n}\n",
"type": "registry:ui",
"target": ""
}
]
}
Loading