# LineChart
A flexible line chart component for displaying data trends over time. Supports multiple series, custom curves, areas, scrubbing, and interactive data exploration.
## Import
```tsx
import { LineChart } from '@coinbase/cds-web-visualization'
```
## Examples
LineChart is a wrapper for [CartesianChart](/components/graphs/CartesianChart) that makes it easy to create standard line charts, supporting a single x/y axis pair. Charts are built using SVGs.
### Basics
The only prop required is `series`, which takes an array of series objects. Each series object needs an `id` and a `data` array of numbers.
```jsx live
```
LineChart also supports multiple lines, interaction, and axes.
Other props, such as `areaType` can be applied to the chart as a whole or per series.
```jsx live
function MultipleLine() {
const pages = useMemo(
() => ['Page A', 'Page B', 'Page C', 'Page D', 'Page E', 'Page F', 'Page G'],
[],
);
const pageViews = useMemo(() => [2400, 1398, 9800, 3908, 4800, 3800, 4300], []);
const uniqueVisitors = useMemo(() => [4000, 3000, 2000, 2780, 1890, 2390, 3490], []);
const chartAccessibilityLabel = `Website visitors across ${pageViews.length} pages.`;
const scrubberAccessibilityLabel = useCallback(
(index: number) => {
return `${pages[index]} has ${pageViews[index]} views and ${uniqueVisitors[index]} unique visitors.`;
},
[pages, pageViews, uniqueVisitors],
);
const numberFormatter = useCallback(
(value: number) => new Intl.NumberFormat('en-US', { maximumFractionDigits: 0 }).format(value),
[],
);
return (
);
}
```
### Data
The data array for each series defines the y values for that series. You can adjust the y values for a series of data by setting the `data` prop on the xAxis.
```jsx live
function DataFormat() {
const yData = useMemo(() => [2, 5.5, 2, 8.5, 1.5, 5], []);
const xData = useMemo(() => [1, 2, 3, 5, 8, 10], []);
const chartAccessibilityLabel = `Chart with custom X and Y data. ${yData.length} data points`;
const scrubberAccessibilityLabel = useCallback(
(index: number) => {
return `Point ${index + 1}: X value ${xData[index]}, Y value ${yData[index]}`;
},
[xData, yData],
);
return (
);
}
```
#### Live Updates
You can change the data passed in via `series` prop to update the chart.
You can also use the `useRef` hook to reference the scrubber and pulse it on each update.
```jsx live
function LiveUpdates() {
const scrubberRef = useRef(null);
const initialData = useMemo(() => {
return sparklineInteractiveData.hour.map((d) => d.value);
}, []);
const [priceData, setPriceData] = useState(initialData);
const lastDataPointTimeRef = useRef(Date.now());
const updateCountRef = useRef(0);
const intervalSeconds = 3600 / initialData.length;
const maxPercentChange = Math.abs(initialData[initialData.length - 1] - initialData[0]) * 0.05;
useEffect(() => {
const priceUpdateInterval = setInterval(
() => {
setPriceData((currentData) => {
const newData = [...currentData];
const lastPrice = newData[newData.length - 1];
const priceChange = (Math.random() - 0.5) * maxPercentChange;
const newPrice = Math.round((lastPrice + priceChange) * 100) / 100;
// Check if we should roll over to a new data point
const currentTime = Date.now();
const timeSinceLastPoint = (currentTime - lastDataPointTimeRef.current) / 1000;
if (timeSinceLastPoint >= intervalSeconds) {
// Time for a new data point - remove first, add new at end
lastDataPointTimeRef.current = currentTime;
newData.shift(); // Remove oldest data point
newData.push(newPrice); // Add new data point
updateCountRef.current = 0;
} else {
// Just update the last data point
newData[newData.length - 1] = newPrice;
updateCountRef.current++;
}
return newData;
});
// Pulse the scrubber on each update
scrubberRef.current?.pulse();
},
2000 + Math.random() * 1000,
);
return () => clearInterval(priceUpdateInterval);
}, [intervalSeconds, maxPercentChange]);
const chartAccessibilityLabel = useMemo(() => {
return `Live Bitcoin price chart. Current price: $${priceData[priceData.length - 1].toFixed(2)}`;
}, [priceData]);
const scrubberAccessibilityLabel = useCallback(
(index: number) => {
const price = priceData[index];
return `Bitcoin price at position ${index + 1}: $${price.toFixed(2)}`;
},
[priceData],
);
return (
);
}
```
#### Missing Data
By default, null values in data create gaps in a line. Use `connectNulls` to skip null values and draw a continuous line.
Note that scrubber beacons and points are still only shown at non-null data values.
```jsx live
function MissingData() {
const pages = ['Page A', 'Page B', 'Page C', 'Page D', 'Page E', 'Page F', 'Page G'];
const pageViews = [2400, 1398, null, 3908, 4800, 3800, 4300];
const uniqueVisitors = [4000, 3000, null, 2780, 1890, 2390, 3490];
const numberFormatter = useCallback(
(value: number) => new Intl.NumberFormat('en-US', { maximumFractionDigits: 0 }).format(value),
[],
);
return (
{/* We can offset the overlay to account for the points being drawn on the lines */}
);
}
```
##### Empty State
```jsx live
```
#### Scales
LineChart uses `linear` scaling on axes by default, but you can also use other types, such as `log`. See [XAxis](/components/graphs/XAxis) and [YAxis](/components/graphs/YAxis) for more information.
```jsx live
```
### Interaction
Charts have built in functionality enabled through scrubbing, which can be used by setting `enableScrubbing` to true. You can listen to value changes through `onScrubberPositionChange`. Adding `Scrubber` to LineChart showcases the current scrubber position.
```jsx live
function Interaction() {
const [scrubberPosition, setScrubberPosition] = useState();
return (
{scrubberPosition !== undefined
? `Scrubber position: ${scrubberPosition}`
: 'Not scrubbing'}
);
}
```
#### Points
You can use `points` from LineChart with `onClick` listeners to render instances of [Point](/components/graphs/Point) that are interactable.
```jsx live
function Points() {
const keyMarketShiftIndices = [4, 6, 7, 9, 10];
const data = [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58];
return (
keyMarketShiftIndices.includes(dataX)
? {
...props,
strokeWidth: 2,
stroke: 'var(--color-bg)',
radius: 5,
onClick: () =>
alert(
`You have clicked a key market shift at position ${dataX + 1} with value ${dataY}!`,
),
accessibilityLabel: `Key market shift point at position ${dataX + 1}, value ${dataY}. Click to view details.`,
}
: false
}
seriesId="prices"
/>
);
}
```
### Animations
You can configure chart transitions using `transition` on LineChart and `beaconTransitions` on [Scrubber](/components/graphs/Scrubber). You can also disable animations by setting the `animate` on LineChart to `false`.
```jsx live
function Transitions() {
const dataCount = 20;
const maxDataOffset = 15000;
const minStepOffset = 2500;
const maxStepOffset = 10000;
const domainLimit = 20000;
const updateInterval = 500;
const myTransitionConfig = { type: 'spring', stiffness: 700, damping: 20 };
const negativeColor = 'rgb(var(--gray15))';
const positiveColor = 'var(--color-fgPositive)';
function generateNextValue(previousValue: number) {
const range = maxStepOffset - minStepOffset;
const offset = Math.random() * range + minStepOffset;
let direction;
if (previousValue >= maxDataOffset) {
direction = -1;
} else if (previousValue <= -maxDataOffset) {
direction = 1;
} else {
direction = Math.random() < 0.5 ? -1 : 1;
}
let newValue = previousValue + offset * direction;
newValue = Math.max(-maxDataOffset, Math.min(maxDataOffset, newValue));
return newValue;
}
function generateInitialData() {
const data = [];
let previousValue = Math.random() * 2 * maxDataOffset - maxDataOffset;
data.push(previousValue);
for (let i = 1; i < dataCount; i++) {
const newValue = generateNextValue(previousValue);
data.push(newValue);
previousValue = newValue;
}
return data;
}
const MyGradient = memo((props: DottedAreaProps) => {
const areaGradient = {
stops: ({ min, max }: AxisBounds) => [
{ offset: min, color: negativeColor, opacity: 1 },
{ offset: 0, color: negativeColor, opacity: 0 },
{ offset: 0, color: positiveColor, opacity: 0 },
{ offset: max, color: positiveColor, opacity: 1 },
],
};
return ;
});
function CustomTransitionsChart() {
const [data, setData] = useState(generateInitialData);
useEffect(() => {
const intervalId = setInterval(() => {
setData((currentData) => {
const lastValue = currentData[currentData.length - 1] ?? 0;
const newValue = generateNextValue(lastValue);
return [...currentData.slice(1), newValue];
});
}, updateInterval);
return () => clearInterval(intervalId);
}, []);
const tickLabelFormatter = useCallback(
(value: number) =>
new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
maximumFractionDigits: 0,
}).format(value),
[],
);
const valueAtIndexFormatter = useCallback(
(dataIndex: number) =>
new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
}).format(data[dataIndex]),
[data],
);
const lineGradient = {
stops: [
{ offset: 0, color: negativeColor },
{ offset: 0, color: positiveColor },
],
};
return (
);
}
return ;
}
```
### Accessibility
You can use `accessibilityLabel` on both the chart and the scrubber to provide descriptive labels. The chart's label gives an overview, while the scrubber's label provides specific information about the current data point being viewed.
```jsx live
function BasicAccessible() {
const data = useMemo(() => [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58], []);
// Chart-level accessibility label provides overview
const chartAccessibilityLabel = useMemo(() => {
const currentPrice = data[data.length - 1];
return `Price chart showing trend over ${data.length} data points. Current value: ${currentPrice}. Use arrow keys to adjust view`;
}, [data]);
// Scrubber-level accessibility label provides specific position info
const scrubberAccessibilityLabel = useCallback(
(index: number) => {
return `Price at position ${index + 1} of ${data.length}: ${data[index]}`;
},
[data],
);
return (
);
}
```
When a chart has a visible header or title, you can use `aria-labelledby` to reference it, and still provide a dynamic scrubber accessibility label.
```jsx live
function AccessibleWithHeader() {
const headerId = useId();
const data = useMemo(() => [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58], []);
// Display label provides overview
const displayLabel = useMemo(
() => `Revenue chart showing trend. Current value: ${data[data.length - 1]}`,
[data],
);
// Scrubber-specific accessibility label
const scrubberAccessibilityLabel = useCallback(
(index: number) => {
return `Viewing position ${index + 1} of ${data.length}, value: ${data[index]}`;
},
[data],
);
return (
);
}
```
### Styling
#### Axes
Using `showXAxis` and `showYAxis` allows you to display the axes. For more information, such as adjusting domain and range, see [XAxis](/components/graphs/XAxis) and [YAxis](/components/graphs/YAxis).
```jsx live
`Day ${dataX}`,
}}
yAxis={{
showGrid: true,
showLine: true,
showTickMarks: true,
}}
/>
```
#### Gradients
Gradients can be applied to the y-axis (default) or x-axis. Each stop requires an `offset`, which is based on the data within the x/y scale and `color`, with an optional `opacity` (defaults to 1).
Values in between stops will be interpolated smoothly using [srgb color space](https://www.w3.org/TR/SVG11/painting.html#ColorInterpolationProperty).
```jsx live
function Gradients() {
const spectrumColors = [
'blue',
'green',
'orange',
'yellow',
'gray',
'indigo',
'pink',
'purple',
'red',
'teal',
'chartreuse',
];
const data = [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58];
const [currentSpectrumColor, setCurrentSpectrumColor] = useState('pink');
return (
{spectrumColors.map((color) => (
setCurrentSpectrumColor(color)}
style={{
backgroundColor: `rgb(var(--${color}20))`,
border: `2px solid rgb(var(--${color}50))`,
outlineColor: `rgb(var(--${color}80))`,
outline:
currentSpectrumColor === color ? `2px solid rgb(var(--${color}80))` : undefined,
}}
width={{ base: 16, tablet: 24, desktop: 24 }}
/>
))}
d + 50),
// You can create a "discrete" gradient by having multiple stops at the same offset
gradient: {
stops: ({ min, max }) => [
// Allows a function which accepts min/max or direct array
{ offset: min, color: `rgb(var(--${currentSpectrumColor}80))` },
{ offset: min + (max - min) / 3, color: `rgb(var(--${currentSpectrumColor}80))` },
{ offset: min + (max - min) / 3, color: `rgb(var(--${currentSpectrumColor}50))` },
{
offset: min + ((max - min) / 3) * 2,
color: `rgb(var(--${currentSpectrumColor}50))`,
},
{
offset: min + ((max - min) / 3) * 2,
color: `rgb(var(--${currentSpectrumColor}20))`,
},
{ offset: max, color: `rgb(var(--${currentSpectrumColor}20))` },
],
},
},
{
id: 'xAxisGradient',
data: data.map((d) => d + 100),
gradient: {
// You can also configure by the x-axis.
axis: 'x',
stops: ({ min, max }) => [
{ offset: min, color: `rgb(var(--${currentSpectrumColor}80))`, opacity: 0 },
{ offset: max, color: `rgb(var(--${currentSpectrumColor}20))`, opacity: 1 },
],
},
},
]}
strokeWidth={4}
yAxis={{
showGrid: true,
}}
/>
);
}
```
You can even pass in a separate gradient for your `Line` and `Area` components.
```jsx live
function GainLossChart() {
const data = useMemo(() => [-40, -28, -21, -5, 48, -5, -28, 2, -29, -46, 16, -30, -29, 8], []);
const negativeColor = 'rgb(var(--gray15))';
const positiveColor = 'var(--color-fgPositive)';
const tickLabelFormatter = useCallback(
(value: number) =>
new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
maximumFractionDigits: 0,
}).format(value),
[],
);
// Line gradient: hard color change at 0 (full opacity for line)
const lineGradient = {
stops: [
{ offset: 0, color: negativeColor },
{ offset: 0, color: positiveColor },
],
};
const chartAccessibilityLabel = `Gain/Loss chart showing price changes. Current value: ${tickLabelFormatter(data[data.length - 1])}`;
const scrubberAccessibilityLabel = useCallback(
(index: number) => {
const value = data[index];
const status = value >= 0 ? 'gain' : 'loss';
return `Position ${index + 1} of ${data.length}: ${tickLabelFormatter(value)} ${status}`;
},
[data, tickLabelFormatter],
);
const GradientDottedArea = memo((props: DottedAreaProps) => (
[
{ offset: min, color: negativeColor, opacity: 0.4 },
{ offset: 0, color: negativeColor, opacity: 0 },
{ offset: 0, color: positiveColor, opacity: 0 },
{ offset: max, color: positiveColor, opacity: 0.4 },
],
}}
/>
));
return (
({ min, max: max - 16 }),
}}
>
);
}
```
#### Lines
You can customize lines by placing props in `LineChart` or at each individual series. Lines can have a `type` of `solid` or `dotted`. They can optionally show an area underneath them (using `showArea`).
```jsx live
```
You can also add instances of [ReferenceLine](/components/graphs/ReferenceLine) to your LineChart to highlight a specific x or y value.
```jsx live
({ min, max: max - 24 }),
}}
>
}
dataY={10}
stroke="var(--color-fg)"
/>
```
#### Points
You can also add instances of [Point](/components/graphs/Point) directly inside of a LineChart.
```jsx live
function HighLowPrice() {
const data = [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58];
const minPrice = Math.min(...data);
const maxPrice = Math.max(...data);
const minPriceIndex = data.indexOf(minPrice);
const maxPriceIndex = data.indexOf(maxPrice);
const formatPrice = useCallback((price: number) => {
return `$${price.toLocaleString('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
})}`;
}, []);
return (
);
}
```
#### Scrubber
When using [Scrubber](/components/graphs/Scrubber) with series that have labels, labels will automatically render to the side of the scrubber beacon.
You can customize the line used for and which series will render a scrubber beacon.
You can have scrubber beacon's pulse by either adding `idlePulse` to Scrubber or use Scrubber's ref to dynamically pulse.
```jsx live
function StylingScrubber() {
const pages = ['Page A', 'Page B', 'Page C', 'Page D', 'Page E', 'Page F', 'Page G'];
const pageViews = [2400, 1398, 9800, 3908, 4800, 3800, 4300];
const uniqueVisitors = [4000, 3000, 2000, 2780, 1890, 2390, 3490];
const numberFormatter = useCallback(
(value: number) => new Intl.NumberFormat('en-US', { maximumFractionDigits: 0 }).format(value),
[],
);
return (
);
}
```
#### Sizing
Charts by default take up `100%` of the `width` and `height` available, but can be customized as any other component.
```jsx live
function DynamicChartSizing() {
const candles = [...btcCandles].reverse();
const prices = candles.map((candle) => parseFloat(candle.close));
const highs = candles.map((candle) => parseFloat(candle.high));
const lows = candles.map((candle) => parseFloat(candle.low));
const latestPrice = prices[prices.length - 1];
const previousPrice = prices[prices.length - 2];
const change24h = ((latestPrice - previousPrice) / previousPrice) * 100;
function DetailCell({ title, description }: { title: string; description: string }) {
return (
{title}
{description}
);
}
// Calculate 7-day moving average
const calculateMA = (data: number[], period: number): number[] => {
const ma: number[] = [];
for (let i = 0; i < data.length; i++) {
if (i >= period - 1) {
const sum = data.slice(i - period + 1, i + 1).reduce((a, b) => a + b, 0);
ma.push(sum / period);
}
}
return ma;
};
const ma7 = calculateMA(prices, 7);
const latestMA7: number = ma7[ma7.length - 1];
const periodHigh = Math.max(...highs);
const periodLow = Math.min(...lows);
const formatPrice = useCallback((price: number) => {
return `$${price.toLocaleString('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
})}`;
}, []);
const formatPercentage = useCallback((value: number) => {
const sign = value >= 0 ? '+' : '';
return `${sign}${value.toFixed(2)}%`;
}, []);
return (
{/* LineChart fills to take up available width and height */}
BTC
{formatPrice(latestPrice)}
);
}
```
##### Compact
You can also have charts in a compact form.
```jsx live
function Compact() {
const dimensions = { width: 62, height: 18 };
const sparklineData = prices
.map((price) => parseFloat(price))
.filter((price, index) => index % 10 === 0);
const positiveFloor = Math.min(...sparklineData) - 10;
const negativeData = sparklineData.map((price) => -1 * price).reverse();
const negativeCeiling = Math.max(...negativeData) + 10;
const formatPrice = useCallback((price: number) => {
return `$${price.toLocaleString('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
})}`;
}, []);
type CompactChartProps = {
data: number[];
showArea?: boolean;
color?: string;
referenceY: number;
};
const CompactChart = memo(({ data, showArea, color, referenceY }: CompactChartProps) => (
));
const ChartCell = memo(
({
data,
showArea,
color,
referenceY,
subdetail,
}: CompactChartProps & { subdetail: string }) => {
const { isPhone } = useBreakpoints();
return (
}
media={}
onClick={() => console.log('clicked')}
spacingVariant="condensed"
style={{ padding: 0 }}
subdetail={subdetail}
title={isPhone ? undefined : assets.btc.name}
/>
);
},
);
return (
);
}
```
### Composed Examples
#### Asset Price with Dotted Area
You can use [PeriodSelector](/components/graphs/PeriodSelector) to have a chart where the user can select a time period and the chart automatically animates.
```jsx live
function AssetPriceWithDottedArea() {
const BTCTab: TabComponent = memo(
forwardRef(
({ label, ...props }: SegmentedTabProps, ref: React.ForwardedRef) => {
const { activeTab } = useTabsContext();
const isActive = activeTab?.id === props.id;
return (
{label}
}
{...props}
/>
);
},
),
);
const BTCActiveIndicator = memo(({ style, ...props }: TabsActiveIndicatorProps) => (
));
const AssetPriceDotted = memo(() => {
const currentPrice =
sparklineInteractiveData.hour[sparklineInteractiveData.hour.length - 1].value;
const tabs = useMemo(
() => [
{ id: 'hour', label: '1H' },
{ id: 'day', label: '1D' },
{ id: 'week', label: '1W' },
{ id: 'month', label: '1M' },
{ id: 'year', label: '1Y' },
{ id: 'all', label: 'All' },
],
[],
);
const [timePeriod, setTimePeriod] = useState(tabs[0]);
const sparklineTimePeriodData = useMemo(() => {
return sparklineInteractiveData[timePeriod.id as keyof typeof sparklineInteractiveData];
}, [timePeriod]);
const sparklineTimePeriodDataValues = useMemo(() => {
return sparklineTimePeriodData.map((d) => d.value);
}, [sparklineTimePeriodData]);
const sparklineTimePeriodDataTimestamps = useMemo(() => {
return sparklineTimePeriodData.map((d) => d.date);
}, [sparklineTimePeriodData]);
const onPeriodChange = useCallback(
(period: TabValue | null) => {
setTimePeriod(period || tabs[0]);
},
[tabs, setTimePeriod],
);
const priceFormatter = useMemo(
() =>
new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
}),
[],
);
const scrubberPriceFormatter = useMemo(
() =>
new Intl.NumberFormat('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
}),
[],
);
const formatPrice = useCallback(
(price: number) => {
return priceFormatter.format(price);
},
[priceFormatter],
);
const formatDate = useCallback((date: Date) => {
const dayOfWeek = date.toLocaleDateString('en-US', { weekday: 'short' });
const monthDay = date.toLocaleDateString('en-US', {
month: 'short',
day: 'numeric',
});
const time = date.toLocaleTimeString('en-US', {
hour: 'numeric',
minute: '2-digit',
hour12: true,
});
return `${dayOfWeek}, ${monthDay}, ${time}`;
}, []);
const scrubberLabel = useCallback(
(index: number) => {
const price = scrubberPriceFormatter.format(sparklineTimePeriodDataValues[index]);
const date = formatDate(sparklineTimePeriodDataTimestamps[index]);
return (
<>
{price} USD {date}
>
);
},
[
scrubberPriceFormatter,
sparklineTimePeriodDataValues,
sparklineTimePeriodDataTimestamps,
formatDate,
],
);
const chartAccessibilityLabel = `Bitcoin price chart for ${timePeriod.label} period. Current price: ${formatPrice(currentPrice)}`;
const scrubberAccessibilityLabel = useCallback(
(index: number) => {
const price = scrubberPriceFormatter.format(sparklineTimePeriodDataValues[index]);
const date = formatDate(sparklineTimePeriodDataTimestamps[index]);
return `${price} USD ${date}`;
},
[
scrubberPriceFormatter,
sparklineTimePeriodDataValues,
sparklineTimePeriodDataTimestamps,
formatDate,
],
);
return (
{formatPrice(currentPrice)}}
end={
}
style={{ padding: 0 }}
title={Bitcoin}
/>
);
});
return ;
}
```
#### Monotone Asset Price
You can adjust [YAxis](/components/graphs/YAxis) and [Scrubber](/components/graphs/Scrubber) to have a chart where the y-axis is overlaid and the beacon is inverted in style.
```jsx live
function MonotoneAssetPrice() {
const prices = sparklineInteractiveData.hour;
const priceFormatter = useMemo(
() =>
new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
}),
[],
);
const scrubberPriceFormatter = useMemo(
() =>
new Intl.NumberFormat('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
}),
[],
);
const formatPrice = useCallback(
(price: number) => {
return priceFormatter.format(price);
},
[priceFormatter],
);
const CustomYAxisTickLabel = useCallback(
(props) => (
),
[],
);
const formatDate = useCallback((date: Date) => {
const dayOfWeek = date.toLocaleDateString('en-US', { weekday: 'short' });
const monthDay = date.toLocaleDateString('en-US', {
month: 'short',
day: 'numeric',
});
const time = date.toLocaleTimeString('en-US', {
hour: 'numeric',
minute: '2-digit',
hour12: true,
});
return `${dayOfWeek}, ${monthDay}, ${time}`;
}, []);
const scrubberLabel = useCallback(
(index: number) => {
const price = scrubberPriceFormatter.format(prices[index].value);
const date = formatDate(prices[index].date);
return (
<>
{price} USD {date}
>
);
},
[scrubberPriceFormatter, prices, formatDate],
);
const InvertedBeacon = useMemo(
() => (props) => (
),
[],
);
return (
price.value),
color: 'var(--color-fg)',
gradient: {
axis: 'x',
stops: ({ min, max }) => [
{ offset: min, color: 'var(--color-fg)', opacity: 0 },
{ offset: 32, color: 'var(--color-fg)', opacity: 1 },
],
},
},
]}
style={{ outlineColor: 'var(--color-fg)' }}
xAxis={{
range: ({ min, max }) => ({ min: 96, max: max }),
}}
yAxis={{
position: 'left',
width: 0,
showGrid: true,
tickLabelFormatter: formatPrice,
TickLabelComponent: CustomYAxisTickLabel,
}}
>
);
}
```
#### Asset Price Widget
```jsx live
function AssetPriceWidget() {
const { isPhone } = useBreakpoints();
const prices = [...btcCandles].reverse().map((candle) => parseFloat(candle.close));
const latestPrice = prices[prices.length - 1];
const formatPrice = (price: number) => {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
}).format(price);
};
const formatPercentChange = (price: number) => {
return new Intl.NumberFormat('en-US', {
style: 'percent',
minimumFractionDigits: 2,
maximumFractionDigits: 2,
}).format(price);
};
const percentChange = (latestPrice - prices[0]) / prices[0];
const chartAccessibilityLabel = `Bitcoin price chart. Current price: ${formatPrice(latestPrice)}. Change: ${formatPercentChange(percentChange)}`;
const scrubberAccessibilityLabel = useCallback(
(index: number) => {
return `Bitcoin price at position ${index + 1}: ${formatPrice(prices[index])}`;
},
[prices],
);
return (
{!isPhone && (
BTC
Bitcoin
)}
{formatPrice(latestPrice)}
+{formatPercentChange(percentChange)}
);
}
```
#### Service Availability
You can have irregular data points by passing in `data` to `xAxis`.
```jsx live
function ServiceAvailability() {
const availabilityEvents = useMemo(
() => [
{ date: new Date('2022-01-01'), availability: 79 },
{ date: new Date('2022-01-03'), availability: 81 },
{ date: new Date('2022-01-04'), availability: 82 },
{ date: new Date('2022-01-06'), availability: 91 },
{ date: new Date('2022-01-07'), availability: 92 },
{ date: new Date('2022-01-10'), availability: 86 },
],
[],
);
const chartAccessibilityLabel = `Availability chart showing ${availabilityEvents.length} data points over time`;
const scrubberAccessibilityLabel = useCallback(
(index: number) => {
const event = availabilityEvents[index];
const formattedDate = event.date.toLocaleDateString('en-US', {
weekday: 'short',
month: 'short',
day: 'numeric',
year: 'numeric',
});
const status =
event.availability >= 90 ? 'Good' : event.availability >= 85 ? 'Warning' : 'Critical';
return `${formattedDate}: Availability ${event.availability}% - Status: ${status}`;
},
[availabilityEvents],
);
return (
event.availability),
gradient: {
stops: ({ min, max }) => [
{ offset: min, color: 'var(--color-fgNegative)' },
{ offset: 85, color: 'var(--color-fgNegative)' },
{ offset: 85, color: 'var(--color-fgWarning)' },
{ offset: 90, color: 'var(--color-fgWarning)' },
{ offset: 90, color: 'var(--color-fgPositive)' },
{ offset: max, color: 'var(--color-fgPositive)' },
],
},
},
]}
xAxis={{
data: availabilityEvents.map((event) => event.date.getTime()),
}}
yAxis={{
domain: ({ min, max }) => ({ min: Math.max(min - 2, 0), max: Math.min(max + 2, 100) }),
}}
>
new Date(value).toLocaleDateString()}
/>
`${value}%`}
/>
({
...props,
fill: 'var(--color-bg)',
stroke: props.fill,
})}
seriesId="availability"
/>
);
}
```
#### Forecast Asset Price
You can combine multiple lines within a series to change styles dynamically.
```jsx live
function ForecastAssetPrice() {
const startYear = 2020;
const data = [50, 45, 47, 46, 54, 54, 60, 61, 63, 66, 70];
const currentIndex = 6;
const strokeWidth = 3;
// To prevent cutting off the edge of our lines
const clipOffset = strokeWidth;
const axisFormatter = useCallback(
(dataIndex: number) => {
return startYear + dataIndex;
},
[startYear],
);
const HistoricalLineComponent = memo((props: SolidLineProps) => {
const { drawingArea, getXScale } = useCartesianChartContext();
const xScale = getXScale();
if (!xScale || !drawingArea) return;
const currentX = xScale(currentIndex);
if (currentX === undefined) return;
return (
<>
>
);
});
// Since the solid and dotted line have different curves,
// we need two separate line components. Otherwise we could
// have one line component with SolidLine and DottedLine inside
// of it and two clipPaths.
const ForecastLineComponent = memo((props: DottedLineProps) => {
const { drawingArea, getXScale } = useCartesianChartContext();
const xScale = getXScale();
if (!xScale || !drawingArea) return;
const currentX = xScale(currentIndex);
if (currentX === undefined) return;
return (
<>
>
);
});
const CustomScrubber = memo(() => {
const { scrubberPosition } = useScrubberContext();
const isScrubbing = scrubberPosition !== undefined;
// We need a fade in animation for the Scrubber
return (
);
});
return (
);
}
```
## Props
| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `AreaComponent` | `AreaComponent` | No | `-` | Custom component to render line area fill. |
| `LineComponent` | `LineComponent` | No | `-` | Component to render the line. Takes precedence over the type prop if provided. |
| `alignContent` | `ResponsiveProp` | No | `-` | - |
| `alignItems` | `ResponsiveProp` | No | `-` | - |
| `alignSelf` | `ResponsiveProp` | No | `-` | - |
| `animate` | `boolean` | No | `true` | Whether to animate the chart. |
| `areaType` | `gradient \| solid \| dotted` | No | `'gradient'` | The type of area fill to add to the line. |
| `as` | `div` | No | `-` | The underlying element or component the polymorphic component will render. Changing as also changes the inherited native props (e.g. href for as=a) and the expected ref type. |
| `aspectRatio` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| auto` | No | `-` | - |
| `background` | `currentColor \| fg \| fgMuted \| fgInverse \| fgPrimary \| fgWarning \| fgPositive \| fgNegative \| bg \| bgAlternate \| bgInverse \| bgOverlay \| bgElevation1 \| bgElevation2 \| bgPrimary \| bgPrimaryWash \| bgSecondary \| bgTertiary \| bgSecondaryWash \| bgNegative \| bgNegativeWash \| bgPositive \| bgPositiveWash \| bgWarning \| bgWarningWash \| bgLine \| bgLineHeavy \| bgLineInverse \| bgLinePrimary \| bgLinePrimarySubtle \| accentSubtleRed \| accentBoldRed \| accentSubtleGreen \| accentBoldGreen \| accentSubtleBlue \| accentBoldBlue \| accentSubtlePurple \| accentBoldPurple \| accentSubtleYellow \| accentBoldYellow \| accentSubtleGray \| accentBoldGray \| transparent` | No | `-` | - |
| `borderBottomLeftRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
| `borderBottomRightRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
| `borderBottomWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
| `borderColor` | `currentColor \| fg \| fgMuted \| fgInverse \| fgPrimary \| fgWarning \| fgPositive \| fgNegative \| bg \| bgAlternate \| bgInverse \| bgOverlay \| bgElevation1 \| bgElevation2 \| bgPrimary \| bgPrimaryWash \| bgSecondary \| bgTertiary \| bgSecondaryWash \| bgNegative \| bgNegativeWash \| bgPositive \| bgPositiveWash \| bgWarning \| bgWarningWash \| bgLine \| bgLineHeavy \| bgLineInverse \| bgLinePrimary \| bgLinePrimarySubtle \| accentSubtleRed \| accentBoldRed \| accentSubtleGreen \| accentBoldGreen \| accentSubtleBlue \| accentBoldBlue \| accentSubtlePurple \| accentBoldPurple \| accentSubtleYellow \| accentBoldYellow \| accentSubtleGray \| accentBoldGray \| transparent` | No | `-` | - |
| `borderEndWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
| `borderRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
| `borderStartWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
| `borderTopLeftRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
| `borderTopRightRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
| `borderTopWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
| `borderWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
| `bordered` | `boolean` | No | `-` | Add a border around all sides of the box. |
| `borderedBottom` | `boolean` | No | `-` | Add a border to the bottom side of the box. |
| `borderedEnd` | `boolean` | No | `-` | Add a border to the trailing side of the box. |
| `borderedHorizontal` | `boolean` | No | `-` | Add a border to the leading and trailing sides of the box. |
| `borderedStart` | `boolean` | No | `-` | Add a border to the leading side of the box. |
| `borderedTop` | `boolean` | No | `-` | Add a border to the top side of the box. |
| `borderedVertical` | `boolean` | No | `-` | Add a border to the top and bottom sides of the box. |
| `bottom` | `ResponsiveProp>` | No | `-` | - |
| `classNames` | `{ root?: string; chart?: string \| undefined; } \| undefined` | No | `-` | Custom class names for the component. |
| `color` | `currentColor \| fg \| fgMuted \| fgInverse \| fgPrimary \| fgWarning \| fgPositive \| fgNegative \| bg \| bgAlternate \| bgInverse \| bgOverlay \| bgElevation1 \| bgElevation2 \| bgPrimary \| bgPrimaryWash \| bgSecondary \| bgTertiary \| bgSecondaryWash \| bgNegative \| bgNegativeWash \| bgPositive \| bgPositiveWash \| bgWarning \| bgWarningWash \| bgLine \| bgLineHeavy \| bgLineInverse \| bgLinePrimary \| bgLinePrimarySubtle \| accentSubtleRed \| accentBoldRed \| accentSubtleGreen \| accentBoldGreen \| accentSubtleBlue \| accentBoldBlue \| accentSubtlePurple \| accentBoldPurple \| accentSubtleYellow \| accentBoldYellow \| accentSubtleGray \| accentBoldGray \| transparent` | No | `-` | - |
| `columnGap` | `0 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9` | No | `-` | - |
| `connectNulls` | `boolean` | No | `-` | When true, the area is connected across null values. |
| `curve` | `bump \| catmullRom \| linear \| linearClosed \| monotone \| natural \| step \| stepBefore \| stepAfter` | No | `'bump'` | The curve interpolation method to use for the line. |
| `dangerouslySetBackground` | `string` | No | `-` | - |
| `display` | `ResponsiveProp` | No | `-` | - |
| `elevation` | `0 \| 1 \| 2` | No | `-` | - |
| `enableScrubbing` | `boolean` | No | `-` | Enables scrubbing interactions. When true, allows scrubbing and makes scrubber components interactive. |
| `flexBasis` | `ResponsiveProp>` | No | `-` | - |
| `flexDirection` | `ResponsiveProp` | No | `-` | - |
| `flexGrow` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset` | No | `-` | - |
| `flexShrink` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset` | No | `-` | - |
| `flexWrap` | `ResponsiveProp` | No | `-` | - |
| `font` | `ResponsiveProp` | No | `-` | - |
| `fontFamily` | `ResponsiveProp` | No | `-` | - |
| `fontSize` | `ResponsiveProp` | No | `-` | - |
| `fontWeight` | `ResponsiveProp` | No | `-` | - |
| `gap` | `0 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9` | No | `-` | - |
| `grid` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| none` | No | `-` | - |
| `gridArea` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| auto` | No | `-` | - |
| `gridAutoColumns` | `ResponsiveProp>` | No | `-` | - |
| `gridAutoFlow` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| row \| column \| dense` | No | `-` | - |
| `gridAutoRows` | `ResponsiveProp>` | No | `-` | - |
| `gridColumn` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| auto` | No | `-` | - |
| `gridColumnEnd` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| auto` | No | `-` | - |
| `gridColumnStart` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| auto` | No | `-` | - |
| `gridRow` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| auto` | No | `-` | - |
| `gridRowEnd` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| auto` | No | `-` | - |
| `gridRowStart` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| auto` | No | `-` | - |
| `gridTemplate` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| none` | No | `-` | - |
| `gridTemplateAreas` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| none` | No | `-` | - |
| `gridTemplateColumns` | `ResponsiveProp>` | No | `-` | - |
| `gridTemplateRows` | `ResponsiveProp>` | No | `-` | - |
| `height` | `ResponsiveProp>` | No | `-` | - |
| `inset` | `number \| Partial` | No | `-` | Inset around the entire chart (outside the axes). |
| `justifyContent` | `ResponsiveProp` | No | `-` | - |
| `key` | `Key \| null` | No | `-` | - |
| `left` | `ResponsiveProp>` | No | `-` | - |
| `lineHeight` | `ResponsiveProp` | No | `-` | - |
| `margin` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
| `marginBottom` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
| `marginEnd` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
| `marginStart` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
| `marginTop` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
| `marginX` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
| `marginY` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
| `maxHeight` | `ResponsiveProp>` | No | `-` | - |
| `maxWidth` | `ResponsiveProp>` | No | `-` | - |
| `minHeight` | `ResponsiveProp>` | No | `-` | - |
| `minWidth` | `ResponsiveProp>` | No | `-` | - |
| `onChange` | `FormEventHandler` | No | `-` | - |
| `onPointClick` | `((event: MouseEvent, point: { x: number; y: number; dataX: number; dataY: number; }) => void)` | No | `-` | Handler for when a point is clicked. Passed through to Point components rendered via points. |
| `onScrubberPositionChange` | `((index: number) => void) \| undefined` | No | `-` | Callback fired when the scrubber position changes. Receives the dataIndex of the scrubber or undefined when not scrubbing. |
| `opacity` | `number \| ({ base?: Opacity; phone?: Opacity \| undefined; tablet?: Opacity \| undefined; desktop?: Opacity \| undefined; } & number) \| undefined` | No | `1` | Opacity of the lines stroke. Will also be applied to points and area fill. |
| `overflow` | `ResponsiveProp` | No | `-` | - |
| `padding` | `0 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9` | No | `-` | - |
| `paddingBottom` | `0 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9` | No | `-` | - |
| `paddingEnd` | `0 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9` | No | `-` | - |
| `paddingStart` | `0 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9` | No | `-` | - |
| `paddingTop` | `0 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9` | No | `-` | - |
| `paddingX` | `0 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9` | No | `-` | - |
| `paddingY` | `0 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9` | No | `-` | - |
| `pin` | `top \| bottom \| left \| right \| all` | No | `-` | Direction in which to absolutely pin the box. |
| `points` | `boolean \| ((defaults: PointBaseProps) => boolean \| Partial \| null) \| undefined` | No | `-` | Controls whether and how to render points at each data point in the series. - true: Show all points with default styling - false or undefined: Hide all points - Function: Called for every entry in the data array to customize individual points |
| `position` | `ResponsiveProp` | No | `-` | - |
| `ref` | `((instance: SVGSVGElement \| null) => void) \| RefObject \| null` | No | `-` | - |
| `right` | `ResponsiveProp>` | No | `-` | - |
| `rowGap` | `0 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9` | No | `-` | - |
| `series` | `LineSeries[]` | No | `-` | Configuration objects that define how to visualize the data. Each series supports Line component props for individual customization. |
| `showArea` | `boolean` | No | `-` | Whether to show area fill under the line. |
| `showXAxis` | `boolean` | No | `-` | Whether to show the X axis. |
| `showYAxis` | `boolean` | No | `-` | Whether to show the Y axis. |
| `strokeOpacity` | `number` | No | `1` | Opacity of the line |
| `strokeWidth` | `number` | No | `2` | Width of the line |
| `style` | `CSSProperties` | No | `-` | Custom styles for the root element. |
| `styles` | `{ root?: CSSProperties; chart?: CSSProperties \| undefined; } \| undefined` | No | `-` | Custom styles for the component. |
| `testID` | `string` | No | `-` | Used to locate this element in unit and end-to-end tests. Under the hood, testID translates to data-testid on Web. On Mobile, testID stays the same - testID |
| `textAlign` | `ResponsiveProp` | No | `-` | - |
| `textDecoration` | `ResponsiveProp` | No | `-` | - |
| `textTransform` | `ResponsiveProp` | No | `-` | - |
| `top` | `ResponsiveProp>` | No | `-` | - |
| `transform` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| none` | No | `-` | - |
| `transition` | `Orchestration & Repeat & Tween \| Orchestration & Repeat & Spring \| Orchestration & Repeat & Keyframes \| Orchestration & Repeat & Inertia \| Orchestration & Repeat & Just \| Orchestration & Repeat & None \| Orchestration & Repeat & PermissiveTransitionDefinition \| Orchestration & Repeat & Tween & { [key: string]: TransitionDefinition; } \| Orchestration & Repeat & Spring & { [key: string]: TransitionDefinition; } \| Orchestration & Repeat & Keyframes & { [key: string]: TransitionDefinition; } \| Orchestration & Repeat & Inertia & { [key: string]: TransitionDefinition; } \| Orchestration & Repeat & Just & { [key: string]: TransitionDefinition; } \| Orchestration & Repeat & None & { [key: string]: TransitionDefinition; } \| Orchestration & Repeat & PermissiveTransitionDefinition & { [key: string]: TransitionDefinition; }` | No | `-` | Transition configuration for line animations. |
| `type` | `solid \| dotted` | No | `'solid'` | The type of line to render. |
| `userSelect` | `ResponsiveProp` | No | `-` | - |
| `visibility` | `ResponsiveProp` | No | `-` | - |
| `width` | `ResponsiveProp>` | No | `-` | - |
| `xAxis` | `(Partial & SharedProps & { bandGridLinePlacement?: AxisBandPlacement; bandTickMarkPlacement?: AxisBandPlacement \| undefined; label?: string \| undefined; labelGap?: number \| undefined; minTickLabelGap?: number \| undefined; requestedTickCount?: number \| undefined; showGrid?: boolean \| undefined; showLine?: boolean \| undefined; showTickMarks?: boolean \| undefined; tickMarkSize?: number \| undefined; ticks?: number[] \| ((value: number) => boolean) \| undefined; tickMarkLabelGap?: number \| undefined; tickInterval?: number \| undefined; tickMinStep?: number \| undefined; tickMaxStep?: number \| undefined; } & { className?: string \| undefined; classNames?: { root?: string \| undefined; label?: string \| undefined; tickLabel?: string \| undefined; gridLine?: string \| undefined; line?: string \| undefined; tickMark?: string \| undefined; } \| undefined; style?: CSSProperties \| undefined; styles?: { root?: CSSProperties \| undefined; label?: CSSProperties \| undefined; tickLabel?: CSSProperties \| undefined; gridLine?: CSSProperties \| undefined; line?: CSSProperties \| undefined; tickMark?: CSSProperties \| undefined; } \| undefined; GridLineComponent?: LineComponent \| undefined; LineComponent?: LineComponent \| undefined; TickMarkLineComponent?: LineComponent \| undefined; tickLabelFormatter?: ((value: number) => ChartTextChildren) \| undefined; TickLabelComponent?: AxisTickLabelComponent \| undefined; } & { position?: top \| bottom \| undefined; height?: number \| undefined; }) \| undefined` | No | `-` | Configuration for x-axis. Accepts axis config and axis props. To show the axis, set showXAxis to true. |
| `yAxis` | `(Partial & SharedProps & { bandGridLinePlacement?: AxisBandPlacement; bandTickMarkPlacement?: AxisBandPlacement \| undefined; label?: string \| undefined; labelGap?: number \| undefined; minTickLabelGap?: number \| undefined; requestedTickCount?: number \| undefined; showGrid?: boolean \| undefined; showLine?: boolean \| undefined; showTickMarks?: boolean \| undefined; tickMarkSize?: number \| undefined; ticks?: number[] \| ((value: number) => boolean) \| undefined; tickMarkLabelGap?: number \| undefined; tickInterval?: number \| undefined; tickMinStep?: number \| undefined; tickMaxStep?: number \| undefined; } & { className?: string \| undefined; classNames?: { root?: string \| undefined; label?: string \| undefined; tickLabel?: string \| undefined; gridLine?: string \| undefined; line?: string \| undefined; tickMark?: string \| undefined; } \| undefined; style?: CSSProperties \| undefined; styles?: { root?: CSSProperties \| undefined; label?: CSSProperties \| undefined; tickLabel?: CSSProperties \| undefined; gridLine?: CSSProperties \| undefined; line?: CSSProperties \| undefined; tickMark?: CSSProperties \| undefined; } \| undefined; GridLineComponent?: LineComponent \| undefined; LineComponent?: LineComponent \| undefined; TickMarkLineComponent?: LineComponent \| undefined; tickLabelFormatter?: ((value: number) => ChartTextChildren) \| undefined; TickLabelComponent?: AxisTickLabelComponent \| undefined; } & { axisId?: string \| undefined; position?: left \| right \| undefined; width?: number \| undefined; }) \| undefined` | No | `-` | Configuration for y-axis. Accepts axis config and axis props. To show the axis, set showYAxis to true. |
| `zIndex` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| auto` | No | `-` | - |