Skip to content

Commit

Permalink
feat(D3 plugin): add base bar-y chart (#336)
Browse files Browse the repository at this point in the history
* feat(D3 plugin): add base bar-y chart

* bar-y tooltip

* add space for dataLabel outside bar

* fix story

* fix stories

* some review fixes

* some review fixes(2)
  • Loading branch information
kuzmadom authored Oct 27, 2023
1 parent f2a6902 commit 4d4264a
Show file tree
Hide file tree
Showing 31 changed files with 1,053 additions and 142 deletions.
22 changes: 21 additions & 1 deletion src/plugins/d3/__stories__/Showcase.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import React from 'react';
import {StoryObj} from '@storybook/react';
import {withKnobs} from '@storybook/addon-knobs';
import {BasicBarXChart} from '../examples/bar-x/Basic';
import {settings} from '../../../libs';
import {D3Plugin} from '../index';
import {Loader} from '../../../components/Loader/Loader';
import {BasicBarXChart} from '../examples/bar-x/Basic';
import {GroupedColumns} from '../examples/bar-x/GroupedColumns';
import {StackedColumns} from '../examples/bar-x/StackedColumns';
import {Basic as BasicBarY} from '../examples/bar-y/Basic';
import {GroupedColumns as GroupedColumnsBarY} from '../examples/bar-y/GroupedColumns';
import {StackedColumns as StackedColumnsBarY} from '../examples/bar-y/StackedColumns';
import {Container, Row, Col, Text} from '@gravity-ui/uikit';
import {BasicPie} from '../examples/pie/Basic';
import {Basic as BasicScatter} from '../examples/scatter/Basic';
Expand Down Expand Up @@ -53,6 +56,23 @@ const ShowcaseStory = () => {
<StackedColumns />
</Col>
</Row>
<Row space={1}>
<Text variant="header-2">Bar-y charts</Text>
</Row>
<Row space={3} style={{minHeight: 280}}>
<Col>
<Text variant="subheader-1">Basic bar chart</Text>
<BasicBarY />
</Col>
<Col>
<Text variant="subheader-1">Grouped bars</Text>
<GroupedColumnsBarY />
</Col>
<Col>
<Text variant="subheader-1">Stacked bars</Text>
<StackedColumnsBarY />
</Col>
</Row>
<Row space={1}>
<Text variant="header-2">Pie charts</Text>
</Row>
Expand Down
54 changes: 54 additions & 0 deletions src/plugins/d3/__stories__/bar-y/BarY.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React from 'react';
import {StoryObj} from '@storybook/react';
import {Button} from '@gravity-ui/uikit';
import {settings} from '../../../../libs';
import {D3Plugin} from '../..';
import {Basic} from '../../examples/bar-y/Basic';
import {GroupedColumns} from '../../examples/bar-y/GroupedColumns';
import {StackedColumns} from '../../examples/bar-y/StackedColumns';

const ChartStory = ({Chart}: {Chart: React.FC}) => {
const [shown, setShown] = React.useState(false);

if (!shown) {
settings.set({plugins: [D3Plugin]});
return <Button onClick={() => setShown(true)}>Show chart</Button>;
}

return (
<div
style={{
height: '80vh',
width: '100%',
}}
>
<Chart />
</div>
);
};

export const BasicBarYChartStory: StoryObj<typeof ChartStory> = {
name: 'Basic',
args: {
Chart: Basic,
},
};

export const GroupedBarYChartStory: StoryObj<typeof ChartStory> = {
name: 'Grouped bars',
args: {
Chart: GroupedColumns,
},
};

export const StackedBarYChartStory: StoryObj<typeof ChartStory> = {
name: 'Stacked bars',
args: {
Chart: StackedColumns,
},
};

export default {
title: 'Plugins/D3/Bar-Y',
component: ChartStory,
};
90 changes: 90 additions & 0 deletions src/plugins/d3/__stories__/bar-y/Playground.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import React from 'react';
import {StoryObj} from '@storybook/react';
import {Button} from '@gravity-ui/uikit';
import {settings} from '../../../../libs';
import {D3Plugin} from '../..';
import {ChartKitWidgetData} from '../../../../types';
import {ChartKit} from '../../../../components/ChartKit';
import {groups} from 'd3';
import nintendoGames from '../../examples/nintendoGames';

function prepareData(): ChartKitWidgetData {
const gamesByPlatform = groups(nintendoGames, (item) => item['platform']);
const data = gamesByPlatform.map(([value, games]) => ({
x: games.length,
y: value,
}));

return {
series: {
data: [
{
type: 'bar-y',
data,
name: 'Games released',
dataLabels: {
enabled: true,
},
},
],
},
xAxis: {
title: {text: 'Number of games released'},
labels: {
enabled: true,
},
},
yAxis: [
{
type: 'category',
categories: gamesByPlatform.map(([key]) => key),
title: {
text: 'Game Platforms',
},
labels: {
enabled: true,
},
ticks: {
pixelInterval: 120,
},
},
],
};
}

const ChartStory = ({data}: {data: ChartKitWidgetData}) => {
const [shown, setShown] = React.useState(false);

if (!shown) {
settings.set({plugins: [D3Plugin]});
return <Button onClick={() => setShown(true)}>Show chart</Button>;
}

return (
<div
style={{
height: '80vh',
width: '100%',
}}
>
<ChartKit type="d3" data={data} />
</div>
);
};

export const PlaygroundBarYChartStory: StoryObj<typeof ChartStory> = {
name: 'Playground',
args: {
data: prepareData(),
},
argTypes: {
data: {
control: 'object',
},
},
};

export default {
title: 'Plugins/D3/Bar-Y',
component: ChartStory,
};
8 changes: 6 additions & 2 deletions src/plugins/d3/examples/bar-x/GroupedColumns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ import nintendoGames from '../nintendoGames';
import {groups} from 'd3';

function prepareData() {
const displayedYears = [2015, 2016, 2017, 2018, 2019];
const games = nintendoGames.filter((ng) =>
displayedYears.includes(new Date(ng.date as number).getFullYear()),
);
const grouped = groups(
nintendoGames,
games,
(d) => d.platform,
(d) => (d.date ? new Date(d.date as number).getFullYear() : 'unknown'),
);
Expand Down Expand Up @@ -40,7 +44,7 @@ export const GroupedColumns = () => {

const widgetData: ChartKitWidgetData = {
series: {
data: data,
data,
},
xAxis: {
type: 'category',
Expand Down
49 changes: 49 additions & 0 deletions src/plugins/d3/examples/bar-y/Basic.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React from 'react';
import {ChartKit} from '../../../../components/ChartKit';
import type {ChartKitWidgetData, BarYSeries, BarYSeriesData} from '../../../../types';
import nintendoGames from '../nintendoGames';
import {groups} from 'd3';

function prepareData(field: 'platform' | 'meta_score' | 'date' = 'platform') {
const gamesByPlatform = groups(nintendoGames, (item) => item[field]);
const data = gamesByPlatform.map(([value, games]) => ({
y: value,
x: games.length,
}));

return {
categories: gamesByPlatform.map(([key]) => key),
series: [
{
data,
name: 'Games released',
},
],
};
}

export const Basic = () => {
const {categories, series} = prepareData();

const widgetData: ChartKitWidgetData = {
series: {
data: series.map<BarYSeries>((s) => ({
type: 'bar-y',
data: s.data as BarYSeriesData[],
name: s.name,
})),
},
xAxis: {title: {text: 'Number of games released'}},
yAxis: [
{
type: 'category',
categories: categories.map(String),
title: {
text: 'Game Platforms',
},
},
],
};

return <ChartKit type="d3" data={widgetData} />;
};
61 changes: 61 additions & 0 deletions src/plugins/d3/examples/bar-y/GroupedColumns.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React from 'react';
import {ChartKit} from '../../../../components/ChartKit';
import type {BarYSeries, ChartKitWidgetData} from '../../../../types';
import nintendoGames from '../nintendoGames';
import {groups} from 'd3';

function prepareData() {
const displayedYears = [2015, 2016, 2017, 2018, 2019];
const games = nintendoGames.filter((ng) =>
displayedYears.includes(new Date(ng.date as number).getFullYear()),
);
const grouped = groups(
games,
(d) => d.platform,
(d) => (d.date ? new Date(d.date as number).getFullYear() : 'unknown'),
);
const categories: string[] = [];
const series = grouped.map(([platform, years]) => {
return {
name: platform,
data: years.map(([year, list]) => {
categories.push(String(year));

return {
y: String(year),
x: list.length,
};
}),
};
});

return {categories, series};
}

export const GroupedColumns = () => {
const {series, categories} = prepareData();
const data = series.map((s) => {
return {
type: 'bar-y',
name: s.name,
data: s.data,
} as BarYSeries;
});

const widgetData: ChartKitWidgetData = {
series: {
data: data,
},
yAxis: [
{
type: 'category',
categories: categories.sort(),
title: {
text: 'Release year',
},
},
],
};

return <ChartKit type="d3" data={widgetData} />;
};
58 changes: 58 additions & 0 deletions src/plugins/d3/examples/bar-y/StackedColumns.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React from 'react';
import {ChartKit} from '../../../../components/ChartKit';
import type {BarYSeries, ChartKitWidgetData} from '../../../../types';
import nintendoGames from '../nintendoGames';
import {groups} from 'd3';

function prepareData() {
const grouped = groups(
nintendoGames,
(d) => d.platform,
(d) => (d.date ? new Date(d.date as number).getFullYear() : 'unknown'),
);
const categories: string[] = [];
const series = grouped.map(([platform, years]) => {
return {
name: platform,
data: years.map(([year, list]) => {
categories.push(String(year));

return {
y: String(year),
x: list.length,
};
}),
};
});

return {categories, series};
}

export const StackedColumns = () => {
const {series, categories} = prepareData();
const data = series.map((s) => {
return {
type: 'bar-y',
stacking: 'normal',
name: s.name,
data: s.data,
} as BarYSeries;
});

const widgetData: ChartKitWidgetData = {
series: {
data: data,
},
yAxis: [
{
type: 'category',
categories: categories.sort(),
title: {
text: 'Release year',
},
},
],
};

return <ChartKit type="d3" data={widgetData} />;
};
Loading

0 comments on commit 4d4264a

Please sign in to comment.