@neo4j-ndl/react-charts
Version:
React implementation of charts from Neo4j Design System
1,954 lines (1,850 loc) • 50.3 kB
Markdown
# Chart
Import: `import { Chart } from '@neo4j-ndl/react-charts'`
## Props
### Chart
| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `callbacks` | `{ onZoom?: ((params: { startValue: number; endValue: number; }) => void); }` | | | Callback functions for chart interactions. |
| `dataset` | `DatasetOption \| DatasetOption[] \| undefined` | ✅ | | The dataset configuration for the chart. Can be a single dataset or an array of datasets. |
| `dataZoom` | `DataZoomComponentOption \| DataZoomComponentOption[]` | | | Data zoom configuration for the chart. |
| `isChartZoomDisabled` | `boolean` | | | Whether the zoom in the chart is disabled |
| `isLoading` | `boolean` | | | Whether the chart is in a loading state. |
| `legend` | `{ show?: boolean; wrappingType?: "wrapping" \| "truncation" \| "overflow"; } \| undefined` | | | Legend configuration for the chart. `wrappingType` is deprecated and no longer has any effect since wrapping is now automatic, will be removed in v 5 |
| `option` | `Omit<EChartsOption, "legend" \| "dataset" \| "series" \| "xAxis" \| "yAxis">` | | | Additional ECharts options to merge with the chart configuration. |
| `palette` | `` `#${string}`[] `` | | | Custom color palette that overrides the default categorical colors. |
| `series` | `NeedleSeries` | ✅ | | The series configuration for the chart. Defines what data to display and how to display it. |
| `settings` | `SetOptionOpts` | | | Settings for how ECharts should update the chart. |
| `xAxis` | `XAXisOption \| XAXisOption[]` | | | X-axis configuration for the chart. |
| `yAxis` | `YAXisOption \| YAXisOption[]` | | | Y-axis configuration for the chart. |
### ChartEmpty
| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `action` | `ReactNode` | | | Optional element (preferably a TextButton) that should provide the user with an action. |
| `message` | `ReactNode` | | `No data available` | A text displayed to the user when the chart is empty. |
| `type` | `'bar' \| 'line' \| 'pie'` | | `line` | The type of chart. This is used to render the appropriate icon. |
## Examples
### Default
```tsx
import { Chart } from '@neo4j-ndl/react-charts';
const Component = () => {
return (
// The Chart component requires its parent to have an explicit height.
// Without one the chart canvas collapses to 0px and nothing renders.
// You can also check the components documentation by hovering over it.
<div
style={{
border: '1px solid silver',
borderRadius: '10px',
height: '350px',
padding: '20px',
width: '100%',
}}
>
<Chart
legend={{
show: true,
}}
dataset={[
{
source: [
['a', 'b', 'c', 'd', 'multiplier'],
[50, 750, 100, 5, 2],
[100, 500, 200, 8, 2],
[150, 500, 175, 3, 2],
[200, 300, 100, 3, 2],
[250, 400, 300, 3, 2],
[300, 600, 300, 3, 2],
],
},
{
source: [
['x', 'y'],
[25, 500],
[125, 1250],
[200, 600],
[null, null],
[275, 900],
[null, null],
[300, 900],
[450, 500],
],
},
]}
series={[
{
color: '#ffa500',
condition: 'less',
notificationType: 'warning',
type: 'thresholdLine',
xAxis: [0, 500],
yAxis: 700,
},
{
color: '#ff0000',
customCondition: (lineValue, thresholdLineValue) => {
return (lineValue as number) > (thresholdLineValue as number);
},
customConditionText: 'Above threshold',
name: 'Above threshold',
notificationType: 'danger',
type: 'thresholdLine',
xAxis: [0, 500],
yAxis: 800,
},
{
datasetIndex: 0,
encode: { x: 'a', y: 'b' },
name: 'first (dataset 0, dimension b)',
type: 'line',
},
{
datasetIndex: 0,
encode: { x: 'a', y: 'c' },
name: 'second (dataset 0, dimension c)',
type: 'line',
},
{
datasetIndex: 1,
encode: { x: 'x', y: 'y' },
name: 'third (dataset 1, dimension y)',
symbol: 'emptyCircle',
type: 'line',
},
{
data: [
[200, 400],
[250, 450],
[270, 475],
null,
[350, 250],
[390, 180],
[470, 220],
],
encode: { x: 'x', y: 'y' },
name: 'fourth (inlined data)',
type: 'line',
xAxisId: 'theXAxis',
},
{
data: [
[200, 230],
[250, 460],
[300, 500],
[350, 30],
[400, 1000],
[450, 200],
[500, 100],
],
encode: { x: 'x', y: 'y' },
name: 'fifth (inlined data)',
symbol: 'emptyCircle',
type: 'line',
xAxisId: 'theXAxis',
},
]}
xAxis={{
id: 'theXAxis',
type: 'value',
}}
yAxis={{
type: 'value',
}}
/>
</div>
);
};
export default Component;
```
### Area Lines
```tsx
import { Chart } from '@neo4j-ndl/react-charts';
const Component = () => {
return (
// The Chart component requires its parent to have an explicit height.
// Without one the chart canvas collapses to 0px and nothing renders.
// You can also check the components documentation by hovering over it.
<div
style={{
border: '1px solid silver',
borderRadius: '10px',
height: '350px',
padding: '20px',
width: '100%',
}}
>
<Chart
legend={{
show: true,
}}
dataset={[
{
source: [
['x', 'y'],
[50, 750],
[100, 500],
[150, 500],
[200, 300],
[250, 400],
[300, 600],
],
},
{
source: [
['x', 'y'],
[50, 50],
[100, 300],
[150, 300],
[200, 100],
[250, 200],
[300, 400],
],
},
{
source: [
['x', 'y'],
[50, 150],
[100, 400],
[150, 400],
[200, 200],
[250, 300],
[300, 500],
],
},
]}
series={[
{
areaStyle: {
origin: 'start',
},
datasetIndex: 1,
encode: { x: 'x', y: 'y' },
name: 'min',
stack: 'the stack id',
type: 'line',
},
{
areaStyle: {},
datasetIndex: 2,
encode: { x: 'x', y: 'y' },
name: 'average',
stack: 'the stack id',
type: 'line',
},
{
areaStyle: {
origin: 'start',
},
datasetIndex: 0,
encode: { x: 'x', y: 'y' },
name: 'max',
stack: 'the stack id',
type: 'line',
},
]}
xAxis={{
axisTick: {
alignWithLabel: true,
},
type: 'category',
}}
yAxis={{}}
/>
</div>
);
};
export default Component;
```
### Bar Chart Horizontal Grouped
```tsx
import { Chart } from '@neo4j-ndl/react-charts';
const Component = () => {
return (
// The Chart component requires its parent to have an explicit height.
// Without one the chart canvas collapses to 0px and nothing renders.
// You can also check the components documentation by hovering over it.
<div
style={{
border: '1px solid silver',
borderRadius: '10px',
height: '350px',
padding: '20px',
width: '100%',
}}
>
<Chart
legend={{
show: true,
}}
dataset={{
dimensions: ['day', 'First', 'Second', 'Third'],
source: [
['Friday', 43, 85, 100],
['Saturday', 83, 73, 120],
['Sunday', 83, 73, 30],
],
}}
xAxis={{
type: 'value',
}}
yAxis={{
axisTick: {
alignWithLabel: true,
},
type: 'category',
}}
series={[
{
encode: {
x: 'First',
y: 'day',
},
name: 'First',
type: 'bar',
},
{
encode: {
x: 'Second',
y: 'day',
},
name: 'Second',
type: 'bar',
},
{
encode: {
x: 'Third',
y: 'day',
},
name: 'Third',
type: 'bar',
},
]}
/>
</div>
);
};
export default Component;
```
### Bar Chart Horizontal Stacked
```tsx
import { Chart } from '@neo4j-ndl/react-charts';
const Component = () => {
return (
// The Chart component requires its parent to have an explicit height.
// Without one the chart canvas collapses to 0px and nothing renders.
// You can also check the components documentation by hovering over it.
<div
style={{
border: '1px solid silver',
borderRadius: '10px',
height: '350px',
padding: '20px',
width: '100%',
}}
>
<Chart
dataset={[
{
source: [
['day', 'People', 'Beer'],
['Friday', 5, 10],
['Saturday', 20, 23],
['Sunday', 36, 132],
],
},
]}
legend={{
show: true,
}}
yAxis={{
data: ['Friday', 'Saturday', 'Sunday'],
splitLine: { show: true },
type: 'category',
}}
xAxis={{
splitLine: { show: false },
type: 'value',
}}
series={[
{
encode: { x: 'People', y: 'day' },
name: 'People',
stack: 'total',
type: 'bar',
},
{
encode: { x: 'Beer', y: 'day' },
itemStyle: { color: '#f28e1c' },
name: 'Beer',
stack: 'total',
type: 'bar',
},
]}
/>
</div>
);
};
export default Component;
```
### Bar Chart Logarithmic Scale
```tsx
import { Chart } from '@neo4j-ndl/react-charts';
const Component = () => {
return (
// The Chart component requires its parent to have an explicit height.
// Without one the chart canvas collapses to 0px and nothing renders.
// You can also check the components documentation by hovering over it.
<div
style={{
border: '1px solid silver',
borderRadius: '10px',
height: '350px',
padding: '20px',
width: '100%',
}}
>
<Chart
legend={{
show: true,
}}
dataset={{
source: [
['Country', 'Population'],
['Country 1', 1400000000],
['Country 2', 1380000000],
['Country 3', 330000000],
['Country 4', 220000000],
['Country 5', 10000000],
['Country 6', 366000],
['Country 7', 800],
],
}}
xAxis={{
type: 'category',
}}
yAxis={{
logBase: 10,
type: 'log',
}}
series={[
{
name: 'Population',
type: 'bar',
},
]}
/>
</div>
);
};
export default Component;
```
### Bar Chart Vertical Grouped
```tsx
import { Chart } from '@neo4j-ndl/react-charts';
const Component = () => {
return (
// The Chart component requires its parent to have an explicit height.
// Without one the chart canvas collapses to 0px and nothing renders.
// You can also check the components documentation by hovering over it.
<div
style={{
border: '1px solid silver',
borderRadius: '10px',
height: '350px',
padding: '20px',
width: '100%',
}}
>
<Chart
legend={{
show: true,
}}
dataset={{
source: [
['day', 'Beer', 'People', 'Drinks'],
['Friday', 43, 85, 100],
['Saturday', 83, 73, 120],
['Sunday', 83, 73, 30],
],
}}
xAxis={{
axisTick: {
alignWithLabel: true,
},
type: 'category',
}}
yAxis={{
type: 'value',
}}
series={[
{
name: 'First',
type: 'bar',
},
{
name: 'Second',
type: 'bar',
},
{
name: 'Third',
type: 'bar',
},
]}
/>
</div>
);
};
export default Component;
```
### Bar Chart Vertical Single
```tsx
import { Chart } from '@neo4j-ndl/react-charts';
const Component = () => {
return (
// The Chart component requires its parent to have an explicit height.
// Without one the chart canvas collapses to 0px and nothing renders.
// You can also check the components documentation by hovering over it.
<div
style={{
border: '1px solid silver',
borderRadius: '10px',
height: '350px',
padding: '20px',
width: '100%',
}}
>
<Chart
legend={{
show: true,
}}
dataset={{
dimensions: ['Country', 'Sales'],
source: [
['Finland', 165],
['Denmark', 140],
['Germany', 130],
['Spain', 125],
['France', 117],
['United Kingdom', 115],
['Romania', 108],
['Sweden', 103],
['Croatia', 94],
['Poland', 75],
['Slovenia', 62],
['Netherlands', 35],
],
}}
series={[
{
encode: {
x: 'Country',
y: 'Sales',
},
name: 'Sales',
type: 'bar' as const,
},
]}
xAxis={{
type: 'category',
}}
yAxis={{
type: 'value',
}}
/>
</div>
);
};
export default Component;
```
### Custom Color Palette
```tsx
import { Chart } from '@neo4j-ndl/react-charts';
const Component = () => {
return (
<div
style={{
border: '1px solid silver',
borderRadius: '10px',
height: '350px',
padding: '20px',
width: '100%',
}}
>
<Chart
palette={['#E63946', '#457B9D', '#2A9D8F', '#E9C46A', '#F4A261']}
legend={{
show: true,
}}
dataset={[
{
source: [
['x', 'a', 'b', 'c', 'd', 'e'],
[50, 750, 100, 300, 200, 400],
[100, 500, 200, 250, 350, 300],
[150, 500, 175, 400, 150, 250],
[200, 300, 100, 350, 400, 500],
[250, 400, 300, 200, 250, 350],
[300, 600, 300, 150, 300, 200],
],
},
]}
series={[
{
datasetIndex: 0,
encode: { x: 'x', y: 'a' },
name: 'Alpha',
type: 'line',
},
{
datasetIndex: 0,
encode: { x: 'x', y: 'b' },
name: 'Beta',
type: 'line',
},
{
datasetIndex: 0,
encode: { x: 'x', y: 'c' },
name: 'Gamma',
type: 'line',
},
{
datasetIndex: 0,
encode: { x: 'x', y: 'd' },
name: 'Delta',
type: 'line',
},
{
datasetIndex: 0,
encode: { x: 'x', y: 'e' },
name: 'Epsilon',
type: 'line',
},
]}
xAxis={{
type: 'value',
}}
yAxis={{
type: 'value',
}}
/>
</div>
);
};
export default Component;
```
### Data Zoom Both Axes
```tsx
import { Chart } from '@neo4j-ndl/react-charts';
const outliers = new Map<number, [number, number]>([
[18, [58, 122]],
[43, [4, -38]],
[79, [96, 148]],
[121, [12, -22]],
[154, [88, 132]],
]);
const sampleData = [
['time', 'response time', 'request volume'],
...Array.from({ length: 180 }, (_, index) => {
const normalResponseTime =
38 + Math.sin(index / 6) * 13 + Math.cos(index / 17) * 7;
const normalRequestVolume =
48 + Math.cos(index / 8) * 18 + Math.sin(index / 23) * 9;
const [responseTime, requestVolume] = outliers.get(index) ?? [
normalResponseTime,
normalRequestVolume,
];
return [
index,
Number(responseTime.toFixed(2)),
Number(requestVolume.toFixed(2)),
];
}),
];
const Component = () => {
return (
// The Chart component requires its parent to have an explicit height.
// Without one the chart canvas collapses to 0px and nothing renders.
// You can also check the components documentation by hovering over it.
<div
style={{
border: '1px solid silver',
borderRadius: '10px',
height: '350px',
padding: '20px',
width: '100%',
}}
>
<Chart
legend={{
show: true,
}}
dataset={[
{
source: sampleData,
},
]}
series={[
{
color: '#ffa500',
condition: 'greater',
notificationType: 'warning',
type: 'thresholdLine',
xAxis: [0, 179],
yAxis: 80,
},
{
color: '#ff0000',
condition: 'greater',
notificationType: 'danger',
type: 'thresholdLine',
xAxis: [0, 179],
yAxis: 110,
},
{
encode: { x: 'time', y: 'response time' },
name: 'Response time',
type: 'line',
},
{
encode: { x: 'time', y: 'request volume' },
name: 'Request volume',
type: 'line',
},
]}
xAxis={{
name: 'Time',
type: 'value',
}}
yAxis={{
name: 'Value',
type: 'value',
}}
option={{
dataZoom: [
{
filterMode: 'none',
type: 'inside',
zoomOnMouseWheel: false,
},
{
filterMode: 'none',
type: 'inside',
xAxisIndex: false,
yAxisIndex: [0],
zoomOnMouseWheel: false,
},
],
grid: {
right: '70px',
},
toolbox: {
feature: {
dataZoom: {
yAxisIndex: [0],
},
},
},
}}
/>
</div>
);
};
export default Component;
```
### Disabled Zoom
```tsx
import { Chart } from '@neo4j-ndl/react-charts';
const Component = () => {
return (
// The Chart component requires its parent to have an explicit height.
// Without one the chart canvas collapses to 0px and nothing renders.
// You can also check the components documentation by hovering over it.
<div
style={{
border: '1px solid silver',
borderRadius: '10px',
height: '350px',
padding: '20px',
width: '100%',
}}
>
<Chart
legend={{
show: true,
}}
dataset={[
{
source: [
['a', 'b', 'c', 'd', 'multiplier'],
[50, 750, 100, 5, 2],
[100, 500, 200, 8, 2],
[150, 500, 175, 3, 2],
[200, 300, 100, 3, 2],
[250, 400, 300, 3, 2],
[300, 600, 300, 3, 2],
],
},
{
source: [
['x', 'y'],
[25, 500],
[125, 1250],
[200, 600],
[null, null],
[275, 900],
[null, null],
[300, 900],
[450, 500],
],
},
]}
series={[
{
color: '#ffa500',
condition: 'less',
notificationType: 'warning',
type: 'thresholdLine',
xAxis: [0, 500],
yAxis: 700,
},
{
color: '#ff0000',
customCondition: (lineValue, thresholdLineValue) => {
return (lineValue as number) > (thresholdLineValue as number);
},
customConditionText: 'Above threshold',
name: 'Above threshold',
notificationType: 'danger',
type: 'thresholdLine',
xAxis: [0, 500],
yAxis: 800,
},
{
datasetIndex: 0,
encode: { x: 'a', y: 'b' },
name: 'first (dataset 0, dimension b)',
type: 'line',
},
{
datasetIndex: 0,
encode: { x: 'a', y: 'c' },
name: 'second (dataset 0, dimension c)',
type: 'line',
},
{
datasetIndex: 1,
encode: { x: 'x', y: 'y' },
name: 'third (dataset 1, dimension y)',
symbol: 'emptyCircle',
type: 'line',
},
{
data: [
[200, 400],
[250, 450],
[270, 475],
null,
[350, 250],
[390, 180],
[470, 220],
],
encode: { x: 'x', y: 'y' },
name: 'fourth (inlined data)',
type: 'line',
xAxisId: 'theXAxis',
},
{
data: [
[200, 230],
[250, 460],
[300, 500],
[350, 30],
[400, 1000],
[450, 200],
[500, 100],
],
encode: { x: 'x', y: 'y' },
name: 'fifth (inlined data)',
symbol: 'emptyCircle',
type: 'line',
xAxisId: 'theXAxis',
},
]}
xAxis={{
id: 'theXAxis',
type: 'value',
}}
yAxis={{
type: 'value',
}}
isChartZoomDisabled={true}
/>
</div>
);
};
export default Component;
```
### Empty State
```tsx
import { TextButton } from '@neo4j-ndl/react';
import { ChartEmpty } from '../ChartEmpty';
const Component = () => {
return (
// The Chart component requires its parent to have an explicit height.
// Without one the chart canvas collapses to 0px and nothing renders.
// You can also check the components documentation by hovering over it.
<div
style={{
border: '1px solid silver',
borderRadius: '10px',
height: '350px',
padding: '20px',
width: '100%',
}}
>
<ChartEmpty type="line" action={<TextButton>Refresh</TextButton>} />
</div>
);
};
export default Component;
```
### Legend Default
```tsx
import { Chart } from '@neo4j-ndl/react-charts';
import { chartData } from './common';
const Component = () => {
return (
// The Chart component requires its parent to have an explicit height.
// Without one the chart canvas collapses to 0px and nothing renders.
// You can also check the components documentation by hovering over it.
<div
style={{
border: '1px solid silver',
borderRadius: '10px',
height: '350px',
padding: '20px',
width: '100%',
}}
>
<Chart
dataset={chartData.dataset}
xAxis={chartData.xAxis}
yAxis={chartData.yAxis}
series={chartData.series}
legend={{
show: true,
}}
/>
</div>
);
};
export default Component;
```
### Loading
```tsx
import { Chart } from '@neo4j-ndl/react-charts';
const Component = () => {
return (
// The Chart component requires its parent to have an explicit height.
// Without one the chart canvas collapses to 0px and nothing renders.
// You can also check the components documentation by hovering over it.
<div
style={{
border: '1px solid silver',
borderRadius: '10px',
height: '350px',
padding: '20px',
width: '100%',
}}
>
<Chart
legend={{
show: true,
}}
isLoading
dataset={[
{
source: [
['a', 'b', 'c', 'd', 'multiplier'],
[50, 750, 100, 5, 2],
[100, 500, 200, 8, 2],
[150, 500, 175, 3, 2],
[200, 300, 100, 3, 2],
[250, 400, 300, 3, 2],
[300, 600, 300, 3, 2],
],
},
{
source: [
['x', 'y'],
[25, 500],
[125, 1250],
[200, 600],
[null, null],
[275, 900],
[null, null],
[300, 900],
[450, 500],
],
},
]}
series={[
{
color: '#ffa500',
condition: 'less',
notificationType: 'warning',
type: 'thresholdLine',
xAxis: [0, 500],
yAxis: 700,
},
{
color: '#ff0000',
customCondition: (lineValue, thresholdLineValue) => {
return (lineValue as number) > (thresholdLineValue as number);
},
customConditionText: 'Above threshold',
name: 'Above threshold',
notificationType: 'danger',
type: 'thresholdLine',
xAxis: [0, 500],
yAxis: 800,
},
{
datasetIndex: 0,
encode: { x: 'a', y: 'b' },
name: 'first (dataset 0, dimension b)',
type: 'line',
},
{
datasetIndex: 0,
encode: { x: 'a', y: 'c' },
name: 'second (dataset 0, dimension c)',
type: 'line',
},
{
datasetIndex: 1,
encode: { x: 'x', y: 'y' },
name: 'third (dataset 1, dimension y)',
symbol: 'emptyCircle',
type: 'line',
},
{
data: [
[200, 400],
[250, 450],
[270, 475],
null,
[350, 250],
[390, 180],
[470, 220],
],
encode: { x: 'x', y: 'y' },
name: 'fourth (inlined data)',
type: 'line',
xAxisId: 'theXAxis',
},
{
data: [
[200, 230],
[250, 460],
[300, 500],
[350, 30],
[400, 1000],
[450, 200],
[500, 100],
],
encode: { x: 'x', y: 'y' },
name: 'fifth (inlined data)',
symbol: 'emptyCircle',
type: 'line',
xAxisId: 'theXAxis',
},
]}
xAxis={{
id: 'theXAxis',
type: 'value',
}}
yAxis={{
type: 'value',
}}
/>
</div>
);
};
export default Component;
```
### Mark Area
```tsx
import { Chart } from '@neo4j-ndl/react-charts';
const Component = () => {
return (
// The Chart component requires its parent to have an explicit height.
// Without one the chart canvas collapses to 0px and nothing renders.
// You can also check the components documentation by hovering over it.
<div
style={{
border: '1px solid silver',
borderRadius: '10px',
height: '350px',
padding: '20px',
width: '100%',
}}
>
<Chart
legend={{
show: true,
}}
dataset={[
{
source: [
['a', 'b', 'c', 'd', 'multiplier'],
[50, 750, 100, 5, 2],
[100, 500, 200, 8, 2],
[150, 500, 175, 3, 2],
[200, 300, 100, 3, 2],
[250, 400, 300, 3, 2],
[300, 600, 300, 3, 2],
],
},
{
source: [
['x', 'y'],
[25, 500],
[125, 1250],
[200, 600],
[null, null],
[275, 900],
[null, null],
[300, 900],
[450, 500],
],
},
]}
series={[
{
color: '#ffa500',
condition: 'less',
notificationType: 'warning',
type: 'thresholdLine',
xAxis: [0, 500],
yAxis: 700,
},
{
color: '#ff0000',
customCondition: (lineValue, thresholdLineValue) => {
return (lineValue as number) > (thresholdLineValue as number);
},
customConditionText: 'Above threshold',
name: 'Above threshold',
notificationType: 'danger',
type: 'thresholdLine',
xAxis: [0, 500],
yAxis: 800,
},
{
datasetIndex: 0,
encode: { x: 'a', y: 'b' },
name: 'first (dataset 0, dimension b)',
type: 'line',
},
{
datasetIndex: 0,
encode: { x: 'a', y: 'c' },
name: 'second (dataset 0, dimension c)',
type: 'line',
},
{
datasetIndex: 1,
encode: { x: 'x', y: 'y' },
name: 'third (dataset 1, dimension y)',
symbol: 'emptyCircle',
type: 'line',
},
{
data: [
[200, 400],
[250, 450],
[270, 475],
null,
[350, 250],
[390, 180],
[470, 220],
],
encode: { x: 'x', y: 'y' },
markArea: {
data: [
[
{
name: 'Morning Peak',
xAxis: '100',
},
{
xAxis: '200',
},
],
],
itemStyle: {
color: 'rgba(255, 173, 177, 0.4)',
},
},
name: 'fourth (inlined data)',
type: 'line',
xAxisId: 'theXAxis',
},
{
data: [
[200, 230],
[250, 460],
[300, 500],
[350, 30],
[400, 1000],
[450, 200],
[500, 100],
],
encode: { x: 'x', y: 'y' },
name: 'fifth (inlined data)',
symbol: 'emptyCircle',
type: 'line',
xAxisId: 'theXAxis',
},
]}
xAxis={{
id: 'theXAxis',
type: 'value',
}}
yAxis={{
type: 'value',
}}
/>
</div>
);
};
export default Component;
```
### Multi Dimension Dataset
```tsx
import { Checkbox } from '@neo4j-ndl/react';
import { Chart } from '@neo4j-ndl/react-charts';
import { useState } from 'react';
const valueGenerators = {
// Smooth bell curve peaking at midday
bellCurve: (date: Date) => {
const hour = date.getHours();
return Number(
Math.min(
0.95,
Math.max(0.05, 0.2 + Math.sin((hour - 12) * (Math.PI / 12)) * 0.75),
).toFixed(2),
);
},
eveningPeakGenerator: (date: Date) => {
const hour = date.getHours();
// Peak at 22:00 (10 PM), lowest at 9:00 (9 AM)
const hoursSince9AM = (hour + 24 - 9) % 24;
return Number(
(0.05 + Math.sin(hoursSince9AM * (Math.PI / 26)) * 0.9).toFixed(2),
);
},
stepDownGenerator: (date: Date) => {
const hour = date.getHours();
// High (0.9) from 12:00 to 20:00, then low (0.1)
return hour >= 12 && hour <= 20 ? 0.9 : 0.1;
},
};
function generateTimeSeriesData<T extends number[]>(
startDate: Date,
hours: number,
// allow multiple
...valueGenerators: ((date: Date) => number)[]
): [Date, ...T][] {
const data: [Date, ...T][] = [];
for (let hour = 0; hour < hours; hour++) {
const date = new Date(startDate);
date.setHours(date.getHours() + hour);
data.push([
date,
...valueGenerators.map((generator) => generator(date)),
] as [Date, ...T]);
}
return data;
}
const Component = () => {
const yDimensions = ['y1', 'y2', 'y3'] as const;
const yDimensionNames: Record<(typeof yDimensions)[number], string> = {
y1: 'Percentage line 1 (Evening peak)',
y2: 'Percentage line 2 (Step down)',
y3: 'Percentage line 3 (Bell curve)',
};
const [checkedYDimensions, setCheckedYDimensions] = useState([
...yDimensions,
]);
const handleToggleYDimension = (yDimension: (typeof yDimensions)[number]) => {
setCheckedYDimensions(
(checkedYDimensions.includes(yDimension)
? checkedYDimensions.filter((d) => d !== yDimension)
: [...checkedYDimensions, yDimension]
).sort(),
);
};
const args = {
dataset: [
{
dimensions: ['x', ...yDimensions],
source: [
...generateTimeSeriesData(
new Date(2024, 0, 1, 12, 0, 0),
25,
valueGenerators.eveningPeakGenerator,
valueGenerators.stepDownGenerator,
valueGenerators.bellCurve,
),
],
},
],
legend: {
show: true,
},
option: {
tooltip: {
type: 'axis',
valueFormatter: (value: number) => `${value * 100} %`,
},
},
series: checkedYDimensions.map((yDimension) => ({
encode: { x: 'x', y: yDimension },
id: yDimension,
name: yDimensionNames[yDimension],
type: 'line' as const,
})),
settings: {
replaceMerge: ['series'],
},
xAxis: {
axisLabel: {
hideOverlap: true,
},
id: 'theXAxis',
type: 'time' as const,
},
yAxis: [
{
axisLabel: {
formatter: (value: number) => `${value * 100}%`,
hideOverlap: true,
},
id: 'theYAxis',
max: 1,
min: 0,
type: 'value' as const,
},
{
axisLabel: {
hideOverlap: true,
},
id: 'theYAxis2',
type: 'value' as const,
},
],
};
return (
<>
<div className="n-flex n-flex-row n-gap-4 n-mb-4">
{yDimensions.map((yDimension) => (
<Checkbox
key={yDimension}
label={yDimensionNames[yDimension]}
isChecked={checkedYDimensions.includes(yDimension)}
onChange={() => handleToggleYDimension(yDimension)}
/>
))}
</div>
{/* The Chart component requires its parent to have an explicit height.
Without one the chart canvas collapses to 0px and nothing renders.
You can also check the components documentation by hovering over it. */}
<div
style={{
border: '1px solid silver',
borderRadius: '10px',
height: '300px',
padding: '20px',
width: '100%',
}}
>
<Chart {...args} />
</div>
</>
);
};
export default Component;
```
### Percentage Chart
```tsx
import { Chart } from '@neo4j-ndl/react-charts';
const Component = () => {
return (
// The Chart component requires its parent to have an explicit height.
// Without one the chart canvas collapses to 0px and nothing renders.
// You can also check the components documentation by hovering over it.
<div
style={{
border: '1px solid silver',
borderRadius: '10px',
height: '350px',
padding: '20px',
width: '100%',
}}
>
<Chart
legend={{
show: true,
}}
dataset={[
{
source: [
['x', 'y'],
[new Date(2024, 0, 1, 12, 0, 0), 0.2],
[new Date(2024, 0, 1, 13, 0, 0), 0.1],
[new Date(2024, 0, 1, 14, 0, 0), 0.2],
[new Date(2024, 0, 1, 15, 0, 0), 0.3],
[new Date(2024, 0, 1, 16, 0, 0), 0.4],
[new Date(2024, 0, 1, 17, 0, 0), 0.5],
[new Date(2024, 0, 1, 18, 0, 0), 0.6],
[new Date(2024, 0, 1, 19, 0, 0), 0.7],
[new Date(2024, 0, 1, 20, 0, 0), 0.8],
[new Date(2024, 0, 1, 21, 0, 0), 0.9],
[new Date(2024, 0, 1, 22, 0, 0), 0.95],
[new Date(2024, 0, 1, 23, 0, 0), 0.9],
[new Date(2024, 0, 2, 0, 0, 0), 0.8],
[new Date(2024, 0, 2, 1, 0, 0), 0.7],
[new Date(2024, 0, 2, 2, 0, 0), 0.6],
[new Date(2024, 0, 2, 3, 0, 0), 0.5],
[new Date(2024, 0, 2, 4, 0, 0), 0.4],
[new Date(2024, 0, 2, 5, 0, 0), 0.3],
[new Date(2024, 0, 2, 6, 0, 0), 0.2],
[new Date(2024, 0, 2, 7, 0, 0), 0.1],
[new Date(2024, 0, 2, 8, 0, 0), 0.05],
[new Date(2024, 0, 2, 9, 0, 0), 0.05],
[new Date(2024, 0, 2, 10, 0, 0), 0.1],
[new Date(2024, 0, 2, 11, 0, 0), 0.2],
[new Date(2024, 0, 2, 12, 0, 0), 0.3],
],
},
{
source: [
['x', 'y'],
[new Date(2024, 0, 1, 12, 0, 0), 0.9],
[new Date(2024, 0, 1, 13, 0, 0), 0.9],
[new Date(2024, 0, 1, 14, 0, 0), 0.9],
[new Date(2024, 0, 1, 15, 0, 0), 0.9],
[new Date(2024, 0, 1, 16, 0, 0), 0.9],
[new Date(2024, 0, 1, 17, 0, 0), 0.9],
[new Date(2024, 0, 1, 18, 0, 0), 0.9],
[new Date(2024, 0, 1, 19, 0, 0), 0.9],
[new Date(2024, 0, 1, 20, 0, 0), 0.9],
[new Date(2024, 0, 1, 21, 0, 0), 0.1],
[new Date(2024, 0, 1, 22, 0, 0), 0.1],
[new Date(2024, 0, 1, 23, 0, 0), 0.1],
[new Date(2024, 0, 2, 0, 0, 0), 0.1],
[new Date(2024, 0, 2, 1, 0, 0), 0.1],
[new Date(2024, 0, 2, 2, 0, 0), 0.1],
[new Date(2024, 0, 2, 3, 0, 0), 0.1],
[new Date(2024, 0, 2, 4, 0, 0), 0.1],
[new Date(2024, 0, 2, 5, 0, 0), 0.1],
[new Date(2024, 0, 2, 6, 0, 0), 0.1],
[new Date(2024, 0, 2, 7, 0, 0), 0.1],
[new Date(2024, 0, 2, 8, 0, 0), 0.1],
[new Date(2024, 0, 2, 9, 0, 0), 0.1],
[new Date(2024, 0, 2, 10, 0, 0), 0.1],
[new Date(2024, 0, 2, 11, 0, 0), 0.1],
[new Date(2024, 0, 2, 12, 0, 0), 0.1],
],
},
]}
xAxis={{
id: 'theXAxis',
type: 'time',
}}
yAxis={[
{
axisLabel: {
formatter: (value: number) => `${value * 100}%`,
},
id: 'theYAxis',
max: 1,
min: 0,
type: 'value',
},
{
id: 'theYAxis2',
type: 'value',
},
]}
series={[
{
datasetIndex: 0,
name: 'Percentage line',
type: 'line',
},
{
datasetIndex: 1,
name: 'Percentage line 2',
type: 'line',
yAxisId: 'theYAxis2',
},
]}
option={{
tooltip: {
valueFormatter: (value: number) => `${value * 100} %`,
},
}}
/>
</div>
);
};
export default Component;
```
### Pie Chart
```tsx
import { Chart } from '@neo4j-ndl/react-charts';
const Component = () => {
return (
// The Chart component requires its parent to have an explicit height.
// Without one the chart canvas collapses to 0px and nothing renders.
// You can also check the components documentation by hovering over it.
<div
style={{
border: '1px solid silver',
borderRadius: '10px',
height: '350px',
padding: '20px',
width: '100%',
}}
>
<Chart
legend={{
show: true,
}}
option={{
tooltip: {
valueFormatter: (value: number) => `${Math.round(value)}`,
},
}}
series={[
{
center: ['50%', '50%'],
encode: {
itemName: 'product',
value: '2015',
},
radius: '90%',
type: 'pie',
},
]}
dataset={[
{
source: [
['product', '2012', '2013', '2014', '2015', '2016', '2017'],
['Milk Tea', 86.5, 92.1, 85.7, 83.1, 73.4, 55.1],
['Matcha Latte', 41.1, 30.4, 65.1, 53.3, 83.8, 98.7],
['Cheese Cocoa', 24.1, 67.2, 79.5, 86.4, 65.2, 82.5],
['Walnut Brownie', 55.2, 67.1, 69.2, 72.4, 53.9, 39.1],
],
},
]}
/>
</div>
);
};
export default Component;
```
### Preview Charts
```tsx
import { CleanIconButton, DropdownButton } from '@neo4j-ndl/react';
import { Preview } from '@neo4j-ndl/react/ai';
import { ExpandIcon } from '@neo4j-ndl/react/icons';
import { Chart } from '@neo4j-ndl/react-charts';
const Component = () => {
return (
<Preview>
<Preview.Header
actions={
<>
<DropdownButton size="small">Send to Dashboards</DropdownButton>
<CleanIconButton description="Expand" size="small">
<ExpandIcon />
</CleanIconButton>
</>
}
>
Visualization
</Preview.Header>
{/* The Chart component requires its parent to have an explicit height.
Without one the chart canvas collapses to 0px and nothing renders.
You can also check the components documentation by hovering over it. */}
<div
style={{
backgroundColor: 'var(--theme-color-neutral-bg-default)',
height: '265px',
}}
>
<Chart
dataset={{
source: [
['day', 'Beer'],
['Monday', 30],
['Tuesday', 20],
['Wednesday', 65],
['Thursday', 40],
['Friday', 43],
['Saturday', 83],
['Sunday', 83],
],
}}
xAxis={{
axisTick: {
alignWithLabel: true,
},
type: 'category',
}}
yAxis={{
type: 'value',
}}
series={[
{
name: 'Beer',
type: 'bar',
},
]}
/>
</div>
</Preview>
);
};
export default Component;
```
### Slider
```tsx
import { Chart } from '@neo4j-ndl/react-charts';
const Component = () => {
return (
// The Chart component requires its parent to have an explicit height.
// Without one the chart canvas collapses to 0px and nothing renders.
// You can also check the components documentation by hovering over it.
<div
style={{
border: '1px solid silver',
borderRadius: '10px',
height: '350px',
padding: '20px',
width: '100%',
}}
>
<Chart
legend={{
show: true,
}}
dataset={[
{
source: [
['a', 'b', 'c', 'd', 'multiplier'],
[50, 750, 100, 5, 2],
[100, 500, 200, 8, 2],
[150, 500, 175, 3, 2],
[200, 300, 100, 3, 2],
[250, 400, 300, 3, 2],
[300, 600, 300, 3, 2],
],
},
{
source: [
['x', 'y'],
[25, 500],
[125, 1250],
[200, 600],
[null, null],
[275, 900],
[null, null],
[300, 900],
[450, 500],
],
},
]}
series={[
{
condition: 'less',
notificationType: 'warning',
type: 'thresholdLine',
xAxis: [0, 500],
yAxis: 700,
},
{
color: '#ff0000',
customCondition: (lineValue, thresholdLineValue) => {
return (lineValue as number) > (thresholdLineValue as number);
},
customConditionText: 'Above threshold',
name: 'Above threshold',
notificationType: 'danger',
type: 'thresholdLine',
xAxis: [0, 500],
yAxis: 800,
},
{
datasetIndex: 0,
encode: { x: 'a', y: 'b' },
name: 'this is one',
type: 'line',
},
{
datasetIndex: 1,
encode: { x: 'x', y: 'y' },
name: 'This is two',
symbol: 'emptyCircle',
type: 'line',
},
{
data: [
[200, 400],
[250, 450],
[270, 475],
null,
[350, 250],
[390, 180],
[470, 220],
],
name: 'This is three',
type: 'line',
xAxisId: 'theXAxis',
},
{
data: [
[200, 230],
[250, 460],
[300, 500],
[350, 30],
[400, 1000],
[450, 300],
[500, 110],
],
name: 'This is four',
symbol: 'emptyCircle',
type: 'line',
xAxisId: 'theXAxis',
},
]}
xAxis={{
id: 'theXAxis',
type: 'value',
}}
yAxis={{
id: 'theYAxis',
type: 'value',
}}
option={{
dataZoom: [
{
type: 'slider',
},
],
}}
/>
</div>
);
};
export default Component;
```
### Threshold Values
```tsx
import { Chart } from '@neo4j-ndl/react-charts';
const Component = () => {
return (
// The Chart component requires its parent to have an explicit height.
// Without one the chart canvas collapses to 0px and nothing renders.
// You can also check the components documentation by hovering over it.
<div
style={{
border: '1px solid silver',
borderRadius: '10px',
height: '350px',
padding: '20px',
width: '100%',
}}
>
<Chart
legend={{
show: true,
}}
dataset={[
{
source: [
['time', 'querySuccessRate', 'pageCacheHitRate'],
[0, 0.92, 0.85],
[1, 0.94, 0.83],
[2, 0.97, 0.8],
[3, 0.95, 0.76],
[4, 0.91, 0.73],
[5, 0.86, 0.71],
[6, 0.82, 0.68],
[7, 0.78, 0.64],
[8, 0.73, 0.61],
[9, 0.69, 0.58],
[10, 0.66, 0.56],
[11, 0.64, 0.55],
[12, 0.67, 0.57],
[13, 0.71, 0.6],
[14, 0.74, 0.64],
[15, 0.78, 0.69],
[16, 0.83, 0.73],
[17, 0.87, 0.76],
[18, 0.9, 0.8],
[19, 0.93, 0.84],
[20, 0.96, 0.87],
[21, 0.98, 0.9],
[22, 0.97, 0.93],
[23, 0.95, 0.96],
[24, 0.92, 0.98],
[25, 0.88, 0.95],
[26, 0.85, 0.91],
[27, 0.82, 0.87],
[28, 0.8, 0.83],
[29, 0.78, 0.79],
[30, 0.76, 0.75],
[31, 0.74, 0.72],
[32, 0.73, 0.7],
[33, 0.75, 0.68],
[34, 0.78, 0.66],
[35, 0.82, 0.65],
[36, 0.86, 0.67],
[37, 0.89, 0.7],
[38, 0.92, 0.74],
[39, 0.95, 0.78],
],
},
]}
series={[
{
color: '#f2b500',
condition: 'less',
notificationType: 'warning',
type: 'thresholdLine',
xAxis: [0, 39],
yAxis: 0.7,
},
{
color: '#c92a2a',
customCondition: (lineValue, thresholdLineValue) => {
return (lineValue as number) >= (thresholdLineValue as number);
},
customConditionText: 'greater than or equal to',
notificationType: 'danger',
type: 'thresholdLine',
xAxis: [0, 39],
yAxis: 0.95,
},
{
datasetIndex: 0,
encode: { x: 'time', y: 'querySuccessRate' },
name: 'Query success rate',
type: 'line',
},
{
datasetIndex: 0,