Skip to content

Commit

Permalink
Charts - more examples (#10845)
Browse files Browse the repository at this point in the history
* chore(charts):  Add custom color scale example for pie chart

* chore(charts): add gnatt-like example for bar charts

* fix(charts): undesired space between axis label and bottom positioned legend
  • Loading branch information
dlabrecq authored Sep 5, 2024
1 parent fdbae60 commit cf30249
Show file tree
Hide file tree
Showing 4 changed files with 211 additions and 24 deletions.
2 changes: 1 addition & 1 deletion packages/react-charts/src/components/Chart/Chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ export const Chart: React.FunctionComponent<ChartProps> = ({

// Adjust for axis label
React.Children.toArray(children).map((child: any) => {
if (child.type.role === 'axis' && child.props.label && !child.props.dependentAxis) {
if (child.type.role === 'axis' && child.props.label && child.props.fixAxisLabelHeight) {
xAxisLabelHeight = getLabelTextSize({ text: child.props.label, theme }).height + 10;
legendTitleHeight = 0;
}
Expand Down
4 changes: 4 additions & 0 deletions packages/react-charts/src/components/ChartAxis/ChartAxis.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,10 @@ export interface ChartAxisProps extends VictoryAxisProps {
* @propType object[]
*/
externalEventMutations?: EventCallbackInterface<string | string[], StringOrNumberOrList>[];
/**
* When true, this prop adjusts the height between the axis label and bottom positioned legend
*/
fixAxisLabelHeight?: boolean;
/**
* When true, this prop reduces the number of tick labels to fit the length of the axis.
* Labels are removed at approximately even intervals from the original array of labels.
Expand Down
175 changes: 174 additions & 1 deletion packages/react-charts/src/components/ChartBar/examples/ChartBar.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@ propComponents: [
'ChartAxis',
'ChartBar',
'ChartGroup',
'ChartLabel',
'ChartVoronoiContainer'
]
hideDarkMode: true
---

import { Chart, ChartAxis, ChartBar, ChartGroup, ChartThemeColor, ChartTooltip, ChartVoronoiContainer } from '@patternfly/react-charts';
import { Chart, ChartAxis, ChartBar, ChartGroup, ChartLabel, ChartThemeColor, ChartTooltip, ChartVoronoiContainer } from '@patternfly/react-charts';
import { VictoryZoomContainer } from 'victory-zoom-container';
import global_danger_color_100 from '@patternfly/react-tokens/dist/esm/global_danger_color_100';
import global_info_color_100 from '@patternfly/react-tokens/dist/esm/global_info_color_100';
import global_warning_color_100 from '@patternfly/react-tokens/dist/esm/global_warning_color_100';

## Introduction
Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)!
Expand Down Expand Up @@ -205,6 +209,175 @@ import { Chart, ChartBar, ChartVoronoiContainer } from '@patternfly/react-charts
</div>
```

### Alerts timeline

A gnatt-like chart using `y` and `y0` data properties for alert start/end dates

```js
import React from 'react';
import { Chart, ChartAxis, ChartBar, ChartGroup, ChartLabel, ChartTooltip, ChartVoronoiContainer } from '@patternfly/react-charts';
import global_danger_color_100 from '@patternfly/react-tokens/dist/esm/global_danger_color_100';
import global_info_color_100 from '@patternfly/react-tokens/dist/esm/global_info_color_100';
import global_warning_color_100 from '@patternfly/react-tokens/dist/esm/global_warning_color_100';


class Timeline extends React.Component {
render() {
// Start = y0, end = y
const alerts = [
[
{ y0: new Date("2024-08-06T01:30:00"), y: new Date("2024-08-09T02:30:00"), severity: 'danger' },
{ y0: new Date("2024-08-10T05:30:00"), y: new Date("2024-08-10T20:00:00"), severity: 'danger' },
{ y0: new Date("2024-08-12T10:00:00"), y: new Date("2024-08-13T10:30:00"), severity: 'danger' }
],
[
{ y0: new Date("2024-08-06T01:30:00"), y: new Date("2024-08-07T02:30:00"), severity: 'danger' },
{ y0: new Date("2024-08-07T07:30:00"), y: new Date("2024-08-09T09:30:00"), severity: 'danger' },
{ y0: new Date("2024-08-10T05:30:00"), y: new Date("2024-08-10T20:00:00"), severity: 'warn' },
{ y0: new Date("2024-08-12T10:00:00"), y: new Date("2024-08-13T10:30:00"), severity: 'danger' }
],
[
{ y0: new Date("2024-08-06T01:30:00"), y: new Date("2024-08-07T02:30:00"), severity: 'danger' },
{ y0: new Date("2024-08-08T07:30:00"), y: new Date("2024-08-09T09:30:00"), severity: 'danger' },
{ y0: new Date("2024-08-10T05:30:00"), y: new Date("2024-08-10T20:00:00"), severity: 'info' },
{ y0: new Date("2024-08-12T10:00:00"), y: new Date("2024-08-13T10:30:00"), severity: 'warn' }
],
[
{ y0: new Date("2024-08-06T01:30:00"), y: new Date("2024-08-08T02:30:00"), severity: 'info' },
{ y0: new Date("2024-08-08T07:30:00"), y: new Date("2024-08-09T09:30:00"), severity: 'info' },
{ y0: new Date("2024-08-10T05:30:00"), y: new Date("2024-08-11T20:00:00"), severity: 'warn' },
{ y0: new Date("2024-08-12T10:00:00"), y: new Date("2024-08-13T10:30:00"), severity: 'info' }
],
[
{ y0: new Date("2024-08-06T01:30:00"), y: new Date("2024-08-07T02:30:00"), severity: 'warn' },
{ y0: new Date("2024-08-08T07:30:00"), y: new Date("2024-08-09T09:30:00"), severity: 'warn' },
{ y0: new Date("2024-08-09T05:30:00"), y: new Date("2024-08-10T20:00:00"), severity: 'warn' },
{ y0: new Date("2024-08-12T10:00:00"), y: new Date("2024-08-13T10:30:00"), severity: 'warn' }
],
[
{ y0: new Date("2024-08-06T01:30:00"), y: new Date("2024-08-08T02:30:00"), severity: 'warn' },
{ y0: new Date("2024-08-08T07:30:00"), y: new Date("2024-08-09T09:30:00"), severity: 'warn' },
{ y0: new Date("2024-08-10T05:30:00"), y: new Date("2024-08-11T20:00:00"), severity: 'warn' },
{ y0: new Date("2024-08-12T10:00:00"), y: new Date("2024-08-13T10:30:00"), severity: 'warn' }
],
[
{ y0: new Date("2024-08-06T01:30:00"), y: new Date("2024-08-07T02:30:00"), severity: 'warn' },
{ y0: new Date("2024-08-07T04:30:00"), y: new Date("2024-08-08T05:30:00"), severity: 'warn' },
{ y0: new Date("2024-08-08T07:30:00"), y: new Date("2024-08-09T09:30:00"), severity: 'warn' },
{ y0: new Date("2024-08-10T05:30:00"), y: new Date("2024-08-10T20:00:00"), severity: 'warn' },
{ y0: new Date("2024-08-11T05:30:00"), y: new Date("2024-08-11T20:00:00"), severity: 'warn' },
{ y0: new Date("2024-08-12T10:00:00"), y: new Date("2024-08-13T10:30:00"), severity: 'warn' }
],
[
{ y0: new Date("2024-08-06T01:30:00"), y: new Date("2024-08-08T02:30:00"), severity: 'warn' },
{ y0: new Date("2024-08-08T07:30:00"), y: new Date("2024-08-09T09:30:00"), severity: 'warn' },
{ y0: new Date("2024-08-10T05:30:00"), y: new Date("2024-08-11T20:00:00"), severity: 'warn' },
{ y0: new Date("2024-08-12T10:00:00"), y: new Date("2024-08-13T10:30:00"), severity: 'warn' }
],
];

const formatDate = (date, isTime) => {
const dateString = date?.toLocaleDateString("en-US", { month: 'short', day: 'numeric' });
const timeString = date?.toLocaleTimeString("en-US", { hour12: false });
return isTime ? `${dateString} ${timeString}` : dateString;
};

const getChart = (alert, index) => {
const data = [];

alert?.map(datum => {
data.push({
...datum,
x: alerts.length - index,
fill: datum.severity === "danger"
? global_danger_color_100.var
: datum.severity === "warn"
? global_warning_color_100.var
: global_info_color_100.var,
});
});

if (data?.length === 0) {
return null;
}
return (
<ChartBar
data={data}
key={index}
style={{
data: {
fill: ({ datum }) => datum.fill,
stroke: ({ datum }) => datum.fill,
}
}}
/>
);
};

return (
<div style={{ height: "400px", width: "450px" }}>
<Chart
ariaDesc="Average number of pets"
ariaTitle="Bar chart example"
containerComponent={
<ChartVoronoiContainer
labelComponent={
<ChartTooltip constrainToVisibleArea labelComponent={<ChartLabel dx={-65} textAnchor="start" />} />
}
labels={({ datum }) => `Severity: ${datum.severity}\nStart: ${formatDate(new Date(datum.y0), true)}\nEnd: ${formatDate(new Date(datum.y), true)}`}
/>
}
domainPadding={{ x: [20, 20], y: [20, 20] }}
legendData={[
{ name: "Danger", symbol: { fill: global_danger_color_100.var } },
{ name: "Info", symbol: { fill: global_info_color_100.var } },
{ name: "Warning", symbol: { fill: global_warning_color_100.var } }
]}
legendPosition="bottom-left"
height={400}
name="chart5"
padding={{
bottom: 75, // Adjusted to accommodate legend
left: 100,
right: 50, // Adjusted to accommodate tooltip
top: 50
}}
width={450}
>
<ChartAxis
dependentAxis
showGrid
tickFormat={(t) => new Date(t).toLocaleDateString("en-US", { month: 'short', day: 'numeric' })}
tickValues={[new Date("2024-08-06T00:00:00"), new Date("2024-08-08T00:00:00"), new Date("2024-08-10T00:00:00"), new Date("2024-08-12T00:00:00")]}
/>
<ChartAxis
axisLabelComponent={
<ChartLabel angle={0} dy={-125} />
}
label="Incidents"
padding={{ top: 20, bottom: 60 }}
style={{
axis: {
stroke: "transparent",
},
ticks: {
stroke: "transparent"
},
tickLabels: {
fill: "transparent"
}
}}
/>
<ChartGroup horizontal>
{alerts.map((alert, index) => getChart(alert, index))}
</ChartGroup>
</Chart>
</div>
);
}
}
```
## Documentation
### Tips
- See Victory's [FAQ](https://formidable.com/open-source/victory/docs/faq)
Expand Down
54 changes: 32 additions & 22 deletions packages/react-charts/src/components/ChartPie/examples/ChartPie.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ hideDarkMode: true
---

import { ChartPie, ChartThemeColor } from '@patternfly/react-charts';
import chart_theme_blue_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_theme_blue_ColorScale_100';
import chart_theme_gold_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_theme_gold_ColorScale_100';
import chart_theme_orange_ColorScale_300 from '@patternfly/react-tokens/dist/esm/chart_theme_orange_ColorScale_300';

## Introduction
Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)!
Expand Down Expand Up @@ -41,59 +44,66 @@ import { ChartPie } from '@patternfly/react-charts';
</div>
```

### Orange with right aligned legend
### Multi-color (ordered) with bottom aligned legend
```js
import React from 'react';
import { ChartPie, ChartThemeColor } from '@patternfly/react-charts';

<div style={{ height: '230px', width: '350px' }}>
<div style={{ height: '275px', width: '300px' }}>
<ChartPie
ariaDesc="Average number of pets"
ariaTitle="Pie chart example"
constrainToVisibleArea
data={[{ x: 'Cats', y: 35 }, { x: 'Dogs', y: 55 }, { x: 'Birds', y: 10 }]}
height={230}
height={275}
labels={({ datum }) => `${datum.x}: ${datum.y}`}
legendData={[{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }]}
legendOrientation="vertical"
legendPosition="right"
name="chart2"
legendPosition="bottom"
name="chart3"
padding={{
bottom: 20,
bottom: 65,
left: 20,
right: 140, // Adjusted to accommodate legend
right: 20,
top: 20
}}
themeColor={ChartThemeColor.orange}
width={350}
themeColor={ChartThemeColor.multiOrdered}
width={300}
/>
</div>
```

### Multi-color (ordered) with bottom aligned legend
### Custom color scale

This demonstrates how to apply a custom color scale.

```js
import React from 'react';
import { ChartPie, ChartThemeColor } from '@patternfly/react-charts';
import chart_theme_blue_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_theme_blue_ColorScale_100';
import chart_theme_gold_ColorScale_100 from '@patternfly/react-tokens/dist/esm/chart_theme_gold_ColorScale_100';
import chart_theme_orange_ColorScale_300 from '@patternfly/react-tokens/dist/esm/chart_theme_orange_ColorScale_300';

<div style={{ height: '275px', width: '300px' }}>
<div style={{ height: '230px', width: '450px' }}>
<ChartPie
ariaDesc="Average number of pets"
ariaTitle="Pie chart example"
colorScale={[ chart_theme_blue_ColorScale_100.var, chart_theme_orange_ColorScale_300.var, chart_theme_gold_ColorScale_100.var, chart_theme_blue_ColorScale_100.var, ]}
constrainToVisibleArea
data={[{ x: 'Cats', y: 35 }, { x: 'Dogs', y: 55 }, { x: 'Birds', y: 10 }]}
height={275}
labels={({ datum }) => `${datum.x}: ${datum.y}`}
legendData={[{ name: 'Cats: 35' }, { name: 'Dogs: 55' }, { name: 'Birds: 10' }]}
legendPosition="bottom"
name="chart3"
data={[{ x: 'Sky', y: 38 }, { x: 'Shady side of pyramid', y: 7 }, { x: 'Sunny side of pyramid', y: 17 }, { x: 'Sky', y: 38 }]}
height={230}
labels={({ datum }) => `${datum.x}`}
legendData={[{ name: 'Sky' }, { name: 'Shady side of pyramid' }, { name: 'Sunny side of pyramid' }]}
legendOrientation="vertical"
legendPosition="right"
name="chart2"
padding={{
bottom: 65,
bottom: 20,
left: 20,
right: 20,
right: 240, // Adjusted to accommodate legend
top: 20
}}
themeColor={ChartThemeColor.multiOrdered}
width={300}
themeColor={ChartThemeColor.orange}
width={450}
/>
</div>
```
Expand Down

0 comments on commit cf30249

Please sign in to comment.