# 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 ### Basic Example ```jsx live function BasicExample() { const [scrubIndex, setScrubIndex] = useState(undefined); const data = [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58]; const accessibilityLabel = useMemo(() => { if (scrubIndex === undefined) return undefined; return `Value: ${data[scrubIndex]} at index ${scrubIndex}`; }, [scrubIndex, data]); return ( ); } ``` ### Simple ```jsx live ``` ### Compact You can specify the dimensions of the chart to make it more compact. ```jsx live function CompactLineChart() { 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, })}`; }, []); const CompactChart = memo(({ data, showArea, color, referenceY }) => ( )); const ChartCell = memo(({ data, showArea, color, referenceY, subdetail, variant }) => { const { isPhone } = useBreakpoints(); return ( } media={} onClick={() => console.log('clicked')} subdetail={subdetail} title={isPhone ? undefined : assets.btc.name} variant={variant} style={{ padding: 0 }} /> ); }); return ( ); }; ``` ### Gain/Loss You can use the y-axis scale and a [linearGradient](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Element/linearGradient) to create a gain/loss chart. ```jsx live function GainLossChart() { const gradientId = useId(); const data = [-40, -28, -21, -5, 48, -5, -28, 2, -29, -46, 16, -30, -29, 8]; const priceFormatter = useCallback( (value) => new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', maximumFractionDigits: 0, }).format(value), [], ); const ChartDefs = ({ threshold = 0 }) => { const { getYScale } = useCartesianChartContext(); // get the default y-axis scale const yScale = getYScale(); if (yScale) { const domain = yScale.domain(); const range = yScale.range(); const baselinePercentage = ((threshold - domain[0]) / (domain[1] - domain[0])) * 100; const negativeColor = 'rgb(var(--gray15))'; const positiveColor = 'var(--color-fgPositive)'; return ( ); } return null; }; const solidColor = `url(#${gradientId}-solid)`; return ( ); } ``` ### Multiple Series You can add multiple series to a line chart. ```jsx live function MultipleSeriesChart() { const [scrubIndex, setScrubIndex] = useState(undefined); const prices = [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58]; const volume = [4, 8, 11, 15, 16, 14, 16, 10, 12, 14, 16, 14, 16, 10]; return ( ); } ``` ### Points You can use the `renderPoints` prop to dynamically show points on a line. ```jsx live function PointsChart() { 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 } curve="monotone" /> ); } ``` ### Empty State This example shows how to use an empty state for a line chart. ```jsx live ``` ### Line Styles ```jsx live ( ), }, { id: 'bottom', data: [4, 8, 11, 15, 16, 14, 16, 10, 12, 14], color: '#800080', curve: 'step', AreaComponent: DottedArea, showArea: true, }, ]} /> ``` ### Live Data ```jsx live function LiveAssetPrice() { const scrubberRef = useRef(null); const [scrubIndex, setScrubIndex] = useState(undefined); 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 accessibilityLabel = useMemo(() => { if (scrubIndex === undefined) return `Bitcoin Price: $${priceData[priceData.length - 1].toFixed(2)}`; const price = priceData[scrubIndex]; return `Bitcoin Price: $${price.toFixed(2)} at position ${scrubIndex + 1}`; }, [scrubIndex, priceData]); return ( ); } ``` ### Data Format You can adjust the y values for a series of data by setting the `data` prop on the xAxis. ```jsx live function DataFormatChart() { const [scrubIndex, setScrubIndex] = useState(undefined); const yData = [2, 5.5, 2, 8.5, 1.5, 5]; const xData = [1, 2, 3, 5, 8, 10]; const accessibilityLabel = useMemo(() => { if (scrubIndex === undefined) return undefined; return `X: ${xData[scrubIndex]}, Y: ${yData[scrubIndex]} at point ${scrubIndex + 1}`; }, [scrubIndex, xData, yData]); return ( true} curve="natural" showXAxis xAxis={{ data: xData, showLine: true, showTickMarks: true, showGrid: true }} showYAxis yAxis={{ domain: { min: 0 }, position: 'left', showLine: true, showTickMarks: true, showGrid: true, }} inset={{ top: 16, right: 16, bottom: 0, left: 0 }} accessibilityLabel={accessibilityLabel} > ); } ``` ### Accessibility You can use `accessibilityLabel` to provide a descriptive label for the chart. This is especially important for charts with scrubbing enabled, where the label should update dynamically to reflect the current data point. ```jsx live function AccessibleBasicChart() { const [scrubIndex, setScrubIndex] = useState(undefined); const data = [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58]; const accessibilityLabel = useMemo(() => { if (scrubIndex === undefined) { return `Current price: ${data[data.length - 1]}`; } return `Price at position ${scrubIndex + 1}: ${data[scrubIndex]}`; }, [scrubIndex, data]); return ( ); } ``` When a chart has a visible header or title, you can use `aria-labelledby` to reference it. ```jsx live function AccessibleChartWithHeader() { const headerId = useId(); const [scrubIndex, setScrubIndex] = useState(undefined); const data = [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58]; const accessibilityLabel = useMemo(() => { if (scrubIndex === undefined) { return `Line chart showing price trend. Current value: ${data[data.length - 1]}`; } return `Value: ${data[scrubIndex]} at position ${scrubIndex + 1}`; }, [scrubIndex, data]); return ( {accessibilityLabel} ); } ``` ### Customization #### Asset Price with Dotted Area ```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 [scrubIndex, setScrubIndex] = useState(undefined); const currentPrice = sparklineInteractiveData.hour[sparklineInteractiveData.hour.length - 1].value; const tabs = [ { 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 accessibilityLabel = useCallback( (index: number) => { const price = scrubberPriceFormatter.format(sparklineTimePeriodDataValues[index]); const date = formatDate(sparklineTimePeriodDataTimestamps[index]); return `${price} USD ${date}`; }, [scrubberPriceFormatter, sparklineTimePeriodDataValues, sparklineTimePeriodDataTimestamps, formatDate], ); return ( Bitcoin} balance={{formatPrice(currentPrice)}} end={ } /> )}); return ; }; ``` #### Forecast Asset Price ```jsx live function ForecastAssetPrice() { const ForecastAreaComponent = memo( (props: AreaComponentProps) => ( ), ); const ForecastChart = memo(() => { const [scrubIndex, setScrubIndex] = useState(undefined); const getDataFromSparkline = useCallback((startDate: Date) => { const allData = sparklineInteractiveData.all; if (!allData || allData.length === 0) return []; const timelineData = allData.filter((point) => point.date >= startDate); return timelineData.map((point) => ({ date: point.date, value: point.value, })); }, []); const historicalData = useMemo(() => getDataFromSparkline(new Date('2019-01-01')), [getDataFromSparkline]); const annualGrowthRate = 10; const generateForecastData = useCallback( (lastDate: Date, lastPrice: number, growthRate: number) => { const dailyGrowthRate = Math.pow(1 + growthRate / 100, 1 / 365) - 1; const forecastData = []; const fiveYearsFromNow = new Date(lastDate); fiveYearsFromNow.setFullYear(fiveYearsFromNow.getFullYear() + 5); // Generate daily forecast points for 5 years const currentDate = new Date(lastDate); let currentPrice = lastPrice; while (currentDate <= fiveYearsFromNow) { currentPrice = currentPrice * (1 + dailyGrowthRate * 10); forecastData.push({ date: new Date(currentDate), value: Math.round(currentPrice), }); currentDate.setDate(currentDate.getDate() + 10); } return forecastData; }, [], ); const priceFormatter = useMemo( () => new Intl.NumberFormat('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2, }), [], ); 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 forecastData = useMemo(() => { if (historicalData.length === 0) return []; const lastPoint = historicalData[historicalData.length - 1]; return generateForecastData(lastPoint.date, lastPoint.value, annualGrowthRate); }, [generateForecastData, historicalData, annualGrowthRate]); // Combine all data points with dates converted to timestamps for x-axis const allDataPoints = useMemo( () => [...historicalData, ...forecastData], [historicalData, forecastData], ); const historicalDataValues = useMemo( () => historicalData.map((d) => d.value), [historicalData], ); const forecastDataValues = useMemo( () => [...historicalData.map((d) => null), ...forecastData.map((d) => d.value)], [historicalData, forecastData], ); const xAxisData = useMemo( () => allDataPoints.map((d) => d.date.getTime()), [allDataPoints], ); const scrubberLabel = useCallback( (index: number) => { const price = priceFormatter.format(allDataPoints[index].value); const date = formatDate(allDataPoints[index].date); return ( <> {price} USD {date} ); }, [priceFormatter, allDataPoints, formatDate], ); const accessibilityLabel = useCallback( (index: number) => { const price = priceFormatter.format(allDataPoints[index].value); const date = formatDate(allDataPoints[index].date); return `${price} USD ${date}`; }, [priceFormatter, allDataPoints, formatDate], ); return ( { return new Date(value).toLocaleDateString('en-US', { month: 'numeric', year: 'numeric', }); }, tickInterval: 2, }} accessibilityLabel={accessibilityLabel} style={{ outlineColor: assets.btc.color }} > ); }); return ; }; ``` #### Availability ```jsx live function AvailabilityChart() { const [scrubIndex, setScrubIndex] = useState(undefined); const availabilityEvents = [ { 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 accessibilityLabel = useMemo(() => { if (scrubIndex === undefined) return undefined; const event = availabilityEvents[scrubIndex]; 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}`; }, [scrubIndex, availabilityEvents]); const ChartDefs = memo(({ yellowThresholdPercentage = 85, greenThresholdPercentage = 90 }) => { const { drawingArea, height, series, getYScale, getYAxis } = useCartesianChartContext(); const yScale = getYScale(); const yAxis = getYAxis(); if (!series || !drawingArea || !yScale) return null; const rangeBounds = yAxis?.domain; const rangeMin = rangeBounds?.min ?? 0; const rangeMax = rangeBounds?.max ?? 100; // Calculate the Y positions in the chart coordinate system const yellowThresholdY = yScale(yellowThresholdPercentage) ?? 0; const greenThresholdY = yScale(greenThresholdPercentage) ?? 0; const minY = yScale(rangeMax) ?? 0; // Top of chart (max value) const maxY = yScale(rangeMin) ?? drawingArea.height; // Bottom of chart (min value) // Calculate percentages based on actual chart positions const yellowThreshold = ((yellowThresholdY - minY) / (maxY - minY)) * 100; const greenThreshold = ((greenThresholdY - minY) / (maxY - minY)) * 100; return ( ); }); return ( event.availability), color: 'url(#availabilityGradient)', }, ]} xAxis={{ data: availabilityEvents.map((event) => event.date.getTime()), }} yAxis={{ domain: ({ min, max }) => ({ min: Math.max(min - 2, 0), max: Math.min(max + 2, 100) }), }} padding={{ left: 2, right: 2 }} accessibilityLabel={accessibilityLabel} > new Date(value).toLocaleDateString()} /> `${value}%`} /> ({ fill: 'var(--color-bg)', stroke: 'url(#availabilityGradient)', strokeWidth: 2, })} seriesId="availability" /> ); } ``` #### Asset Price Widget You can coordinate LineChart with custom styles to create a custom card that shows the latest price and percent change. ```jsx live function BitcoinChartWithScrubberBeacon() { 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]; return ( {!isPhone && ( BTC Bitcoin )} {formatPrice(latestPrice)} +{formatPercentChange(percentChange)}
); }; ``` ## 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. | | `accentHeight` | `string \| number` | No | `-` | - | | `accumulate` | `none \| sum` | No | `-` | - | | `additive` | `sum \| replace` | No | `-` | - | | `alignContent` | `ResponsiveProp
` | No | `-` | - | | `alignItems` | `ResponsiveProp
` | No | `-` | - | | `alignSelf` | `ResponsiveProp
` | No | `-` | - | | `alignmentBaseline` | `alphabetic \| hanging \| ideographic \| mathematical \| inherit \| auto \| baseline \| before-edge \| text-before-edge \| middle \| central \| after-edge \| text-after-edge` | No | `-` | - | | `allowReorder` | `no \| yes` | No | `-` | - | | `alphabetic` | `string \| number` | No | `-` | - | | `amplitude` | `string \| number` | No | `-` | - | | `animate` | `boolean` | No | `true` | Whether to animate the chart. | | `arabicForm` | `initial \| medial \| terminal \| isolated` | No | `-` | - | | `areaType` | `dotted \| solid \| gradient` | No | `'gradient'` | The type of area fill to add to the line. | | `as` | `svg` | No | `-` | - | | `ascent` | `string \| number` | No | `-` | - | | `aspectRatio` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset \| auto` | No | `-` | - | | `attributeName` | `string` | No | `-` | - | | `attributeType` | `string` | No | `-` | - | | `autoReverse` | `false \| true \| true \| false` | No | `-` | - | | `azimuth` | `string \| number` | 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 | `-` | - | | `baseFrequency` | `string \| number` | No | `-` | - | | `baseProfile` | `string \| number` | No | `-` | - | | `baselineShift` | `string \| number` | No | `-` | - | | `bbox` | `string \| number` | No | `-` | - | | `begin` | `string \| number` | No | `-` | - | | `bias` | `string \| number` | 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 | `-` | - | | `by` | `string \| number` | No | `-` | - | | `calcMode` | `string \| number` | No | `-` | - | | `capHeight` | `string \| number` | No | `-` | - | | `className` | `string` | No | `-` | - | | `clip` | `string \| number` | No | `-` | - | | `clipPath` | `string` | No | `-` | - | | `clipPathUnits` | `string \| number` | No | `-` | - | | `clipRule` | `string \| number` | No | `-` | - | | `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 | `-` | - | | `colorInterpolation` | `string \| number` | No | `-` | - | | `colorInterpolationFilters` | `inherit \| auto \| sRGB \| linearRGB` | No | `-` | - | | `colorProfile` | `string \| number` | No | `-` | - | | `colorRendering` | `string \| number` | No | `-` | - | | `columnGap` | `0 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9` | No | `-` | - | | `contentScriptType` | `string \| number` | No | `-` | - | | `contentStyleType` | `string \| number` | No | `-` | - | | `crossOrigin` | ` \| anonymous \| use-credentials` | No | `-` | - | | `cursor` | `string \| number` | No | `-` | - | | `curve` | `bump \| catmullRom \| linear \| linearClosed \| monotone \| natural \| step \| stepBefore \| stepAfter` | No | `'linear'` | The curve interpolation method to use for the line. | | `cx` | `string \| number` | No | `-` | - | | `cy` | `string \| number` | No | `-` | - | | `d` | `string` | No | `-` | - | | `dangerouslySetBackground` | `string` | No | `-` | - | | `decelerate` | `string \| number` | No | `-` | - | | `descent` | `string \| number` | No | `-` | - | | `diffuseConstant` | `string \| number` | No | `-` | - | | `direction` | `string \| number` | No | `-` | - | | `display` | `ResponsiveProp` | No | `-` | - | | `divisor` | `string \| number` | No | `-` | - | | `dominantBaseline` | `string \| number` | No | `-` | - | | `dur` | `string \| number` | No | `-` | - | | `dx` | `string \| number` | No | `-` | - | | `dy` | `string \| number` | No | `-` | - | | `edgeMode` | `string \| number` | No | `-` | - | | `elevation` | `0 \| 1 \| 2` | No | `-` | - | | `enableBackground` | `string \| number` | No | `-` | - | | `enableScrubbing` | `boolean` | No | `-` | Enables scrubbing interactions. When true, allows scrubbing and makes scrubber components interactive. | | `end` | `string \| number` | No | `-` | - | | `exponent` | `string \| number` | No | `-` | - | | `externalResourcesRequired` | `false \| true \| true \| false` | No | `-` | - | | `fill` | `string` | No | `-` | - | | `fillOpacity` | `string \| number` | No | `-` | - | | `fillRule` | `inherit \| nonzero \| evenodd` | No | `-` | - | | `filter` | `string` | No | `-` | - | | `filterRes` | `string \| number` | No | `-` | - | | `filterUnits` | `string \| number` | No | `-` | - | | `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 | `-` | - | | `floodColor` | `string \| number` | No | `-` | - | | `floodOpacity` | `string \| number` | No | `-` | - | | `focusable` | `auto \| Booleanish` | No | `-` | - | | `font` | `ResponsiveProp` | No | `-` | - | | `fontFamily` | `ResponsiveProp` | No | `-` | - | | `fontSize` | `ResponsiveProp` | No | `-` | - | | `fontSizeAdjust` | `string \| number` | No | `-` | - | | `fontStretch` | `string \| number` | No | `-` | - | | `fontStyle` | `string \| number` | No | `-` | - | | `fontVariant` | `string \| number` | No | `-` | - | | `fontWeight` | `ResponsiveProp` | No | `-` | - | | `format` | `string \| number` | No | `-` | - | | `fr` | `string \| number` | No | `-` | - | | `from` | `string \| number` | No | `-` | - | | `fx` | `string \| number` | No | `-` | - | | `fy` | `string \| number` | No | `-` | - | | `g1` | `string \| number` | No | `-` | - | | `g2` | `string \| number` | No | `-` | - | | `gap` | `0 \| 5 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1 \| 1.5 \| 2 \| 3 \| 4 \| 6 \| 7 \| 8 \| 9` | No | `-` | - | | `glyphName` | `string \| number` | No | `-` | - | | `glyphOrientationHorizontal` | `string \| number` | No | `-` | - | | `glyphOrientationVertical` | `string \| number` | No | `-` | - | | `glyphRef` | `string \| number` | No | `-` | - | | `gradientTransform` | `string` | No | `-` | - | | `gradientUnits` | `string` | 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 | `-` | - | | `hanging` | `string \| number` | No | `-` | - | | `height` | `ResponsiveProp>` | No | `-` | - | | `horizAdvX` | `string \| number` | No | `-` | - | | `horizOriginX` | `string \| number` | No | `-` | - | | `href` | `string` | No | `-` | - | | `id` | `string` | No | `-` | - | | `ideographic` | `string \| number` | No | `-` | - | | `imageRendering` | `string \| number` | No | `-` | - | | `in` | `string` | No | `-` | - | | `in2` | `string \| number` | No | `-` | - | | `inset` | `number \| Partial` | No | `-` | Inset around the entire chart (outside the axes). | | `intercept` | `string \| number` | No | `-` | - | | `justifyContent` | `ResponsiveProp` | No | `-` | - | | `k` | `string \| number` | No | `-` | - | | `k1` | `string \| number` | No | `-` | - | | `k2` | `string \| number` | No | `-` | - | | `k3` | `string \| number` | No | `-` | - | | `k4` | `string \| number` | No | `-` | - | | `kernelMatrix` | `string \| number` | No | `-` | - | | `kernelUnitLength` | `string \| number` | No | `-` | - | | `kerning` | `string \| number` | No | `-` | - | | `key` | `Key \| null` | No | `-` | - | | `keyPoints` | `string \| number` | No | `-` | - | | `keySplines` | `string \| number` | No | `-` | - | | `keyTimes` | `string \| number` | No | `-` | - | | `lang` | `string` | No | `-` | - | | `left` | `ResponsiveProp>` | No | `-` | - | | `lengthAdjust` | `string \| number` | No | `-` | - | | `letterSpacing` | `string \| number` | No | `-` | - | | `lightingColor` | `string \| number` | No | `-` | - | | `limitingConeAngle` | `string \| number` | No | `-` | - | | `lineHeight` | `ResponsiveProp` | No | `-` | - | | `local` | `string \| number` | 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 | `-` | - | | `markerEnd` | `string` | No | `-` | - | | `markerHeight` | `string \| number` | No | `-` | - | | `markerMid` | `string` | No | `-` | - | | `markerStart` | `string` | No | `-` | - | | `markerUnits` | `string \| number` | No | `-` | - | | `markerWidth` | `string \| number` | No | `-` | - | | `mask` | `string` | No | `-` | - | | `maskContentUnits` | `string \| number` | No | `-` | - | | `maskUnits` | `string \| number` | No | `-` | - | | `mathematical` | `string \| number` | No | `-` | - | | `max` | `string \| number` | No | `-` | - | | `maxHeight` | `ResponsiveProp>` | No | `-` | - | | `maxWidth` | `ResponsiveProp>` | No | `-` | - | | `media` | `string` | No | `-` | - | | `method` | `string` | No | `-` | - | | `min` | `string \| number` | No | `-` | - | | `minHeight` | `ResponsiveProp>` | No | `-` | - | | `minWidth` | `ResponsiveProp>` | No | `-` | - | | `mode` | `string \| number` | No | `-` | - | | `name` | `string` | No | `-` | - | | `numOctaves` | `string \| number` | No | `-` | - | | `offset` | `string \| number` | No | `-` | - | | `onChange` | `FormEventHandler` | No | `-` | - | | `onPointClick` | `((event: MouseEvent, point: { x: number; y: number; dataX: number; dataY: number; }) => void)` | No | `-` | Handler for when a dot is clicked. Automatically makes dots appear pressable when provided. | | `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` | `-moz-initial \| inherit \| initial \| revert \| revert-layer \| unset` | No | `-` | - | | `operator` | `string \| number` | No | `-` | - | | `order` | `string \| number` | No | `-` | - | | `orient` | `string \| number` | No | `-` | - | | `orientation` | `string \| number` | No | `-` | - | | `origin` | `string \| number` | No | `-` | - | | `overflow` | `ResponsiveProp