Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
20 changes: 20 additions & 0 deletions docs/data/material/migration/upgrade-to-v9/upgrade-to-v9.md
Original file line number Diff line number Diff line change
Expand Up @@ -559,3 +559,23 @@ If you were already using the `surplus` key via `componentsProps`, move it to `s
-<AvatarGroup componentsProps={{ surplus: { className: 'my-class' } }}>
+<AvatarGroup slotProps={{ surplus: { className: 'my-class' } }}>
```

#### Slider deprecated props removed

Use the [slider-props codemod](https://github.com/mui/material-ui/tree/HEAD/packages/mui-codemod#slider-props) below to migrate the code as described in the following section:

```bash
npx @mui/codemod@latest deprecations/slider-props <path>
```

The deprecated `Slider` props have been removed.
Use the `slots` and `slotProps` props instead:

```diff
<Slider
- components={{ Track: CustomTrack }}
- componentsProps={{ track: { testid: 'test-id' } }}
+ slots={{ track: CustomTrack }}
+ slotProps={{ track: { testid: 'test-id' } }}
/>
```
18 changes: 0 additions & 18 deletions docs/pages/material-ui/api/slider.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,6 @@
},
"default": "'primary'"
},
"components": {
"type": {
"name": "shape",
"description": "{ Input?: elementType, Mark?: elementType, MarkLabel?: elementType, Rail?: elementType, Root?: elementType, Thumb?: elementType, Track?: elementType, ValueLabel?: elementType }"
},
"default": "{}",
"deprecated": true,
"deprecationInfo": "use the <code>slots</code> prop instead. This prop will be removed in a future major release. See <a href=\"https://mui.com/material-ui/migration/migrating-from-deprecated-apis/\">Migrating from deprecated APIs</a> for more details."
},
"componentsProps": {
"type": {
"name": "shape",
"description": "{ input?: func<br>&#124;&nbsp;object, mark?: func<br>&#124;&nbsp;object, markLabel?: func<br>&#124;&nbsp;object, rail?: func<br>&#124;&nbsp;object, root?: func<br>&#124;&nbsp;object, thumb?: func<br>&#124;&nbsp;object, track?: func<br>&#124;&nbsp;object, valueLabel?: func<br>&#124;&nbsp;{ children?: element, className?: string, open?: bool, style?: object, value?: node, valueLabelDisplay?: 'auto'<br>&#124;&nbsp;'off'<br>&#124;&nbsp;'on' } }"
},
"default": "{}",
"deprecated": true,
"deprecationInfo": "use the <code>slotProps</code> prop instead. This prop will be removed in a future major release. See <a href=\"https://mui.com/material-ui/migration/migrating-from-deprecated-apis/\">Migrating from deprecated APIs</a> for more details."
},
"defaultValue": {
"type": { "name": "union", "description": "Array&lt;number&gt;<br>&#124;&nbsp;number" }
},
Expand Down
4 changes: 0 additions & 4 deletions docs/translations/api-docs/slider/slider.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@
"color": {
"description": "The color of the component. It supports both default and custom theme colors, which can be added as shown in the <a href=\"https://mui.com/material-ui/customization/palette/#custom-colors\">palette customization guide</a>."
},
"components": { "description": "The components used for each slot inside." },
"componentsProps": {
"description": "The extra props for the slot components. You can override the existing props or add new ones."
},
"defaultValue": {
"description": "The default value. Use when the component is not controlled."
},
Expand Down
71 changes: 6 additions & 65 deletions packages/mui-material/src/Slider/Slider.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,65 +45,6 @@ export interface SliderOwnProps<Value extends number | readonly number[]> {
SliderPropsColorOverrides
>
| undefined;
/**
* The components used for each slot inside.
*
* @deprecated use the `slots` prop instead. This prop will be removed in a future major release. See [Migrating from deprecated APIs](https://mui.com/material-ui/migration/migrating-from-deprecated-apis/) for more details.
*
* @default {}
*/
components?:
| {
Root?: React.ElementType | undefined;
Track?: React.ElementType | undefined;
Rail?: React.ElementType | undefined;
Thumb?: React.ElementType | undefined;
Mark?: React.ElementType | undefined;
MarkLabel?: React.ElementType | undefined;
ValueLabel?: React.ElementType | undefined;
Input?: React.ElementType | undefined;
}
| undefined;
/**
* The extra props for the slot components.
* You can override the existing props or add new ones.
*
* @deprecated use the `slotProps` prop instead. This prop will be removed in a future major release. See [Migrating from deprecated APIs](https://mui.com/material-ui/migration/migrating-from-deprecated-apis/) for more details.
*
* @default {}
*/
componentsProps?:
| {
root?:
| SlotComponentProps<'span', SliderComponentsPropsOverrides, SliderOwnerState>
| undefined;
track?:
| SlotComponentProps<'span', SliderComponentsPropsOverrides, SliderOwnerState>
| undefined;
rail?:
| SlotComponentProps<'span', SliderComponentsPropsOverrides, SliderOwnerState>
| undefined;
thumb?:
| SlotComponentProps<'span', SliderComponentsPropsOverrides, SliderOwnerState>
| undefined;
mark?:
| SlotComponentProps<'span', SliderComponentsPropsOverrides, SliderOwnerState>
| undefined;
markLabel?:
| SlotComponentProps<'span', SliderComponentsPropsOverrides, SliderOwnerState>
| undefined;
valueLabel?:
| SlotComponentProps<
typeof SliderValueLabelComponent,
SliderComponentsPropsOverrides,
SliderOwnerState
>
| undefined;
input?:
| SlotComponentProps<'input', SliderComponentsPropsOverrides, SliderOwnerState>
| undefined;
}
| undefined;
/**
* Override or extend the styles applied to the component.
*/
Expand Down Expand Up @@ -339,12 +280,12 @@ export interface SliderValueLabelProps extends React.HTMLAttributes<HTMLSpanElem
value: React.ReactNode;
}

type SliderRootProps = NonNullable<SliderTypeMap['props']['componentsProps']>['root'];
type SliderMarkProps = NonNullable<SliderTypeMap['props']['componentsProps']>['mark'];
type SliderMarkLabelProps = NonNullable<SliderTypeMap['props']['componentsProps']>['markLabel'];
type SliderRailProps = NonNullable<SliderTypeMap['props']['componentsProps']>['rail'];
type SliderTrackProps = NonNullable<SliderTypeMap['props']['componentsProps']>['track'];
type SliderThumbProps = NonNullable<SliderTypeMap['props']['componentsProps']>['thumb'];
type SliderRootProps = NonNullable<SliderTypeMap['props']['slotProps']>['root'];
type SliderMarkProps = NonNullable<SliderTypeMap['props']['slotProps']>['mark'];
type SliderMarkLabelProps = NonNullable<SliderTypeMap['props']['slotProps']>['markLabel'];
type SliderRailProps = NonNullable<SliderTypeMap['props']['slotProps']>['rail'];
type SliderTrackProps = NonNullable<SliderTypeMap['props']['slotProps']>['track'];
type SliderThumbProps = NonNullable<SliderTypeMap['props']['slotProps']>['thumb'];

export declare const SliderRoot: React.FC<SliderRootProps>;
export declare const SliderMark: React.FC<SliderMarkProps>;
Expand Down
80 changes: 16 additions & 64 deletions packages/mui-material/src/Slider/Slider.js
Original file line number Diff line number Diff line change
Expand Up @@ -563,8 +563,6 @@ const Slider = React.forwardRef(function Slider(inputProps, ref) {
'aria-labelledby': ariaLabelledby,
// eslint-disable-next-line react/prop-types
component = 'span',
components = {},
componentsProps = {},
color = 'primary',
classes: classesProp,
className,
Expand Down Expand Up @@ -637,24 +635,23 @@ const Slider = React.forwardRef(function Slider(inputProps, ref) {

const classes = useUtilityClasses(ownerState);

// support both `slots` and `components` for backward compatibility
const RootSlot = slots?.root ?? components.Root ?? SliderRoot;
const RailSlot = slots?.rail ?? components.Rail ?? SliderRail;
const TrackSlot = slots?.track ?? components.Track ?? SliderTrack;
const ThumbSlot = slots?.thumb ?? components.Thumb ?? SliderThumb;
const ValueLabelSlot = slots?.valueLabel ?? components.ValueLabel ?? SliderValueLabel;
const MarkSlot = slots?.mark ?? components.Mark ?? SliderMark;
const MarkLabelSlot = slots?.markLabel ?? components.MarkLabel ?? SliderMarkLabel;
const InputSlot = slots?.input ?? components.Input ?? 'input';
const RootSlot = slots?.root ?? SliderRoot;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Really curious why in Slider we don't follow other components. Just pass elementType as the default one, then let the useSlot get what it needs from externalForwardedProps. Here we're manually getting the elementType, then the slotsProps, and then we pass them to useSlot.

I don't know which one is better, but from what I've seen in other components so far, we're letting useSlot handle all of this.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

that's true.

const RailSlot = slots?.rail ?? SliderRail;
const TrackSlot = slots?.track ?? SliderTrack;
const ThumbSlot = slots?.thumb ?? SliderThumb;
const ValueLabelSlot = slots?.valueLabel ?? SliderValueLabel;
const MarkSlot = slots?.mark ?? SliderMark;
const MarkLabelSlot = slots?.markLabel ?? SliderMarkLabel;
const InputSlot = slots?.input ?? 'input';

const rootSlotProps = slotProps?.root ?? componentsProps.root;
const railSlotProps = slotProps?.rail ?? componentsProps.rail;
const trackSlotProps = slotProps?.track ?? componentsProps.track;
const thumbSlotProps = slotProps?.thumb ?? componentsProps.thumb;
const valueLabelSlotProps = slotProps?.valueLabel ?? componentsProps.valueLabel;
const markSlotProps = slotProps?.mark ?? componentsProps.mark;
const markLabelSlotProps = slotProps?.markLabel ?? componentsProps.markLabel;
const inputSlotProps = slotProps?.input ?? componentsProps.input;
const rootSlotProps = slotProps?.root;
const railSlotProps = slotProps?.rail;
const trackSlotProps = slotProps?.track;
const thumbSlotProps = slotProps?.thumb;
const valueLabelSlotProps = slotProps?.valueLabel;
const markSlotProps = slotProps?.mark;
const markLabelSlotProps = slotProps?.markLabel;
const inputSlotProps = slotProps?.input;

const rootProps = useSlotProps({
elementType: RootSlot,
Expand Down Expand Up @@ -909,51 +906,6 @@ Slider.propTypes /* remove-proptypes */ = {
PropTypes.oneOf(['primary', 'secondary', 'error', 'info', 'success', 'warning']),
PropTypes.string,
]),
/**
* The components used for each slot inside.
*
* @deprecated use the `slots` prop instead. This prop will be removed in a future major release. See [Migrating from deprecated APIs](https://mui.com/material-ui/migration/migrating-from-deprecated-apis/) for more details.
*
* @default {}
*/
components: PropTypes.shape({
Input: PropTypes.elementType,
Mark: PropTypes.elementType,
MarkLabel: PropTypes.elementType,
Rail: PropTypes.elementType,
Root: PropTypes.elementType,
Thumb: PropTypes.elementType,
Track: PropTypes.elementType,
ValueLabel: PropTypes.elementType,
}),
/**
* The extra props for the slot components.
* You can override the existing props or add new ones.
*
* @deprecated use the `slotProps` prop instead. This prop will be removed in a future major release. See [Migrating from deprecated APIs](https://mui.com/material-ui/migration/migrating-from-deprecated-apis/) for more details.
*
* @default {}
*/
componentsProps: PropTypes.shape({
input: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
mark: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
markLabel: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
rail: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
root: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
thumb: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
track: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
valueLabel: PropTypes.oneOfType([
PropTypes.func,
PropTypes.shape({
children: PropTypes.element,
className: PropTypes.string,
open: PropTypes.bool,
style: PropTypes.object,
value: PropTypes.node,
valueLabelDisplay: PropTypes.oneOf(['auto', 'off', 'on']),
}),
]),
}),
/**
* The default value. Use when the component is not controlled.
*/
Expand Down
25 changes: 2 additions & 23 deletions packages/mui-material/src/Slider/Slider.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function testOnChange() {
<Slider color="info" />;
<Slider color="warning" />;

// slotProps and componentsProps as objects
// slotProps as objects
<Slider
slotProps={{
root: { onMouseDown: () => 'onMouseDown event triggered' },
Expand All @@ -33,18 +33,9 @@ function testOnChange() {
thumb: { className: 'thumb' },
valueLabel: { valueLabelDisplay: 'auto' },
}}
componentsProps={{
root: { onMouseDown: () => 'onMouseDown event triggered' },
input: { disabled: true },
mark: { onClick: () => 'clicked' },
markLabel: { className: 'markLabel' },
rail: { className: 'rail' },
thumb: { className: 'thumb' },
valueLabel: { valueLabelDisplay: 'auto' },
}}
/>;

// slotProps and componentsProps as functions
// slotProps as functions
<Slider
slotProps={{
root: ({ color }) => ({ className: color === 'primary' ? 'root_primary' : 'root_secondary' }),
Expand All @@ -58,18 +49,6 @@ function testOnChange() {
}),
thumb: ({ orientation }) => ({ className: orientation === 'vertical' ? 'thumb_vertical' : '' }),
}}
componentsProps={{
root: ({ color }) => ({ className: color === 'primary' ? 'root_primary' : 'root_secondary' }),
input: ({ size }) => ({ disabled: size === 'medium' }),
mark: ({ marked }) => ({
className: marked ? 'marked' : '',
}),
markLabel: ({ max }) => ({ className: max === 99 ? 'red' : 'normal' }),
rail: ({ dragging }) => ({
className: dragging ? 'rail' : '',
}),
thumb: ({ orientation }) => ({ className: orientation === 'vertical' ? 'thumb_vertical' : '' }),
}}
/>;

// value, onChange, and onChangeCommitted value type
Expand Down
27 changes: 10 additions & 17 deletions packages/mui-material/src/Slider/Slider.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ describe.skipIf(!supportsTouch())('<Slider />', () => {
testDeepOverrides: { slotName: 'thumb', slotClassName: classes.thumb },
testVariantProps: { color: 'primary', orientation: 'vertical', size: 'small' },
testStateOverrides: { prop: 'color', value: 'secondary', styleKey: 'colorSecondary' },
testLegacyComponentsProp: true,
slots: {
root: {
expectedClassName: classes.root,
Expand Down Expand Up @@ -327,7 +326,7 @@ describe.skipIf(!supportsTouch())('<Slider />', () => {
it('should focus the slider when dragging', () => {
const { container } = render(
<Slider
componentsProps={{ thumb: { 'data-testid': 'thumb' } }}
slotProps={{ thumb: { 'data-testid': 'thumb' } }}
defaultValue={30}
step={10}
marks
Expand Down Expand Up @@ -808,7 +807,7 @@ describe.skipIf(!supportsTouch())('<Slider />', () => {
<Slider
valueLabelDisplay="on"
value={50}
componentsProps={{ thumb: { 'data-testid': 'thumb' } }}
slotProps={{ thumb: { 'data-testid': 'thumb' } }}
/>,
);
expect(document.querySelector(`.${classes.valueLabelOpen}`)).not.to.equal(null);
Expand All @@ -825,7 +824,7 @@ describe.skipIf(!supportsTouch())('<Slider />', () => {
<Slider
valueLabelDisplay="auto"
value={50}
componentsProps={{ thumb: { 'data-testid': 'thumb' } }}
slotProps={{ thumb: { 'data-testid': 'thumb' } }}
/>,
);

Expand All @@ -849,11 +848,7 @@ describe.skipIf(!supportsTouch())('<Slider />', () => {
ValueLabelComponent.propTypes = { value: PropTypes.number };

const { setProps } = render(
<Slider
components={{ ValueLabel: ValueLabelComponent }}
valueLabelDisplay="on"
value={50}
/>,
<Slider slots={{ valueLabel: ValueLabelComponent }} valueLabelDisplay="on" value={50} />,
);

expect(screen.queryByTestId('value-label')).to.have.class('open');
Expand Down Expand Up @@ -952,7 +947,7 @@ describe.skipIf(!supportsTouch())('<Slider />', () => {
<Slider
value={30}
onChange={handleChange}
componentsProps={{ thumb: { 'data-testid': 'thumb' } }}
slotProps={{ thumb: { 'data-testid': 'thumb' } }}
/>
</ThemeProvider>,
);
Expand Down Expand Up @@ -1369,7 +1364,7 @@ describe.skipIf(!supportsTouch())('<Slider />', () => {
render(
<Slider
value={10}
components={{ ValueLabel: ValueLabelComponent }}
slots={{ valueLabel: ValueLabelComponent }}
valueLabelDisplay="on"
valueLabelFormat={(n) => n.toString(2)}
/>,
Expand Down Expand Up @@ -1607,7 +1602,7 @@ describe.skipIf(!supportsTouch())('<Slider />', () => {
});
});

describe('prop: components', () => {
describe('prop: slots', () => {
it('should render custom components if specified', () => {
// ARRANGE
const dataTestId = 'slider-input-testid';
Expand All @@ -1616,22 +1611,20 @@ describe.skipIf(!supportsTouch())('<Slider />', () => {
return <input {...props} data-testid={dataTestId} name={name} />;
}

render(<Slider components={{ Input: CustomInput }} />);
render(<Slider slots={{ input: CustomInput }} />);

// ASSERT
expect(screen.getByTestId(dataTestId).name).to.equal(name);
});
});

describe('prop: componentsProps', () => {
describe('prop: slotProps', () => {
it('should forward the props to their respective components', () => {
// ARRANGE
const dataTestId = 'slider-input-testid';
const id = 'slider-input-id';

render(
<Slider defaultValue={10} componentsProps={{ input: { 'data-testid': dataTestId, id } }} />,
);
render(<Slider defaultValue={10} slotProps={{ input: { 'data-testid': dataTestId, id } }} />);

// ASSERT
expect(screen.getByTestId(dataTestId).id).to.equal(id);
Expand Down
Loading