docs/data/material/migration/migration-v4/v5-component-changes.md
Material UI v5 introduces a number of breaking changes from v4. Many of these changes can be resolved automatically using the codemods described in the main migration guide.
The following document lists all breaking changes related to components in v5 and how to address them.
If you haven't already, please be sure to review Breaking changes in v5 part one: styles and themes to continue the migration process.
:::warning Breaking changes that are handled by the codemods are denoted by a ✅ emoji in the table of contents on the right side of the screen.
If you have already followed the instructions in the main migration guide and run the codemods, then you should not need to take any further action on these items.
All other changes must be handled manually. :::
As the core components use Emotion as their style engine, the props used by Emotion are not intercepted. The prop as in the following code snippet will not be propagated to SomeOtherComponent.
<MuiComponent component={SomeOtherComponent} as="button" />
expandIcon to expandIconWrapperThis change was made to make it clearer that the element is a wrapper around the icon, not the icon itself.
Update the CSS class name and the theme overrides accordingly.
-'.MuiAccordionSummary-expandIcon': {
+'.MuiAccordionSummary-expandIconWrapper': {
createTheme({
components: {
MuiAccordionSummary: {
styleOverrides: {
- expandIcon: {
+ expandIconWrapper: {
// ...
},
},
},
},
});
Remove z-index when position static and relative. This avoids the creation of a stacking context and rendering issues.
The color prop has no longer any effect in dark mode. The app bar uses the background color required by the elevation to follow the Material Design guidelines. Use enableColorOnDark to restore the behavior of v4.
<AppBar enableColorOnDark />
Move the component from the lab to the core. The component is now stable.
-import Alert from '@mui/lab/Alert';
-import AlertTitle from '@mui/lab/AlertTitle';
+import Alert from '@mui/material/Alert';
+import AlertTitle from '@mui/material/AlertTitle';
Move the component from the lab to the core. The component is now stable.
-import Autocomplete from '@mui/lab/Autocomplete';
-import useAutocomplete from '@mui/lab/useAutocomplete';
+import Autocomplete from '@mui/material/Autocomplete';
+import useAutocomplete from '@mui/material/useAutocomplete';
Remove debug prop. There are a couple of simpler alternatives: open={true}, Chrome devtools "Emulate focused", or React devtools prop setter.
renderOptionrenderOption should now return the full DOM structure of the option.
It makes customizations easier. You can recover from the change with:
<Autocomplete
- renderOption={(option, { selected }) => (
- <React.Fragment>
+ renderOption={(props, option, { selected }) => (
+ <li {...props}>
<Checkbox
icon={icon}
checkedIcon={checkedIcon}
style={{ marginRight: 8 }}
checked={selected}
/>
{option.title}
- </React.Fragment>
+ </li>
)}
/>
closeIcon to clearIconRename closeIcon prop to clearIcon to avoid confusion.
-<Autocomplete closeIcon={defaultClearIcon} />
+<Autocomplete clearIcon={defaultClearIcon} />
The following values of the reason argument in onChange and onClose were renamed for consistency:
create-option to createOptionselect-option to selectOptionremove-option to removeOptionChange the CSS rules that use [data-focus="true"] to use .Mui-focused. The data-focus attribute is not set on the focused option anymore; instead, global class names are used.
-'.MuiAutocomplete-option[data-focus="true"]': {
+'.MuiAutocomplete-option.Mui-focused': {
Rename getOptionSelected to isOptionEqualToValue to better describe its purpose.
<Autocomplete
- getOptionSelected={(option, value) => option.title === value.title}
+ isOptionEqualToValue={(option, value) => option.title === value.title}
Rename circle to circular for consistency:
-<Avatar variant="circle">
-<Avatar classes={{ circle: 'className' }}>
+<Avatar variant="circular">
+<Avatar classes={{ circular: 'className' }}>
Since circular is the default value, the variant prop can be deleted:
-<Avatar variant="circle">
+<Avatar>
Move the AvatarGroup from the lab to the core.
-import AvatarGroup from '@mui/lab/AvatarGroup';
+import AvatarGroup from '@mui/material/AvatarGroup';
Rename circle to circular and rectangle to rectangular for consistency.
-<Badge overlap="circle">
-<Badge overlap="rectangle">
+<Badge overlap="circular">
+<Badge overlap="rectangular">
<Badge classes={{
- anchorOriginTopRightRectangle: 'className',
- anchorOriginBottomRightRectangle: 'className',
- anchorOriginTopLeftRectangle: 'className',
- anchorOriginBottomLeftRectangle: 'className',
- anchorOriginTopRightCircle: 'className',
- anchorOriginBottomRightCircle: 'className',
- anchorOriginTopLeftCircle: 'className',
+ anchorOriginTopRightRectangular: 'className',
+ anchorOriginBottomRightRectangular: 'className',
+ anchorOriginTopLeftRectangular: 'className',
+ anchorOriginBottomLeftRectangular: 'className',
+ anchorOriginTopRightCircular: 'className',
+ anchorOriginBottomRightCircular: 'className',
+ anchorOriginTopLeftCircular: 'className',
}}>
The event in onChange is now typed as a React.SyntheticEvent instead of a React.ChangeEvent.
-<BottomNavigation onChange={(event: React.ChangeEvent<{}>) => {}} />
+<BottomNavigation onChange={(event: React.SyntheticEvent) => {}} />
Remove the span element that wraps the children.
Remove the wrapper classKey too.
You can find out more details about this change in this GitHub pull request.
<button class="MuiBottomNavigationAction-root">
- <span class="MuiBottomNavigationAction-wrapper">
{icon}
<span class="MuiBottomNavigationAction-label">
{label}
</span>
- </span>
</button>
The borderRadius system prop value transformation has been changed.
If it receives a number, it multiplies this value with the theme.shape.borderRadius value.
Use a string to provide an explicit px value.
-<Box borderRadius="borderRadius">
+<Box borderRadius={1}>
-<Box borderRadius={16}>
+<Box borderRadius="16px">
The Box system props have an optional alternative API in v5, using the sx prop.
Check out MUI System docs to learn more about the tradeoffs of this API.
<Box border="1px dashed grey" p={[2, 3, 4]} m={2}>
<Box sx={{ border: "1px dashed grey", p: [2, 3, 4], m: 2 }}>
The following properties have been renamed because they are considered deprecated CSS properties by the CSS specification:
gridGap to gapgridColumnGap to columnGapgridRowGap to rowGap-<Box gridGap={1}>
-<Box gridColumnGap={2}>
-<Box gridRowGap={3}>
+<Box gap={1}>
+<Box columnGap={2}>
+<Box rowGap={3}>
:::info The system grid function was not documented in v4. :::
The clone prop was removed because its behavior can be obtained by applying the sx prop directly to the child if it is a Material UI component.
-<Box sx={{ border: '1px dashed grey' }} clone>
- <Button>Save</Button>
-</Box>
+<Button sx={{ border: '1px dashed grey' }}>Save</Button>
sxThe ability to pass a render prop was removed because its behavior can be obtained by applying the sx prop directly to the child if it is a Material UI component.
-<Box sx={{ border: '1px dashed grey' }}>
- {(props) => <Button {...props}>Save</Button>}
-</Box>
+<Button sx={{ border: '1px dashed grey' }}>Save</Button>
For non-Material UI components, use the component prop.
-<Box sx={{ border: '1px dashed grey' }}>
- {(props) => <button {...props}>Save</button>}
-</Box>
+<Box component="button" sx={{ border: '1px dashed grey' }}>Save</Box>
The button color prop is now "primary" by default, and "default" has been removed.
This makes the button closer to the Material Design guidelines and simplifies the API.
-<Button color="default">
+<Button>
:::info
If you prefer to use the default color in v4, take a look at this CodeSandbox demo to see how to make it work in v5.
:::
The span element that wraps children has been removed.
The label classKey is also removed.
You can find out more details about this change in this GitHub pull request, it used to be necessary for iOS.
<button class="MuiButton-root">
- <span class="MuiButton-label">
children
- </span>
</button>
Rename default variant to filled for consistency.
Since filled is the default value, the variant prop can be deleted:
-<Chip variant="default">
+<Chip>
The checkbox color prop is now "primary" by default.
To continue using the "secondary" color, you must explicitly indicate secondary.
This brings the checkbox closer to the Material Design guidelines.
-<Checkbox />
+<Checkbox color="secondary" />
The component doesn't have .MuiIconButton-root and .MuiIconButton-label class names anymore.
Target .MuiButtonBase-root instead.
-<span class="MuiIconButton-root MuiButtonBase-root MuiCheckbox-root PrivateSwitchBase-root">
- <span class="MuiIconButton-label">
- <input class="PrivateSwitchBase-input">
+<span class="MuiButtonBase-root MuiCheckbox-root PrivateSwitchBase-root">
+ <span class="PrivateSwitchBase-input">
The static variant has been renamed to determinate, and the previous appearance of determinate has been replaced by that of static.
This was an exception to Material Design, and was removed from the specification.
-<CircularProgress variant="static" classes={{ static: 'className' }} />
+<CircularProgress variant="determinate" classes={{ determinate: 'className' }} />
:::error
If you had previously customized determinate, then your customizations are most likely no longer valid.
Please remove them.
:::
The collapsedHeight prop was renamed collapsedSize to support the horizontal direction.
-<Collapse collapsedHeight={40}>
+<Collapse collapsedSize={40}>
The classes.container key was changed to match the convention of the other components.
-<Collapse classes={{ container: 'collapse' }}>
+<Collapse classes={{ root: 'collapse' }}>
The component was migrated to use the @mui/styled-engine (emotion or styled-components) instead of jss.
You should remove the @global key when defining the style overrides for it.
You could also start using the CSS template syntax over the JavaScript object syntax.
const theme = createTheme({
components: {
MuiCssBaseline: {
- styleOverrides: {
- '@global': {
- html: {
- WebkitFontSmoothing: 'auto',
- },
- },
- },
+ styleOverrides: `
+ html {
+ -webkit-font-smoothing: auto;
+ }
+ `
},
},
});
The body font size has changed from theme.typography.body2 (0.875rem) to theme.typography.body1 (1rem).
To return to the previous size, you can override it in the theme:
const theme = createMuiTheme({
components: {
MuiCssBaseline: {
styleOverrides: {
body: {
fontSize: '0.875rem',
lineHeight: 1.43,
letterSpacing: '0.01071em',
},
},
},
},
});
The on* transition props were removed.
Use TransitionProps instead.
<Dialog
- onEnter={onEnter}
- onEntered={onEntered}
- onEntering={onEntering}
- onExit={onExit}
- onExited={onExited}
- onExiting={onExiting}
+ TransitionProps={{
+ onEnter,
+ onEntered,
+ onEntering,
+ onExit,
+ onExited,
+ onExiting,
+ }}
>
Remove the disableBackdropClick prop because it is redundant.
Ignore close events from onClose when reason === 'backdropClick' instead.
<Dialog
- disableBackdropClick
- onClose={handleClose}
+ onClose={(event, reason) => {
+ if (reason !== 'backdropClick') {
+ handleClose(event, reason);
+ }
+ }}
/>
Remove the withMobileDialog higher-order component.
:::warning This is handled in the preset-safe codemod by applying hard-coded function to prevent application crash, but further fixes are required. :::
The hook API allows a simpler and more flexible solution:
-import withMobileDialog from '@mui/material/withMobileDialog';
+import { useTheme, useMediaQuery } from '@mui/material';
function ResponsiveDialog(props) {
- const { fullScreen } = props;
+ const theme = useTheme();
+ const fullScreen = useMediaQuery(theme.breakpoints.down('sm'));
const [open, setOpen] = React.useState(false);
// ...
-export default withMobileDialog()(ResponsiveDialog);
+export default ResponsiveDialog;
Flatten DialogTitle DOM structure and remove the disableTypography prop.
-<DialogTitle disableTypography>
- <Typography variant="h4" component="h2">
+<DialogTitle>
+ <Typography variant="h4" component="span">
My header
</Typography>
Use border-color instead of background-color.
This prevents inconsistent height on scaled screens.
If you have customized the color of the border, you will need to update the CSS property override:
.MuiDivider-root {
- background-color: #f00;
+ border-color: #f00;
}
In v4, using orientation="vertical" and variant="middle" was adding a left and right margins of 16px in the component.
In the v5, to avoid fixed spacing on the component, this margin was removed.
:::info If you want to use the previous margin values, this change can be made in your theme with the following code. See the example on CodeSandbox demo. :::
const theme = createTheme({
components: {
MuiDivider: {
+ styleOverrides: {
+ root: ({ ownerState, theme }) => ({
+ ...(ownerState.orientation === 'vertical' && ownerState.variant === 'middle' && {
+ marginLeft: theme.spacing(2),
+ marginRight: theme.spacing(2),
+ }),
+ })
+ }
},
},
});
Rename the ExpansionPanel components to Accordion to use a more common naming convention:
-import ExpansionPanel from '@mui/material/ExpansionPanel';
-import ExpansionPanelSummary from '@mui/material/ExpansionPanelSummary';
-import ExpansionPanelDetails from '@mui/material/ExpansionPanelDetails';
-import ExpansionPanelActions from '@mui/material/ExpansionPanelActions';
+import Accordion from '@mui/material/Accordion';
+import AccordionSummary from '@mui/material/AccordionSummary';
+import AccordionDetails from '@mui/material/AccordionDetails';
+import AccordionActions from '@mui/material/AccordionActions';
-<ExpansionPanel>
+<Accordion>
- <ExpansionPanelSummary>
+ <AccordionSummary>
<Typography>Location</Typography>
<Typography>Select trip destination</Typography>
- </ExpansionPanelSummary>
+ </AccordionSummary>
- <ExpansionPanelDetails>
+ <AccordionDetails>
<Chip label="Barbados" onDelete={() => {}} />
<Typography variant="caption">Select your destination of choice</Typography>
- </ExpansionPanelDetails>
+ </AccordionDetails>
<Divider />
- <ExpansionPanelActions>
+ <AccordionActions>
<Button size="small">Cancel</Button>
<Button size="small">Save</Button>
- </ExpansionPanelActions>
+ </AccordionActions>
-</ExpansionPanel>
+</Accordion>
The event in onChange is now typed as a React.SyntheticEvent instead of a React.ChangeEvent.
-<Accordion onChange={(event: React.ChangeEvent<{}>, expanded: boolean) => {}} />
+<Accordion onChange={(event: React.SyntheticEvent, expanded: boolean) => {}} />
Remove display: flex from AccordionDetails (formerly ExpansionPanelDetails) as it was too opinionated—most developers expect display: block.
Rename focused to focusVisible for consistency:
<AccordionSummary
classes={{
- focused: 'custom-focus-visible-classname',
+ focusVisible: 'custom-focus-visible-classname',
}}
/>
Remove IconButtonProps prop from AccordionSummary (formerly ExpansionPanelSummary).
The component renders a <div> element instead of an IconButton, so the prop is no longer necessary.
-<Fab variant="round">
+<Fab variant="circular">
The span element that wraps children has been removed.
The label classKey is also removed.
You can find out more details about this change in this GitHub pull request, it used to be necessary for iOS.
<button class="MuiFab-root">
- <span class="MuiFab-label">
{children}
- </span>
</button>
Change the default variant from standard to outlined.
standard has been removed from the Material Design guidelines.
:::success This is handled in variant-prop codemod—read the details before running this codemod. :::
-<FormControl value="Standard" />
-<FormControl value="Outlined" variant="outlined" />
+<FormControl value="Standard" variant="standard" />
+<FormControl value="Outlined" />
The label prop is now required.
If you were using a FormControlLabel without a label, you can replace it with just the value of the control prop.
-<FormControlLabel control={<Checkbox />} />
+<Checkbox />
Rename the justify prop to justifyContent to align with the CSS property name.
-<Grid justify="center">
+<Grid justifyContent="center">
The props alignItems, alignContent, and justifyContent—along with their classes and style overrides keys—have been removed:
"align-items-xs-center", "align-items-xs-flex-start", "align-items-xs-flex-end", "align-items-xs-baseline", "align-content-xs-center", "align-content-xs-flex-start", "align-content-xs-flex-end", "align-content-xs-space-between", "align-content-xs-space-around", "justify-content-xs-center", "justify-content-xs-flex-end", "justify-content-xs-space-between", "justify-content-xs-space-around" and "justify-content-xs-space-evenly".
These props are now considered part of MUI System, not the Grid component itself.
If you still wish to add overrides for them, you can use the callback as a value in styleOverrides.
const theme = createTheme({
components: {
MuiGrid: {
- styleOverrides: {
- 'align-items-xs-flex-end': {
- marginTop: 20,
- },
- },
+ styleOverrides: ({ ownerState }) => ({
+ ...ownerState.alignItems === 'flex-end' && {
+ marginTop: 20,
+ },
+ }),
},
},
});
The negative margins apply only to the top and left sides of the grid container. If you need negative margins on all sides, we recommend using the new Grid v2 instead:
- import Grid from '@mui/material/Grid';
+ import Grid from '@mui/material/Grid2';
To learn more about Grid2, check out the Grid2 component doc and the upgrade guide.
:::info Grid2 was introduced in Material UI v5.9.1 and features negative margins on all sides by default. :::
Rename the GridList components to ImageList to align with the current Material Design naming.
spacing prop to gap to align with the CSS attribute.cellHeight prop to rowHeight.variant prop to GridList.actionPosition prop to position. (Note also the related classname changes.)Use CSS object-fit. For IE 11 support either use a polyfill such as
this npm package, or else continue to use the v4 component.
-import GridList from '@mui/material/GridList';
-import GridListTile from '@mui/material/GridListTile';
-import GridListTileBar from '@mui/material/GridListTileBar';
+import ImageList from '@mui/material/ImageList';
+import ImageListItem from '@mui/material/ImageListItem';
+import ImageListItemBar from '@mui/material/ImageListItemBar';
-<GridList spacing={8} cellHeight={200}>
- <GridListTile>
+<ImageList gap={8} rowHeight={200}>
+ <ImageListItem>
- <GridListTileBar
+ <ImageListItemBar
title="Title"
subtitle="Subtitle"
/>
- </GridListTile>
-</GridList>
+ </ImageListItem>
+</ImageList>
This component is deprecated because its functionality can be created with the sx prop or the useMediaQuery hook.
:::success
This is handled in the preset-safe codemod by applying fake Hidden component to prevent application crash, but further fixes are required.
:::
Use the sx prop to replace implementation="css":
-<Hidden implementation="css" xlUp><Paper /></Hidden>
-<Hidden implementation="css" xlUp><button /></Hidden>
+<Paper sx={{ display: { xl: 'none', xs: 'block' } }} />
+<Box component="button" sx={{ display: { xl: 'none', xs: 'block' } }} />
-<Hidden implementation="css" mdDown><Paper /></Hidden>
-<Hidden implementation="css" mdDown><button /></Hidden>
+<Paper sx={{ display: { xs: 'none', md: 'block' } }} />
+<Box component="button" sx={{ display: { xs: 'none', md: 'block' } }} />
Use the useMediaQuery hook to replace implementation="js":
-<Hidden implementation="js" xlUp><Paper /></Hidden>
+const hidden = useMediaQuery(theme => theme.breakpoints.up('xl'));
+return hidden ? null : <Paper />;
The default value of fontSize was changed from default to medium for consistency.
In the unlikely event that you were using the value default, the prop can be removed:
-<Icon fontSize="default">icon-name</Icon>
+<Icon>icon-name</Icon>
Padding for the default size has been reduced to 8px, bringing it down to 40px.
For the old default size of 48px, use size="large".
The change was made to better match Google's products when Material Design stopped documenting the icon button pattern.
- <IconButton>
+ <IconButton size="large">
The span element that wraps children has been removed.
The label classKey is also removed.
You can find out more details about this change in this GitHub pull request, it used to be necessary for iOS.
<button class="MuiIconButton-root">
- <span class="MuiIconButton-label">
<svg />
- </span>
</button>
The default underline prop is changed from "hover" to "always".
To recreate the behavior from v4, apply defaultProps in the theme.
:::success This is handled in link-underline-hover codemod—read the details before running this codemod. :::
createTheme({
components: {
MuiLink: {
defaultProps: {
underline: 'hover',
},
},
},
});
The on* transition props were removed.
Use TransitionProps instead.
<Menu
- onEnter={onEnter}
- onEntered={onEntered}
- onEntering={onEntering}
- onExit={onExit}
- onExited={onExited}
- onExiting={onExiting}
+ TransitionProps={{
+ onEnter,
+ onEntered,
+ onEntering,
+ onExit,
+ onExited,
+ onExiting,
+ }}
>
:::info
The selectedMenu variant will no longer vertically align the selected item with the anchor.
:::
Change the default value of anchorOrigin.vertical to follow the Material Design guidelines.
The menu is now displayed below the anchor instead of on top of it.
You can restore the previous behavior with:
<Menu
+ anchorOrigin={{
+ vertical: 'top',
+ horizontal: 'left',
+ }}
The MenuItem component inherits the ButtonBase component instead of ListItem.
The class names related to "MuiListItem-*" have been removed, and theming ListItem no longer has an effect on MenuItem.
-<li className="MuiButtonBase-root MuiMenuItem-root MuiListItem-root">
+<li className="MuiButtonBase-root MuiMenuItem-root">
prop listItemClasses is removed, use classes instead.
-<MenuItem listItemClasses={{...}}>
+<MenuItem classes={{...}}>
Read more about the MenuItem CSS API.
Remove the disableBackdropClick prop because it is redundant.
Use onClose with reason === 'backdropClick' instead.
<Modal
- disableBackdropClick
- onClose={handleClose}
+ onClose={(event, reason) => {
+ if (reason !== 'backdropClick') {
+ handleClose(event, reason);
+ }
+ }}
/>
onEscapeKeyDown propRemove the onEscapeKeyDown prop because it is redundant.
Use onClose with reason === "escapeKeyDown" instead.
<Modal
- onEscapeKeyDown={handleEscapeKeyDown}
+ onClose={(event, reason) => {
+ if (reason === 'escapeKeyDown') {
+ handleEscapeKeyDown(event);
+ }
+ }}
/>
onRendered propRemove the onRendered prop.
Depending on your use case, you can either use a callback ref on the child element, or an effect hook in the child component.
Merge the selectMenu slot into select.
The selectMenu slot was redundant.
The root slot is no longer applied to the select, but to the root.
-<NativeSelect classes={{ root: 'class1', select: 'class2', selectMenu: 'class3' }} />
+<NativeSelect classes={{ select: 'class1 class2 class3' }} />
Remove the labelWidth prop.
The label prop now fulfills the same purpose, using CSS layout instead of JavaScript measurement to render the gap in the outlined.
-<OutlinedInput labelWidth={20} />
+<OutlinedInput label="First Name" />
Change the background opacity based on the elevation in dark mode.
This change was made to better conform to the Material Design guidelines.
You can revert it in the theme:
const theme = createTheme({
components: {
MuiPaper: {
+ styleOverrides: { root: { backgroundImage: 'unset' } },
},
},
});
Move the component from the lab to the core.
The component is now stable.
-import Pagination from '@mui/lab/Pagination';
-import PaginationItem from '@mui/lab/PaginationItem';
-import { usePagination } from '@mui/lab/Pagination';
+import Pagination from '@mui/material/Pagination';
+import PaginationItem from '@mui/material/PaginationItem';
+import usePagination from '@mui/material/usePagination';
-<Pagination shape="round">
-<PaginationItem shape="round">
+<Pagination shape="circular">
+<PaginationItem shape="circular">
The on* transition props were removed.
Use TransitionProps instead.
<Popover
- onEnter={onEnter}
- onEntered={onEntered}
- onEntering={onEntering}
- onExit={onExit}
- onExited={onExited}
- onExiting={onExiting}
+ TransitionProps={{
+ onEnter,
+ onEntered,
+ onEntering,
+ onExit,
+ onExited,
+ onExiting,
+ }}
>
The getContentAnchorEl prop was removed to simplify the positioning logic.
Upgrade Popper.js from v1 to v2.
The CSS prefixes have changed:
popper: {
zIndex: 1,
- '&[x-placement*="bottom"] .arrow': {
+ '&[data-popper-placement*="bottom"] .arrow': {
Method names have changed:
-popperRef.current.scheduleUpdate()
+popperRef.current.update()
-popperRef.current.update()
+popperRef.current.forceUpdate()
The Modifiers API has been changed too significantly to fully cover here.
Read the Popper.js migration guide for complete details.
Remove the onRendered prop.
Depending on your use case, you can either use a callback ref on the child element, or an effect hook in the child component.
The radio color prop is now "primary" by default.
To continue using the "secondary" color, you must explicitly indicate secondary.
This brings the radio closer to the Material Design guidelines.
-<Radio />
+<Radio color="secondary" />
This component no longer has the class names .MuiIconButton-root or .MuiIconButton-label.
Instead, target .MuiButtonBase-root.
- <span class="MuiIconButton-root MuiButtonBase-root MuiRadio-root PrivateSwitchBase-root">
- <span class="MuiIconButton-label">
- <input class="PrivateSwitchBase-input">
+ <span class="MuiButtonBase-root MuiRadio-root PrivateSwitchBase-root">
+ <span class="PrivateSwitchBase-input">
Move the component from the lab to the core.
The component is now stable.
-import Rating from '@mui/lab/Rating';
+import Rating from '@mui/material/Rating';
Change the default empty icon to improve accessibility.
If you have a custom icon prop but no emptyIcon prop, you can restore the previous behavior with:
<Rating
icon={customIcon}
+ emptyIcon={null}
/>
Rename visuallyhidden to visuallyHidden for consistency:
<Rating
classes={{
- visuallyhidden: 'custom-visually-hidden-classname',
+ visuallyHidden: 'custom-visually-hidden-classname',
}}
/>
This component has been removed.
You can get a reference to the underlying DOM node of our components via ref prop.
The component relied on ReactDOM.findDOMNode which is deprecated in React.StrictMode.
:::success
This is handled in the preset-safe codemod by applying fake RootRef component to prevent application crash, but further fixes are required.
:::
-<RootRef rootRef={ref}>
- <Button />
-</RootRef>
+<Button ref={ref} />
Change the default variant from standard to outlined.
standard has been removed from the Material Design guidelines.
If you are composing the Select with a form control component, you only need to update FormControl—the select inherits the variant from its context.
:::success This is handled in variant-prop codemod—read the details before running this codemod. :::
-<Select value="Standard" />
-<Select value="Outlined" variant="outlined" />
+<Select value="Standard" variant="standard" />
+<Select value="Outlined" />
Remove the labelWidth prop.
The label prop now fulfills the same purpose, using the CSS layout instead of JavaScript measurements to render the gap in the outlined variant.
The TextField already handles this by default.
-<Select variant="outlined" labelWidth={20} />
+<Select variant="outlined" label="Gender" />
Merge the selectMenu slot into select.
The selectMenu slot was redundant.
The root slot is no longer applied to the select, but to the root.
-<Select classes={{ root: 'class1', select: 'class2', selectMenu: 'class3' }} />
+<Select classes={{ select: 'class1 class2 class3' }} />
The event in onChange is now typed as a SelectChangeEvent<T> instead of a React.ChangeEvent.
+ import Select, { SelectChangeEvent } from '@mui/material/Select';
-<Select onChange={(event: React.SyntheticEvent, value: unknown) => {}} />
+<Select onChange={(event: SelectChangeEvent<T>, child: React.ReactNode) => {}} />
This was necessary to prevent overriding the event.target of the events that caused the change.
Move the component from the lab to the core.
The component is now stable.
-import Skeleton from '@mui/lab/Skeleton';
+import Skeleton from '@mui/material/Skeleton';
Rename circle to circular and rect to rectangular for consistency:
-<Skeleton variant="circle" />
-<Skeleton variant="rect" />
-<Skeleton classes={{ circle: 'custom-circle-classname', rect: 'custom-rect-classname', }} />
+<Skeleton variant="circular" />
+<Skeleton variant="rectangular" />
+<Skeleton classes={{ circular: 'custom-circle-classname', rectangular: 'custom-rect-classname', }} />
The event in onChange is now typed as a React.SyntheticEvent instead of a React.ChangeEvent.
-<Slider onChange={(event: React.SyntheticEvent, value: unknown) => {}} />
+<Slider onChange={(event: Event, value: unknown) => {}} />
This was necessary to prevent overriding the event.target of the events that caused the change.
The ValueLabelComponent and ThumbComponent props are now part of the components prop.
<Slider
- ValueLabelComponent={CustomValueLabel}
- ThumbComponent={CustomThumb}
+ components={{
+ ValueLabel: CustomValueLabel,
+ Thumb: CustomThumb,
+ }}
/>
Rework the CSS to match the latest Material Design guidelines and make custom styles more intuitive. See documentation.
<a href="/material-ui/react-slider/#continuous-sliders"></a>
You can reduce the density of the slider, closer to v4 with the size="small" prop.
The notification now displays at the bottom left on large screens.
This better matches the behavior of Gmail, Google Keep, material.io, etc.
You can restore the v4 behavior with:
-<Snackbar />
+<Snackbar anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }} />
The on* transition props were removed.
Use TransitionProps instead.
<Snackbar
- onEnter={onEnter}
- onEntered={onEntered}
- onEntering={onEntering}
- onExit={onExit}
- onExited={onExited}
- onExiting={onExiting}
+ TransitionProps={{
+ onEnter,
+ onEntered,
+ onEntering,
+ onExit,
+ onExited,
+ onExiting,
+ }}
>
Move the component from the lab to the core.
The component is now stable.
-import SpeedDial from '@mui/lab/SpeedDial';
-import SpeedDialAction from '@mui/lab/SpeedDialAction';
-import SpeedDialIcon from '@mui/lab/SpeedDialIcon';
+import SpeedDial from '@mui/material/SpeedDial';
+import SpeedDialAction from '@mui/material/SpeedDialAction';
+import SpeedDialIcon from '@mui/material/SpeedDialIcon';
The root component Paper was replaced with a <div>.
Stepper no longer has elevation, and it does not inherit props from Paper anymore.
This change is meant to encourage composition.
+<Paper square elevation={2}>
- <Stepper elevation={2}>
+ <Stepper>
<Step>
<StepLabel>Hello world</StepLabel>
</Step>
</Stepper>
+<Paper>
The built-in 24px padding has been removed.
To keep it intact, add the following:
-<Stepper>
+<Stepper style={{ padding: 24 }}>
<Step>
<StepLabel>Hello world</StepLabel>
</Step>
</Stepper>
The default value of fontSize was changed from default to medium for consistency.
In the unlikely event that you were using the value default, the prop can be removed:
-<SvgIcon fontSize="default">
+<SvgIcon>
<path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z" />
</SvgIcon>
The second argument from onChange has been deprecated.
You can pull out the checked state by accessing event.target.checked.
function MySwitch() {
- const handleChange = (event: React.ChangeEvent<HTMLInputElement>, checked: boolean) => {
+ const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
+ const checked = event.target.checked;
};
return <Switch onChange={handleChange} />;
}
The color prop is now "primary" by default.
To continue using the "secondary" color, you must explicitly indicate secondary.
This brings Switch closer to the Material Design guidelines.
-<Switch />
+<Switch color="secondary" />
This component no longer has the .MuiIconButton-root and .MuiIconButton-label.
Instead, target .MuiButtonBase-root.
<span class="MuiSwitch-root">
- <span class="MuiIconButton-root MuiButtonBase-root MuiSwitch-switchBase PrivateSwitchBase-root">
- <span class="MuiIconButton-label">
- <input class="MuiSwitch-input PrivateSwitchBase-input">
+ <span class="MuiButtonBase-root MuiSwitch-switchBase PrivateSwitchBase-root">
+ <span class="MuiSwitch-input PrivateSwitchBase-input">
Rename the default value of the padding prop to normal.
-<Table padding="default" />
-<TableCell padding="default" />
+<Table padding="normal" />
+<TableCell padding="normal" />
The customization of the table pagination's actions labels must be done with the getItemAriaLabel prop.
This increases consistency with the Pagination component.
<TablePagination
- backIconButtonText="Back"
- nextIconButtonText="Next"
+ getItemAriaLabel={…}
Rename onChangeRowsPerPage to onRowsPerPageChange and onChangePage to onPageChange for API consistency.
<TablePagination
- onChangeRowsPerPage={()=>{}}
- onChangePage={()=>{}}
+ onRowsPerPageChange={()=>{}}
+ onPageChange={()=>{}}
Separate classes for different table pagination labels.
<TablePagination
- classes={{ caption: 'foo' }}
+ classes={{ selectLabel: 'foo', displayedRows: 'foo' }}
/>
Move the custom class on input to select.
The input key is applied on another element.
<TablePagination
- classes={{ input: 'foo' }}
+ classes={{ select: 'foo' }}
/>
Change the default indicatorColor and textColor prop values to "primary".
This is done to match the most common use cases with Material Design.
If you'd prefer to keep the v4 color styles, use "secondary" and "inherit", respectively, as shown below:
-<Tabs />
+<Tabs indicatorColor="secondary" textColor="inherit" />
The event in onChange is now typed as a React.SyntheticEvent instead of a React.ChangeEvent.
-<Tabs onChange={(event: React.ChangeEvent<{}>, value: unknown) => {}} />
+<Tabs onChange={(event: React.SyntheticEvent, value: unknown) => {}} />
The API that controls the scroll buttons has been split into two props.
scrollButtons prop controls when the scroll buttons are displayed depending on the space available.allowScrollButtonsMobile prop removes the CSS media query that systematically hides the scroll buttons on mobile.-<Tabs scrollButtons="on" />
-<Tabs scrollButtons="desktop" />
-<Tabs scrollButtons="off" />
+<Tabs scrollButtons allowScrollButtonsMobile />
+<Tabs scrollButtons />
+<Tabs scrollButtons={false} />
Default minimum and maximum widths have been changed to match the Material Design specifications:
minWidth was changed from 72px to 90px.maxWidth was changed from 264px to 360px.The span element that wraps children has been removed.
The wrapper classKey is also removed.
You can find out more details about this change in this GitHub pull request.
<button class="MuiTab-root">
- <span class="MuiTab-wrapper">
{icon}
{label}
- </span>
</button>
Change the default variant from standard to outlined.
standard has been removed from the Material Design guidelines.
:::success This is handled in variant-prop codemod—read the details before running this codemod. :::
-<TextField value="Standard" />
-<TextField value="Outlined" variant="outlined" />
+<TextField value="Standard" variant="standard" />
+<TextField value="Outlined" />
Rename rowsMax prop to maxRows for consistency with HTML attributes.
-<TextField rowsMax={6}>
+<TextField maxRows={6}>
Rename rows prop to minRows for dynamic resizing.
You need to use the minRows prop in the following case:
-<TextField rows={2} maxRows={5} />
+<TextField minRows={2} maxRows={5} />
Change ref forwarding expectations on custom inputComponent.
The component should forward the ref prop instead of the inputRef prop.
-function NumberFormatCustom(props) {
- const { inputRef, onChange, ...other } = props;
+const NumberFormatCustom = React.forwardRef(function NumberFormatCustom(
+ props,
+ ref,
+) {
const { onChange, ...other } = props;
return (
<NumberFormat
{...other}
- getInputRef={inputRef}
+ getInputRef={ref}
Rename marginDense and inputMarginDense classes to sizeSmall and inputSizeSmall to match the prop.
-<Input margin="dense" />
+<Input size="small" />
Set the InputAdornment position prop to start or end.
Use start if used as the value of the startAdornment prop.
Use end if used as the value of the endAdornment prop.
-<TextField startAdornment={<InputAdornment>kg</InputAdornment>} />
-<TextField endAdornment={<InputAdornment>kg</InputAdornment>} />
+<TextField startAdornment={<InputAdornment position="start">kg</InputAdornment>} />
+<TextField endAdornment={<InputAdornment position="end">kg</InputAdornment>} />
Remove the rows prop, use the minRows prop instead.
This change aims to clarify the behavior of the prop.
-<TextareaAutosize rows={2} />
+<TextareaAutosize minRows={2} />
Rename rowsMax prop to maxRows for consistency with HTML attributes.
-<TextareaAutosize rowsMax={6}>
+<TextareaAutosize maxRows={6}>
Rename rowsMin prop with minRows for consistency with HTML attributes.
-<TextareaAutosize rowsMin={1}>
+<TextareaAutosize minRows={1}>
Move the component from the lab to the core.
The component is now stable.
-import ToggleButton from '@mui/lab/ToggleButton';
-import ToggleButtonGroup from '@mui/lab/ToggleButtonGroup';
+import ToggleButton from '@mui/material/ToggleButton';
+import ToggleButtonGroup from '@mui/material/ToggleButtonGroup';
The span element that wraps children has been removed.
The label classKey is also removed.
You can find out more details about this change in this GitHub pull request.
<button class="MuiToggleButton-root">
- <span class="MuiToggleButton-label">
{children}
- </span>
</button>
Tooltips are now interactive by default.
The previous default behavior failed the success criterion 1.4.3 ("hoverable") in WCAG 2.1.
To reflect the new default value, the prop was renamed to disableInteractive.
If you want to restore the v4 behavior, you can apply the following diff:
-<Tooltip>
+<Tooltip disableInteractive>
# Interactive tooltips no longer need the `interactive` prop.
-<Tooltip interactive>
+<Tooltip>
Remove the srOnly variant.
You can use the visuallyHidden utility in conjunction with the sx prop instead.
+import { visuallyHidden } from '@mui/utils';
-<Typography variant="srOnly">Create a user</Typography>
+<span style={visuallyHidden}>Create a user</span>
The following classes and style overrides keys were removed:
"colorInherit", "colorPrimary", "colorSecondary", "colorTextPrimary", "colorTextSecondary", "colorError", "displayInline", and "displayBlock".
These props are now considered part of MUISystem rather than the Typography component itself.
If you still wish to add overrides for them, you can use the callback as a value in styleOverrides.
For example:
const theme = createTheme({
components: {
MuiTypography: {
- styleOverrides: {
- colorSecondary: {
- marginTop: '20px',
- },
- },
+ styleOverrides: ({ ownerState }) => ({
+ ...ownerState.color === 'secondary' && {
+ marginTop: '20px',
+ },
+ }),
},
},
});
The default background color is now #fff in light mode and #121212 in dark mode.
This matches the Material Design guidelines.
Breakpoints are now treated as values instead of ranges.
The behavior of down(key) was changed to define a media query below the value defined by the corresponding breakpoint (exclusive), rather than the breakpoint above.
between(start, end) was also updated to define a media query for the values between the actual start (inclusive) and end (exclusive) values.
When using the down() breakpoints utility, you need to update the breakpoint key by one step up.
When using between(start, end), the end breakpoint should also be updated by one step up.
Here are some examples of the changes required:
-theme.breakpoints.down('sm') // '@media (max-width:959.95px)' - [0, sm + 1) => [0, md)
+theme.breakpoints.down('md') // '@media (max-width:959.95px)' - [0, md)
-theme.breakpoints.between('sm', 'md') // '@media (min-width:600px) and (max-width:1279.95px)' - [sm, md + 1) => [0, lg)
+theme.breakpoints.between('sm', 'lg') // '@media (min-width:600px) and (max-width:1279.95px)' - [0, lg)
-theme.breakpoints.between('sm', 'xl') // '@media (min-width:600px)'
+theme.breakpoints.up('sm') // '@media (min-width:600px)'
The same should be done when using the Hidden component:
-<Hidden smDown>{...}</Hidden> // '@media (min-width:600px)'
+<Hidden mdDown>{...}</Hidden> // '@media (min-width:600px)'
The default breakpoints were changed to better match common use cases as well as the Material Design guidelines.
You can find out more details about this change in this GitHub issue
{
xs: 0,
sm: 600,
- md: 960,
+ md: 900,
- lg: 1280,
+ lg: 1200,
- xl: 1920,
+ xl: 1536,
}
If you prefer the old breakpoint values, use the snippet below:
import { createTheme } from '@mui/material/styles';
const theme = createTheme({
breakpoints: {
values: {
xs: 0,
sm: 600,
md: 960,
lg: 1280,
xl: 1920,
},
},
});
The theme.breakpoints.width utility has been removed because it was redundant.
Use theme.breakpoints.values to get the same values.
-theme.breakpoints.width('md')
+theme.breakpoints.values.md
The signature of theme.palette.augmentColor helper has changed:
-theme.palette.augmentColor(red);
+theme.palette.augmentColor({ color: red, name: 'brand' });
The theme.typography.round helper was removed because it was no longer used.
If you need it, use the function below:
function round(value) {
return Math.round(value * 1e5) / 1e5;
}
The module is now called DistributiveOmit.
This change removes the confusion with the built-in Omit helper introduced in TypeScript v3.5.
The built-in Omit, while similar, is non-distributive.
This leads to differences when applied to union types.
See this Stack Overflow answer for further details.
-import { Omit } from '@mui/types';
+import { DistributiveOmit } from '@mui/types';