008 / RECHARTS / LINE
Focus Line
An interaction-first time-series line optimized for precise keyboard focus, pointer/touch scrubbing, crosshair inspection, and persistent locked tooltips.
- SPEC
- #008
- ENGINE
- Recharts
- FAMILY
- Line
- RENDERER
- svg
- STATUS
- preview
Installation
Checking public registry…
View local registry JSONCopied as source into your project (requires recharts, @hugeicons/react, @hugeicons/core-free-icons).
Overview
Focus Line is a specialized Recharts time-series line component engineered around the observation inspection model. While Signal Line prioritizes trend perception, Focus Line prioritizes precise observation access:
"Let me move through this series precisely, inspect individual observations, and keep one observation selected while I continue using the interface."
It bridges pointer scrubbing, accessible keyboard stepping, neutral crosshair inspection, and persistent locked tooltips into a unified, predictable observation architecture.
Focus vs. Active Datum vs. Locked Selection
Chart root figure tabIndex=0 receives keyboard input via --chart-focus. Single tab stop, no point spam.
Transient observation resolved via horizontal pointer scrub or Left/Right arrows. Disappears on pointer leave unless locked.
Pinned observation with concentric ring ───◎─── and persistent tooltip that survives pointer leave, color updates, and resizes.
import { FocusLine } from "@/components/charts/recharts/line-focus"const latencyData = [ { time: "09:00", latency: 122 }, { time: "10:00", latency: 138 }, { time: "11:00", latency: 147 }, { time: "12:00", latency: 133 }, { time: "13:00", latency: 164 }, { time: "14:00", latency: 181 }, { time: "15:00", latency: 156 },]export function LatencyInspector() { return ( <FocusLine data={latencyData} xKey="time" series={{ key: "latency", label: "P95 latency", }} lockableTooltip initialFocus="none" valueFormatter={(v) => `${v} ms`} showGrid /> )}The Tri-State Mental Model
Focus Line enforces a strict separation between keyboard focus, transient inspection, and persistent selection. Collapsing these three concepts into a single boolean state causes unpredictable UX and accessibility failures.
| Concept | Role | User Action | Visual Representation | CSS Token |
|---|---|---|---|---|
| Focus | Keyboard navigation capability | Tab into chart | Root container focus ring | var(--chart-focus) |
| Active Datum | Transient inspection state | Pointer move or ← → | Solid dot + neutral crosshair | color + var(--chart-crosshair) |
| Locked Datum | Persistent selection state | Click, tap, or Enter / Space | Concentric double ring (───◎───) + pinned tooltip | selectionColor |
Focus is Not Selection
- Keyboard Focus signals that the chart surface is ready to receive arrow navigation. It does not select or commit a data point.
- Active Datum represents what the user is inspecting right now. If unlocked, moving the pointer off the chart clears the active datum.
- Locked Datum represents an observation intentionally pinned by the user. Moving the mouse elsewhere, resizing the window, or toggling dark mode does not dismiss the pinned tooltip.
- Pressing Escape or clicking the pinned point releases the lock.
Dual Modality & Nearest-X Inspection
Focus Line treats pointer scrubbing and keyboard navigation as two access paths into the same underlying observation sequence.
Pointer enters anywhere in the plot frame. X-coordinate calculates Euclidean nearest categorical/temporal observation without requiring a 2px stroke hit.
Single tab stop on root figure. Left/Right moves through ordered sequence; Home/End jumps directly to boundaries; Enter/Space locks or unlocks.
null is not 0) · NaN and Infinity safely filteredHorizontal Nearest-X Scrubbing
Users should never be forced to land their pointer directly on a 2px SVG line. Focus Line utilizes the entire Cartesian plot area:
- Moving horizontally across the plot resolves the nearest observation along the X-axis.
- The neutral vertical crosshair aligns seamlessly with the observation's coordinate.
- The custom inspection tooltip updates with tabular numerals and series color identity.
- If a datum is locked, pointer scrubbing does not displace the pinned observation until unlocked.
Mobile Touch Safety
To prevent trapping users on touchscreens:
- The root element uses
touch-action: pan-y, ensuring vertical page scrolling is never blocked. - Tapping anywhere along the observation's vertical column inspects that datum.
- Tapping locks the observation; tapping again or outside dismisses the pinned selection.
Keyboard Navigation Reference
Focus Line provides a single tab stop on the root <figure tabIndex={0}>. It never injects individual tab stops on hundreds of SVG points.
| Key | Action | Context |
|---|---|---|
| → / ArrowRight | Inspect next chronological observation | Active inspection steps forward |
| ← / ArrowLeft | Inspect previous chronological observation | Active inspection steps backward |
| Home | Jump to the first observation in the series | Jumps directly to start |
| End | Jump to the latest observation in the series | Jumps directly to end |
| Enter or Space | Lock / unlock the currently inspected observation | Toggles persistent selection |
| Escape | Dismiss locked selection | Reverts to transient inspection |
Global Color System Integration
Focus Line participates in the Plotcn global color architecture with independent appearance roles:
| Color Role | Prop | Default Token | Visual Impact |
|---|---|---|---|
| Series Color | color | var(--chart-1) | Trend line stroke, active marker point, tooltip series indicator |
| Selection Color | selectionColor | var(--chart-selection) | Concentric outer ring, pinned inner dot, lock badge |
| Crosshair | — | var(--chart-crosshair) | Neutral dashed vertical guide line (remains theme-neutral) |
| Chart Focus | — | var(--chart-focus) | Root keyboard focus shell ring (independent of series colors) |
Non-Color Geometric Distinction
Even when color and selectionColor are assigned identical values (e.g., #18181b in monochrome dashboards), locked selection remains immediately distinguishable through geometry:
- Active Point: Single filled circle (
r: 4.5px). - Locked Point: Concentric double-ring marker (
───◎───) with an outer ring (r: 8px) and inner anchor dot (r: 4px).
Truthful Missing Data Contract
When telemetry signals experience dropouts, Focus Line adheres to strict data integrity:
- Missing Observations Remain Missing:
nullorundefinedvalues are never converted to zero (null ≠ 0). - Visual Gaps: The line breaks cleanly across missing intervals under
missingValuePolicy="gap". - No Fabricated Tooltip Values: Focus Line does not interpolate fake synthetic numbers between missing points.
- Truthful Tooltip Readout: Inspecting an observation with missing metrics explicitly shows
—orUnavailable.
Installation
Install Focus Line directly into your project using the shadcn CLI:
Checking public registry…
View local registry JSONCopied as source into your project (requires recharts, @hugeicons/react, @hugeicons/core-free-icons).
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 horizontal domain coordinates (e.g., time, timestamp). |
series | FocusSeriesConfig<TData> | — | Required | Single primary series configuration ({ key, label }). |
color | string | "var(--chart-1)" | Optional | Primary theme stroke color for trend line, active dot, and tooltip marker. |
selectionColor | string | "var(--chart-selection)" | Optional | Accent color for the locked concentric marker and pinned selection. |
lockableTooltip | boolean | true | Optional | Enables persistent tooltip locking via click, tap, or Enter/Space. |
initialFocus | "none" | "first" | "last" | "none" | Optional | Datum selection state when chart first receives keyboard focus. |
curve | "monotone" | "linear" | "step" | "monotone" | Optional | Curve interpolation algorithm for the continuous trend line. |
domain | [number, number] | ["auto", "auto"] | ["auto", "auto"] | Optional | Vertical Y scale range with zero-span safeguarding. |
height | number | string | 320 | Optional | Container height in pixels or standard CSS dimension strings. |
showGrid | boolean | true | Optional | Whether to render subtle horizontal Cartesian grid reference lines. |
showLegend | boolean | false | Optional | Whether to display the series legend below the chart. |
missingValuePolicy | "gap" | "carry" | "gap" | Optional | Visual treatment of missing values: honest visual break or forward carry. |
animation | "draw" | "fade" | "none" | "draw" | Optional | Entry animation style. Bypassed automatically when reduced motion is preferred. |
onActiveDatumChange | (datum: ActiveDatum | null) => void | undefined | Optional | Callback fired whenever the transiently inspected datum changes. |
onLockedDatumChange | (datum: ActiveDatum | null) => void | undefined | Optional | Callback fired when an observation is pinned or released. |
valueFormatter | (value: number) => string | n.toLocaleString() | Optional | Custom formatter for tooltip metric values and vertical scale ticks. |
xFormatter | (value: string | number) => string | String | Optional | Custom formatter for horizontal domain tick labels. |
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.
<FocusLine
data={data}
xKey="date"
seriesKey="value"
/>Primary theme stroke color for the trend line, transient active marker, and tooltip identity.
color="#3b82f6"Default: "var(--chart-1, #3b82f6)"Accent color for the locked concentric marker (───◎───) and persistent inspection highlight.
selectionColor="#f59e0b"Default: "var(--chart-selection, #f59e0b)"Allows users to pin the inspected observation via click, tap, or Enter/Space keys.
lockableTooltip={true}Default: trueDatum selection state when the chart first receives keyboard focus.
initialFocus="none"Default: "none"Curve interpolation algorithm for the continuous trend line.
curve="monotone"Default: "monotone"Container height in pixels or standard CSS dimension strings.
height={320}Default: 320Whether to render subtle horizontal Cartesian grid reference lines.
showGrid={true}Default: trueWhether to display the series legend below the chart.
showLegend={false}Default: false| Property | Type | Default | Required | Description |
|---|---|---|---|---|
dataReq | readonly TData[] | [] | Yes | Readonly array of ordered observation records. Caller data is never mutated. Best for: Primary dataset |
xKeyReq | keyof TData & string | — | Yes | Property name for the horizontal X-axis domain coordinate. Best for: Domain coordinates |
seriesReq | FocusSeriesConfig<TData> | — | Yes | Configuration for the single primary numeric series ({ key, label }). Best for: Primary metric |
colorOpt | string | "var(--chart-1, #3b82f6)" | No | Primary theme stroke color for the trend line, transient active marker, and tooltip identity. Best for: Brand identity |
string | "var(--chart-selection, #f59e0b)" | No | Accent color for the locked concentric marker (───◎───) and persistent inspection highlight. Best for: Locked selection accent | |
boolean | true | No | Allows users to pin the inspected observation via click, tap, or Enter/Space keys. Best for: Persistent comparison | |
initialFocusOpt | "none" | "first" | "last" | "none" | No | Datum selection state when the chart first receives keyboard focus. Best for: Keyboard exploration |
curveOpt | "linear" | "monotone" | "step" | "monotone" | No | Curve interpolation algorithm for the continuous trend line. Best for: Trend aesthetics |
domainOpt | [number, number] | ["auto", "auto"] | ["auto", "auto"] | No | Vertical Y-axis scale range. 'auto' computes a padded domain safeguarding against zero span. Best for: Scale limits |
heightOpt | number | string | 320 | No | Container height in pixels or standard CSS dimension strings. Best for: Viewport sizing |
showGridOpt | boolean | true | No | Whether to render subtle horizontal Cartesian grid reference lines. |
showLegendOpt | boolean | false | No | Whether to display the series legend below the chart. |
"gap" | "carry" | "gap" | No | Behavior for null or undefined observations: 'gap' breaks the line truthfully; 'carry' holds last valid value. | |
animationOpt | "draw" | "fade" | "none" | "draw" | No | Entry animation style. Respects user prefers-reduced-motion preferences automatically. |
(datum: ActiveDatum<TData> | null) => void | undefined | No | Callback invoked whenever the transiently inspected observation changes. | |
(datum: ActiveDatum<TData> | null) => void | undefined | No | Callback invoked when an observation is pinned (locked) or released (unlocked). | |
titleOpt | string | "Focus Line Chart" | No | Accessible title for assistive technologies and screen readers. |
descriptionOpt | string | undefined | No | Accessible description detailing keyboard shortcuts and inspection instructions. |
loadingOpt | boolean | false | No | Renders a neutral loading skeleton without fabricating artificial observations. |
errorOpt | Error | string | null | null | No | Displays an actionable error banner when data fails to load. |
unavailableOpt | boolean | string | null | false | No | Displays an unavailability notice when metrics cannot be resolved. |
Component Variants & Edge States
Production cookbooks showcasing configuration variants alongside verified handling of loading, empty data, and network error states.
P95 Request Latency Inspection
High-precision hourly API latency trend demonstrating nearest-X scrub inspection with neutral crosshairs.
Keyboard-First Exploration
Accessible single-tab-stop exploration. Tab into the chart, then navigate using Left and Right Arrow keys.
Persistent Locked Observation
Click or press Enter on an observation to lock it. The tooltip and concentric marker persist when moving the pointer away.
Truthful Gap Handling for Missing Data
Missing observations create an honest break in the trend line without fabricating intermediate values or converting null to zero.
Skeletons indicate runtime fetch or pending data queries.
Handles empty collections ([]) gracefully without crashing.
Graceful failure banner when data source or script fails.
Responsive Behavior
- Desktop (): Full X-axis tick intervals, spacious container padding, and full tooltip layout.
- Tablet (): Thinned ticks, compact margins, and synchronized nearest-X inspection.
- Mobile (): Safe pan-y touch gestures preserving page scrolling, single-tap inspection, and viewport-clamped tooltip positioning.
- Persistent Selection Across Resize: Resizing the container or toggling device previews retains the active locked observation coordinate.
Container-Driven Breakpoints
Focus Line uses container-driven measurement to adapt tick frequency and tooltip sizing. Active and locked observations remain anchored cleanly across container resizes.
Full X-axis ticks, spacious margins, complete tooltip readouts, and unconstrained inspection hover area.
Reduced tick frequency, compact padding, preserved crosshairs, and synchronized scrub tracking.
Single-tap inspection, pan-y touch action ensuring normal page scrolling is never blocked, and compact clamped tooltip.
Accessibility & Screen Reader Model
- Semantic Shell: Encapsulated within a
<figure role="region" tabIndex={0}>element witharia-labelledbyandaria-describedby. - Accessible Description: Clarifies observation count, series identity, and explicit keyboard instructions: "P95 latency time-series over 7 observations. Use Left and Right Arrow keys to inspect, Enter to lock, and Escape to release."
- Single Tab Stop: Focuses the container once. Arrow keys navigate observations internally without polluting the document tab sequence.
- Restrained Live Regions: Avoids aggressive
aria-livechatter during rapid pointer scrubbing; updates screen reader announcements during intentional keyboard steps. - Reduced Motion: Entry draw transitions are immediately bypassed when
prefers-reduced-motion: reduceis enabled.
Accessibility & Navigation Standards
Single keyboard tab stop on root figure with ArrowLeft, ArrowRight, Home, End, Enter, and Escape shortcuts. Screen readers announce factual observation values without spamming live regions.
Container mounts as region with explicit assistive label.
Locked selection uses a distinctive concentric double-ring marker (───◎───) in addition to color accent, ensuring full accessibility without relying on color alone.
Embeds visually hidden summary (.sr-only) declaring: “Announces domain time, series label, and metric value factually for the focused observation.”
All entrance transitions immediately bypass when prefers-reduced-motion is detected in system preferences.
| Key | Action |
|---|---|
| ArrowRight | Inspect next observation in the series. |
| ArrowLeft | Inspect previous observation in the series. |
| Home | Jump inspection to the first observation. |
| End | Jump inspection to the last observation. |
| Enter / Space | Lock or unlock the currently active observation. |
| Escape | Release locked selection and dismiss active tooltip. |
Data Safety Checklist
- ✓ Truthful Observations: Nearest-X inspection selects real, recorded observations; never synthetic interpolated numbers.
- ✓ No Null-to-Zero Conversion: Missing data renders as explicit gaps (
null ≠ 0). - ✓ Non-Finite Filtering:
NaN,Infinity, and unparseable values are excluded from geometry calculations. - ✓ Immutability: Caller data arrays are never mutated.
- ✓ Stale Selection Cleanup: If the underlying dataset changes and the locked observation is removed, the lock state is safely cleared.
- ✓ Modality Stability: Switching between mouse and keyboard does not produce conflicting multi-cursor artifacts.
Internal Architecture & File Dependencies
Source-first ownership model. Inspect the exact component call tree, dependencies, and full implementation below.
Handles container dimension measurement and CSS token scoping
Coordinates coordinate scales, Cartesian grid, and primary trend line