Chart
A chart is a graphical representation for data visualization. A chart can represent tabular numeric data, functions, as well as many other data points.
Name | Type | Description | Required | Default |
---|---|---|---|---|
chartTitle | string | Title of the chart. Appears above the chart. | | |
heightToWidthRatio | string | Sets the height-to-width ratio of the chart. The width of the chart is automatically set to 100% of the width of the Whisper card and popup window so the height is defined as a ratio of the width (rather than as an absolute value). | 1 | |
horizontalLineTotal | number | Set the total number of horizontal lines showing on the grid. | auto-calculated | |
horizontalGridLines | boolean | Show horizontal lines on the grid. | true | |
margin | { left:number, right:number, top:number, bottom:number } | Set the margins around the chart. This is especially useful for widening the left or bottom margins to accommodate larger tick mark labels. The units are expressed in pixels. | { left: 40, right: 10, top: 10, bottom: 40 } | |
series | Series< +SeriesType>[] | An array of the series that will appear in the chart. Up to 10 series may be provided. SeriesType { Area = 'area', Line = 'line', Mark = 'mark', VerticalBar = 'verticalBar', } | | |
showChartInPopupWindowOnly | boolean | If true, the chart will only appear in the popup window and not in the Whisper itself. | false | |
showCrosshair | boolean | If true, show a tooltip when hovering over the chart, which displays the nearest x value and the corresponding y values for all series. | true | |
verticalGridLines | boolean | Show vertical lines on the grid. | true | |
verticalLineTotal | number | Set the total number of vertical lines showing on the grid. | auto-calculated | |
xAxis | boolean | Show the x-axis. | true | |
xAxisLabel | string | Set the x-axis label. | | |
xAxisPadding | number | Sets the right and left (inside the x-axis) padding as a percentage of the chart width. Half of the provided value is applied to each side. | no padding | |
xAxisScale | +AxisScale | Scales determine how the data should be interpreted. The three scales available are linear, ordinal, and time. Linear: a continuous scale that works with numbers. Ordinal: a discrete, ordered set that works with numbers or strings. For example, the x values could contain the months of the year in string form. Time: used for time series. x values will be interpreted as unix time. | liner | |
xAxisTickTotal | number | Total number of tick marks on the x-axis. | auto-calculated | |
xAxisTickLabelAngle | number | Set the angle of the tick mark labels on the x-axis in terms of degrees (positive or negative). | 0 | |
yAxis | boolean | Show the y-axis | true | |
yAxisLabel | string | Set the y-axis label | | |
yAxisPadding | number | Sets the right and left (inside the y-axis) padding as a percentage of the chart width. Half of the provided value is applied to each side. | no padding | |
yAxisScale | +AxisScale | Scales determine how the data should be interpreted. The three scales available are linear, ordinal, and time. Linear: a continuous scale that works with numbers. Ordinal: a discrete, ordered set that works with numbers or strings. For example, the y values could contain the months of the year in string form. Time: used for time series. Y values will be interpreted as unix time. | liner | |
yAxisTickLabelAngle | number | Set the angle of the tick mark labels on the y-axis in terms of degrees (positive or negative). | 0 | |
yAxisTickTotal | number | Total number of tick marks on the y-axis. | auto-calculated | |
| | | |
Please note: Types marked with + are Olive LDK enums
Area Graph:

Bar Graph:

Line Graph:

Mark Graph:

Four Series Graph:

Please note: The Chart Component is a beta feature.
Javascript
React
import { whisper } from '@oliveai/ldk';
import {
SeriesType,
WhisperComponentType,
} from '@oliveai/ldk/dist/whisper/types';
const areaSeries = [
{
data: [
{ x: 1, y: 0 },
{ x: 1, y: 10 },
{ x: 2, y: 5 },
{ x: 3, y: 15 },
],
title: 'Test Area 1',
type: SeriesType.Area,
},
{
data: [
{ x: 1, y: 0 },
{ x: 1, y: 3 },
{ x: 2, y: 1 },
{ x: 3, y: 6 },
],
title: 'Test Area 2',
type: SeriesType.Area,
},
];
const barSeriesData = [
{
barWidth: 2,
data: [
{ x: 50, y: 200 },
{ x: 150, y: 100 },
{ x: 400, y: 50 },
{ x: 600, y: 150 },
],
title: 'Test Bars 1',
type: SeriesType.VerticalBar,
},
{
barWidth: 1,
data: [
{ x: 100, y: 200 },
{ x: 200, y: 100 },
{ x: 300, y: 50 },
{ x: 500, y: 150 },
],
title: 'Test Bars 2',
type: SeriesType.VerticalBar,
},
];
const lineSeriesData = [
{
data: [
{ x: 20, y: 200 },
{ x: 150, y: 100 },
{ x: 400, y: 50 },
{ x: 600, y: 150 },
],
title: 'Test Bars 1',
type: SeriesType.Line,
},
{
data: [
{ x: 10, y: 200 },
{ x: 100, y: 100 },
{ x: 200, y: 50 },
{ x: 300, y: 150 },
],
title: 'Test Bars 2',
type: SeriesType.Line,
},
];
const markSeriesData = [
{
data: [
{ x: 20, y: 200 },
{ x: 150, y: 100 },
{ x: 400, y: 50 },
{ x: 600, y: 150 },
],
title: 'Test Bars 1',
type: SeriesType.Mark,
},
{
data: [
{ x: 10, y: 200 },
{ x: 100, y: 100 },
{ x: 200, y: 50 },
{ x: 300, y: 150 },
],
title: 'Test Bars 2',
type: SeriesType.Mark,
},
];
const fourSeriesData = [
{
data: [
{ x: 100, y: 0 },
{ x: 100, y: 100 },
{ x: 200, y: 500 },
{ x: 300, y: 150 },
],
title: 'Test Area 1',
type: SeriesType.Area,
},
{
data: [
{ x: 100, y: 0 },
{ x: 100, y: 300 },
{ x: 200, y: 100 },
{ x: 300, y: 600 },
],
title: 'Test Area 2',
type: SeriesType.Area,
},
{
barWidth: 2,
data: [
{ x: 50, y: 200 },
{ x: 150, y: 100 },
{ x: 400, y: 50 },
{ x: 600, y: 150 },
],
title: 'Test Bars 1',
type: SeriesType.VerticalBar,
},
{
barWidth: 1,
data: [
{ x: 100, y: 200 },
{ x: 200, y: 100 },
{ x: 300, y: 50 },
{ x: 500, y: 150 },
],
title: 'Test Bars 2',
type: SeriesType.VerticalBar,
},
{
data: [
{ x: 20, y: 200 },
{ x: 150, y: 100 },
{ x: 400, y: 50 },
{ x: 600, y: 150 },
],
title: 'Test Bars 1',
type: SeriesType.Line,
},
{
data: [
{ x: 10, y: 200 },
{ x: 100, y: 100 },
{ x: 200, y: 50 },
{ x: 300, y: 150 },
],
title: 'Test Bars 2',
type: SeriesType.Line,
},
{
data: [
{ x: 20, y: 200 },
{ x: 150, y: 100 },
{ x: 400, y: 50 },
{ x: 600, y: 150 },
],
title: 'Test Bars 1',
type: SeriesType.Mark,
},
{
data: [
{ x: 10, y: 200 },
{ x: 100, y: 100 },
{ x: 200, y: 50 },
{ x: 300, y: 150 },
],
title: 'Test Bars 2',
type: SeriesType.Mark,
},
];
const chartWhisper = async () => {
await whisper.create({
label: 'Chart',
onClose: () => {
console.log('Closed chart Whisper');
},
components: [
{
type: WhisperComponentType.Chart,
chartTitle: 'Area Graph',
series: areaSeries,
xAxisLabel: "Custom X Axis Label",
yAxisLabel: "Custom Y Axis Label",
},
{
type: WhisperComponentType.Chart,
chartTitle: "Bar Graph",
series: barSeriesData,
xAxisLabel: "Custom X Axis Label",
yAxisLabel: "Custom Y Axis Label",
},
{
type: WhisperComponentType.Chart,
chartTitle: "Line Graph",
series: lineSeriesData,
xAxisLabel: "Custom X Axis Label",
yAxisLabel: "Custom Y Axis Label",
},
{
type: WhisperComponentType.Chart,
chartTitle: "Mark Graph",
series: markSeriesData,
xAxisLabel: "Custom X Axis Label",
yAxisLabel: "Custom Y Axis Label",
},
{
type: WhisperComponentType.Chart,
chartTitle: "Four Series Graph",
series: fourSeriesData,
xAxisLabel: "Custom X Axis Label",
yAxisLabel: "Custom Y Axis Label",
},
],
});
}
import { whisper, React, ReactWhisper } from '@oliveai/ldk';
import { AxisScale, SeriesColor, SeriesType } from '@oliveai/ldk/dist/whisper/types';
import { onActionWrapper } from '../utils';
type SeriesInput = {
barWidth?: number;
color?: SeriesColor;
numberOfPoints?: number;
title: string;
type: SeriesType;
};
const generateSeries = (inputs: SeriesInput[]) =>
inputs.map((input) => {
const data = [];
for (let i = 0; i < (input.numberOfPoints || 20); i += 1) {
const x = Math.floor(Math.random() * 100);
const y = Math.floor(Math.random() * 100);
data.push({ x, y });
}
return { ...input, data };
});
type RegenerateButtonParams = {
setter: React.Dispatch<React.SetStateAction<SeriesInput[]>>;
seriesData: SeriesInput[];
};
const RegenerateButton = ({ setter, seriesData }: RegenerateButtonParams) => {
const handleClick = () => {
setter(generateSeries(seriesData));
};
return (
<oh-box justifyContent={whisper.JustifyContent.Center} direction={whisper.Direction.Horizontal}>
<oh-button label="Regenerate Chart Data" onClick={handleClick} />
</oh-box>
);
};
export const testChart = (): Promise<boolean> =>
new Promise(async (resolve, reject) => {
const resolverMap = new Map([
['AreaGraph', false],
['BarGraph', false],
['LineGraph', false],
['MarkGraph', false],
['FourSeries', false],
]);
const ConfirmationButtons = ({
question,
testName,
}: {
question: string;
testName: string;
}) => {
const [isTested, setIsTested] = React.useState(false);
const handleClick: whisper.WhisperHandler = (error, thisWhisper) => {
onActionWrapper(error, testName, resolverMap, thisWhisper, resolve, reject);
setIsTested(true);
};
return (
<>
<oh-box
justifyContent={whisper.JustifyContent.Center}
direction={whisper.Direction.Horizontal}
>
<oh-markdown body={question} />
</oh-box>
<oh-box
justifyContent={whisper.JustifyContent.Center}
direction={whisper.Direction.Horizontal}
>
{isTested ? (
<oh-icon name="done" />
) : (
<>
<oh-button label="Yes" onClick={handleClick} />
<oh-button label="No" onClick={() => reject(new Error(`${testName} failed`))} />
</>
)}
</oh-box>
</>
);
};
try {
const AreaGraph = () => {
const series = [
{
data: [
{ x: 1, y: 0 },
{ x: 1, y: 10 },
{ x: 2, y: 5 },
{ x: 3, y: 15 },
],
title: 'Test Area 1',
type: SeriesType.Area,
},
{
data: [
{ x: 1, y: 0 },
{ x: 1, y: 3 },
{ x: 2, y: 1 },
{ x: 3, y: 6 },
],
title: 'Test Area 2',
type: SeriesType.Area,
},
];
return (
<>
<oh-chart
chartTitle="Area Graph Test"
series={series}
xAxisLabel="Custom X Axis Label"
yAxisLabel="Custom Y Axis Label"
/>
<ConfirmationButtons
question="Does the chart display an area graph, custom axis labels, and a tooltip when you hover your mouse?"
testName="AreaGraph"
/>
<oh-divider />
</>
);
};
const BarGraph = () => {
const seriesData = [
{
barWidth: 2,
numberOfPoints: 5,
title: 'Test Bars 1',
type: SeriesType.VerticalBar,
},
{
barWidth: 1,
numberOfPoints: 5,
title: 'Test Bars 2',
type: SeriesType.VerticalBar,
},
];
const [series, setSeries] = React.useState(generateSeries(seriesData));
return (
<>
<oh-chart
chartTitle="Bar Graph Test"
series={series}
xAxisLabel="Custom X Axis Label"
yAxisLabel="Custom Y Axis Label"
/>
<ConfirmationButtons
question="Does the chart display a bar graph, custom axis labels, and a tooltip when you hover your mouse? Are the bars for Test Bars 1 wider than Test Bars 2?"
testName="BarGraph"
/>
<RegenerateButton setter={setSeries} seriesData={seriesData} />
<oh-divider />
</>
);
};
const LineGraph = () => {
const seriesData = [
{
numberOfPoints: 5,
title: 'Test Lines 1',
type: SeriesType.Line,
},
{
numberOfPoints: 5,
title: 'Test Lines 2',
type: SeriesType.Line,
},
];
const [series, setSeries] = React.useState(generateSeries(seriesData));
const [sortedSeries, setSortedSeries] = React.useState(series);
React.useEffect(() => {
setSortedSeries(
series.map((unsortedSeries) => {
const data = unsortedSeries.data.sort((a, b) => a.x - b.x);
return {
...unsortedSeries,
data,
};
}),
);
}, [series]);
return (
<>
<oh-chart
chartTitle="Line Graph Test"
series={sortedSeries}
xAxisLabel="Custom X Axis Label"
yAxisLabel="Custom Y Axis Label"
/>
<ConfirmationButtons
question="Does the chart display a line graph, custom axis labels, and a tooltip when you hover your mouse?"
testName="LineGraph"
/>
<RegenerateButton setter={setSeries} seriesData={seriesData} />
<oh-divider />
</>
);
};
const MarkGraph = () => {
const seriesData = [
{
numberOfPoints: 5,
title: 'Test Mark 1',
type: SeriesType.Mark,
},
{
numberOfPoints: 5,
title: 'Test Mark 2',
type: SeriesType.Mark,
},
];
const [series, setSeries] = React.useState(generateSeries(seriesData));
return (
<>
<oh-chart
chartTitle="Mark Graph Test"
series={series}
xAxisLabel="Custom X Axis Label"
yAxisLabel="Custom Y Axis Label"
/>
<ConfirmationButtons
question="Does the chart display a mark graph, custom axis labels, and a tooltip when you hover your mouse?"
testName="MarkGraph"
/>
<RegenerateButton setter={setSeries} seriesData={seriesData} />
<oh-divider />
</>
);
};
const FourSeries = () => {
const seriesData: SeriesInput[] = [
{
numberOfPoints: 5,
title: 'Area Graph',
type: SeriesType.Area,
},
{
numberOfPoints: 5,
title: 'Bar Graph',
type: SeriesType.VerticalBar,
},
{
numberOfPoints: 5,
title: 'Line Graph',
type: SeriesType.Line,
},
{
numberOfPoints: 5,
title: 'Mark Graph',
type: SeriesType.Mark,
},
];
const [series, setSeries] = React.useState(generateSeries(seriesData));
return (
<>
<oh-chart
chartTitle="Four Series Test"
series={series}
xAxisLabel="Custom X Axis Label"
yAxisLabel="Custom Y Axis Label"
/>
<ConfirmationButtons
question="Does the chart display area, bar, line, and mark graphs?"
testName="FourSeries"
/>
<RegenerateButton setter={setSeries} seriesData={seriesData} />
<oh-divider />
</>
);
};
const ChartTest = () => (
<oh-whisper label="Chart Test" onClose={() => console.debug('closed')}>
<AreaGraph />
<BarGraph />
<LineGraph />
<MarkGraph />
<FourSeries />
</oh-whisper>
);
ReactWhisper.renderNewWhisper(<ChartTest />);
} catch (e) {
console.error(e);
reject(e);
}
});
Last modified 1yr ago