Animated Charts
Data-driven SVG charts that grow as they reveal — bars grow up from the baseline, lines and areas draw themselves along their stroke — triggered when they enter the viewport.
npx shadcn@latest add https://webberui.com/r/animated-charts.jsonPlayground
Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.
<AnimatedCharts />
Installation
npx shadcn@latest add https://webberui.com/r/animated-charts.jsonOr, once registries are configured in components.json, install it as @webberui/animated-charts.
Usage
import { AnimatedChart } from "@/components/ui/animated-charts";
const data = [
{ label: "January", value: 320 },
{ label: "February", value: 480 },
{ label: "March", value: 410 },
{ label: "April", value: 640 },
];
<AnimatedChart data={data} variant="line" />Switching variant on the same data gives you all three styles — line, bar, or area:
<AnimatedChart data={data} variant="bar" />
<AnimatedChart data={data} variant="area" />Custom colors (any CSS color; the default follows the text color and adapts to light and dark automatically):
<AnimatedChart data={data} variant="area" color="#6366f1" showValues />The chart width fills the container automatically (measured internally with a ResizeObserver), and the height is controlled by height.
Props
AnimatedChart
| Prop | Type | Default | Description |
|---|---|---|---|
data | ChartDataPoint[] | — | The chart data, laid out along the X axis in order |
variant | "line" | "bar" | "area" | "line" | Chart style |
height | number | 240 | SVG height (px, including the label strip at the bottom) |
color | string | currentColor | Line/bar color (any CSS color) |
duration | number | 1.2 | Duration of the line/area stroke growth (seconds) |
stagger | number | 0.08 | Stagger interval for bars and data points (seconds) |
delay | number | 0 | Delay before the reveal starts (seconds) |
showGrid | boolean | true | Whether to show horizontal grid lines |
showLabels | boolean | true | Whether to show X axis labels |
showDots | boolean | true | Whether lines/areas show dots at the data points |
showValues | boolean | false | Whether to show values on the data points/bars |
strokeWidth | number | 2 | Line stroke width (px) |
once | boolean | true | Play only the first time the element enters the viewport |
className | string | — | Class appended to the outermost container |
ChartDataPoint
| Field | Type | Description |
|---|---|---|
label | string | X axis label (for example a month or a category name) |
value | number | The value; bars grow from the baseline, lines/areas position themselves by it |
How it works
- Growth reveal: bars grow up from the baseline (the position of value 0) via
scaleY, withtransform-box: fill-boxplustransform-originmaking positive values expand from the bottom and negative values from the top; lines and areas are drawn with Motion'spathLengthfrom 0 to 1, with the area fill fading in alongside - Viewport trigger:
useInViewdetects entering the viewport before playing, andoncecontrols whether it plays only once - Responsive: the container width is measured internally with a
ResizeObserver, and the SVG is drawn in pixel coordinates (not a scaled viewBox), so strokes and dots never distort at any width; the Observer is cleaned up withdisconnecton unmount - Value range: the range always includes 0 as the bar baseline and supports negative values; when every value is identical it falls back to a safe ratio to avoid dividing by zero
- Color: the default is
currentColor, following the container's text color, so neutral colors and light/dark mode adapt automatically; pass any CSS color tocolorfor an accent. Grid lines and labels stay a fixed understated neutral and do not change with the series color - Stagger: bars and data points reveal one after another via
staggerChildrenat the container level
Accessibility
- When the user has "reduce motion" enabled at the system level, the chart shows its final state directly (bars at full height, paths complete, dots in place) with no growth animation, and the DOM structure matches SSR
- The SVG is marked
role="img"with anaria-label(a summary of "label: value" for each data point), plus ansr-onlytext summary for assistive technology to announce - Grid lines, bars, paths, dots, and value labels are all decorative and marked
aria-hidden
Pricing Table
A pricing table with a monthly/yearly segmented switch; prices spring-tween on switch, the selected pill slides, the featured plan scales up and is highlighted, and yearly shows a discount badge.
Activity Feed
A live list that inserts items automatically — new events push in from the top and existing rows reflow smoothly with FLIP — with timeline and relative-time support.