Skip to main content
Impact: HIGH - Significantly improves data visualization quality and animation polish
This skill provides guidance for creating professional data visualizations with smooth, staggered animations and proper labeling.

Bar Chart Animations

Stagger bar entrances with 3-5 frame delays and use spring() for organic motion.
const bars = data.map((item, i) => {
  const height = spring({ frame, fps, config: { damping: 18 } });
  return <div style={{ height: height * item.value }} />;
});
Staggering creates visual hierarchy and makes complex data easier to process. Use 3-5 frame delays between bars for the best effect.

Always Include Y-Axis Labels

Charts without axis labels are hard to read. Always add labeled tick marks.
<div style={{ display: "flex", alignItems: "flex-end", gap: 8 }}>{bars}</div>
Charts without axis labels fail to communicate scale and context. Always include both axes with clear labels.

Value Labels Inside Bars

Position value labels inside bars when height is sufficient, fade in after bar animates.
const barHeight = normalizedHeight * progress;

<div style={{ height: barHeight, backgroundColor: COLOR_BAR }}>
  {barHeight > 30 && (
    <span style={{ opacity: progress, fontSize: 11 }}>
      {item.value.toLocaleString()}
    </span>
  )}
</div>;
Small bars don’t have enough space for readable labels. The barHeight > 30 check ensures labels only appear when there’s sufficient space, preventing text overflow and visual clutter.

Pie Chart Animation

Animate segments using stroke-dashoffset, starting from 12 o’clock.
const circumference = 2 * Math.PI * radius;
const segmentLength = (value / total) * circumference;
const offset = interpolate(progress, [0, 1], [segmentLength, 0]);

<circle
  r={radius}
  cx={center}
  cy={center}
  fill="none"
  stroke={color}
  strokeWidth={strokeWidth}
  strokeDasharray={`${segmentLength} ${circumference}`}
  strokeDashoffset={offset}
  transform={`rotate(-90 ${center} ${center})`}
/>;
The rotate(-90) transform starts the animation at 12 o’clock (top) instead of 3 o’clock (right), which is the default SVG behavior.

Key Patterns

Use calculated delays for consistent timing:
const STAGGER_DELAY = 5; // frames between each bar
const delay = i * STAGGER_DELAY;
3-5 frames works well for most charts. Faster feels rushed, slower feels sluggish.
For chart animations, use moderate damping:
config: { damping: 18, stiffness: 80 }
This provides subtle bounce without looking cartoonish.
Show elements only when space permits:
{barHeight > 30 && <Label />}
Prevents cramped, unreadable layouts.

Common Mistakes to Avoid

Don’t animate all bars simultaneously - It’s overwhelming and loses the data story. Stagger entrances instead.
Don’t skip axis labels - Context-free charts are confusing. Always include labeled axes.
Don’t use linear interpolation for organic elements - Use spring() instead of interpolate() for natural motion.

Spring Physics

Learn how to configure springs for different effects

Sequencing

Master staggered animations and timing

Build docs developers (and LLMs) love