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

[charts] Add domainLimit to axis config #15294

Merged
merged 11 commits into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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
103 changes: 103 additions & 0 deletions docs/data/charts/sparkline/CustomDomainYAxis.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import * as React from 'react';
import Stack from '@mui/material/Stack';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import { SparkLineChart } from '@mui/x-charts/SparkLineChart';

const settings = {
valueFormatter: (v) => `${v}%`,
height: 100,
showTooltip: true,
showHighlight: true,
};

// Extend a value to match a multiple of the step.
function extend(value, step) {
if (value > 0) {
// If >0 go to the next step
return step * Math.ceil(value / step);
}
// If <0 go to the previous step
return step * Math.floor(value / step);
}

const values = [60, -15, 66, 68, 87, 82, 83, 85, 92, 75, 76, 50, 91];
JCQuintas marked this conversation as resolved.
Show resolved Hide resolved

export default function CustomDomainYAxis() {
return (
<Stack
sx={(theme) => ({
width: '100%',
'& p': { mb: 1, mt: 2 },
'& svg': {
borderWidth: 1,
borderStyle: 'solid',
borderColor: theme.palette.divider,
JCQuintas marked this conversation as resolved.
Show resolved Hide resolved
},
})}
>
<Typography>
<code>domainLimit=&quot;nice&quot;</code>, range from -100 to 100
</Typography>
<Stack
sx={{
width: '100%',
}}
direction="row"
spacing={2}
>
<Box sx={{ flexGrow: 1 }}>
<SparkLineChart data={values} {...settings} />
</Box>
<Box sx={{ flexGrow: 1 }}>
<SparkLineChart plotType="bar" data={values} {...settings} />
</Box>
</Stack>
<Typography>
<code>domainLimit=&quot;strict&quot;</code>, range from -15 to 92
</Typography>
<Stack sx={{ width: '100%' }} direction="row" spacing={2}>
<Box sx={{ flexGrow: 1 }}>
<SparkLineChart
data={values}
yAxis={{ domainLimit: 'strict' }}
{...settings}
/>
</Box>
<Box sx={{ flexGrow: 1 }}>
<SparkLineChart
plotType="bar"
data={values}
yAxis={{ domainLimit: 'strict' }}
{...settings}
/>
</Box>
</Stack>
<Typography>custom function, range from -50 to 100</Typography>
<Stack sx={{ width: '100%' }} direction="row" spacing={2}>
<Box sx={{ flexGrow: 1 }}>
<SparkLineChart
data={values}
yAxis={{
domainLimit: ([min, max]) => [
min - (Math.abs(min) % 50),
max + 50 - (Math.abs(max) % 50),
],
}}
{...settings}
/>
</Box>
<Box sx={{ flexGrow: 1 }}>
<SparkLineChart
plotType="bar"
data={values}
yAxis={{
domainLimit: ([min, max]) => [extend(min, 50), extend(max, 50)],
}}
{...settings}
/>
</Box>
</Stack>
</Stack>
);
}
103 changes: 103 additions & 0 deletions docs/data/charts/sparkline/CustomDomainYAxis.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import * as React from 'react';
import Stack from '@mui/material/Stack';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import { SparkLineChart } from '@mui/x-charts/SparkLineChart';

const settings = {
valueFormatter: (v: number | null) => `${v}%`,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
valueFormatter: (v: number | null) => `${v}%`,
valueFormatter: (value: number | null) => `${value}%`,

height: 100,
showTooltip: true,
showHighlight: true,
} as const;

// Extend a value to match a multiple of the step.
function extend(value: number, step: number) {
if (value > 0) {
// If >0 go to the next step
return step * Math.ceil(value / step);
}
// If <0 go to the previous step
return step * Math.floor(value / step);
}

const values = [60, -15, 66, 68, 87, 82, 83, 85, 92, 75, 76, 50, 91];

export default function CustomDomainYAxis() {
return (
<Stack
sx={(theme) => ({
width: '100%',
'& p': { mb: 1, mt: 2 },
'& svg': {
borderWidth: 1,
borderStyle: 'solid',
borderColor: theme.palette.divider,
},
})}
>
<Typography>
<code>domainLimit=&quot;nice&quot;</code>, range from -100 to 100
</Typography>
<Stack
sx={{
width: '100%',
}}
direction="row"
spacing={2}
>
<Box sx={{ flexGrow: 1 }}>
<SparkLineChart data={values} {...settings} />
</Box>
<Box sx={{ flexGrow: 1 }}>
<SparkLineChart plotType="bar" data={values} {...settings} />
</Box>
</Stack>
<Typography>
<code>domainLimit=&quot;strict&quot;</code>, range from -15 to 92
</Typography>
<Stack sx={{ width: '100%' }} direction="row" spacing={2}>
<Box sx={{ flexGrow: 1 }}>
<SparkLineChart
data={values}
yAxis={{ domainLimit: 'strict' }}
{...settings}
/>
</Box>
<Box sx={{ flexGrow: 1 }}>
<SparkLineChart
plotType="bar"
data={values}
yAxis={{ domainLimit: 'strict' }}
{...settings}
/>
</Box>
</Stack>
<Typography>custom function, range from -50 to 100</Typography>
<Stack sx={{ width: '100%' }} direction="row" spacing={2}>
<Box sx={{ flexGrow: 1 }}>
<SparkLineChart
data={values}
yAxis={{
domainLimit: ([min, max]) => [
min - (Math.abs(min) % 50),
max + 50 - (Math.abs(max) % 50),
],
}}
{...settings}
/>
</Box>
<Box sx={{ flexGrow: 1 }}>
<SparkLineChart
plotType="bar"
data={values}
yAxis={{
domainLimit: ([min, max]) => [extend(min, 50), extend(max, 50)],
}}
{...settings}
/>
</Box>
</Stack>
</Stack>
);
}
11 changes: 11 additions & 0 deletions docs/data/charts/sparkline/sparkline.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,14 @@ The following demo shows two sparklines, one with small and another with large v
The first row has the default y-axis values, while on the second row a fixed range from `0` to `100` has been set.

{{"demo": "CustomYAxis.js"}}

You can adjust the y-axis range of a sparkline relatively to its data by using the `domainLimit` option in the `yAxis` configuration.

- `"nice"` Rounds the domain at human friendly values. It's the default behavior.
- `"strict"` Sets the domain to the min/max value to display.
- `([minValue, maxValue]) => [min, max]` Takes the range of value to be display by the axis and return the axis range.

The demo below shows different ways to set the y-axis range.
They always display the same data, going from -15 to 92, but with different `domainLimit` settings.
JCQuintas marked this conversation as resolved.
Show resolved Hide resolved

{{"demo": "CustomDomainYAxis.js"}}
5 changes: 5 additions & 0 deletions docs/pages/x/api/charts/axis-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
},
"data": { "type": { "description": "V[]" } },
"dataKey": { "type": { "description": "string" } },
"domainLimit": {
"type": {
"description": "'nice' | 'strict' | ((range: [number, number]) =&gt; [number, number])"
}
},
"hideTooltip": { "type": { "description": "boolean" } },
"max": { "type": { "description": "number | Date" } },
"min": { "type": { "description": "number | Date" } },
Expand Down
4 changes: 2 additions & 2 deletions docs/pages/x/api/charts/bar-chart-pro.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,13 @@
"xAxis": {
"type": {
"name": "arrayOf",
"description": "Array&lt;{ classes?: object, colorMap?: { colors: Array&lt;string&gt;, type: 'ordinal', unknownColor?: string, values?: Array&lt;Date<br>&#124;&nbsp;number<br>&#124;&nbsp;string&gt; }<br>&#124;&nbsp;{ color: Array&lt;string&gt;<br>&#124;&nbsp;func, max?: Date<br>&#124;&nbsp;number, min?: Date<br>&#124;&nbsp;number, type: 'continuous' }<br>&#124;&nbsp;{ colors: Array&lt;string&gt;, thresholds: Array&lt;Date<br>&#124;&nbsp;number&gt;, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, fill?: string, hideTooltip?: bool, id?: number<br>&#124;&nbsp;string, label?: string, labelFontSize?: number, labelStyle?: object, max?: Date<br>&#124;&nbsp;number, min?: Date<br>&#124;&nbsp;number, position?: 'bottom'<br>&#124;&nbsp;'top', reverse?: bool, scaleType?: 'band'<br>&#124;&nbsp;'linear'<br>&#124;&nbsp;'log'<br>&#124;&nbsp;'point'<br>&#124;&nbsp;'pow'<br>&#124;&nbsp;'sqrt'<br>&#124;&nbsp;'time'<br>&#124;&nbsp;'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array&lt;func<br>&#124;&nbsp;object<br>&#124;&nbsp;bool&gt;<br>&#124;&nbsp;func<br>&#124;&nbsp;object, tickFontSize?: number, tickInterval?: 'auto'<br>&#124;&nbsp;array<br>&#124;&nbsp;func, tickLabelInterval?: 'auto'<br>&#124;&nbsp;func, tickLabelPlacement?: 'middle'<br>&#124;&nbsp;'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'<br>&#124;&nbsp;'extremities'<br>&#124;&nbsp;'middle'<br>&#124;&nbsp;'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'<br>&#124;&nbsp;'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }<br>&#124;&nbsp;bool }&gt;"
"description": "Array&lt;{ classes?: object, colorMap?: { colors: Array&lt;string&gt;, type: 'ordinal', unknownColor?: string, values?: Array&lt;Date<br>&#124;&nbsp;number<br>&#124;&nbsp;string&gt; }<br>&#124;&nbsp;{ color: Array&lt;string&gt;<br>&#124;&nbsp;func, max?: Date<br>&#124;&nbsp;number, min?: Date<br>&#124;&nbsp;number, type: 'continuous' }<br>&#124;&nbsp;{ colors: Array&lt;string&gt;, thresholds: Array&lt;Date<br>&#124;&nbsp;number&gt;, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'<br>&#124;&nbsp;'strict'<br>&#124;&nbsp;func, fill?: string, hideTooltip?: bool, id?: number<br>&#124;&nbsp;string, label?: string, labelFontSize?: number, labelStyle?: object, max?: Date<br>&#124;&nbsp;number, min?: Date<br>&#124;&nbsp;number, position?: 'bottom'<br>&#124;&nbsp;'top', reverse?: bool, scaleType?: 'band'<br>&#124;&nbsp;'linear'<br>&#124;&nbsp;'log'<br>&#124;&nbsp;'point'<br>&#124;&nbsp;'pow'<br>&#124;&nbsp;'sqrt'<br>&#124;&nbsp;'time'<br>&#124;&nbsp;'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array&lt;func<br>&#124;&nbsp;object<br>&#124;&nbsp;bool&gt;<br>&#124;&nbsp;func<br>&#124;&nbsp;object, tickFontSize?: number, tickInterval?: 'auto'<br>&#124;&nbsp;array<br>&#124;&nbsp;func, tickLabelInterval?: 'auto'<br>&#124;&nbsp;func, tickLabelPlacement?: 'middle'<br>&#124;&nbsp;'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'<br>&#124;&nbsp;'extremities'<br>&#124;&nbsp;'middle'<br>&#124;&nbsp;'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'<br>&#124;&nbsp;'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }<br>&#124;&nbsp;bool }&gt;"
}
},
"yAxis": {
"type": {
"name": "arrayOf",
"description": "Array&lt;{ classes?: object, colorMap?: { colors: Array&lt;string&gt;, type: 'ordinal', unknownColor?: string, values?: Array&lt;Date<br>&#124;&nbsp;number<br>&#124;&nbsp;string&gt; }<br>&#124;&nbsp;{ color: Array&lt;string&gt;<br>&#124;&nbsp;func, max?: Date<br>&#124;&nbsp;number, min?: Date<br>&#124;&nbsp;number, type: 'continuous' }<br>&#124;&nbsp;{ colors: Array&lt;string&gt;, thresholds: Array&lt;Date<br>&#124;&nbsp;number&gt;, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, fill?: string, hideTooltip?: bool, id?: number<br>&#124;&nbsp;string, label?: string, labelFontSize?: number, labelStyle?: object, max?: Date<br>&#124;&nbsp;number, min?: Date<br>&#124;&nbsp;number, position?: 'left'<br>&#124;&nbsp;'right', reverse?: bool, scaleType?: 'band'<br>&#124;&nbsp;'linear'<br>&#124;&nbsp;'log'<br>&#124;&nbsp;'point'<br>&#124;&nbsp;'pow'<br>&#124;&nbsp;'sqrt'<br>&#124;&nbsp;'time'<br>&#124;&nbsp;'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array&lt;func<br>&#124;&nbsp;object<br>&#124;&nbsp;bool&gt;<br>&#124;&nbsp;func<br>&#124;&nbsp;object, tickFontSize?: number, tickInterval?: 'auto'<br>&#124;&nbsp;array<br>&#124;&nbsp;func, tickLabelInterval?: 'auto'<br>&#124;&nbsp;func, tickLabelPlacement?: 'middle'<br>&#124;&nbsp;'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'<br>&#124;&nbsp;'extremities'<br>&#124;&nbsp;'middle'<br>&#124;&nbsp;'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'<br>&#124;&nbsp;'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }<br>&#124;&nbsp;bool }&gt;"
"description": "Array&lt;{ classes?: object, colorMap?: { colors: Array&lt;string&gt;, type: 'ordinal', unknownColor?: string, values?: Array&lt;Date<br>&#124;&nbsp;number<br>&#124;&nbsp;string&gt; }<br>&#124;&nbsp;{ color: Array&lt;string&gt;<br>&#124;&nbsp;func, max?: Date<br>&#124;&nbsp;number, min?: Date<br>&#124;&nbsp;number, type: 'continuous' }<br>&#124;&nbsp;{ colors: Array&lt;string&gt;, thresholds: Array&lt;Date<br>&#124;&nbsp;number&gt;, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'<br>&#124;&nbsp;'strict'<br>&#124;&nbsp;func, fill?: string, hideTooltip?: bool, id?: number<br>&#124;&nbsp;string, label?: string, labelFontSize?: number, labelStyle?: object, max?: Date<br>&#124;&nbsp;number, min?: Date<br>&#124;&nbsp;number, position?: 'left'<br>&#124;&nbsp;'right', reverse?: bool, scaleType?: 'band'<br>&#124;&nbsp;'linear'<br>&#124;&nbsp;'log'<br>&#124;&nbsp;'point'<br>&#124;&nbsp;'pow'<br>&#124;&nbsp;'sqrt'<br>&#124;&nbsp;'time'<br>&#124;&nbsp;'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array&lt;func<br>&#124;&nbsp;object<br>&#124;&nbsp;bool&gt;<br>&#124;&nbsp;func<br>&#124;&nbsp;object, tickFontSize?: number, tickInterval?: 'auto'<br>&#124;&nbsp;array<br>&#124;&nbsp;func, tickLabelInterval?: 'auto'<br>&#124;&nbsp;func, tickLabelPlacement?: 'middle'<br>&#124;&nbsp;'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'<br>&#124;&nbsp;'extremities'<br>&#124;&nbsp;'middle'<br>&#124;&nbsp;'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'<br>&#124;&nbsp;'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }<br>&#124;&nbsp;bool }&gt;"
}
},
"zoom": {
Expand Down
Loading