@patternfly/react-charts
Version:
This library provides a set of React chart components for use with the PatternFly reference implementation.
430 lines (395 loc) • 15 kB
Markdown
---
id: Stack chart
section: charts
propComponents: [
'Chart',
'ChartArea',
'ChartBar',
'ChartStack',
'ChartTooltip'
]
hideDarkMode: true
---
import { createRef } from 'react';
import {
Chart,
ChartArea,
ChartAxis,
ChartBar,
ChartStack,
ChartLegendTooltip,
ChartThemeColor,
ChartTooltip,
ChartVoronoiContainer,
createContainer
} from '@patternfly/react-charts/victory';
import { getResizeObserver } from '@patternfly/react-core';
## Introduction
Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)!
The examples below are based on the [Victory](https://formidable.com/open-source/victory/docs/victory-chart/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior.
## Examples
### Basic with right aligned legend
```js
import { Chart, ChartAxis, ChartBar, ChartStack, ChartVoronoiContainer } from '@patternfly/react-charts/victory';
<div style={{ height: '250px', width: '600px' }}>
<Chart
ariaDesc="Average number of pets"
ariaTitle="Stack chart example"
containerComponent={<ChartVoronoiContainer labels={({ datum }) => `${datum.name}: ${datum.y}`} constrainToVisibleArea />}
domainPadding={{ x: [30, 25] }}
legendData={[{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }, { name: 'Mice' }]}
legendOrientation="vertical"
legendPosition="right"
height={250}
name="chart1"
padding={{
bottom: 50,
left: 50,
right: 200, // Adjusted to accommodate legend
top: 50
}}
width={600}
>
<ChartAxis />
<ChartAxis dependentAxis showGrid />
<ChartStack>
<ChartBar data={[{ name: 'Cats', x: '2015', y: 1 }, { name: 'Cats', x: '2016', y: 2 }, { name: 'Cats', x: '2017', y: 5 }, { name: 'Cats', x: '2018', y: 3 }]} />
<ChartBar data={[{ name: 'Dogs', x: '2015', y: 2 }, { name: 'Dogs', x: '2016', y: 1 }, { name: 'Dogs', x: '2017', y: 7 }, { name: 'Dogs', x: '2018', y: 4 }]} />
<ChartBar data={[{ name: 'Birds', x: '2015', y: 4 }, { name: 'Birds', x: '2016', y: 4 }, { name: 'Birds', x: '2017', y: 9 }, { name: 'Birds', x: '2018', y: 7 }]} />
<ChartBar data={[{ name: 'Mice', x: '2015', y: 3 }, { name: 'Mice', x: '2016', y: 3 }, { name: 'Mice', x: '2017', y: 8 }, { name: 'Mice', x: '2018', y: 5 }]} />
</ChartStack>
</Chart>
</div>
```
### Horizontal with bottom aligned legend
```js
import { Chart, ChartAxis, ChartBar, ChartStack, ChartThemeColor, ChartVoronoiContainer } from '@patternfly/react-charts/victory';
<div style={{ height: '275px', width: '450px' }}>
<Chart
ariaDesc="Average number of pets"
ariaTitle="Stack chart example"
containerComponent={<ChartVoronoiContainer labels={({ datum }) => `${datum.name}: ${datum.y}`} constrainToVisibleArea />}
domainPadding={{ x: [30, 25] }}
legendData={[{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }, { name: 'Mice' }]}
legendPosition="bottom"
height={275}
name="chart2"
padding={{
bottom: 75, // Adjusted to accommodate legend
left: 50,
right: 50,
top: 50
}}
themeColor={ChartThemeColor.yellow}
width={450}
>
<ChartAxis />
<ChartAxis dependentAxis showGrid />
<ChartStack>
<ChartBar data={[{ name: 'Cats', x: '2015', y: 1 }, { name: 'Cats', x: '2016', y: 2 }, { name: 'Cats', x: '2017', y: 5 }, { name: 'Cats', x: '2018', y: 3 }]} />
<ChartBar data={[{ name: 'Dogs', x: '2015', y: 2 }, { name: 'Dogs', x: '2016', y: 1 }, { name: 'Dogs', x: '2017', y: 7 }, { name: 'Dogs', x: '2018', y: 4 }]} />
<ChartBar data={[{ name: 'Birds', x: '2015', y: 4 }, { name: 'Birds', x: '2016', y: 4 }, { name: 'Birds', x: '2017', y: 9 }, { name: 'Birds', x: '2018', y: 7 }]} />
<ChartBar data={[{ name: 'Mice', x: '2015', y: 3 }, { name: 'Mice', x: '2016', y: 3 }, { name: 'Mice', x: '2017', y: 8 }, { name: 'Mice', x: '2018', y: 5 }]} />
</ChartStack>
</Chart>
</div>
```
### Multi-color (ordered) horizontal with bottom aligned legend
This demonstrates an alternate way of applying tooltips using data labels.
```js
import { Chart, ChartBar, ChartAxis, ChartStack, ChartThemeColor, ChartTooltip } from '@patternfly/react-charts/victory';
<div style={{ height: '275px', width: '450px' }}>
<Chart
ariaDesc="Average number of pets"
ariaTitle="Stack chart example"
domainPadding={{ x: [30, 25] }}
legendData={[{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }, { name: 'Mice' }]}
legendPosition="bottom-left"
height={275}
name="chart3"
padding={{
bottom: 75, // Adjusted to accommodate legend
left: 50,
right: 50,
top: 50
}}
themeColor={ChartThemeColor.multiOrdered}
width={450}
>
<ChartAxis />
<ChartAxis dependentAxis showGrid />
<ChartStack horizontal>
<ChartBar
data={[
{ name: 'Cats', x: '2015', y: 1, label: 'Cats: 1' },
{ name: 'Cats', x: '2016', y: 2, label: 'Cats: 2' },
{ name: 'Cats', x: '2017', y: 5, label: 'Cats: 5' },
{ name: 'Cats', x: '2018', y: 3, label: 'Cats: 3' }
]}
labelComponent={<ChartTooltip constrainToVisibleArea />}
/>
<ChartBar
data={[
{ name: 'Dogs', x: '2015', y: 2, label: 'Dogs: 2' },
{ name: 'Dogs', x: '2016', y: 1, label: 'Dogs: 1' },
{ name: 'Dogs', x: '2017', y: 7, label: 'Dogs: 7' },
{ name: 'Dogs', x: '2018', y: 4, label: 'Dogs: 4' }
]}
labelComponent={<ChartTooltip constrainToVisibleArea />}
/>
<ChartBar
data={[
{ name: 'Birds', x: '2015', y: 4, label: 'Birds: 4' },
{ name: 'Birds', x: '2016', y: 4, label: 'Birds: 4' },
{ name: 'Birds', x: '2017', y: 9, label: 'Birds: 9' },
{ name: 'Birds', x: '2018', y: 7, label: 'Birds: 7' }
]}
labelComponent={<ChartTooltip constrainToVisibleArea />}
/>
<ChartBar
data={[
{ name: 'Mice', x: '2015', y: 3, label: 'Mice: 3' },
{ name: 'Mice', x: '2016', y: 3, label: 'Mice: 3' },
{ name: 'Mice', x: '2017', y: 8, label: 'Mice: 8' },
{ name: 'Mice', x: '2018', y: 5, label: 'Mice: 5' }
]}
labelComponent={<ChartTooltip constrainToVisibleArea />}
/>
</ChartStack>
</Chart>
</div>
```
### Monthly data with responsive container
```js
import { Chart, ChartAxis, ChartBar, ChartStack, ChartTooltip } from '@patternfly/react-charts/victory';
import { getResizeObserver } from '@patternfly/react-core';
class MonthlyResponsiveStack extends React.Component {
constructor(props) {
super(props);
this.containerRef = createRef();
this.observer = () => {};
this.state = {
width: 0
};
this.handleResize = () => {
if(this.containerRef.current && this.containerRef.current.clientWidth){
this.setState({ width: this.containerRef.current.clientWidth });
}
};
this.bars = [];
for(let i = 1; i < 32; i++){
this.bars.push({ x: `Aug. ${i}`, y: Math.floor(Math.random() * 6) + 1 });
};
this.renderSocketBars = () => {
let socketBars = this.bars.map((tick, index) => {
return {
x: tick.x,
y: tick.y,
name: 'Sockets',
label: `${tick.x} Sockets: ${tick.y}`
};
});
return <ChartBar data={socketBars} labelComponent={<ChartTooltip constrainToVisibleArea />} />;
}
this.renderCoresBars = () => {
let coresBars = this.bars.map((tick, index) => {
return {
x: tick.x,
y: tick.y,
name: 'Cores',
label: `${tick.x} Cores: ${tick.y}`
};
});
return <ChartBar data={coresBars} labelComponent={<ChartTooltip constrainToVisibleArea />} />;
}
this.renderNodesBars = () => {
let nodesBars = this.bars.map((tick, index) => {
return {
key: index,
x: tick.x,
y: tick.y,
name: 'Nodes',
label: `${tick.x} Nodes: ${tick.y}`
};
});
return <ChartBar data={nodesBars} labelComponent={<ChartTooltip constrainToVisibleArea />} />;
}
this.getTickValues = (offset = 2) => {
let tickValues = [];
for(let i = 1; i < 32; i++){
if (i % offset == 0){
tickValues.push(`Aug. ${i}`);
}
}
return tickValues;
}
}
componentDidMount() {
this.observer = getResizeObserver(this.containerRef.current, this.handleResize);
this.handleResize();
}
componentWillUnmount() {
this.observer();
}
render(){
const { width } = this.state;
return (
<div ref={this.containerRef}>
<div style={{ height: '225px' }}>
<Chart
ariaDesc="Stack Chart with monthly metric data"
ariaTitle="Monthly Stack Chart"
domainPadding={{ x: [30, 25] }}
legendData={[{ name: 'Sockets' }, { name: 'Cores' }, { name: 'Nodes' }]}
legendPosition="bottom"
height={225}
name="chart4"
padding={{
bottom: 75, // Adjusted to accommodate legend
left: 50,
right: 50,
top: 50
}}
width={width}
>
<ChartAxis tickValues = {this.getTickValues()} fixLabelOverlap />
<ChartAxis dependentAxis showGrid />
<ChartStack domainPadding={{x: [10, 2]}}>
{ this.renderSocketBars() }
{ this.renderCoresBars() }
{ this.renderNodesBars() }
</ChartStack>
</Chart>
</div>
</div>
)
}
}
```
### Multi-color (unordered) responsive container
This demonstrates monthly data with a bottom aligned legend and responsiveness for mobile.
```js
import { Chart, ChartArea, ChartAxis, ChartStack, ChartLegendTooltip, ChartThemeColor, createContainer } from '@patternfly/react-charts/victory';
import { getResizeObserver } from '@patternfly/react-core';
class MultiColorChart extends React.Component {
constructor(props) {
super(props);
this.containerRef = createRef();
this.observer = () => {};
this.state = {
width: 0
};
this.handleResize = () => {
if(this.containerRef.current && this.containerRef.current.clientWidth){
this.setState({ width: this.containerRef.current.clientWidth });
}
};
}
componentDidMount() {
this.observer = getResizeObserver(this.containerRef.current, this.handleResize);
this.handleResize();
}
componentWillUnmount() {
this.observer();
}
render() {
const { width } = this.state;
// Note: Container order is important
const CursorVoronoiContainer = createContainer("voronoi", "cursor");
const legendData = [{ childName: 'cats', name: 'Cats' }, { childName: 'dogs', name: 'Dogs' }, { childName: 'birds', name: 'Birds' }];
return (
<div ref={this.containerRef}>
<div style={{ height: '225px' }}>
<Chart
ariaDesc="Average number of pets"
ariaTitle="Area chart example"
containerComponent={
<CursorVoronoiContainer
cursorDimension="x"
labels={({ datum }) => `${datum.y !== null ? datum.y : 'no data'}`}
labelComponent={<ChartLegendTooltip legendData={legendData} title={(datum) => datum.x}/>}
mouseFollowTooltips
voronoiDimension="x"
voronoiPadding={50}
/>
}
legendData={legendData}
legendPosition="bottom-left"
height={225}
name="chart5"
padding={{
bottom: 75, // Adjusted to accomodate legend
left: 50,
right: 50,
top: 50,
}}
maxDomain={{y: 30}}
themeColor={ChartThemeColor.multiUnordered}
width={width}
>
<ChartAxis />
<ChartAxis dependentAxis showGrid />
<ChartStack>
<ChartArea
data={[
{ x: 'Sunday', y: 6 },
{ x: 'Monday', y: 2 },
{ x: 'Tuesday', y: 8 },
{ x: 'Wednesday', y: 15 },
{ x: 'Thursday', y: 6 },
{ x: 'Friday', y: 2 },
{ x: 'Saturday', y: 0 }
]}
interpolation="monotoneX"
name="cats"
/>
<ChartArea
data={[
{ x: 'Sunday', y: 4 },
{ x: 'Monday', y: 5 },
{ x: 'Tuesday', y: 7 },
{ x: 'Wednesday', y: 6 },
{ x: 'Thursday', y: 10 },
{ x: 'Friday', y: 3 },
{ x: 'Saturday', y: 5 }
]}
interpolation="monotoneX"
name="dogs"
/>
<ChartArea
data={[
{ x: 'Sunday', y: 8 },
{ x: 'Monday', y: 18 },
{ x: 'Tuesday', y: 14 },
{ x: 'Wednesday', y: 8 },
{ x: 'Thursday', y: 6 },
{ x: 'Friday', y: 8 },
{ x: 'Saturday', y: 12 }
]}
interpolation="monotoneX"
name="birds"
/>
</ChartStack>
</Chart>
</div>
</div>
);
}
}
```
## Documentation
### Tips
- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq)
- For single data points or zero values, you may want to set the `domain` prop
- `ChartLegend` may be used as a standalone component, instead of using `legendData`
- Themes are inherited, so a default theme may override `themeColor` for a child component
- The `theme` and `themeColor` props should be applied at the most top level component
### Note
Currently, the generated documentation below is not able to resolve type definitions from Victory imports. For the
components used in the examples above, Victory pass-thru props are also documented here:
- For `Chart` props, see [VictoryChart](https://formidable.com/open-source/victory/docs/victory-chart)
- For `ChartArea` props, see [VictoryArea](https://formidable.com/open-source/victory/docs/victory-area)
- For `ChartAxis` props, see [VictoryAxis](https://formidable.com/open-source/victory/docs/victory-axis)
- For `ChartBar` props, see [VictoryBar](https://formidable.com/open-source/victory/docs/victory-bar)
- For `ChartStack` props, see [VictoryStack](https://formidable.com/open-source/victory/docs/victory-stack)
- For `ChartTooltip` props, see [VictoryTooltip](https://formidable.com/open-source/victory/docs/victory-tooltip)