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.

Props:

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
Please note: Types marked with + are Olive LDK enums

Examples:

Area Graph:
Bar Graph:
Line Graph:
Mark Graph:
Four Series Graph:
Please note: The Chart Component is a beta feature.
Javascript
React
1
import { whisper } from '@oliveai/ldk';
2
import {
3
SeriesType,
4
WhisperComponentType,
5
} from '@oliveai/ldk/dist/whisper/types';
6
7
const areaSeries = [
8
{
9
data: [
10
{ x: 1, y: 0 },
11
{ x: 1, y: 10 },
12
{ x: 2, y: 5 },
13
{ x: 3, y: 15 },
14
],
15
title: 'Test Area 1',
16
type: SeriesType.Area,
17
},
18
{
19
data: [
20
{ x: 1, y: 0 },
21
{ x: 1, y: 3 },
22
{ x: 2, y: 1 },
23
{ x: 3, y: 6 },
24
],
25
title: 'Test Area 2',
26
type: SeriesType.Area,
27
},
28
];
29
30
const barSeriesData = [
31
{
32
barWidth: 2,
33
data: [
34
{ x: 50, y: 200 },
35
{ x: 150, y: 100 },
36
{ x: 400, y: 50 },
37
{ x: 600, y: 150 },
38
],
39
title: 'Test Bars 1',
40
type: SeriesType.VerticalBar,
41
},
42
{
43
barWidth: 1,
44
data: [
45
{ x: 100, y: 200 },
46
{ x: 200, y: 100 },
47
{ x: 300, y: 50 },
48
{ x: 500, y: 150 },
49
],
50
title: 'Test Bars 2',
51
type: SeriesType.VerticalBar,
52
},
53
];
54
55
const lineSeriesData = [
56
{
57
data: [
58
{ x: 20, y: 200 },
59
{ x: 150, y: 100 },
60
{ x: 400, y: 50 },
61
{ x: 600, y: 150 },
62
],
63
title: 'Test Bars 1',
64
type: SeriesType.Line,
65
},
66
{
67
data: [
68
{ x: 10, y: 200 },
69
{ x: 100, y: 100 },
70
{ x: 200, y: 50 },
71
{ x: 300, y: 150 },
72
],
73
title: 'Test Bars 2',
74
type: SeriesType.Line,
75
},
76
];
77
78
const markSeriesData = [
79
{
80
data: [
81
{ x: 20, y: 200 },
82
{ x: 150, y: 100 },
83
{ x: 400, y: 50 },
84
{ x: 600, y: 150 },
85
],
86
title: 'Test Bars 1',
87
type: SeriesType.Mark,
88
},
89
{
90
data: [
91
{ x: 10, y: 200 },
92
{ x: 100, y: 100 },
93
{ x: 200, y: 50 },
94
{ x: 300, y: 150 },
95
],
96
title: 'Test Bars 2',
97
type: SeriesType.Mark,
98
},
99
];
100
101
const fourSeriesData = [
102
{
103
data: [
104
{ x: 100, y: 0 },
105
{ x: 100, y: 100 },
106
{ x: 200, y: 500 },
107
{ x: 300, y: 150 },
108
],
109
title: 'Test Area 1',
110
type: SeriesType.Area,
111
},
112
{
113
data: [
114
{ x: 100, y: 0 },
115
{ x: 100, y: 300 },
116
{ x: 200, y: 100 },
117
{ x: 300, y: 600 },
118
],
119
title: 'Test Area 2',
120
type: SeriesType.Area,
121
},
122
{
123
barWidth: 2,
124
data: [
125
{ x: 50, y: 200 },
126
{ x: 150, y: 100 },
127
{ x: 400, y: 50 },
128
{ x: 600, y: 150 },
129
],
130
title: 'Test Bars 1',
131
type: SeriesType.VerticalBar,
132
},
133
{
134
barWidth: 1,
135
data: [
136
{ x: 100, y: 200 },
137
{ x: 200, y: 100 },
138
{ x: 300, y: 50 },
139
{ x: 500, y: 150 },
140
],
141
title: 'Test Bars 2',
142
type: SeriesType.VerticalBar,
143
},
144
{
145
data: [
146
{ x: 20, y: 200 },
147
{ x: 150, y: 100 },
148
{ x: 400, y: 50 },
149
{ x: 600, y: 150 },
150
],
151
title: 'Test Bars 1',
152
type: SeriesType.Line,
153
},
154
{
155
data: [
156
{ x: 10, y: 200 },
157
{ x: 100, y: 100 },
158
{ x: 200, y: 50 },
159
{ x: 300, y: 150 },
160
],
161
title: 'Test Bars 2',
162
type: SeriesType.Line,
163
},
164
{
165
data: [
166
{ x: 20, y: 200 },
167
{ x: 150, y: 100 },
168
{ x: 400, y: 50 },
169
{ x: 600, y: 150 },
170
],
171
title: 'Test Bars 1',
172
type: SeriesType.Mark,
173
},
174
{
175
data: [
176
{ x: 10, y: 200 },
177
{ x: 100, y: 100 },
178
{ x: 200, y: 50 },
179
{ x: 300, y: 150 },
180
],
181
title: 'Test Bars 2',
182
type: SeriesType.Mark,
183
},
184
];
185
186
const chartWhisper = async () => {
187
await whisper.create({
188
label: 'Chart',
189
onClose: () => {
190
console.log('Closed chart Whisper');
191
},
192
components: [
193
{
194
type: WhisperComponentType.Chart,
195
chartTitle: 'Area Graph',
196
series: areaSeries,
197
xAxisLabel: "Custom X Axis Label",
198
yAxisLabel: "Custom Y Axis Label",
199
},
200
{
201
type: WhisperComponentType.Chart,
202
chartTitle: "Bar Graph",
203
series: barSeriesData,
204
xAxisLabel: "Custom X Axis Label",
205
yAxisLabel: "Custom Y Axis Label",
206
},
207
{
208
type: WhisperComponentType.Chart,
209
chartTitle: "Line Graph",
210
series: lineSeriesData,
211
xAxisLabel: "Custom X Axis Label",
212
yAxisLabel: "Custom Y Axis Label",
213
},
214
{
215
type: WhisperComponentType.Chart,
216
chartTitle: "Mark Graph",
217
series: markSeriesData,
218
xAxisLabel: "Custom X Axis Label",
219
yAxisLabel: "Custom Y Axis Label",
220
},
221
{
222
type: WhisperComponentType.Chart,
223
chartTitle: "Four Series Graph",
224
series: fourSeriesData,
225
xAxisLabel: "Custom X Axis Label",
226
yAxisLabel: "Custom Y Axis Label",
227
},
228
],
229
});
230
}
231
Copied!
1
import { whisper, React, ReactWhisper } from '@oliveai/ldk';
2
import { AxisScale, SeriesColor, SeriesType } from '@oliveai/ldk/dist/whisper/types';
3
import { onActionWrapper } from '../utils';
4
5
type SeriesInput = {
6
barWidth?: number;
7
color?: SeriesColor;
8
numberOfPoints?: number;
9
title: string;
10
type: SeriesType;
11
};
12
13
const generateSeries = (inputs: SeriesInput[]) =>
14
inputs.map((input) => {
15
const data = [];
16
17
for (let i = 0; i < (input.numberOfPoints || 20); i += 1) {
18
const x = Math.floor(Math.random() * 100);
19
const y = Math.floor(Math.random() * 100);
20
data.push({ x, y });
21
}
22
23
return { ...input, data };
24
});
25
26
type RegenerateButtonParams = {
27
setter: React.Dispatch<React.SetStateAction<SeriesInput[]>>;
28
seriesData: SeriesInput[];
29
};
30
31
const RegenerateButton = ({ setter, seriesData }: RegenerateButtonParams) => {
32
const handleClick = () => {
33
setter(generateSeries(seriesData));
34
};
35
36
return (
37
<oh-box justifyContent={whisper.JustifyContent.Center} direction={whisper.Direction.Horizontal}>
38
<oh-button label="Regenerate Chart Data" onClick={handleClick} />
39
</oh-box>
40
);
41
};
42
43
export const testChart = (): Promise<boolean> =>
44
new Promise(async (resolve, reject) => {
45
const resolverMap = new Map([
46
['AreaGraph', false],
47
['BarGraph', false],
48
['LineGraph', false],
49
['MarkGraph', false],
50
['FourSeries', false],
51
]);
52
53
const ConfirmationButtons = ({
54
question,
55
testName,
56
}: {
57
question: string;
58
testName: string;
59
}) => {
60
const [isTested, setIsTested] = React.useState(false);
61
62
const handleClick: whisper.WhisperHandler = (error, thisWhisper) => {
63
onActionWrapper(error, testName, resolverMap, thisWhisper, resolve, reject);
64
setIsTested(true);
65
};
66
67
return (
68
<>
69
<oh-box
70
justifyContent={whisper.JustifyContent.Center}
71
direction={whisper.Direction.Horizontal}
72
>
73
<oh-markdown body={question} />
74
</oh-box>
75
<oh-box
76
justifyContent={whisper.JustifyContent.Center}
77
direction={whisper.Direction.Horizontal}
78
>
79
{isTested ? (
80
<oh-icon name="done" />
81
) : (
82
<>
83
<oh-button label="Yes" onClick={handleClick} />
84
<oh-button label="No" onClick={() => reject(new Error(`${testName} failed`))} />
85
</>
86
)}
87
</oh-box>
88
</>
89
);
90
};
91
92
try {
93
const AreaGraph = () => {
94
const series = [
95
{
96
data: [
97
{ x: 1, y: 0 },
98
{ x: 1, y: 10 },
99
{ x: 2, y: 5 },
100
{ x: 3, y: 15 },
101
],
102
title: 'Test Area 1',
103
type: SeriesType.Area,
104
},
105
{
106
data: [
107
{ x: 1, y: 0 },
108
{ x: 1, y: 3 },
109
{ x: 2, y: 1 },
110
{ x: 3, y: 6 },
111
],
112
title: 'Test Area 2',
113
type: SeriesType.Area,
114
},
115
];
116
117
return (
118
<>
119
<oh-chart
120
chartTitle="Area Graph Test"
121
series={series}
122
xAxisLabel="Custom X Axis Label"
123
yAxisLabel="Custom Y Axis Label"
124
/>
125
<ConfirmationButtons
126
question="Does the chart display an area graph, custom axis labels, and a tooltip when you hover your mouse?"
127
testName="AreaGraph"
128
/>
129
<oh-divider />
130
</>
131
);
132
};
133
134
const BarGraph = () => {
135
const seriesData = [
136
{
137
barWidth: 2,
138
numberOfPoints: 5,
139
title: 'Test Bars 1',
140
type: SeriesType.VerticalBar,
141
},
142
{
143
barWidth: 1,
144
numberOfPoints: 5,
145
title: 'Test Bars 2',
146
type: SeriesType.VerticalBar,
147
},
148
];
149
150
const [series, setSeries] = React.useState(generateSeries(seriesData));
151
152
return (
153
<>
154
<oh-chart
155
chartTitle="Bar Graph Test"
156
series={series}
157
xAxisLabel="Custom X Axis Label"
158
yAxisLabel="Custom Y Axis Label"
159
/>
160
<ConfirmationButtons
161
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?"
162
testName="BarGraph"
163
/>
164
<RegenerateButton setter={setSeries} seriesData={seriesData} />
165
<oh-divider />
166
</>
167
);
168
};
169
170
const LineGraph = () => {
171
const seriesData = [
172
{
173
numberOfPoints: 5,
174
title: 'Test Lines 1',
175
type: SeriesType.Line,
176
},
177
{
178
numberOfPoints: 5,
179
title: 'Test Lines 2',
180
type: SeriesType.Line,
181
},
182
];
183
184
const [series, setSeries] = React.useState(generateSeries(seriesData));
185
const [sortedSeries, setSortedSeries] = React.useState(series);
186
187
React.useEffect(() => {
188
setSortedSeries(
189
series.map((unsortedSeries) => {
190
const data = unsortedSeries.data.sort((a, b) => a.x - b.x);
191
return {
192
...unsortedSeries,
193
data,
194
};
195
}),
196
);
197
}, [series]);
198
199
return (
200
<>
201
<oh-chart
202
chartTitle="Line Graph Test"
203
series={sortedSeries}
204
xAxisLabel="Custom X Axis Label"
205
yAxisLabel="Custom Y Axis Label"
206
/>
207
<ConfirmationButtons
208
question="Does the chart display a line graph, custom axis labels, and a tooltip when you hover your mouse?"
209
testName="LineGraph"
210
/>
211
<RegenerateButton setter={setSeries} seriesData={seriesData} />
212
<oh-divider />
213
</>
214
);
215
};
216
217
const MarkGraph = () => {
218
const seriesData = [
219
{
220
numberOfPoints: 5,
221
title: 'Test Mark 1',
222
type: SeriesType.Mark,
223
},
224
{
225
numberOfPoints: 5,
226
title: 'Test Mark 2',
227
type: SeriesType.Mark,
228
},
229
];
230
231
const [series, setSeries] = React.useState(generateSeries(seriesData));
232
233
return (
234
<>
235
<oh-chart
236
chartTitle="Mark Graph Test"
237
series={series}
238
xAxisLabel="Custom X Axis Label"
239
yAxisLabel="Custom Y Axis Label"
240
/>
241
<ConfirmationButtons
242
question="Does the chart display a mark graph, custom axis labels, and a tooltip when you hover your mouse?"
243
testName="MarkGraph"
244
/>
245
<RegenerateButton setter={setSeries} seriesData={seriesData} />
246
<oh-divider />
247
</>
248
);
249
};
250
251
const FourSeries = () => {
252
const seriesData: SeriesInput[] = [
253
{
254
numberOfPoints: 5,
255
title: 'Area Graph',
256
type: SeriesType.Area,
257
},
258
{
259
numberOfPoints: 5,
260
title: 'Bar Graph',
261
type: SeriesType.VerticalBar,
262
},
263
{
264
numberOfPoints: 5,
265
title: 'Line Graph',
266
type: SeriesType.Line,
267
},
268
{
269
numberOfPoints: 5,
270
title: 'Mark Graph',
271
type: SeriesType.Mark,
272
},
273
];
274
275
const [series, setSeries] = React.useState(generateSeries(seriesData));
276
277
return (
278
<>
279
<oh-chart
280
chartTitle="Four Series Test"
281
series={series}
282
xAxisLabel="Custom X Axis Label"
283
yAxisLabel="Custom Y Axis Label"
284
/>
285
<ConfirmationButtons
286
question="Does the chart display area, bar, line, and mark graphs?"
287
testName="FourSeries"
288
/>
289
<RegenerateButton setter={setSeries} seriesData={seriesData} />
290
<oh-divider />
291
</>
292
);
293
};
294
295
const ChartTest = () => (
296
<oh-whisper label="Chart Test" onClose={() => console.debug('closed')}>
297
<AreaGraph />
298
<BarGraph />
299
<LineGraph />
300
<MarkGraph />
301
<FourSeries />
302
</oh-whisper>
303
);
304
ReactWhisper.renderNewWhisper(<ChartTest />);
305
} catch (e) {
306
console.error(e);
307
reject(e);
308
}
309
});
Copied!
Copy link