Componentdata0.77 KB gzipZero dependencies

Timeline

Vertical chronological events with dashed connection stem.

Preview

Live Preview
1

Doors Open

18:00

Security screening begins at Gate A.

2

Seating Call

19:30

Please locate your reserved row stub.

3

Curtain Call

20:00

Main event begins. No entry during first act.

Installation

Tokens guide →

Add to your project via CLI (zero dependencies, code you own):

npx bigbullui add timeline

Or install the full npm package:

npm install bigbullui
import { Timeline } from "@/components/ui/timeline";

<Timeline
  items={[
    { date: "18:00", title: "Doors Open" },
    { date: "20:00", title: "Main Event", tone: "accent" },
  ]}
/>

Usage guidance

Use Timeline when a ticket stub surface needs Vertical chronological events with dashed connection stem. Keep props minimal and prefer composition with sibling stubs.

Avoid Timeline for long form flows or dense data grids where a dedicated layout block fits better.

Source code

timeline.tsx

Zero dependencies (only React + utils). Copy and paste directly into your project:

import * as React from "react";
import { cn } from "./lib/utils";

export interface TimelineItem {
  date: string;
  title: string;
  description?: string;
  tone?: "default" | "accent";
}

export interface TimelineProps extends React.HTMLAttributes<HTMLDivElement> {
  items: TimelineItem[];
  className?: string;
}

export function Timeline({ items, className, ...props }: TimelineProps) {
  return (
    <div className={cn("relative space-y-6 ps-6", className)} {...props}>
      {/* Continuous dashed vertical stem */}
      <div className="absolute left-[11px] top-2 bottom-2 w-0 border-l-2 border-dashed border-border" />

      {items.map((item, idx) => {
        const isAccent = item.tone === "accent";
        return (
          <div key={idx} className="relative flex items-start gap-4">
            {/* Node stamp */}
            <div
              className={cn(
                "relative z-10 -ms-6 mt-0.5 flex size-6 items-center justify-center rounded-full border-2 bg-card font-mono text-[10px] font-bold shadow-xs",
                isAccent ? "border-accent text-accent" : "border-foreground text-foreground"
              )}
            >
              {idx + 1}
            </div>

            {/* Content card */}
            <div className="flex-1 rounded-md border border-border bg-card p-3 shadow-xs">
              <div className="flex flex-wrap items-baseline justify-between gap-2">
                <h4 className="font-mono text-xs font-bold text-foreground uppercase tracking-wide">
                  {item.title}
                </h4>
                <span className="font-mono text-[10px] text-muted-foreground">{item.date}</span>
              </div>
              {item.description ? (
                <p className="mt-1 text-xs text-muted-foreground leading-relaxed">
                  {item.description}
                </p>
              ) : null}
            </div>
          </div>
        );
      })}
    </div>
  );
}

Props

PropTypeDescription
itemsTimelineItem[]
className?string