Examples
One realistic dataset, rendered two ways — the exact same milestones, through both bindings, so you can compare them directly rather than guessing how the vanilla API differs from React.
A product roadmap
Four milestones tracking an early-stage product from idea to funding:
const points = [
{ date: '2023', title: 'Idea validated with 20 customer interviews' },
{ date: '2024 Q1', title: 'MVP shipped to first 10 users' },
{ date: '2024 Q3', title: 'Reached 1,000 active users' },
{ date: '2025', title: 'Raised seed funding' },
]; Pick a binding below to see the full working code for that same data:
import { Timeline } from '@trailvine/react';
const points = [
{ date: '2023', title: 'Idea validated with 20 customer interviews' },
{ date: '2024 Q1', title: 'MVP shipped to first 10 users' },
{ date: '2024 Q3', title: 'Reached 1,000 active users' },
{ date: '2025', title: 'Raised seed funding' },
];
export default function RoadmapTimeline() {
return (
<Timeline
points={points}
layout={{ width: 800, marginX: 20, bands: [70, 20, 60, 30] }}
path={{ curveType: 'elbow', radius: 8 }}
wrap={{ maxChars: 22, maxLines: 2 }}
mobileBehavior="vertical"
/>
);
}What's happening here
layout.bandsgives each point its own height ([70, 20, 60, 30]) rather than a flat alternating pattern — see the options reference for how band cycling works.wrapcaps each label at 22 characters per line, 2 lines max, so longer titles like "Idea validated with 20 customer interviews" wrap cleanly instead of overflowing.mobileBehavior: 'vertical'switches the timeline to a vertical layout automatically below a narrow viewport width — try resizing your browser on the playground to see it live.
Next steps
- Options reference — every field on
layout,path, andwrap. - React API / Vanilla API — full reference for each binding.
- Playground — tune your own data and options live, then copy the result as code.