Charts - Composition
Learn how to use composition to build advanced custom Charts.
The MUI X Charts components follow an architecture based on context providers: you can pass your series and axes definitions to specialized components that transform the data and make it available to its descendants. These descendants can then be composed.
There are two main types of components used to create Charts: structural and graphical.
Structural components
Structural components are used to define a chart's dimensions, surfaces, and data.
- Basics
ChartDataProviderprovides data to descendants.ChartsSurfacerenders the SVG element.
- Helpers
ChartContainercombines the Data Provider and Surface components.ChartsWrapperstyled div that positions surface, tooltip, and legend on a grid.
Chart Data Provider and Surface usage
Notice that the width and height props are passed to ChartDataProvider and not ChartsSurface.
ChartsLegend is placed inside ChartDataProvider to get access to the context, but outside ChartsSurface since it's not an SVG component.
<ChartDataProvider
// The configuration of the chart
series={[{ type: 'bar', data: [100, 200] }]}
xAxis={[{ scaleType: 'band', data: ['A', 'B'] }]}
width={500}
height={300}
>
<ChartsLegend />
<ChartsSurface
// Ref needs to be directly on ChartsSurface
ref={mySvgRef}
>
{children}
</ChartsSurface>
</ChartDataProvider>
Chart Container usage
ChartContainer is the direct concatenation of ChartDataProvider and ChartsSurface.
It takes care of dispatching props between the two components.
Using ChartContainer has one major drawback: all the children will be inside ChartsSurface.
You can't render HTML elements such as ChartsLegend as shown in the previous example.
<ChartContainer
// The configuration of the chart
series={[{ type: 'bar', data: [100, 200] }]}
xAxis={[{ scaleType: 'band', data: ['A', 'B'] }]}
width={500}
height={300}
// Ref is forwarded internally to ChartsSurface
ref={mySvgRef}
>
{children} // Only SVG component here
</ChartContainer>
Chart Wrapper usage
Charts are often constructed of a graphic with a legend.
ChartsWrapper helps position those elements in a grid structure.
The children should have a CSS gridArea property set to 'chart', 'legend', or 'toolbar'.
This is done by default on built-in components.
The layout can be modified with the wrapper props.
<ChartDataProvider height={300} series={ /* ... */ }>
<ChartsWrapper legendDirection='horizontal' legendPosition={{ vertical: 'bottom' }}>
<ChartsLegend direction='horizontal' />
<ChartsSurface>
{children}
</ChartsSurface>
</ChartsWrapper>
</ChartDataProvider>
Graphical components
Graphical components are used to render the visual elements of a chart.
They are descendants of ChartDataProvider described above.
These are too numerous to list, but common examples include:
LinePlotBarPlotChartsXAxisChartsLegendChartsTooltip
You can also create your own custom components for this purpose.
Container options
Responsive dimensions
ChartContainer is responsive by default: it automatically adjusts its dimensions to fit the available space defined by the parent element.
Provide the width and height props to define the dimensions of a chart.
The demo below lets you switch between a chart with discrete dimensions (width={500} height={300}) and one with no dimensions defined, so you see how they differ.
Properties
ChartContainer takes all props that are not specific to a single graphical element.
This includes:
- The
xAxisandyAxisprops—see Axis for details - The
colorsprop—see Styling—Color palette for details - The
seriesanddatasetprops
Series
The series prop is an array of series definitions.
See the following documents to learn more about each specific series type:
When using a self-contained Chart component, it's assumed that the series type corresponds to the Chart type.
For example, BarChart assumes that series is of type 'bar'.
<BarChart
series={[
{
// No need to specify the series type
data: [1, 2, 3],
},
]}
/>
When composing a custom chart, ChartContainer doesn't know the series type, so you must explicitly define it.
For example, the custom chart below uses both BarPlot and LinePlot, and each one requires a corresponding type for its data.
<ChartContainer
series={[
// This series is for the bar plot
{ data: [1, 2, 3], type: 'bar' },
// This series is for the line plot
{ data: [3, 2, 1], type: 'line' },
]}
>
<BarPlot /> {/* Only displays the series with type: 'bar' */}
<LinePlot /> {/* Only displays series with type: 'line' */}
</ChartContainer>
Those series can use the dataset prop the same way that a single-component chart does.
See Bars—Using a dataset for more details.
In the demo below, the chart is constructed by combining BarPlot and LinePlot.
You can modify the series type property to switch between rendering a line and a bar.
<ChartContainer
series={[
{ type, data: [1, 2, 3, 2, 1] },
{ type, data: [4, 3, 1, 3, 4] },
]}
>
<BarPlot />
<LinePlot />
<ChartsXAxis label="X axis" axisId="x-axis-id" />
</ChartContainer>
Subcomponents
Plotting
To display data, you can use the components named [Type]Plot such as LinePlot, AreaPlot, MarkPlot, BarPlot, and more.
Clipping
Use the ChartsClipPath component to ensure chart elements stay confined to the designated drawing area.
This component defines a rectangular clip path that acts as a boundary.
Here's how to apply it:
- Define the clip path: Use
<ChartsClipPath id={clipPathId} />to establish the clip path for the drawing area.clipPathIdmust be a unique identifier. - Wrap the Chart: Enclose the chart elements you want to clip within a
<g>element. Set theclipPathattribute tourl(#${clipPathId})to reference the previously defined clip path. Example:<g clipPath={`url(#${clipPathId})`}>
<ChartContainer>
<g clipPath={`url(#${clipPathId})`}>
// The plotting to clip in the drawing area.
<ScatterPlot />
<LinePlot />
</g>
<ChartsClipPath id={clipPathId} /> // Defines the clip path of the drawing area.
</ChartContainer>
The demo below lets you toggle clipping for scatter and line plots. Observe how the line markers extend beyond the clip area, rendering on top of the axes.
Axis
To add axes, use ChartsXAxis and ChartsYAxis as described in Axis—Composition.
These components take an axisId prop that indicates which axis defined in the container should be rendered.
If axisId is not provided, the first axis is used by default.
Grid
Use ChartsGrid to add a grid to the component.
See Axis—Grid for more information.
Legend
Use ChartsLegend to display a legend with information about the chart.
See HTML components for more information about custom legends.
Interaction
You can add interactive elements such as ChartsAxisHighlight and ChartsTooltip as illustrated in the demo below.
- Sales Data
Examples
Bell curve
This example demonstrates how to combine scatter and line plots to overlay a normal distribution curve (known as a bell curve) over scattered data points. The bell curve is calculated based on the mean and standard deviation of the data.
API
See the documentation below for a complete reference to all of the props and classes available to the components mentioned here.