Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,29 @@ import {
import { styled } from '@mui/material/styles';
import { useXAxes, useYAxes } from '@mui/x-charts/hooks';
import { rafThrottle } from '@mui/x-internals/rafThrottle';
import clsx from 'clsx';
import { chartAxisZoomSliderClasses } from './chartAxisZoomSliderClasses';
import { ChartsTooltipZoomSliderValue } from './ChartsTooltipZoomSliderValue';
import {
selectorChartAxisZoomData,
UseChartProZoomSignature,
} from '../../internals/plugins/useChartProZoom';
import { ChartAxisZoomSliderThumb } from './ChartAxisZoomSliderThumb';

const Group = styled('g')({
[`&.${chartAxisZoomSliderClasses.root}.${chartAxisZoomSliderClasses.horizontal} .${chartAxisZoomSliderClasses.track}.${chartAxisZoomSliderClasses.selecting}`]:
{ cursor: 'ew-resize' },
[`&.${chartAxisZoomSliderClasses.root}.${chartAxisZoomSliderClasses.vertical} .${chartAxisZoomSliderClasses.track}.${chartAxisZoomSliderClasses.selecting}`]:
{ cursor: 'ns-resize' },
});

Copy link
Member

Choose a reason for hiding this comment

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

That's a bit weird to have that many classes. Users would need a specificity higher than 0-5-0 to verride those rules.

What about moving that style into the ZoomSliderTrack?

You can look at this component. In short, you pass the props of interest (the direction and the selecting state) such that it adapts its style to it, but do not propagate those props. The goal is to have only one class such that any style override wins over the default one

https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/internals/components/PickersToolbar.tsx/#L51-L82

Copy link
Member Author

@bernardobelchior bernardobelchior May 26, 2025

Choose a reason for hiding this comment

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

I've updated the code as suggested. Is that what you had in mind?

Copy link
Member

Choose a reason for hiding this comment

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

I think we can go further on the simplification with

const ZoomSliderTrack = styled('rect', {
  shouldForwardProp: (prop) =>
    shouldForwardProp(prop) && prop !== 'axisDirection' && prop !== 'isSelecting',
})<{ axisDirection: 'x' | 'y'; isSelecting: boolean }>(({ theme }) => ({
  fill:
    theme.palette.mode === 'dark'
      ? (theme.vars || theme).palette.grey[800]
      : (theme.vars || theme).palette.grey[300],
  cursor: 'pointer',
  variants: [
    {
      props: { axisDirection: 'y', isSelecting: true },
      style: {
        cursor: 'ns-resize',
      },
    },
    {
      props: { axisDirection: 'x', isSelecting: true },
      style: {
        cursor: 'ew-resize',
      },
    },
  ],
}));

Copy link
Member Author

Choose a reason for hiding this comment

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

That seems to work 😄 done 👍

const ZoomSliderTrack = styled('rect')(({ theme }) => ({
'&': {
[`&.${chartAxisZoomSliderClasses.track}`]: {
fill:
theme.palette.mode === 'dark'
? (theme.vars || theme).palette.grey[800]
: (theme.vars || theme).palette.grey[300],
cursor: 'crosshair',
cursor: 'pointer',
},
}));

Expand Down Expand Up @@ -122,9 +131,15 @@ export function ChartAxisZoomSlider({ axisDirection, axisId }: ChartZoomSliderPr
}

const backgroundRectOffset = (ZOOM_SLIDER_SIZE - ZOOM_SLIDER_TRACK_SIZE) / 2;
const className = clsx(
chartAxisZoomSliderClasses.root,
axisDirection === 'x'
? chartAxisZoomSliderClasses.horizontal
: chartAxisZoomSliderClasses.vertical,
);

return (
<g transform={`translate(${x} ${y})`}>
<Group className={className} transform={`translate(${x} ${y})`}>
<ChartAxisZoomSliderTrack
x={axisDirection === 'x' ? 0 : backgroundRectOffset}
y={axisDirection === 'x' ? backgroundRectOffset : 0}
Expand All @@ -143,7 +158,7 @@ export function ChartAxisZoomSlider({ axisDirection, axisId }: ChartZoomSliderPr
axisDirection={axisDirection}
reverse={reverse}
/>
</g>
</Group>
);
}

Expand All @@ -162,6 +177,11 @@ function ChartAxisZoomSliderTrack({
const ref = React.useRef<SVGRectElement>(null);
const { instance, svgRef } = useChartContext<[UseChartProZoomSignature]>();
const store = useStore<[UseChartProZoomSignature]>();
const [isSelecting, setIsSelecting] = React.useState(false);
const className = clsx(
chartAxisZoomSliderClasses.track,
isSelecting && chartAxisZoomSliderClasses.selecting,
);

const onPointerDown = function onPointerDown(event: React.PointerEvent<SVGRectElement>) {
const rect = ref.current;
Expand Down Expand Up @@ -241,6 +261,7 @@ function ChartAxisZoomSliderTrack({
rect.releasePointerCapture(pointerUpEvent.pointerId);
rect.removeEventListener('pointermove', onPointerMove);
document.removeEventListener('pointerup', onPointerUp);
setIsSelecting(false);

if (pointerMoved) {
return;
Expand Down Expand Up @@ -271,14 +292,17 @@ function ChartAxisZoomSliderTrack({
document.addEventListener('pointerup', onPointerUp);
rect.addEventListener('pointermove', onPointerMove);

setIsSelecting(true);
instance.setAxisZoomData(axisId, (prev) => ({
...prev,
start: zoomFromPointerDown,
end: zoomFromPointerDown,
}));
};

return <ZoomSliderTrack ref={ref} onPointerDown={onPointerDown} {...other} />;
return (
<ZoomSliderTrack ref={ref} className={className} onPointerDown={onPointerDown} {...other} />
);
}

const formatter = Intl.NumberFormat(undefined, { maximumFractionDigits: 0 });
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import generateUtilityClass from '@mui/utils/generateUtilityClass';
import generateUtilityClasses from '@mui/utils/generateUtilityClasses';

export interface ChartAxisZoomSliderClasses {
/** Styles applied to the root element. */
root: string;
/** Styles applied to the root element when the slider is horizontal. */
horizontal: string;
/** Styles applied to the root element when the slider is vertical. */
vertical: string;

/** Styles applied to the track of the zoom slider. */
track: string;
/** Styles applied to the track of the zoom slider when a range selection is being made. */
selecting: string;
}

export type ChartAxisZoomSliderClassKey = keyof ChartAxisZoomSliderClasses;

export function getChartAxisZoomSliderUtilityClass(slot: string) {
return generateUtilityClass('MuiChartAxisZoomSlider', slot);
}

export const chartAxisZoomSliderClasses: ChartAxisZoomSliderClasses = generateUtilityClasses(
'MuiChartAxisZoomSlider',
['root', 'vertical', 'horizontal', 'track', 'selecting'],
);