027 / RECHARTS / BAR & COLUMN
Interactive Bars
Category-first bar inspection with a precise band cursor, persistent touch locking, and keyboard traversal across single or grouped categorical series.
- SPEC
- #027
- ENGINE
- Recharts
- FAMILY
- Bar & Column
- RENDERER
- svg
- STATUS
- preview
Installation
Checking public registry…
View local registry JSONCopied as source into your project (requires recharts).
Overview
Interactive Bars is Plotcn's specialized categorical Bar chart engineered specifically for reliable data inspection across pointer, touch, and keyboard modalities.
Rather than treating interaction as an afterthought or ephemeral hover decoration, Interactive Bars makes the category band the primary interaction target:
Governing Principle: Interactive Bars is designed for reliable inspection, not merely hover decoration. The active category must remain understandable and controllable across pointer, touch, and keyboard input without requiring pixel-perfect bar hits, blocking page scroll, fabricating values, or tying interaction state to ephemeral Recharts tooltip internals.
Interaction Hierarchy
Installation
Checking public registry…
View local registry JSONCopied as source into your project (requires recharts).
Usage
import { InteractiveBars } from "@/components/charts/recharts/bar-interactive"const data = [ { quarter: "Q1", product: 82, services: 54, enterprise: 38 }, { quarter: "Q2", product: 96, services: 61, enterprise: 44 }, { quarter: "Q3", product: 88, services: 67, enterprise: 52 }, { quarter: "Q4", product: 104, services: 72, enterprise: 58 },]export function RevenueMixExample() { return ( <InteractiveBars data={data} categoryKey="quarter" series={[ { key: "product", label: "Product Revenue", valueFormatter: (v) => `$${v}M` }, { key: "services", label: "Services Revenue", valueFormatter: (v) => `$${v}M` }, { key: "enterprise", label: "Enterprise Sales", valueFormatter: (v) => `$${v}M` }, ]} showLegend lockOnTouch lockOnClick /> )}Interaction State Machine
The chart manages three clean states: IDLE, ACTIVE, and LOCKED.
- IDLE: The chart is resting with no active category.
- ACTIVE (Transient): A pointer enters a category band. The band lights up subtly and the tooltip opens. As soon as the pointer leaves the chart, the state resets to
IDLE. - LOCKED (Persistent): A user taps a category on touch, clicks with a mouse, or presses
Enter/Spacewhile traversing with keyboard. The category and tooltip remain pinned even after the cursor leaves or the page is scrolled.
Active vs Locked
- Active: Designed for fluid desktop exploration. Moving between bars updates the active readout immediately without cluttering the screen when moving away.
- Locked: Solves the fundamental flaw of touch interfaces where hovering does not exist. The user taps to lock, reads the values, scrolls the page to review text, and dismisses when ready.
Category Band vs Rectangle
Conventional charts require users to position their cursor directly over thin rectangular bars to trigger a tooltip. In grouped charts or dense data, this causes frustrating missed hits.
In Plotcn's Interactive Bars:
- The entire category band acts as the primary hit area.
- Hovering or tapping anywhere within the band activates the full category group.
- The tooltip reports all visible peer series simultaneously.
- Direct contact with a specific rectangle refines
activeSeriesKeyto emphasize that series without hiding peer comparisons.
Zero & Tiny Bars
In conventional bar charts, zero-valued bars have zero height and are impossible to hit. Designers often introduce dangerous "fake minimum bar heights" that visually falsify the data.
Plotcn strictly guarantees mathematical truthfulness:
- Zero-valued bars are drawn with 0 height.
- Tiny bars (e.g.
0.001) remain microscopically small. - Both remain 100% inspectable because the broad category band captures the interaction, and the tooltip truthfully reports
$0.00or$0.01.
Touch Lock Lifecycle
- Tap Bar: Finger taps anywhere in the category band.
- Lock Established: The category band is outlined, and the tooltip is locked into place.
- Finger Lifts: The user removes their finger. The inspection state persists.
- Scroll Page: The user scrolls down to read accompanying text. Native scrolling is completely unimpeded (
touch-actionis never globally blocked). - Dismiss / Transfer: Tapping another category transfers the lock; pressing
Escapeor tapping the locked category again dismisses the inspection.
Single Tab-Stop Keyboard Traversal
Plotcn avoids keyboard "tab explosions" where each bar creates an independent tab stop.
- 1 Tab Stop: Pressing
Tabfocuses the entire chart container. - Arrow Keys:
ArrowLeft/ArrowRight(vertical layout) orArrowUp/ArrowDown(horizontal layout) step sequentially across categories. - Extremes:
Homejumps to the first category,Endjumps to the last. - Locking:
EnterorSpacelocks the currently focused category;Escapeunlocks it without losing focus.
Grouped-Series Inspection
When multiple peer series share a category:
- The category band envelops the entire group.
- The tooltip presents all visible series in their canonical configured order.
- Exact bar contact highlights that individual series row with a star and bold readout while keeping the surrounding comparative numbers in view.
Input Modality Precedence
When transitioning between modalities (e.g., hovering with a mouse, then using arrow keys, or tapping on a touchscreen):
- Locked State takes top priority: transient mouse movement outside will not dismiss a deliberately locked card.
- Keyboard Traversal takes second priority: moving an arrow key intentionally moves the active inspection.
- Pointer Hover is transient: it updates only when no category is actively locked.
Focus vs Active vs Locked
To prevent user confusion, Plotcn establishes three visually distinct treatments:
- FOCUS: Structural blue focus ring around the
<figure>container for keyboard awareness. - ACTIVE: Subtle, low-opacity band fill (
rgba(59, 130, 246, 0.09)) indicating transient pointer hover. - LOCKED: High-contrast dashed structural border (
var(--chart-selection)), persistent background tint, and an explicitLockedbadge in the tooltip header.
Interactive Legend
When interactiveLegend={true} is enabled, clicking legend items toggles series visibility while preserving key invariants:
- Hiding a series never shifts the palette colors of remaining series.
- Active and locked categories remain intact.
- The tooltip dynamically omits hidden series while truthfully reporting missing observations as
"Unavailable".
Layout & Orientation
Interactive Bars supports both vertical and horizontal layouts:
- Vertical (
layout="vertical"): Ideal for standard categorical timelines (quarters, months, categories) with left-to-right arrow navigation. - Horizontal (
layout="horizontal"): Ideal for long category labels and mobile scorecards with top-to-bottom arrow navigation.
Rendering Architecture
The component cleanly decouples visual mark rendering from interaction state management:
- Recharts Core handles the SVG Cartesian axes, gridlines, and grouped
<Bar>shapes. - Interaction Reducer manages discrete category band coordinates, active series keys, and persistent lock state.
- Controlled Tooltip renders outside the Recharts event loop, ensuring tooltip stability across resize, theme change, and touch scrolling.
- Accessibility Shell synchronizes live polite announcements and structured HTML tables.
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.
<InteractiveBars
data={data}
categoryKey="quarter"
series={[
{ key: "product", label: "Product" },
{ key: "services", label: "Services" },
{ key: "enterprise", label: "Enterprise" },
]}
/>Layout orientation: vertical (default) puts categories on X, horizontal puts categories on Y.
layout="vertical"Default: "vertical"Cursor highlighting policy: full category band only or band plus active bar emphasis.
cursorMode="band-and-bar"Default: "band-and-bar"Whether to render subtle background Cartesian gridlines.
showGrid={true}Default: trueWhether to display the structural series legend.
showLegend={false}Default: falseWhether clicking legend items toggles series visibility.
interactiveLegend={false}Default: falseDisplay mode for permanent numeric value labels.
valueLabel="none"Default: "none"Whether mouse clicks establish a persistent inspection lock.
lockOnClick={true}Default: trueWhether touch taps establish a persistent inspection lock.
lockOnTouch={true}Default: true| Property | Type | Default | Required | Description |
|---|---|---|---|---|
dataReq | readonly TData[] | [] | Yes | Array of categorical data records. Order is strictly preserved. |
categoryKeyReq | keyof TData & string | — | Yes | Key on data records representing the discrete category label. |
seriesReq | readonly InteractiveBarSeries<TData>[] | — | Yes | One or more peer numeric series definitions specifying key, label, and formatters. |
layoutOpt | "vertical" | "horizontal" | "vertical" | No | Layout orientation: vertical (default) puts categories on X, horizontal puts categories on Y. |
heightOpt | number | string | 340 | No | Container height in pixels or CSS height string. |
domainOpt | [number, number] | "auto" | "auto" | No | Quantitative domain policy. Defaults to zero-anchored extent covering all series values. |
cursorModeOpt | "band-and-bar" | "band" | "band-and-bar" | No | Cursor highlighting policy: full category band only or band plus active bar emphasis. |
showGridOpt | boolean | true | No | Whether to render subtle background Cartesian gridlines. |
showLegendOpt | boolean | false | No | Whether to display the structural series legend. |
boolean | false | No | Whether clicking legend items toggles series visibility. | |
valueLabelOpt | "none" | "auto" | "none" | No | Display mode for permanent numeric value labels. |
lockOnClickOpt | boolean | true | No | Whether mouse clicks establish a persistent inspection lock. |
lockOnTouchOpt | boolean | true | No | Whether touch taps establish a persistent inspection lock. |
motionOpt | boolean | { duration?: number } | true | No | Animation toggle honoring prefers-reduced-motion. |
Component Variants & Edge States
Production cookbooks showcasing configuration variants alongside verified handling of loading, empty data, and network error states.
Quarterly Revenue Mix
Three peer revenue streams compared across four quarters with persistent touch lock.
Zero and Micro Value Inspection
Proves that zero and tiny bars remain 100% inspectable without artificial geometry distortion.
Missing Observations
Demonstrates that missing records are omitted without fake zero-substitution and reported truthfully.
Horizontal Team Benchmarks
Horizontal orientation for long category labels and compact mobile screens.
Skeletons indicate runtime fetch or pending data queries.
Handles empty collections ([]) gracefully without crashing.
Graceful failure banner when data source or script fails.
Container-Driven Breakpoints
Container-driven responsiveness. Preserves category hit targets, full category bands, persistent inspection lock, and exact tooltips down to 320px mobile viewports without blocking native vertical scrolling.
Category bands maintain generous touch targets; quantitative tick count is thinned accessibly; legend wraps cleanly.
Full category band hit regions allow comfortable touch activation and tap-to-lock inspection of all peer series.
Full layout displaying subtle Cartesian gridlines, hover cursor bands, exact series rectangle emphasis, and multi-series tooltip cards.
Accessibility & Navigation Standards
Accessible categorical bar chart with single tab stop, orientation-specific arrow-key traversal, Home/End navigation, Enter/Space persistent lock, Escape unlock, polite live region announcements, and offscreen structured HTML table.
Container mounts as region with explicit assistive label.
Series identity is reinforced through grouped bar positions, tooltip labels, legend marks, and structured table data, remaining fully functional in monochrome.
Embeds visually hidden summary (.sr-only) declaring: “Announces category name, category index of total, and exact values for all peer series factually, including explicit 'Unavailable' announcements for missing records.”
All entrance transitions and cursor animations are suppressed when prefers-reduced-motion is enabled.
| Key | Action |
|---|---|
| ArrowRight / ArrowLeft | Traverse categories in vertical layout |
| ArrowDown / ArrowUp | Traverse categories in horizontal layout |
| Home | Jump focus to the first category |
| End | Jump focus to the last category |
| Enter / Space | Toggle persistent inspection lock on active category |
| Escape | Unlock inspection and dismiss tooltip |
Data Safety Guarantees
Plotcn enforces strict operational safety rules:
- Preserved Order: Category order matches caller order without automatic ranking or sorting.
- Zero vs Missing: Zero is a valid number (
0); missing (nullorundefined) is explicitly rendered as"Unavailable". - No Geometry Inflation: Quantitative marks are never stretched to create larger hit targets; category bands provide the hit area.
- Data Updates While Locked: If the underlying dataset updates while a category is locked, the tooltip immediately reflects the fresh values rather than showing a stale snapshot.
Internal Architecture & File Dependencies
Source-first ownership model. Inspect the exact component call tree, dependencies, and full implementation below.
Provides responsive sizing and theme token scope