Chart Data Appending Engine
Relevant source files
The following files were used as context for generating this wiki page:
The Chart Data Appending Engine manages transitions and animations for real-time data visualization within the HX-UI library. It differentiates between initial data loading and subsequent incremental updates to prevent visual "jittering" or reshuffling of existing data points when new data arrives.
This engine extends the base capabilities of Recharts 3 by implementing specific matching strategies that ensure existing points remain in place during updates, which is critical for monitoring systems and log streams.
Sources: README.md:58-62, src/charts/animation.ts:7-25
Animation Architecture
The architecture separates the animation logic from the rendering components. It uses a specialized React hook to track the component lifecycle and determine which animation properties to apply based on the current state and data volume.
The diagram shows the decision flow from receiving data to applying specific animation properties to the chart components.
Sources: src/charts/useChartAnimation.ts:31-50, src/charts/animation.ts:40-45, src/charts/animation.ts:60-95
Data Matching Strategies
The engine solves the Recharts default behavior where indices are used to pair data, causing whole lines to rearrange when the array length changes. It provides three primary matching modes to handle different data stream types.
| Mode | Behavior | Use Case |
|---|---|---|
index | Pairs data by array index; stretches points proportionally. | Batch data replacement (initial load). |
append | Pairs data sequentially; new items fade in while old items stay in place. | Tail-appending streams like log viewers or monitors. |
matchByDataKey | Pairs points by a specific business ID (e.g., "id"). | Sliding window data (old points exit, new points enter). |
Sources: src/charts/animation.ts:14-25, src/charts/animation.ts:88-92
Component Lifecycle Management
The useChartAnimation hook manages the transition from "Initial" to "Incremental" states. It uses a useRef to track the first render because the first render status does not require a re-render cycle itself, and it uses requestAnimationFrame to ensure the first frame is fully drawn before switching to incremental mode.
This sequence ensures that the "drawing" animation only happens once, and subsequent updates use stable positioning.
Sources: src/charts/useChartAnimation.ts:33-47, src/charts/animation.ts:72-85
Configuration and Performance
The engine includes performance safeguards to prevent frame drops on low-end devices during high-volume data updates.
Animation Options
The ChartAnimationOptions interface allows consumers to customize the motion behavior:
match: Defines theAnimationMatchModeor a specific data key.duration: Defaults to 320ms to prevent perceived lag in live streams.easing: Defaults toease-outfor smoother deceleration.disabled: Manual override to disable all animations.
Sources: src/charts/animation.ts:30-38
Optimization Thresholds
Animations are automatically disabled when the data point count exceeds the ANIMATION_POINT_LIMIT.
// src/charts/animation.ts:43-48
export const ANIMATION_POINT_LIMIT = 800;
export function shouldDisableAnimation(pointCount: number): boolean {
return pointCount > ANIMATION_POINT_LIMIT;
}
Sources: src/charts/animation.ts:43-48
Integration with Chart Components
HX-UI chart components (e.g., HxLineChart, HxAreaChart, HxBarChart) integrate the engine by passing animation options through the useChartAnimation hook and spreading the resulting props onto the Recharts primitive elements.
// Example from src/charts/Charts.tsx:49-50
const anim = useChartAnimation({ ...animation }, data.length);
// ...
<Line
{...anim}
dataKey={s.dataKey}
// ... other props
/>
Sources: src/charts/Charts.tsx:49-50, src/charts/Charts.tsx:90-91, src/charts/Charts.tsx:135-136
The Chart Data Appending Engine ensures a stable visual experience for dynamic data by strictly controlling how Recharts pairs new data points with existing ones, prioritizing visual continuity over simple index-based transitions.