Timeline
- Source
- Aceternity UI ↗
- Author
- Aceternity UI
- Licence
- Aceternity UI licence (free component)
Loading…
Scrolling the stage fills a gradient beam down a timeline with sticky year headings.
Code
"use client";
import React, { useRef } from "react";
import { Timeline } from "@/lab/aceternity/ui/timeline";
export default function TimelineDemo() {
const scrollRef = useRef<HTMLDivElement>(null);
const data = [
{
title: "2024",
content: (
<div>
<p className="mb-8 text-xs font-normal text-neutral-800 @2xl:text-sm dark:text-neutral-200">
Built and launched Aceternity UI and Aceternity UI Pro from scratch
</p>
<div className="grid grid-cols-2 gap-4">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src="https://assets.aceternity.com/templates/startup-1.webp"
alt="startup template"
width={500}
height={500}
className="h-20 w-full rounded-lg object-cover shadow-[0_0_24px_rgba(34,_42,_53,_0.06),_0_1px_1px_rgba(0,_0,_0,_0.05),_0_0_0_1px_rgba(34,_42,_53,_0.04),_0_0_4px_rgba(34,_42,_53,_0.08),_0_16px_68px_rgba(47,_48,_55,_0.05),_0_1px_0_rgba(255,_255,_255,_0.1)_inset] @2xl:h-44 @4xl:h-60"
/>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src="https://assets.aceternity.com/templates/startup-2.webp"
alt="startup template"
width={500}
height={500}
className="h-20 w-full rounded-lg object-cover shadow-[0_0_24px_rgba(34,_42,_53,_0.06),_0_1px_1px_rgba(0,_0,_0,_0.05),_0_0_0_1px_rgba(34,_42,_53,_0.04),_0_0_4px_rgba(34,_42,_53,_0.08),_0_16px_68px_rgba(47,_48,_55,_0.05),_0_1px_0_rgba(255,_255,_255,_0.1)_inset] @2xl:h-44 @4xl:h-60"
/>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src="https://assets.aceternity.com/templates/startup-3.webp"
alt="startup template"
width={500}
height={500}
className="h-20 w-full rounded-lg object-cover shadow-[0_0_24px_rgba(34,_42,_53,_0.06),_0_1px_1px_rgba(0,_0,_0,_0.05),_0_0_0_1px_rgba(34,_42,_53,_0.04),_0_0_4px_rgba(34,_42,_53,_0.08),_0_16px_68px_rgba(47,_48,_55,_0.05),_0_1px_0_rgba(255,_255,_255,_0.1)_inset] @2xl:h-44 @4xl:h-60"
/>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src="https://assets.aceternity.com/templates/startup-4.webp"
alt="startup template"
width={500}
height={500}
className="h-20 w-full rounded-lg object-cover shadow-[0_0_24px_rgba(34,_42,_53,_0.06),_0_1px_1px_rgba(0,_0,_0,_0.05),_0_0_0_1px_rgba(34,_42,_53,_0.04),_0_0_4px_rgba(34,_42,_53,_0.08),_0_16px_68px_rgba(47,_48,_55,_0.05),_0_1px_0_rgba(255,_255,_255,_0.1)_inset] @2xl:h-44 @4xl:h-60"
/>
</div>
</div>
),
},
{
title: "Early 2023",
content: (
<div>
<p className="mb-8 text-xs font-normal text-neutral-800 @2xl:text-sm dark:text-neutral-200">
I usually run out of copy, but when I see content this big, I try to
integrate lorem ipsum.
</p>
<p className="mb-8 text-xs font-normal text-neutral-800 @2xl:text-sm dark:text-neutral-200">
Lorem ipsum is for people who are too lazy to write copy. But we are
not. Here are some more example of beautiful designs I built.
</p>
<div className="grid grid-cols-2 gap-4">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src="https://assets.aceternity.com/pro/hero-sections.png"
alt="hero template"
width={500}
height={500}
className="h-20 w-full rounded-lg object-cover shadow-[0_0_24px_rgba(34,_42,_53,_0.06),_0_1px_1px_rgba(0,_0,_0,_0.05),_0_0_0_1px_rgba(34,_42,_53,_0.04),_0_0_4px_rgba(34,_42,_53,_0.08),_0_16px_68px_rgba(47,_48,_55,_0.05),_0_1px_0_rgba(255,_255,_255,_0.1)_inset] @2xl:h-44 @4xl:h-60"
/>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src="https://assets.aceternity.com/features-section.png"
alt="feature template"
width={500}
height={500}
className="h-20 w-full rounded-lg object-cover shadow-[0_0_24px_rgba(34,_42,_53,_0.06),_0_1px_1px_rgba(0,_0,_0,_0.05),_0_0_0_1px_rgba(34,_42,_53,_0.04),_0_0_4px_rgba(34,_42,_53,_0.08),_0_16px_68px_rgba(47,_48,_55,_0.05),_0_1px_0_rgba(255,_255,_255,_0.1)_inset] @2xl:h-44 @4xl:h-60"
/>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src="https://assets.aceternity.com/pro/bento-grids.png"
alt="bento template"
width={500}
height={500}
className="h-20 w-full rounded-lg object-cover shadow-[0_0_24px_rgba(34,_42,_53,_0.06),_0_1px_1px_rgba(0,_0,_0,_0.05),_0_0_0_1px_rgba(34,_42,_53,_0.04),_0_0_4px_rgba(34,_42,_53,_0.08),_0_16px_68px_rgba(47,_48,_55,_0.05),_0_1px_0_rgba(255,_255,_255,_0.1)_inset] @2xl:h-44 @4xl:h-60"
/>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src="https://assets.aceternity.com/cards.png"
alt="cards template"
width={500}
height={500}
className="h-20 w-full rounded-lg object-cover shadow-[0_0_24px_rgba(34,_42,_53,_0.06),_0_1px_1px_rgba(0,_0,_0,_0.05),_0_0_0_1px_rgba(34,_42,_53,_0.04),_0_0_4px_rgba(34,_42,_53,_0.08),_0_16px_68px_rgba(47,_48,_55,_0.05),_0_1px_0_rgba(255,_255,_255,_0.1)_inset] @2xl:h-44 @4xl:h-60"
/>
</div>
</div>
),
},
{
title: "Changelog",
content: (
<div>
<p className="mb-4 text-xs font-normal text-neutral-800 @2xl:text-sm dark:text-neutral-200">
Deployed 5 new components on Aceternity today
</p>
<div className="mb-8">
<div className="flex items-center gap-2 text-xs text-neutral-700 @2xl:text-sm dark:text-neutral-300">
✅ Card grid component
</div>
<div className="flex items-center gap-2 text-xs text-neutral-700 @2xl:text-sm dark:text-neutral-300">
✅ Startup template Aceternity
</div>
<div className="flex items-center gap-2 text-xs text-neutral-700 @2xl:text-sm dark:text-neutral-300">
✅ Random file upload lol
</div>
<div className="flex items-center gap-2 text-xs text-neutral-700 @2xl:text-sm dark:text-neutral-300">
✅ Himesh Reshammiya Music CD
</div>
<div className="flex items-center gap-2 text-xs text-neutral-700 @2xl:text-sm dark:text-neutral-300">
✅ Salman Bhai Fan Club registrations open
</div>
</div>
<div className="grid grid-cols-2 gap-4">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src="https://assets.aceternity.com/pro/hero-sections.png"
alt="hero template"
width={500}
height={500}
className="h-20 w-full rounded-lg object-cover shadow-[0_0_24px_rgba(34,_42,_53,_0.06),_0_1px_1px_rgba(0,_0,_0,_0.05),_0_0_0_1px_rgba(34,_42,_53,_0.04),_0_0_4px_rgba(34,_42,_53,_0.08),_0_16px_68px_rgba(47,_48,_55,_0.05),_0_1px_0_rgba(255,_255,_255,_0.1)_inset] @2xl:h-44 @4xl:h-60"
/>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src="https://assets.aceternity.com/features-section.png"
alt="feature template"
width={500}
height={500}
className="h-20 w-full rounded-lg object-cover shadow-[0_0_24px_rgba(34,_42,_53,_0.06),_0_1px_1px_rgba(0,_0,_0,_0.05),_0_0_0_1px_rgba(34,_42,_53,_0.04),_0_0_4px_rgba(34,_42,_53,_0.08),_0_16px_68px_rgba(47,_48,_55,_0.05),_0_1px_0_rgba(255,_255,_255,_0.1)_inset] @2xl:h-44 @4xl:h-60"
/>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src="https://assets.aceternity.com/pro/bento-grids.png"
alt="bento template"
width={500}
height={500}
className="h-20 w-full rounded-lg object-cover shadow-[0_0_24px_rgba(34,_42,_53,_0.06),_0_1px_1px_rgba(0,_0,_0,_0.05),_0_0_0_1px_rgba(34,_42,_53,_0.04),_0_0_4px_rgba(34,_42,_53,_0.08),_0_16px_68px_rgba(47,_48,_55,_0.05),_0_1px_0_rgba(255,_255,_255,_0.1)_inset] @2xl:h-44 @4xl:h-60"
/>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src="https://assets.aceternity.com/cards.png"
alt="cards template"
width={500}
height={500}
className="h-20 w-full rounded-lg object-cover shadow-[0_0_24px_rgba(34,_42,_53,_0.06),_0_1px_1px_rgba(0,_0,_0,_0.05),_0_0_0_1px_rgba(34,_42,_53,_0.04),_0_0_4px_rgba(34,_42,_53,_0.08),_0_16px_68px_rgba(47,_48,_55,_0.05),_0_1px_0_rgba(255,_255,_255,_0.1)_inset] @2xl:h-44 @4xl:h-60"
/>
</div>
</div>
),
},
];
return (
<div
ref={scrollRef}
className="@container relative h-full w-full overflow-x-clip overflow-y-auto overscroll-contain"
>
<Timeline data={data} container={scrollRef} />
</div>
);
}
Prompt
Build "Timeline", a scroll animation. What it does: Scrolling the stage fills a gradient beam down a timeline with sticky year headings. Write it as a single self-contained React component in TypeScript that fills its parent (w-full h-full), styled with Tailwind CSS, using motion. Technique: the Motion library. It sits on a dark background, in a 16:10 frame. Respect prefers-reduced-motion with a still state, pause work when the element is off screen, and keep it accessible. Original: https://ui.aceternity.com/components/timeline (Aceternity UI, Aceternity UI licence (free component)).