Skip to content

Commit

Permalink
Charts: Add gradient fill for line chart (#41143)
Browse files Browse the repository at this point in the history
* added area fill for line chart

* add sample site traffic data

* fix sample data

* move y axis to right for the story

* add more ticks to story

* changelog

* draw lower lines later

* there should not be decimals for traffic data

* fix lock file

* add withGradientFill to args to show toggle in stories
  • Loading branch information
kangzj authored Jan 17, 2025
1 parent 3e36cc3 commit ca7e9cd
Show file tree
Hide file tree
Showing 7 changed files with 333 additions and 12 deletions.
14 changes: 14 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: added

Add gradient fill for line chart
1 change: 1 addition & 0 deletions projects/js-packages/charts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"@react-spring/web": "9.7.3",
"@visx/axis": "^3.12.0",
"@visx/event": "^3.8.0",
"@visx/gradient": "3.12.0",
"@visx/grid": "^3.12.0",
"@visx/group": "^3.12.0",
"@visx/legend": "^3.12.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { LinearGradient } from '@visx/gradient';
import {
XYChart,
AnimatedLineSeries,
AnimatedAreaSeries,
AnimatedAxis,
AnimatedGrid,
Tooltip,
Expand All @@ -14,10 +16,9 @@ import { withResponsive } from '../shared/with-responsive';
import styles from './line-chart.module.scss';
import type { BaseChartProps, DataPointDate, SeriesData } from '../../types';

// TODO: revisit grid and axis options - accept as props for frid lines, axis, values: x, y, all, none

interface LineChartProps extends BaseChartProps< SeriesData[] > {
margin?: { top: number; right: number; bottom: number; left: number };
withGradientFill: boolean;
}

type TooltipData = {
Expand Down Expand Up @@ -83,6 +84,7 @@ const LineChart: FC< LineChartProps > = ( {
withTooltips = true,
showLegend = false,
legendOrientation = 'horizontal',
withGradientFill = false,
options = {},
} ) => {
const providerTheme = useChartTheme();
Expand Down Expand Up @@ -133,16 +135,43 @@ const LineChart: FC< LineChartProps > = ( {
/>
<AnimatedAxis orientation="left" numTicks={ 4 } { ...options?.axis?.y } />

{ data.map( ( seriesData, index ) => (
<AnimatedLineSeries
key={ seriesData?.label }
dataKey={ seriesData?.label }
data={ seriesData.data as DataPointDate[] } // TODO: this needs fixing or a more specific type for each chart
{ ...accessors }
stroke={ theme.colors[ index % theme.colors.length ] }
strokeWidth={ 2 }
/>
) ) }
{ data.map( ( seriesData, index ) => {
const stroke = seriesData.options?.stroke ?? theme.colors[ index % theme.colors.length ];

return (
<>
<LinearGradient
id={ `area-gradient-${ index + 1 }` }
from={ stroke }
to="white"
toOpacity={ 0.1 }
{ ...seriesData.options?.gradient }
/>
<AnimatedLineSeries
key={ seriesData?.label }
dataKey={ seriesData?.label }
data={ seriesData.data as DataPointDate[] } // TODO: this needs fixing or a more specific type for each chart
{ ...accessors }
stroke={ stroke }
strokeWidth={ 2 }
/>
{ /** Theoretically the area series should work without the line series; however it outlines the area with borders, which isn't ideal. */ }
{ /** TODO: Investigate whehter we could leverage area series alone. */ }
{ withGradientFill && (
<AnimatedAreaSeries
key={ seriesData?.label }
dataKey={ seriesData?.label }
data={ seriesData.data as DataPointDate[] } // TODO: this needs fixing or a more specific type for each chart
{ ...accessors }
stroke={ stroke }
strokeWidth={ 0 }
fill={ `url(#area-gradient-${ index + 1 })` }
renderLine={ false }
/>
) }
</>
);
} ) }

{ withTooltips && (
<Tooltip
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import LineChart from '../line-chart';
import sampleData from './sample-data';
import webTrafficData from './site-traffic-sample';
import type { Meta, StoryFn, StoryObj } from '@storybook/react';

const meta: Meta< typeof LineChart > = {
Expand Down Expand Up @@ -37,6 +38,7 @@ Default.args = {
data: sampleData,
showLegend: false,
legendOrientation: 'horizontal',
withGradientFill: false,
options: {
axis: {
x: {
Expand Down Expand Up @@ -93,10 +95,22 @@ FixedDimensions.args = {
data: sampleData,
withTooltips: true,
};

FixedDimensions.parameters = {
docs: {
description: {
story: 'Line chart with fixed dimensions that override the responsive behavior.',
},
},
};

// Story with gradient filled line chart
export const GridientFilled: StoryObj< typeof LineChart > = Template.bind( {} );
GridientFilled.args = {
...Default.args,
data: webTrafficData,
withGradientFill: true,
options: {
axis: { x: { numTicks: 10 }, y: { orientation: 'right' } },
},
};
Loading

0 comments on commit ca7e9cd

Please sign in to comment.