diff --git a/packages/react-charts/src/victory/components/ChartStack/examples/ChartStack.md b/packages/react-charts/src/victory/components/ChartStack/examples/ChartStack.md index baf17cfb888..92bef38d902 100644 --- a/packages/react-charts/src/victory/components/ChartStack/examples/ChartStack.md +++ b/packages/react-charts/src/victory/components/ChartStack/examples/ChartStack.md @@ -11,7 +11,6 @@ propComponents: [ hideDarkMode: true --- -import { createRef } from 'react'; import { Chart, ChartArea, @@ -25,6 +24,7 @@ import { createContainer } from '@patternfly/react-charts/victory'; import { getResizeObserver } from '@patternfly/react-core'; +import { useEffect, useRef, useState } from 'react'; ## Introduction Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)! @@ -33,380 +33,34 @@ The examples below are based on the [Victory](https://formidable.com/open-source ## Examples ### Basic with right aligned legend -```js -import { Chart, ChartAxis, ChartBar, ChartStack, ChartVoronoiContainer } from '@patternfly/react-charts/victory'; +```ts file = "ChartStackBasicRightLegend.tsx" -
- `${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} - > - - - - - - - - - -
``` ### Horizontal with bottom aligned legend -```js -import { Chart, ChartAxis, ChartBar, ChartStack, ChartThemeColor, ChartVoronoiContainer } from '@patternfly/react-charts/victory'; +```ts file = "ChartStackBottomLegend.tsx" -
- `${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} - > - - - - - - - - - -
``` ### 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'; +```ts file = "ChartStackMultiColorOrdered.tsx" -
- - - - - } - /> - } - /> - } - /> - } - /> - - -
``` ### 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 } />; - } - - 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 } />; - } - - 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 } />; - } +```ts file = "ChartStackMonthlyResponsive.tsx" - 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 ( -
-
- - - - - { this.renderSocketBars() } - { this.renderCoresBars() } - { this.renderNodesBars() } - - -
-
- ) - } -} ``` ### 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(); - } +```ts file = "ChartStackMultiColorUnordered.tsx" - 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 ( -
-
- `${datum.y !== null ? datum.y : 'no data'}`} - labelComponent={ 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} - > - - - - - - - - -
-
- ); - } -} ``` ## Documentation diff --git a/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackBasicRightLegend.tsx b/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackBasicRightLegend.tsx new file mode 100644 index 00000000000..a135dff5b0d --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackBasicRightLegend.tsx @@ -0,0 +1,68 @@ +import { Chart, ChartAxis, ChartBar, ChartStack, ChartVoronoiContainer } from '@patternfly/react-charts/victory'; + +interface PetData { + name: string; + x: string; + y: number; +} + +export const ChartStackBasicRightLegend: React.FunctionComponent = () => { + const data1: PetData[] = [ + { name: 'Cats', x: '2015', y: 1 }, + { name: 'Cats', x: '2016', y: 2 }, + { name: 'Cats', x: '2017', y: 5 }, + { name: 'Cats', x: '2018', y: 3 } + ]; + const data2: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 1 }, + { name: 'Dogs', x: '2017', y: 7 }, + { name: 'Dogs', x: '2018', y: 4 } + ]; + const data3: PetData[] = [ + { name: 'Birds', x: '2015', y: 4 }, + { name: 'Birds', x: '2016', y: 4 }, + { name: 'Birds', x: '2017', y: 9 }, + { name: 'Birds', x: '2018', y: 7 } + ]; + const data4: PetData[] = [ + { name: 'Mice', x: '2015', y: 3 }, + { name: 'Mice', x: '2016', y: 3 }, + { name: 'Mice', x: '2017', y: 8 }, + { name: 'Mice', x: '2018', y: 5 } + ]; + + return ( +
+ `${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} + > + + + + + + + + + +
+ ); +}; diff --git a/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackBottomLegend.tsx b/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackBottomLegend.tsx new file mode 100644 index 00000000000..3f5906a1a5c --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackBottomLegend.tsx @@ -0,0 +1,75 @@ +import { + Chart, + ChartAxis, + ChartBar, + ChartStack, + ChartThemeColor, + ChartVoronoiContainer +} from '@patternfly/react-charts/victory'; + +interface PetData { + name: string; + x: string; + y: number; +} + +export const ChartStackBottomLegend: React.FunctionComponent = () => { + const data1: PetData[] = [ + { name: 'Cats', x: '2015', y: 1 }, + { name: 'Cats', x: '2016', y: 2 }, + { name: 'Cats', x: '2017', y: 5 }, + { name: 'Cats', x: '2018', y: 3 } + ]; + const data2: PetData[] = [ + { name: 'Dogs', x: '2015', y: 2 }, + { name: 'Dogs', x: '2016', y: 1 }, + { name: 'Dogs', x: '2017', y: 7 }, + { name: 'Dogs', x: '2018', y: 4 } + ]; + const data3: PetData[] = [ + { name: 'Birds', x: '2015', y: 4 }, + { name: 'Birds', x: '2016', y: 4 }, + { name: 'Birds', x: '2017', y: 9 }, + { name: 'Birds', x: '2018', y: 7 } + ]; + const data4: PetData[] = [ + { name: 'Mice', x: '2015', y: 3 }, + { name: 'Mice', x: '2016', y: 3 }, + { name: 'Mice', x: '2017', y: 8 }, + { name: 'Mice', x: '2018', y: 5 } + ]; + + return ( +
+ `${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} + > + + + + + + + + + +
+ ); +}; diff --git a/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackMonthlyResponsive.tsx b/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackMonthlyResponsive.tsx new file mode 100644 index 00000000000..2cd320a132d --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackMonthlyResponsive.tsx @@ -0,0 +1,107 @@ +import { Chart, ChartAxis, ChartBar, ChartStack, ChartTooltip } from '@patternfly/react-charts/victory'; +import { getResizeObserver } from '@patternfly/react-core'; +import { useEffect, useRef, useState } from 'react'; + +interface Bar { + x: string; + y: number; +} + +export const ChartStackMonthlyResponsive: React.FunctionComponent = () => { + const containerRef = useRef(null); + const observer = useRef(() => {}); + const [width, setWidth] = useState(0); + + const handleResize = () => { + if (containerRef.current && containerRef.current.clientWidth) { + setWidth(containerRef.current.clientWidth); + } + }; + const bars: Bar[] = []; + for (let i = 1; i < 32; i++) { + bars.push({ x: `Aug. ${i}`, y: Math.floor(Math.random() * 6) + 1 }); + } + + const renderSocketBars = () => { + const socketBars = bars.map((tick, index) => ({ + key: index, + x: tick.x, + y: tick.y, + name: 'Sockets', + label: `${tick.x} Sockets: ${tick.y}` + })); + return } />; + }; + + const renderCoresBars = () => { + const coresBars = bars.map((tick, index) => ({ + key: index, + x: tick.x, + y: tick.y, + name: 'Cores', + label: `${tick.x} Cores: ${tick.y}` + })); + return } />; + }; + + const renderNodesBars = () => { + const nodesBars = bars.map((tick, index) => ({ + key: index, + x: tick.x, + y: tick.y, + name: 'Nodes', + label: `${tick.x} Nodes: ${tick.y}` + })); + return } />; + }; + + const getTickValues = (offset = 2) => { + const tickValues = []; + for (let i = 1; i < 32; i++) { + if (i % offset === 0) { + tickValues.push(`Aug. ${i}`); + } + } + return tickValues; + }; + + useEffect(() => { + observer.current = getResizeObserver(containerRef.current, handleResize); + handleResize(); + + return () => { + observer.current(); + }; + }, []); + + return ( +
+
+ + + + + {renderSocketBars()} + {renderCoresBars()} + {renderNodesBars()} + + +
+
+ ); +}; diff --git a/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackMultiColorOrdered.tsx b/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackMultiColorOrdered.tsx new file mode 100644 index 00000000000..39eb4222bfb --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackMultiColorOrdered.tsx @@ -0,0 +1,74 @@ +import { + Chart, + ChartBar, + ChartAxis, + ChartStack, + ChartThemeColor, + ChartTooltip +} from '@patternfly/react-charts/victory'; + +interface PetData { + name?: string; + x?: string; + y?: number; + label?: string; +} + +export const ChartStackMultiColorOrdered: React.FunctionComponent = () => { + const data1: PetData[] = [ + { 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' } + ]; + const data2: PetData[] = [ + { 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' } + ]; + const data3: PetData[] = [ + { 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' } + ]; + const data4: PetData[] = [ + { 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' } + ]; + const legendData: PetData[] = [{ name: 'Cats' }, { name: 'Dogs' }, { name: 'Birds' }, { name: 'Mice' }]; + + return ( +
+ + + + + } /> + } /> + } /> + } /> + + +
+ ); +}; diff --git a/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackMultiColorUnordered.tsx b/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackMultiColorUnordered.tsx new file mode 100644 index 00000000000..a714e23bde2 --- /dev/null +++ b/packages/react-charts/src/victory/components/ChartStack/examples/ChartStackMultiColorUnordered.tsx @@ -0,0 +1,114 @@ +import { + Chart, + ChartArea, + ChartAxis, + ChartStack, + ChartLegendTooltip, + ChartThemeColor, + createContainer +} from '@patternfly/react-charts/victory'; +import { getResizeObserver } from '@patternfly/react-core'; +import { useEffect, useRef, useState } from 'react'; + +interface Data { + x: string; + y: number; +} + +export const ChartStackMultiColorUnordered: React.FunctionComponent = () => { + const containerRef = useRef(null); + const observer = useRef(() => {}); + const [width, setWidth] = useState(0); + + const handleResize = () => { + if (containerRef.current && containerRef.current.clientWidth) { + setWidth(containerRef.current.clientWidth); + } + }; + + useEffect(() => { + observer.current = getResizeObserver(containerRef.current, handleResize); + handleResize(); + + return () => { + observer.current(); + }; + }, []); + + // Note: Container order is important + const CursorVoronoiContainer = createContainer('voronoi', 'cursor'); + const legendData = [ + { childName: 'cats', name: 'Cats' }, + { childName: 'dogs', name: 'Dogs' }, + { childName: 'birds', name: 'Birds' } + ]; + const data1: 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 } + ]; + const data2: 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 } + ]; + const data3: 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 } + ]; + + return ( +
+
+ `${datum.y !== null ? datum.y : 'no data'}`} + labelComponent={ 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} + > + + + + + + + + +
+
+ ); +};