Skip to content
+

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
    • ChartDataProvider provides data to descendants.
    • ChartsSurface renders the SVG element.
  • Helpers
    • ChartContainer combines the Data Provider and Surface components.
    • ChartsWrapper styled 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:

  • LinePlot
  • BarPlot
  • ChartsXAxis
  • ChartsLegend
  • ChartsTooltip

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.

ABCDEX axis

Properties

ChartContainer takes all props that are not specific to a single graphical element. This includes:

  • The xAxis and yAxis props—see Axis for details
  • The colors prop—see Styling—Color palette for details
  • The series and dataset props

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:

  1. Define the clip path: Use <ChartsClipPath id={clipPathId} /> to establish the clip path for the drawing area. clipPathId must be a unique identifier.
  2. Wrap the Chart: Enclose the chart elements you want to clip within a <g> element. Set the clipPath attribute to url(#${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.