006 / RECHARTS / LINE
Milestone Line
Time-series trend with sparse event annotations and milestone pins for releases, incidents, launches, and policy changes.
- SPEC
- #006
- ENGINE
- Recharts
- FAMILY
- Line
- RENDERER
- svg
- STATUS
- preview
Installation
Checking public registry…
View local registry JSONCopied as source into your project (requires recharts).
Overview
Milestone Line is a dedicated time-series visualization for showing a quantitative trend together with a small number of meaningful events, releases, incidents, launches, policy changes, or campaigns.
Its core mental model is:
Show what happened to the metric, and make the important moments around that trend easy to identify without overwhelming the chart.
Milestone annotations remain sparse, intentional, readable, responsive, accessible, and semantically separate from the numeric observation series itself.
Decoupled Event Pins & Quantitative Trend Geometry
Clean quantitative line vertices representing real observation values.
Pins remain in their own collision-free space. Zero fake Y-interpolation.
Subtle dashed reference lines connect events cleanly to the timeline.
import { MilestoneLine } from "@/components/charts/recharts/line-milestones"const growthData = [ { date: "Jan", users: 45000 }, { date: "Feb", users: 52000 }, { date: "Mar", users: 58000 }, { date: "Apr", users: 63000 }, { date: "May", users: 78000 }, { date: "Jun", users: 84000 }, { date: "Jul", users: 95000 },]const milestones = [ { id: "pricing-v2", x: "Feb", label: "Pricing v2", description: "Updated subscription tiers" }, { id: "mobile-launch", x: "May", label: "Mobile app", description: "Public release on iOS and Android" }, { id: "enterprise-tier", x: "Jul", label: "Enterprise", description: "SSO and audit log rollout" },]export function ProductGrowthCard() { return ( <MilestoneLine data={growthData} xKey="date" series={{ key: "users", label: "Active users" }} milestones={milestones} showMilestoneGuides showGrid /> )}The Milestone Model
In Milestone Line, the milestone layer is treated as an independent semantic structure. It is:
- Not another data series: Milestones do not contribute Y-values to the quantitative scale or distort the domain.
- Not a legend item: Milestones are contextual events, not repetitive series keys.
- Not a second Y-axis: Milestones are positioned strictly along the horizontal domain axis ().
- Not arbitrary HTML overlays: Guides and pins are coordinated natively inside the Cartesian SVG coordinate space.
Top Annotation Lane
Rather than anchoring milestone pins directly onto line vertices—which would require interpolating fake metric numbers between observations—Milestone Line places milestone pins and labels in a dedicated top annotation lane above the plot area:
- Uncluttered Trend: The quantitative line remains clean and easy to follow.
- True Event Placement: Events can exist between observation points without requiring fake Y interpolation.
- Deterministic Collision: Label collision algorithms operate cleanly in horizontal space without competing with line vertices.
- Subtle Vertical Guides: Thin dashed reference lines connect the top event pin down through the plot area.
Data Model Separation
Milestone Line enforces strict separation between numeric observations and milestone events:
// Numeric Observations (data: readonly TData[])export interface UserMetricDatum { date: string // Horizontal domain coordinate users: number // Quantitative metric level}// Milestone Events (milestones: readonly Milestone<XVal>[])export interface Milestone<XValue = string | number> { id: string // Stable, unique milestone identifier x: XValue // Exact domain position along the X axis label: string // Short, concise title (e.g. "V2 launch") description?: string // Optional contextual detail for tooltips}Stable Milestone IDs
Every milestone must have a stable, caller-provided id (such as "pricing-v2" or "incident-104"). Identity is never derived from array index. Stable IDs ensure deterministic React rendering keys, reliable keyboard focus, and unambiguous selection state.
Duplicate-X & Same-Date Handling
Multiple events can occur on the exact same date or interval (e.g. a version release and a simultaneous pricing change). Overlapping two independent pins creates unreadable text and pointer conflict.
Milestone Line resolves this deterministically by grouping same-date milestones:
Single Event: Same-Date Events (2+): ● [● 2] │ │ │ │- When multiple milestones share an coordinate, Milestone Line renders a single grouped badge showing the event count (
● 2). - Hovering, focusing, or clicking the grouped pin presents all associated events ordered by caller input sequence in a unified inspection tooltip.
Missing Data & Domain Safety
- Missing Series Observations: If an observation's metric value is
nullor unrecorded, the trend line breaks truthfully. However, the milestone pin and vertical guide remain visible. An unrecorded metric does not erase an operational milestone. - No Fake Interpolation: When a milestone falls between observations or occurs during a metric gap, Milestone Line never invents or interpolates fake metric values. The inspection tooltip simply indicates that metric values were not recorded.
- Out-of-Domain Milestones: If a milestone's coordinate falls outside the chart domain, it is safely omitted. It is never clamped to chart borders, which would falsely misrepresent the date of the event.
- Caller Data Immutability: Input arrays (
dataandmilestones) are never mutated.
Causality & Responsible Interpretation
Responsible: "The V2 release occurred on May 10th during this observation period."Irresponsible: "The V2 release drove a 24% increase in user signups."Unless the host application explicitly provides verified analytical attribution, time-series visualizations must present events as contextual markers along the timeline.
Installation
Install Milestone Line directly into your project using the shadcn CLI:
Checking public registry…
View local registry JSONCopied as source into your project (requires recharts).
Component Props
| Property | Type | Default | Required | Description |
|---|---|---|---|---|
data | readonly TData[] | [] | Required | Readonly array of observation records. Caller data is never mutated. |
xKey | keyof TData & string | — | Required | Property name for the horizontal X-axis domain coordinates. |
seriesKey | keyof TData & string | "users" | Optional | Property name for the numeric trend series value. |
series | MilestoneSeriesConfig | undefined | Optional | Optional descriptor combining key, label, formatter, and color. |
milestones | readonly Milestone[] | [] | Optional | Sparse collection of contextual event markers with stable IDs. |
curve | "monotone" | "linear" | "natural" | "step" | "monotone" | Optional | Interpolation curve applied to the quantitative trend line. |
missingValuePolicy | "gap" | "connect" | "gap" | Optional | Whether missing metric observations create an honest gap or bridge across. |
height | number | string | 360 | Optional | Container height in pixels or standard CSS dimension strings. |
color | string | "var(--chart-1, #3b82f6)" | Optional | Primary theme stroke color for the trend line. |
showMilestoneGuides | boolean | true | Optional | Whether to render thin vertical dashed guides from the annotation lane. |
milestoneColor | string | "var(--chart-milestone-pin, #71717a)" | Optional | Stroke and pin color for contextual milestone markers and guides. |
showGrid | boolean | true | Optional | Whether to render subtle horizontal background reference gridlines. |
showXAxis | boolean | true | Optional | Whether to render the horizontal category scale. |
showYAxis | boolean | true | Optional | Whether to render the vertical numeric scale. |
showLegend | boolean | false | Optional | Whether to display the chart legend. |
valueFormatter | (value: number) => string | n.toLocaleString() | Optional | Custom formatter for Y-axis ticks and tooltip numbers. |
xFormatter | (value: string | number) => string | String | Optional | Custom formatter for X-axis tick labels. |
motion | boolean | { duration?: number } | true | Optional | Controls entry reveal animations, respecting reduced-motion preferences. |
Props Reference & Interactive Prop Explorer
Inspect every component property, customize semantic color roles live with instant visual feedback, and copy production-ready code with active prop configurations.
Colors & Appearance Configuration
Customize primary, reference, or annotation series colors. Defaults derive from Plotcn theme tokens.
<MilestoneLine
data={data}
xKey="date"
series={{ key: "users", label: "Active users" }}
milestones={milestones}
/>Interpolation curve applied to the quantitative trend line.
curve="monotone"Default: "monotone"Handling of null/undefined series values: 'gap' leaves an honest break; 'connect' bridges across missing points.
missingValuePolicy="gap"Default: "gap"Container height in pixels or standard CSS dimension strings.
height={360}Default: 360Primary theme stroke color for the trend line.
color="#3b82f6"Default: "var(--chart-1, #3b82f6)"Whether to render thin vertical dashed reference guides from the top annotation lane.
showMilestoneGuides={true}Default: trueStroke and pin color for contextual milestone markers and guides.
milestoneColor="#71717a"Default: "var(--chart-milestone-pin, #71717a)"| Property | Type | Default | Required | Description |
|---|---|---|---|---|
dataReq | readonly TData[] | [] | Yes | Readonly array of structured observation records. Caller data is never mutated. Best for: Primary dataset |
xKeyReq | keyof TData & string | — | Yes | Property name for the horizontal X-axis domain (e.g. date, month, or sprint). Best for: Domain coordinates |
seriesKeyOpt | keyof TData & string | "users" | No | Property name for the numeric metric value plotted as the trend line. Best for: Quantitative trend series |
milestonesOpt | readonly Milestone<XVal>[] | [] | No | Sparse contextual milestone moments: { id: string, x: XVal, label: string, description?: string }. Best for: Contextual events |
curveOpt | "monotone" | "linear" | "natural" | "step" | "monotone" | No | Interpolation curve applied to the quantitative trend line. Best for: Line geometry aesthetic |
"gap" | "connect" | "gap" | No | Handling of null/undefined series values: 'gap' leaves an honest break; 'connect' bridges across missing points. Best for: Missing value integrity | |
heightOpt | number | string | 360 | No | Container height in pixels or standard CSS dimension strings. Best for: Slot sizing |
colorOpt | string | "var(--chart-1, #3b82f6)" | No | Primary theme stroke color for the trend line. Best for: Brand identity |
boolean | true | No | Whether to render thin vertical dashed reference guides from the top annotation lane. Best for: Event alignment clarity | |
string | "var(--chart-milestone-pin, #71717a)" | No | Stroke and pin color for contextual milestone markers and guides. Best for: Event marker styling | |
showGridOpt | boolean | true | No | Whether to display subtle horizontal background reference gridlines. |
showXAxisOpt | boolean | true | No | Whether to display the horizontal category scale. |
showYAxisOpt | boolean | true | No | Whether to display the vertical numeric scale. |
showLegendOpt | boolean | false | No | Whether to display the chart legend. Single-series milestone charts keep this off by default. |
(value: number) => string | n => n.toLocaleString() | No | Custom formatter for Y-axis ticks and tooltip metric values. | |
xFormatterOpt | (value: string | number) => string | String | No | Custom formatter for X-axis tick labels. |
motionOpt | boolean | { duration?: number } | true | No | Controls entry reveal animations, respecting user reduced motion preferences. |
titleOpt | string | "Milestone Line Chart" | No | Accessible heading announced by screen readers. |
descriptionOpt | string | undefined | No | Long-form context describing the trend and milestones. |
loadingOpt | boolean | false | No | Renders a neutral loading skeleton without fake milestone pins. |
errorOpt | Error | string | null | null | No | Renders an actionable error state banner with optional retry trigger. |
unavailableOpt | boolean | string | null | false | No | Renders a metric unavailability notice when data cannot be computed. |
Component Variants & Edge States
Production cookbooks showcasing configuration variants alongside verified handling of loading, empty data, and network error states.
Product Growth & Milestones
Monthly active users with sparse event pins for pricing changes, mobile releases, and enterprise launches.
API Latency & Operational Interventions
P99 latency trend annotated with infrastructure migration and cache deployment milestones without asserting causality.
Organic Signups & Marketing Campaigns
Signups trajectory alongside major marketing pushes and seasonal campaign activations.
Same-Date Grouped Milestones
Demonstrates automatic grouped badge handling (● 2) and combined inspection when multiple events occur on the same date.
Skeletons indicate runtime fetch or pending data queries.
Handles empty collections ([]) gracefully without crashing.
Graceful failure banner when data source or script fails.
Responsive Collision Strategy
Milestone Line uses container-driven deterministic collision handling:
- Desktop (): Full persistent text labels in the top annotation lane with 2-lane staggering if helpful, vertical guides, and rich hover inspection.
- Tablet (): Thinned X-axis labels, preserved milestone pins, selective label display to prevent overlap.
- Mobile (): Pin markers preserved across all events, dense labels collapsed into compact pins, touch selection opens a dedicated below-chart active event detail panel.
Core Rule: Responsive collapsing may hide persistent text labels when horizontal space is constrained, but never removes milestone pins or erases event discoverability.
Container-Driven Breakpoints
Milestone Line uses container-driven deterministic collision handling. On narrow viewports, dense text labels collapse into compact pins, preserving 100% of event positions and interaction discoverability without clipping or overlapping.
Persistent text labels in top annotation lane with 2-lane staggering if helpful, full event guides, nearest-X trend tooltips, and rich milestone inspection.
Thinned X-axis labels, preserved milestone pins, selective label display, tooltip pinned within viewport boundaries.
Pin markers preserved across all events, dense labels collapsed, touch-first selection opens dedicated below-chart active event detail strip.
Accessibility & Keyboard Navigation
Milestone Line provides comprehensive accessibility for assistive technologies and keyboard users:
- Semantic Role: The chart container renders as
<figure role="region">with properaria-labelledbyandaria-describedbyattributes. - Factual Summary: Announces observation count and milestone event details factually (e.g. "Time-series visualization showing 8 observations for Active users with 3 annotated milestone events: 'Pricing v2' at Feb, 'Mobile app' at May, 'Enterprise' at Jul. Events indicate contextual moments and do not infer causality.").
- Keyboard Navigation:
ArrowRight/ArrowLeft: Navigate through observation points along the timeline.Tab: Focus individual milestone pin markers in the annotation lane.Enter/Space: Activate and select the focused milestone pin.Escape: Dismiss active milestone inspection and reset focus.
- Color Independence: Restrained zinc pins with geometric circle and badge shapes; zero reliance on color alone to convey milestone identity.
- Reduced Motion: Full support for
prefers-reduced-motion: reduce; renders final trend and milestones immediately without entrance delay.
Accessibility & Navigation Standards
Factual screen reader announcement reporting observation count and milestone event details without inferring causal links.
Container mounts as region with explicit assistive label.
Geometric pin markers and text badges communicate milestone identity; zero reliance on color alone to convey meaning.
Embeds visually hidden summary (.sr-only) declaring: “Announces trend observations alongside sparse event moments factually.”
Transitions disable automatically under prefers-reduced-motion; final trend and milestones render immediately.
| Key | Action |
|---|---|
| ArrowRight | Inspect next observation along the timeline. |
| ArrowLeft | Inspect previous observation along the timeline. |
| Tab | Focus individual milestone pin markers in the annotation lane. |
| Enter / Space | Activate and lock the focused milestone details. |
| Escape | Dismiss active milestone inspection and reset focus. |
Data Safety Guarantees
Milestone Line upholds Plotcn's rigorous data safety standards:
- ✓ No Fabricated Metric Values: Milestones between observations never invent interpolated Y values.
- ✓ No Border Clamping: Milestones outside the data domain are omitted rather than falsely clamped to edges.
- ✓ Missing Values Remain Missing: Unrecorded observations create honest line gaps while milestone pins remain discoverable.
- ✓ Duplicate ID Detection: Duplicate milestone IDs are warned in development to prevent selection ambiguity.
- ✓ Same-Date Events Remain Distinct: Same-X milestones group cleanly without overlapping pins.
- ✓ Deterministic Collision Handling: Labels collapse based on measured horizontal spacing without random hiding.
- ✓ Caller Data Immutability: Caller arrays and observation objects are never mutated.
- ✓ Non-Causal Presentation: Visual placement avoids implying that events caused metric movements.
Internal Architecture & File Dependencies
Source-first ownership model. Inspect the exact component call tree, dependencies, and full implementation below.
Manages container constraints and ResizeObserver width updates for collision resolution
Synchronizes horizontal X-axis, vertical Y-axis, grid, and trend line paths