beta
Chart — <mv-chart>
Dependency-free SVG chart (area, bar, line, sparkline): pixel-perfect rendering, rounded scale, animated draw-in on appearance, crosshair and tooltip on hover and keyboard, and a data table for screen readers.
| Category | Data display |
|---|---|
| Type | Web Component (<mv-chart>) |
| Status | beta |
| Keywords | chart, graph, area, bar, line, sparkline, dataviz, dashboard |
When to use
- A dashboard needs a simple area, bar or line chart with tooltips and no charting dependency
- KPI tiles need tiny sparklines with no axes to show a trend next to a figure
- Values must be formatted as currency, percent or compact numbers and stay accessible via a data table
Avoid when
- Only a single headline number with a trend is needed → use Number Ticker instead
- The data needs scatter, pie, stacked series, dual axes or zoom; only area, bar, line and sparkline are drawn
- Exact values must be read and compared across many rows → use Table instead
Install
node scripts/add.mjs chart --out ./src/marvelousAI agent with the Marvelous UI MCP server: install_components({ slugs: ["chart"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).
Files copied (dependencies included): tokens/tokens.css, core/base.css, core/dom.js, core/element.js, core/motion.js, core/observe.js, components/chart/chart.js, components/chart/chart.css.
Usage
Canonical markup — start from it and customize with attributes, data-* and CSS variables:
<div id="chart-demo" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,22rem),1fr));gap:1rem;width:100%;max-width:64rem;margin-inline:auto">
<article class="mv-card" style="grid-column:1/-1">
<header class="mv-card-header">
<h3 class="mv-card-title">Revenue</h3>
<p class="mv-card-description">2026 vs. 2025, by month</p>
</header>
<div class="mv-card-content">
<mv-chart type="area" format="currency" height="240" label="Monthly revenue, 2026 and 2025"
data='{"labels":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"series":[{"name":"2026","values":[31200,34800,33100,39400,42800,41200,45900,38700,48290,null,null,null]},{"name":"2025","values":[26400,27900,30100,29800,33600,35200,34100,30900,37800,40200,43900,47100]}]}'></mv-chart>
</div>
</article>
<article class="mv-card">
<header class="mv-card-header">
<h3 class="mv-card-title">New sign-ups</h3>
<p class="mv-card-description">Last 14 days</p>
</header>
<div class="mv-card-content">
<mv-chart type="bar" height="200" label="Daily sign-ups"
data='{"labels":["10","11","12","13","14","15","16","17","18","19","20","21","22","23"],"series":[{"name":"Sign-ups","values":[42,58,51,64,72,38,31,69,77,81,74,93,48,40]}]}'></mv-chart>
</div>
</article>
<article class="mv-card">
<header class="mv-card-header">
<h3 class="mv-card-title">Response time</h3>
<p class="mv-card-description">Median and 95th percentile, in ms</p>
</header>
<div class="mv-card-content">
<mv-chart type="line" height="200" curve="linear" label="API response time"
data='{"labels":["12 AM","3 AM","6 AM","9 AM","12 PM","3 PM","6 PM","9 PM"],"series":[{"name":"Median","values":[82,76,79,118,134,126,142,96]},{"name":"p95","values":[210,188,204,312,356,338,388,254]}]}'></mv-chart>
</div>
</article>
</div>API
Attributes
| Name | Type | Default | Description |
|---|---|---|---|
type | area | bar | line | area | Chart type. |
data | JSON | { labels: string[], series: [{ name, values: number[], color? }] }. Also via the data property or a <script type="application/json"> child. | |
height | number (px) | 240 (44 as sparkline) | Height of the plot area. |
label | string | Accessible name of the chart and caption of the data table. | |
format | decimal | currency | percent | decimal | Intl format of the values (axis, tooltip, table). |
currency | ISO 4217 | USD | Currency for format=currency. |
compact | boolean | Compact notation everywhere (12.4K). The axis switches to compact above 10,000. | |
locale | BCP 47 | en-US | Formatting locale. |
curve | smooth | linear | smooth | Monotone interpolation (no overshoot) or straight segments. |
sparkline | boolean | Mini chart with no axes or interaction (KPI tiles). | |
legend | true | false | auto (≥ 2 series) | Forces or hides the legend. |
animate | view | none | view | Animated draw-in the first time it appears on screen. |
Properties
| Name | Type | Description |
|---|---|---|
data | object | Read/write; writing redraws instantly. |
Methods
| Name | Description |
|---|---|
render() | Redraws (called automatically on resize). |
Events
| Name | Description |
|---|---|
mv-hover | Active point changed. detail: { index, label }. |
CSS classes
| Name | Description |
|---|---|
mv-chart-legend / -plot / -tooltip | Generated, stylable parts. |
CSS variables
| Name | Description |
|---|---|
--mv-chart-1 … --mv-chart-5 | Categorical palette, in a fixed order (1 = accent). |
--mv-chart-grid | Grid line color. |
--mv-chart-surface | Color of the ring around points (= card background). |
Accessibility
role=group + aria-roledescription “chart” and aria-label; focusable: ← → Home End step through the points and the value is announced (aria-live). A visually hidden data table lists every value. The SVG is aria-hidden. Color is never the only cue: a legend appears for ≥ 2 series. Reduced motion: no draw-in animation.