charts
MUI X Charts
Package
npm install @mui/x-charts
# Free, MIT license — all chart types included
All charts are available in the free Community tier.
Basic Charts
BarChart
import { BarChart } from '@mui/x-charts/BarChart';
const data = [
{ month: 'Jan', revenue: 4000, expenses: 2400 },
{ month: 'Feb', revenue: 3000, expenses: 1398 },
{ month: 'Mar', revenue: 2000, expenses: 9800 },
{ month: 'Apr', revenue: 2780, expenses: 3908 },
];
<BarChart
dataset={data}
xAxis={[{ scaleType: 'band', dataKey: 'month' }]}
series={[
{ dataKey: 'revenue', label: 'Revenue', color: '#2563eb' },
{ dataKey: 'expenses', label: 'Expenses', color: '#dc2626' },
]}
width={600}
height={400}
/>
Horizontal Bar Chart
<BarChart
dataset={data}
yAxis={[{ scaleType: 'band', dataKey: 'month' }]}
series={[{ dataKey: 'revenue', label: 'Revenue' }]}
layout="horizontal"
width={600}
height={400}
/>
LineChart
import { LineChart } from '@mui/x-charts/LineChart';
<LineChart
xAxis={[{
scaleType: 'time',
data: [new Date(2024, 0), new Date(2024, 1), new Date(2024, 2), new Date(2024, 3)],
valueFormatter: (date: Date) => date.toLocaleDateString('en-US', { month: 'short' }),
}]}
series={[
{
data: [2400, 1398, 9800, 3908],
label: 'Revenue',
area: true, // fill area under line
curve: 'catmullRom', // 'linear' | 'monotoneX' | 'catmullRom' | 'step'
showMark: true,
},
]}
width={600}
height={400}
/>
PieChart
import { PieChart } from '@mui/x-charts/PieChart';
<PieChart
series={[{
data: [
{ id: 0, value: 10, label: 'Series A', color: '#2563eb' },
{ id: 1, value: 15, label: 'Series B', color: '#7c3aed' },
{ id: 2, value: 20, label: 'Series C', color: '#16a34a' },
],
innerRadius: 30, // donut chart when > 0
outerRadius: 100,
paddingAngle: 2,
cornerRadius: 5,
startAngle: -90,
endAngle: 270,
cx: 150,
cy: 150,
highlightScope: { faded: 'global', highlighted: 'item' },
faded: { innerRadius: 30, additionalRadius: -30, color: 'gray' },
}]}
width={400}
height={300}
/>
ScatterChart
import { ScatterChart } from '@mui/x-charts/ScatterChart';
<ScatterChart
series={[{
label: 'Height vs Weight',
data: [
{ x: 170, y: 70, id: 'p1' },
{ x: 175, y: 85, id: 'p2' },
{ x: 160, y: 60, id: 'p3' },
{ x: 180, y: 90, id: 'p4' },
],
}]}
xAxis={[{ label: 'Height (cm)' }]}
yAxis={[{ label: 'Weight (kg)' }]}
width={500}
height={400}
/>
Composition API
Build charts from primitives for maximum control. Mix chart types in one view.
import {
ResponsiveChartContainer,
BarPlot,
LinePlot,
ChartsXAxis,
ChartsYAxis,
ChartsTooltip,
ChartsAxisHighlight,
ChartsLegend,
ChartsGrid,
MarkPlot,
} from '@mui/x-charts';
// Mixed bar + line chart with dual Y-axis
<ResponsiveChartContainer
series={[
{ type: 'bar', data: [10, 20, 15, 25], label: 'Revenue ($K)', yAxisId: 'leftAxis' },
{ type: 'line', data: [5, 15, 10, 20], label: 'Growth (%)', yAxisId: 'rightAxis' },
]}
xAxis={[{
id: 'x-axis',
data: ['Q1', 'Q2', 'Q3', 'Q4'],
scaleType: 'band',
}]}
yAxis={[
{ id: 'leftAxis', label: 'Revenue ($K)' },
{ id: 'rightAxis', label: 'Growth (%)', position: 'right' },
]}
height={400}
>
<ChartsGrid horizontal />
<BarPlot />
<LinePlot />
<MarkPlot />
<ChartsXAxis axisId="x-axis" />
<ChartsYAxis axisId="leftAxis" />
<ChartsYAxis axisId="rightAxis" position="right" />
<ChartsTooltip trigger="axis" />
<ChartsAxisHighlight x="band" />
<ChartsLegend />
</ResponsiveChartContainer>
Why Composition?
- Mix bar + line + scatter in one chart
- Dual Y-axis configurations
- Custom layout ordering (what renders on top)
- Add custom SVG elements between chart layers
- Full control over which sub-components are included
Custom Axes
Scale Types
// Band axis (categorical) — most common for bar charts
xAxis={[{ scaleType: 'band', data: ['Jan', 'Feb', 'Mar'] }]}
// Linear axis (numeric) — scatter plots, continuous data
yAxis={[{ scaleType: 'linear', min: 0, max: 100 }]}
// Time axis — date values
xAxis={[{
scaleType: 'time',
data: [new Date('2024-01-01'), new Date('2024-02-01'), new Date('2024-03-01')],
valueFormatter: (date: Date) => date.toLocaleDateString(),
}]}
// Log axis — logarithmic scale
yAxis={[{ scaleType: 'log', min: 1, max: 10000 }]}
// Point axis — evenly spaced regardless of value
xAxis={[{ scaleType: 'point', data: [1, 10, 100, 1000] }]}
Tick Formatting
yAxis={[{
valueFormatter: (value: number) => `$${(value / 1000).toFixed(0)}K`,
label: 'Revenue',
tickMinStep: 1000,
tickMaxStep: 5000,
}]}
Dual Y-Axis
yAxis={[
{ id: 'left', label: 'Revenue ($)', position: 'left' },
{ id: 'right', label: 'Percentage (%)', position: 'right', min: 0, max: 100 },
]}
series={[
{ data: [1000, 2000, 3000], yAxisId: 'left', type: 'bar' },
{ data: [20, 45, 80], yAxisId: 'right', type: 'line' },
]}
Custom Tooltips
Built-in Tooltip Modes
// Show tooltip per data item (hover over specific bar/point)
<ChartsTooltip trigger="item" />
// Show tooltip for entire axis value (all series at that x position)
<ChartsTooltip trigger="axis" />
// Disable tooltip
<ChartsTooltip trigger="none" />
Custom Tooltip Content
import { ChartsTooltip, type ChartsItemContentProps } from '@mui/x-charts';
import Paper from '@mui/material/Paper';
import Typography from '@mui/material/Typography';
function CustomItemTooltip(props: ChartsItemContentProps) {
const { series, dataIndex, color } = props;
if (dataIndex === undefined) return null;
return (
<Paper sx={{ p: 1.5, borderRadius: 1 }} elevation={4}>
<Typography variant="caption" sx={{ color }}>
{series.label}
</Typography>
<Typography variant="body2" fontWeight={700}>
${series.data[dataIndex]?.toLocaleString()}
</Typography>
</Paper>
);
}
<BarChart
series={[...]}
slots={{ itemContent: CustomItemTooltip }}
/>
Legends
// Position legend at the top
<BarChart
series={[...]}
slotProps={{
legend: {
direction: 'row', // 'row' | 'column'
position: {
vertical: 'top', // 'top' | 'middle' | 'bottom'
horizontal: 'middle', // 'left' | 'middle' | 'right'
},
padding: { top: 20 },
itemMarkWidth: 10,
itemMarkHeight: 10,
markGap: 5,
itemGap: 15,
},
}}
/>
// Hide legend
<BarChart
series={[...]}
slotProps={{ legend: { hidden: true } }}
/>
Click Handlers & Interactivity
<BarChart
series={[{ data: [10, 20, 30], label: 'Revenue' }]}
xAxis={[{ scaleType: 'band', data: ['Jan', 'Feb', 'Mar'] }]}
onItemClick={(event, d) => {
// d.type: 'bar' | 'line' | 'scatter' | 'pie'
// d.seriesId: string
// d.dataIndex: number
console.log(`Clicked: series=${d.seriesId}, index=${d.dataIndex}`);
router.push(`/details/${data[d.dataIndex].id}`);
}}
onAxisClick={(event, d) => {
// d.axisValue: the x-axis value at click position
// d.dataIndex: index into the data array
console.log(`Axis clicked: ${d.axisValue}`);
}}
/>
Highlight & Dim
<BarChart
series={[
{
data: [10, 20, 30],
highlightScope: { highlighted: 'item', faded: 'global' },
},
]}
/>
Responsive Charts
Charts auto-fill parent width when using ResponsiveChartContainer or when width/height are omitted on basic charts with a sized parent.
// Parent must have explicit dimensions
<Box sx={{ width: '100%', height: 400 }}>
<BarChart
series={[...]}
xAxis={[...]}
// width and height omitted — fills parent
/>
</Box>
// Or use ResponsiveChartContainer for composition
<Box sx={{ width: '100%', height: 400 }}>
<ResponsiveChartContainer series={[...]} xAxis={[...]}>
<BarPlot />
<ChartsXAxis />
<ChartsYAxis />
</ResponsiveChartContainer>
</Box>
Margin Configuration
<BarChart
margin={{ top: 20, right: 30, bottom: 40, left: 60 }}
// Increase left margin for wide y-axis labels
// Increase bottom for rotated x-axis labels
/>
Stacked Series
<BarChart
series={[
{ data: [10, 15, 20], stack: 'total', label: 'Product A' },
{ data: [5, 10, 15], stack: 'total', label: 'Product B' },
{ data: [3, 7, 12], stack: 'total', label: 'Product C' },
]}
xAxis={[{ scaleType: 'band', data: ['Q1', 'Q2', 'Q3'] }]}
/>
// Stacked area chart
<LineChart
series={[
{ data: [10, 15, 20], area: true, stack: 'total', label: 'Desktop' },
{ data: [5, 10, 15], area: true, stack: 'total', label: 'Mobile' },
{ data: [3, 7, 12], area: true, stack: 'total', label: 'Tablet' },
]}
/>
Multiple stack groups:
series={[
{ data: [10, 15], stack: 'group1', stackOrder: 'ascending' },
{ data: [5, 10], stack: 'group1' },
{ data: [3, 7], stack: 'group2' }, // separate stack
]}
Animation
// Disable animation
<BarChart
skipAnimation={true}
series={[...]}
/>
// Animations are enabled by default with sensible durations
// Custom duration/easing not directly exposed as props — use CSS transitions
// for additional animation effects on the container
Color Palette
Custom Colors per Series
<BarChart
series={[
{ data: [10, 20, 30], label: 'A', color: '#2563eb' },
{ data: [5, 15, 25], label: 'B', color: '#7c3aed' },
]}
/>
Categorical Palette
import { blueberryTwilightPalette, mangoFusionPalette, cheerfulFiestaPalette } from '@mui/x-charts/colorPalettes';
<BarChart
colors={mangoFusionPalette}
series={[...]}
/>
Theme-Aware Colors
import { useTheme } from '@mui/material/styles';
function ThemedChart({ data }) {
const theme = useTheme();
return (
<BarChart
series={[
{ data: data.values, color: theme.palette.primary.main },
]}
sx={{
'& .MuiChartsAxis-tickLabel': {
fill: theme.palette.text.secondary,
},
'& .MuiChartsAxis-line': {
stroke: theme.palette.divider,
},
}}
/>
);
}
SparkLineChart
Inline mini charts for dashboards and tables.
import { SparkLineChart } from '@mui/x-charts/SparkLineChart';
// Line sparkline
<SparkLineChart
data={[1, 4, 2, 5, 7, 2, 4, 6]}
height={40}
width={150}
curve="natural"
area
colors={['#2563eb']}
/>
// Bar sparkline
<SparkLineChart
data={[3, 1, 4, 1, 5, 9, 2, 6]}
height={40}
width={150}
plotType="bar"
colors={['#16a34a']}
/>
// In a DataGrid cell
const columns: GridColDef[] = [
{ field: 'name', headerName: 'Product' },
{
field: 'trend',
headerName: 'Last 7 Days',
width: 150,
renderCell: (params) => (
<SparkLineChart
data={params.value}
height={30}
width={120}
area
colors={[params.value[params.value.length - 1] > params.value[0] ? '#16a34a' : '#dc2626']}
/>
),
},
];
Gauge Charts
import { Gauge, gaugeClasses } from '@mui/x-charts/Gauge';
// Simple gauge
<Gauge
value={75}
startAngle={-110}
endAngle={110}
width={200}
height={200}
text={({ value }) => `${value}%`}
sx={{
[`& .${gaugeClasses.valueArc}`]: {
fill: '#2563eb',
},
[`& .${gaugeClasses.valueText}`]: {
fontSize: 24,
fontWeight: 'bold',
},
}}
/>
Dataset Approach
Pass a dataset array and reference fields by dataKey:
const dataset = [
{ month: 'Jan', revenue: 4000, profit: 2400 },
{ month: 'Feb', revenue: 3000, profit: 1398 },
{ month: 'Mar', revenue: 2000, profit: 800 },
];
<BarChart
dataset={dataset}
xAxis={[{ scaleType: 'band', dataKey: 'month' }]}
series={[
{ dataKey: 'revenue', label: 'Revenue' },
{ dataKey: 'profit', label: 'Profit' },
]}
/>
This is the preferred pattern when data comes from an API — avoids manual array extraction.
Styling with sx
<BarChart
series={[...]}
sx={{
// Axis labels
'& .MuiChartsAxis-tickLabel': {
fontSize: '0.75rem',
fill: 'text.secondary',
},
// Axis lines
'& .MuiChartsAxis-line': {
stroke: 'divider',
},
// Grid lines
'& .MuiChartsGrid-line': {
strokeDasharray: '4 4',
stroke: 'divider',
},
// Legend text
'& .MuiChartsLegend-series text': {
fontSize: '0.8rem !important',
},
}}
/>
Performance Tips
- Use
dataset+dataKeyinstead of extracting arrays manually - For large datasets (1000+ points), consider downsampling before rendering
skipAnimationfor frequently updating charts (real-time data)- Lazy-load chart components with
React.lazy:const BarChart = lazy(() => import('@mui/x-charts/BarChart').then(m => ({ default: m.BarChart }))); - Charts auto-resize on window resize — avoid unnecessary re-renders of the parent
More from lobbi-docs/claude
vision-multimodal
Vision and multimodal capabilities for Claude including image analysis, PDF processing, and document understanding. Activate for image input, base64 encoding, multiple images, and visual analysis.
242design-system
Apply and manage the AI-powered design system with 50+ curated styles
126complex-reasoning
Multi-step reasoning patterns and frameworks for systematic problem solving. Activate for Chain-of-Thought, Tree-of-Thought, hypothesis-driven debugging, and structured analytical approaches that leverage extended thinking.
105gcp
Google Cloud Platform services including GKE, Cloud Run, Cloud Storage, BigQuery, and Pub/Sub. Activate for GCP infrastructure, Google Cloud deployment, and GCP integration.
73kanban
Kanban methodology including boards, WIP limits, flow metrics, and continuous delivery. Activate for Kanban boards, workflow visualization, and lean project management.
62debugging
Debugging techniques for Python, JavaScript, and distributed systems. Activate for troubleshooting, error analysis, log investigation, and performance debugging. Includes extended thinking integration for complex debugging scenarios.
59