Block Milestones — React Page Block
Milestone progress: a roadmap strip whose completed steps light up in sequence on scroll-in, the current step breathes, and upcoming steps stay dimmed. Which steps are done is pure data.

Usage
import { BlockMilestones } from "@/components/BlockMilestones";
export function Roadmap() {
return (
<BlockMilestones
title="Where we are in the plan."
milestones={[
{ name: "Whiteboard", note: "The first graph." },
{ name: "Replays", note: "Scrub the week." },
{ name: "Self-hosted", note: "In progress.", current: true },
]}
current={2}
{...{
title: "Where we are in the plan.",
current: 0,
accent: "#d5ed9a",
scheme: "dark"
}}
/>
);
}Implementation notes & API
Purpose: roadmap/milestone progress strip. Copy it, ship it — every string, link and color arrives through props. Runtime: pure DOM + CSS. No WebGPU, canvas, animation library or external assets; SSR-safe on first render. Theming: root custom properties (--vb-bg, --vb-fg, --vb-accent, --vb-border, --vb-radius, --vb-container) or the accent/scheme/className/style props. scheme flips the dark default to light. Guardrails: responsive via container queries down to 320px; interactive behavior degrades on touch; prefers-reduced-motion drops entrance/scroll motion while content stays complete. The aria-label is "Milestone progress"; a vertical version renders on narrow screens. Reduced motion shows the settled strip.
| Property | Type | Notes / default |
|---|---|---|
eyebrow / title / description | ReactNode | Section header |
milestones | readonly Milestone[] | { name, note?, current? } |
current | number | Index in progress; steps before it count as done |
demoNote | ReactNode | null | Fictional-roadmap marker; pass null with your plan |
scheme | "dark" | "light" | dark |
accent | string (hex) | Sets --vb-accent for the whole block |
className / style | string / CSSProperties | Applied to the section root |
children | ReactNode | Replaces the default content entirely |