Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic MUI Chart stories with controls #174

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/storybook/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"@babel/preset-typescript": "^7.21.5",
"@monorail/components": "workspace:*",
"@monorail/themes": "workspace:*",
"@mui/x-charts": "^6.18.3",
"@storybook/addon-a11y": "^7.0.20",
"@storybook/addon-actions": "^7.0.20",
"@storybook/addon-controls": "^7.0.20",
Expand Down
58 changes: 58 additions & 0 deletions packages/storybook/src/BarChart/BarChart.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Edit this file to add new stories
import React from 'react'
import type { BarChartProps } from '@mui/x-charts'
import { BarChart } from '@mui/x-charts'

import { story } from '../helpers/storybook.js'

export default { title: 'Charts/BarChart', component: BarChart }

type BarChartStoryControls = Partial<BarChartProps> & {
stack: boolean
}

const args = {
layout: 'vertical',
stack: false,
} as const

const argTypes = {
stack: { control: 'boolean' },
layout: {
control: { type: 'radio' },
options: ['vertical', 'horizontal'],
},
}

const Template = story<BarChartStoryControls>(
args => {
return (
<BarChart
layout={args.layout}
xAxis={
args.layout === 'vertical'
? [{ scaleType: 'band', data: ['group A', 'group B', 'group C'] }]
: undefined
}
yAxis={
args.layout === 'horizontal'
? [{ scaleType: 'band', data: ['group A', 'group B', 'group C'] }]
: undefined
}
series={[
{ data: [4, 3, 5], ...(args.stack === true && { stack: 'total' }) },
{ data: [1, 6, 3], ...(args.stack === true && { stack: 'total' }) },
{ data: [2, 5, 6], ...(args.stack === true && { stack: 'total' }) },
]}
width={500}
height={300}
/>
)
},
{
args,
argTypes,
},
)

export const Default = story(Template)
160 changes: 160 additions & 0 deletions packages/storybook/src/ChartsLegend/ChartsLegend.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
// Edit this file to add new stories
import React from 'react'
import type { PieChartSlotComponentProps } from '@mui/x-charts'
import { PieChart } from '@mui/x-charts'

import { useTheme } from '@monorail/utils'

import { story } from '../helpers/storybook.js'

export default { title: 'Charts/Legend', component: PieChart }

export type AnchorX = 'left' | 'right' | 'middle'
export type AnchorY = 'top' | 'bottom' | 'middle'

type ChartsLegendStoryControls = PieChartSlotComponentProps['legend'] & {
vertical: AnchorY
horizontal: AnchorX
breakLine: boolean
labelFill: string | undefined
labelFontSize: number | undefined
hidden: boolean
}

const args: ChartsLegendStoryControls = {
direction: 'column',
vertical: 'middle',
horizontal: 'right',
itemMarkWidth: 20,
itemMarkHeight: 2,
markGap: 5,
itemGap: 10,
padding: 0,
hidden: false,
labelFill: undefined,
labelFontSize: undefined,
breakLine: false,
}

const argTypes = {
padding: { control: 'number' },
itemGap: { control: 'number' },
hidden: { control: 'boolean' },
// Position
direction: {
control: { type: 'radio' },
options: ['row', 'column'],
table: { category: 'Position' },
},
vertical: {
control: { type: 'radio' },
options: ['top', 'middle', 'bottom'],
table: { category: 'Position' },
},
horizontal: {
control: { type: 'radio' },
options: ['middle', 'left', 'right'],
table: { category: 'Position' },
},
// Mark
itemMarkWidth: { control: 'number', table: { category: 'Mark' } },
itemMarkHeight: { control: 'number', table: { category: 'Mark' } },
markGap: { control: 'number', table: { category: 'Mark' } },
// Label
labelFontSize: {
control: 'number',
table: {
category: 'Label',
},
},
labelFill: {
control: 'color',
table: { category: 'Label' },
},
breakLine: { control: 'boolean', table: { category: 'Label' } },
}

const Template = story<ChartsLegendStoryControls>(
args => {
const theme = useTheme()
return (
<PieChart
width={600}
height={400}
margin={{ top: 100, left: 100, bottom: 100 }}
series={[
{
data: [
{
id: 0,
value: 10,
label: args.breakLine === false ? 'Series A' : 'Series\nA',
},
{
id: 1,
value: 15,
label: args.breakLine === false ? 'Series B' : 'Series\nB',
},
{
id: 2,
value: 20,
label: args.breakLine === false ? 'Series C' : 'Series\nC',
},
{
id: 3,
value: 10,
label: args.breakLine === false ? 'Series D' : 'Series\nD',
},
{
id: 4,
value: 15,
label: args.breakLine === false ? 'Series E' : 'Series\nE',
},
{
id: 5,
value: 20,
label: args.breakLine === false ? 'Series F' : 'Series\nF',
},
{
id: 6,
value: 10,
label: args.breakLine === false ? 'Series G' : 'Series\nG',
},
{
id: 7,
value: 15,
label: args.breakLine === false ? 'Series H' : 'Series\nH',
},
],
},
]}
slotProps={{
legend: {
direction: args.direction,
position: {
vertical: args.vertical as AnchorY,
horizontal: args.horizontal as AnchorX,
},
itemMarkWidth: args.itemMarkWidth,
itemMarkHeight: args.itemMarkHeight,
markGap: args.markGap,
itemGap: args.itemGap,
padding: args.padding,
hidden: args.hidden,
labelStyle: {
fontSize:
args.labelFontSize ?? theme.typography.subtitle1.fontSize,
fill: args.labelFill ?? theme.palette.text.primary,
},
},
}}
/>
)
},
{
args,
argTypes,
},
)

export const Default = story(Template)
125 changes: 125 additions & 0 deletions packages/storybook/src/ChartsTooltip/ChartsTooltip.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// Edit this file to add new stories
import React from 'react'
import type { ChartsItemContentProps, ChartsTooltipProps } from '@mui/x-charts'
import { BarChart, chartsTooltipClasses } from '@mui/x-charts'

import { Paper, Stack, Typography } from '@monorail/components'

import { story } from '../helpers/storybook.js'

export default { title: 'Charts/Tooltip and Highlights', component: BarChart }

type ChartsTooltipStoryControls = {
trigger: ChartsTooltipProps['trigger']
xAxisHighlight: 'none' | 'line' | 'band'
yAxisHighlight: 'none' | 'line'
hideTooltip: boolean
}

const args = {
trigger: 'axis',
xAxisHighlight: 'band',
yAxisHighlight: 'none',
hideTooltip: false,
} as const

const argTypes = {
trigger: {
control: { type: 'radio' },
options: ['axis', 'item'],
},
xAxisHighlight: {
control: { type: 'radio' },
options: ['none', 'line', 'band'],
},
yAxisHighlight: {
control: { type: 'radio' },
options: ['none', 'line'],
},
hideTooltip: { control: 'boolean' },
}

const Template = story<ChartsTooltipStoryControls>(
args => {
return (
<Stack direction="column" sx={{ width: '100%', maxWidth: 400 }}>
<BarChart
margin={{ top: 10, right: 10 }}
height={200}
xAxis={[
{
data: ['page A', 'page B', 'page C', 'page D', 'page E'],
scaleType: 'band',
hideTooltip: args.hideTooltip,
},
]}
series={[
{ data: [2, 5, 3, 4, 1], stack: '1', label: 'Series x' },
{ data: [10, 3, 1, 2, 10], stack: '1', label: 'Series y' },
{ data: [10, 3, 1, 2, 10], stack: '1', label: 'Series z' },
]}
axisHighlight={{
x: args.xAxisHighlight,
y: args.yAxisHighlight,
}}
tooltip={{ trigger: args.trigger }}
slotProps={{
legend: {
hidden: true,
},
}}
sx={{
[`& .${chartsTooltipClasses.row}`]: {
backgroundColor: 'red',
},
}}
/>
</Stack>
)
},
{
args,
argTypes,
},
)

export const Default = story(Template)

export const CustomTooltip = story(() => (
<Stack direction="column" sx={{ width: '100%', maxWidth: 400 }}>
<BarChart
margin={{ top: 10, right: 10 }}
height={200}
xAxis={[
{
data: ['page A', 'page B', 'page C', 'page D', 'page E'],
scaleType: 'band',
},
]}
series={[
{ data: [2, 5, 3, 4, 1], stack: '1', label: 'Series x' },
{ data: [10, 3, 1, 2, 10], stack: '1', label: 'Series y' },
{ data: [10, 3, 1, 2, 10], stack: '1', label: 'Series z' },
]}
tooltip={{
trigger: 'item',
itemContent: (props: ChartsItemContentProps) => {
const { series, itemData } = props
return itemData.dataIndex !== undefined ? (
<Paper sx={{ padding: 3, backgroundColor: series.color }}>
<Typography variant="subtitle1">My Custom Tooltip</Typography>
<Typography>{series.data[itemData.dataIndex]}</Typography>
</Paper>
) : (
<></>
)
},
}}
slotProps={{
legend: {
hidden: true,
},
}}
/>
</Stack>
))
Loading