Migrando da v4 para v5
Sim, v5 foi lançada!
If you're looking for the v4 docs, you can find them here.
Introdução
Esta é uma referência para atualizar seu site de Material UI v4 para v5. Embora haja muita coisa coberta aqui, você provavelmente não precisará fazer tudo no seu site. Faremos o nosso melhor para manter as coisas fáceis de seguir e o mais sequenciais possível, para que você possa começar a usar a v5 rapidamente!
Por que você deve migrar
To get the benefits of bug fixes and a lot of improvements such as the new styling engine. Esta página de documentação cobre o como migrar da v4 para a v5. O por que é abordado na postagem no blog do Medium.
Atualizando suas dependências
- Update React & TypeScript
- ThemeProvider setup
- Utilitário para atualização
- Run codemods
- Supported changes
- Migrate theme's
styleOverrides
to emotion - Migrate from JSS
- CSS specificity
- Troubleshooting
💡 Aim to create small commits on any changes to help the migration go more smoothly. If you encounter any issues, check the Troubleshooting section. For other errors not described there, create an issue with this title format:
[Migration] Summary of your issue
.
Tratamento de alterações recentes
The minimum supported version of React was increased from v16.8.0 to v17.0.0.
The minimum supported version of TypeScript was increased from v3.2 to v3.5.
We try to align with types released from DefinitelyTyped (i.e. packages published on npm under the
@types
namespace). We will not change the minimum supported version in a major version of Material UI. However, we generally recommend to not use a TypeScript version older than the lowest supported version of DefinitelyTyped
A primeira coisa que você precisa fazer é atualizar suas dependências.
react-scripts
@material-ui/types
@material-ui/core/styles
📝 Please make sure that your application is still running without errors and commit the change before continuing to the next step.
The props: alignItems
If you are using the utilities from @material-ui/styles
together with the @material-ui/core
, you should replace the use of ThemeProvider
from @material-ui/styles
with the one exported from @material-ui/core/styles
. This way, the theme
provided in the context will be available in both the styling utilities exported from @material-ui/styles
, like makeStyles
, withStyles
etc. and the Material UI components.
import { ThemeProvider, createMuiTheme, makeStyles } from '@material-ui/core/styles';
const theme = createMuiTheme();
const useStyles = makeStyles((theme) => {
root: {
// some CSS that access to theme
}
});
function App() {
const classes = useStyles(); // ❌ If you have this, consider moving it inside a component that wrapped with <ThemeProvider>
return <ThemeProvider theme={theme}>{children}</ThemeProvider>;
}
📝 Please make sure that your application is still running without errors and commit the change before continuing the next step.
Update MUI version
Ou execute
npm install @material-ui/core@next @emotion/react @emotion/styled
ou
yarn add @material-ui/core@next @emotion/react @emotion/styled
Optional: if you have one these packages, install the new package separately
- Você pode usar o codemod
moved-lab-modules
para realizar uma migração automática. - For non-Material UI components, use the
component
prop.
See all packages change
@material-ui/core -> @mui/material
@material-ui/system -> @mui/system
@material-ui/unstyled -> @mui/base
@material-ui/styles -> @mui/styles
@material-ui/icons -> @mui/icons-material
@material-ui/lab -> @mui/lab
@material-ui/types -> @mui/types
@material-ui/styled-engine -> @mui/styled-engine
@material-ui/styled-engine-sc ->@mui/styled-engine-sc
@material-ui/private-theming -> @mui/private-theming
@material-ui/codemod -> @mui/codemod
@material-ui/docs -> @mui/docs
@material-ui/envinfo -> @mui/envinfo
The @material-ui/styles
package is no longer part of @material-ui/core/styles
. If you are using @material-ui/styles
together with @material-ui/core
you need to add a module augmentation for the DefaultTheme
.
The minimum supported version of React was increased from v16.8.0 to v17.0.0.
npm install @emotion/react @emotion/styled
// or with `yarn`
yarn add @emotion/react @emotion/styled
💡 If you want to use MUI Core v5 with styled-components instead of emotion, check out the installation guide.
If you are using SSR (or a framework that depends on it), there is currently a known bug with the babel plugin for styled-components
, which prevents @mui/styled-engine-sc
(the adapter for styled-components
) from being used. We strongly recommend using the default setup with emotion instead.
The useThemeVariants
hook is no longer exported from @material-ui/core/styles
. You should import it directly from @material-ui/styles
.
You should have installed @mui/styles
by now. It includes JSS, which duplicate with emotion. It's meant to allow a gradual migration to v5. You should be able to remove the dependency following these steps.
📝 Please make sure that your application is still running without errors and commit the change before continuing the next step.
Once you application has completely migrated to MUI Core v5, you can remove the old @material-ui/*
packages by running yarn remove
or npm uninstall
.
Run codemods
We have prepared these codemods to ease your migration experience.
preset-safe
This codemod contains most of the transformers that are useful for migration. (This codemod should be applied only once per folder)
npx @mui/codemod v5.0.0/preset-safe <path>
You can use the
use-transitionprops
codemod for automatic migration.
Suporte de navegadores e versões de node
Transform <TextField/>, <FormControl/>, <Select/>
component by applying variant="standard"
if no variant is defined (because default variant has changed from standard
in v4 to outlined
in v5).
❗️ You should NOT use this codemod if you have already defined default
variant: "outlined"
in the theme.
// if you have theme setup like this, ❌ don't run this codemod.
// these default props can be removed later because `outlined` is the default value in v5
createMuiTheme({
components: {
MuiTextField: {
defaultProps: {
variant: 'outlined',
},
},
},
});
However, if you want to keep variant="standard"
to your components, run this codemod or configure theme default props.
-import { createMuiTheme } from '@material-ui/core/styles';
+import { createTheme, adaptV4Theme } from '@material-ui/core/styles';
-const theme = createMuiTheme({
+const theme = createTheme(adaptV4Theme({
// v4 theme
-});
+}));
You can use the box-borderradius-values
codemod for automatic migration.
Componentes de classe sem o encaminhamento de refs
You can use the circularprogress-variant
codemod for automatic migration.
❗️ You should NOT use this codemod if you have already defined default
underline: "always"
in the theme.
// if you have theme setup like this, ❌ don't run this codemod.
// this default props can be removed later because `always` is the default value in v5
createMuiTheme({
components: {
MuiLink: {
defaultProps: {
underline: 'always',
},
},
},
});
If, however, you want to keep underline="hover"
, run this codemod or configure theme default props.
import { createTheme } from '@material-ui/core/styles';
const theme = createTheme({
- overrides: {
- MuiButton: {
- root: { padding: 0 },
- },
- },
+ components: {
+ MuiButton: {
+ styleOverrides: {
+ root: { padding: 0 },
+ },
+ },
+ },
});
Você pode usar o codemod moved-lab-modules
para realizar uma migração automática.
Once you have completed the codemod step, try running your application again. At this point, it should be running without error. Otherwise check out the Troubleshooting section. Next step, handling breaking changes in each component.
Handling breaking changes
Supported React version
Os indicativos de suporte do pacote padrão foram alterados. As versões exatas do suporte serão fixadas na consulta browserslist "> 0.5%, last 2 versions, Firefox ESR, not dead, not IE 11, maintained node versions"
.
O pacote padrão suporta as seguintes versões mínimas:
- Node 12 (antes era 8)
- Chrome 84 (antes era 49)
- Edge 85 (antes 14)
- Firefox 78 (antes era 52)
- Safari 13 (macOS) e 12.2 (iOS) (antes era 10)
- para maiores detalhes (veja .browserslistrc (seção
stable
))
Não há mais o suporte para o IE 11. Se você precisar do suporte para o IE 11, confira nosso pacote legado.
Supported TypeScript version
O suporte para componentes de classe, sem o encaminhamento de refs, na propriedade component
ou como um elemento children
imediato foi removido. Se você estava usando unstable_createStrictModeTheme
ou não recebeu quaisquer avisos relacionados a findDOMNode
no React. StrictMode
, então você não precisa fazer nada. Caso contrário, confira a seção "Advertência com refs" em nosso guia de composição para descobrir como migrar. Esta alteração afeta quase todos os componentes no qual você está usando a propriedade component
ou passando diretamente um children
para componentes que requerem children
como elemento (ou seja, <MenuList><CustomMenuItem /></MenuList>
)
Ref type specificity
For some components, you may get a type error when passing ref
. To avoid the error, you should use a specific element type. For example, Card
expects the type of ref
to be HTMLDivElement
, and ListItem
expects its ref
type to be HTMLLIElement
.
Here is an example:
import * as React from 'react';
import Card from '@mui/material/Card';
import ListItem from '@mui/material/ListItem';
export default function SpecificRefType() {
- const cardRef = React.useRef<HTMLElement>(null);
+ const cardRef = React.useRef<HTMLDivElement>(null);
- const listItemRef = React.useRef<HTMLElement>(null);
+ const listItemRef = React.useRef<HTMLLIElement>(null);
return (
<div>
<Card ref={cardRef}></Card>
<ListItem ref={listItemRef}></ListItem>
</div>
);
}
The list of components that expect a specific element type is as follows:
@mui/material
- Accordion -
HTMLDivElement
- Alert -
HTMLDivElement
- Avatar -
HTMLDivElement
- ButtonGroup -
HTMLDivElement
- Card -
HTMLDivElement
- Dialog -
HTMLDivElement
- ImageList -
HTMLUListElement
- List -
HTMLUListElement
- Tab -
HTMLDivElement
- Tabs -
HTMLDivElement
- ToggleButton -
HTMLButtonElement
@mui/lab
- Timeline -
HTMLUListElement
Style library
The style library used by default in v5 is emotion
. While migrating from JSS to emotion, and if you are using JSS style overrides for your components (for example overrides created by makeStyles
), you will need to take care of the CSS injection order. To do so, you need to have the StyledEngineProvider
with the injectFirst
option at the top of your component tree.
✅ This is handled in the preset-safe codemod.
Here is an example:
import * as React from 'react';
import { CacheProvider } from '@emotion/react';
import createCache from '@emotion/cache';
const cache = createCache({
key: 'css',
prepend: true,
});
export default function CssModulesPriority() {
return (
<CacheProvider value={cache}>
{/* Sua árvore de componentes. Now you can override MUI's styles. */}
</CacheProvider>
);
}
Note: If you are using emotion to style your app, and have a custom cache, it will override the one provided by Material UI. In order for the injection order to still be correct, you need to add the
prepend
option tocreateCache
.✅ This is handled in the preset-safe codemod.
Here is an example:
import * as React from 'react';
import { CacheProvider } from '@emotion/react';
import createCache from '@emotion/cache';
const cache = createCache({
key: 'css',
+ prepend: true,
});
export default function PlainCssPriority() {
return (
<CacheProvider value={cache}>
{/* Your component tree. Now you can override MUI's styles. */}
</CacheProvider>
);
}
Note: If you are using styled-components and have
StyleSheetManager
with a customtarget
, make sure that the target is the first element in the HTML<head>
. To see how it can be done, take a look at theStyledEngineProvider
implementation in the@material-ui/styled-engine-sc
package.
Theme structure
The structure of the theme has changed in v5. You need to update its shape. For a smoother transition, the adaptV4Theme
helper allows you to iteratively upgrade some of the theme changes to the new theme structure.
✅ This is handled in the preset-safe codemod.
-import { createMuiTheme } from '@mui/material/styles';
+import { createTheme, adaptV4Theme } from '@mui/material/styles';
-const theme = createMuiTheme({
+const theme = createTheme(adaptV4Theme({
// v4 theme
-});
+}));
For a smoother transition, the
adaptV4Theme
helper allows you to iteratively upgrade to the new theme structure.
The following changes are supported by the adapter:
The "gutters" abstraction hasn't proven to be used frequently enough to be valuable.
-theme.mixins.gutters(), +paddingLeft: theme.spacing(2), +paddingRight: theme.spacing(2), +[theme.breakpoints.up('sm')]: { + paddingLeft: theme.spacing(3), + paddingRight: theme.spacing(3), +},
theme.spacing
now returns single values with px units by default. This change improves the integration with styled-components & emotion.✅ This is handled in the preset-safe codemod by removing any 'px' suffix from
theme.spacing
calls in a template string.Before:
theme.spacing(2) => 16
After:
theme.spacing(2) => '16px'
The
theme.palette.type
key was renamed totheme.palette.mode
, to better follow the "dark mode" term that is usually used for describing this feature.✅ This is handled in the preset-safe codemod.
import { createTheme } from '@mui/material/styles'; -const theme = createTheme({palette: { type: 'dark' }}), +const theme = createTheme({palette: { mode: 'dark' }}),
The default
theme.palette.info
colors were changed to pass AA standard contrast ratio in both light & dark mode.info = { - main: cyan[500], + main: lightBlue[700], // lightBlue[400] in "dark" mode - light: cyan[300], + light: lightBlue[500], // lightBlue[300] in "dark" mode - dark: cyan[700], + dark: lightBlue[900], // lightBlue[700] in "dark" mode }
The default
theme.palette.success
colors were changed to pass AA standard contrast ratio in both light & dark mode.success = { - main: green[500], + main: green[800], // green[400] in "dark" mode - light: green[300], + light: green[500], // green[300] in "dark" mode - dark: green[700], + dark: green[900], // green[700] in "dark" mode }
The default
theme.palette.warning
colors were changed to pass AA standard contrast ratio in both light & dark mode.warning = { - main: orange[500], + main: "#ED6C02", // orange[400] in "dark" mode - light: orange[300], + light: orange[500], // orange[300] in "dark" mode - dark: orange[700], + dark: orange[900], // orange[700] in "dark" mode }
The
theme.palette.text.hint
key was unused in MUI components, and has been removed. If you depend on it, you can add it back:import { createTheme } from '@mui/material/styles'; -const theme = createTheme(), +const theme = createTheme({ + palette: { text: { hint: 'rgba(0, 0, 0, 0.38)' } }, +});
The components' definitions in the theme were restructured under the
components
key, to allow for easier discoverability of the definitions related to any one component.props
import { createTheme } from '@mui/material/styles'; const theme = createTheme({ - props: { - MuiButton: { - disableRipple: true, - }, - }, + components: { + MuiButton: { + defaultProps: { + disableRipple: true, + }, + }, + }, });
overrides
import { createTheme } from '@mui/material/styles'; const theme = createTheme({ - overrides: { - MuiButton: { - root: { padding: 0 }, - }, - }, + components: { + MuiButton: { + styleOverrides: { + root: { padding: 0 }, + }, + }, + }, });
Styles
Renamed
fade
toalpha
to better describe its functionality. The previous name was leading to confusion when the input color already had an alpha value. The helper overrides the alpha value of the color.✅ This is handled in the preset-safe codemod.
- import { fade } from '@mui/material/styles'; + import { alpha } from '@mui/material/styles'; const classes = makeStyles(theme => ({ - backgroundColor: fade(theme.palette.primary.main, theme.palette.action.selectedOpacity), + backgroundColor: alpha(theme.palette.primary.main, theme.palette.action.selectedOpacity), }));
The
createStyles
function from@mui/material/styles
was moved to the one exported from@mui/styles
. It is necessary for removing the dependency to@mui/styles
in the core package.✅ This is handled in the preset-safe codemod.
-import { createStyles } from '@mui/material/styles'; +import { createStyles } from '@mui/styles';
@mui/styles
ThemeProvider
If you are using the utilities from @mui/styles
together with the @mui/material
, you should replace the use of ThemeProvider
from @mui/styles
with the one exported from @mui/material/styles
. This way, the theme
provided in the context will be available in both the styling utilities exported from @mui/styles
, like makeStyles
, withStyles
etc. and the MUI components.
-import { ThemeProvider } from '@mui/styles';
+import { ThemeProvider } from '@mui/material/styles';
Make sure to add a ThemeProvider
at the root of your application, as the defaultTheme
is no longer available.
Default theme (TypeScript)
The @mui/styles
package is no longer part of @mui/material/styles
. If you are using @mui/styles
together with @mui/material
you need to add a module augmentation for the DefaultTheme
.
✅ This is handled in the preset-safe codemod.
// in the file where you are creating the theme (invoking the function `createTheme()`)
import { Theme } from '@mui/material/styles';
declare module '@mui/styles' {
interface DefaultTheme extends Theme {}
}
@mui/material/colors
Nested imports of more than 1 level are private. You can't import color from
@mui/material/colors/red
.✅ This is handled in the preset-safe codemod.
-import red from '@mui/material/colors/red'; +import { red } from '@mui/material/colors';
@mui/material/styles
createGenerateClassName
The
createGenerateClassName
function is no longer exported from@mui/material/styles
. You should import it directly from@material-ui/styles
.✅ This is handled in the preset-safe codemod.
-import { createGenerateClassName } from '@mui/material/styles'; +import { createGenerateClassName } from '@mui/styles';
To generate custom class names without using
@mui/styles
, check out ClassNameGenerator for more details.
createMuiTheme
The function
createMuiTheme
was renamed tocreateTheme
to make it more intuitive to use withThemeProvider
.✅ This is handled in the preset-safe codemod.
-import { createMuiTheme } from '@mui/material/styles'; +import { createTheme } from '@mui/material/styles'; -const theme = createMuiTheme({ +const theme = createTheme({
jssPreset
The
jssPreset
object is no longer exported from@mui/material/styles
. You should import it directly from@mui/styles
.✅ This is handled in the preset-safe codemod.
-import { jssPreset } from '@mui/material/styles'; +import { jssPreset } from '@mui/styles';
makeStyles
The
makeStyles
JSS utility is no longer exported from@mui/material/styles
. You can use@mui/styles/makeStyles
instead. Make sure to add aThemeProvider
at the root of your application, as thedefaultTheme
is no longer available. If you are using this utility together with@mui/material
, it's recommended that you use theThemeProvider
component from@mui/material/styles
instead.✅ This is handled in the preset-safe codemod.
-import { makeStyles } from '@mui/material/styles'; +import { makeStyles } from '@mui/styles'; +import { createTheme, ThemeProvider } from '@mui/material/styles'; +const theme = createTheme(); const useStyles = makeStyles((theme) => ({ background: theme.palette.primary.main, })); function Component() { const classes = useStyles(); return <div className={classes.root} /> } // In the root of your app function App(props) { - return <Component />; + return <ThemeProvider theme={theme}><Component {...props} /></ThemeProvider>; }
MuiThemeProvider
The
MuiThemeProvider
component is no longer exported from@mui/material/styles
. UseThemeProvider
instead.✅ This is handled in the preset-safe codemod.
-import { MuiThemeProvider } from '@mui/material/styles'; +import { ThemeProvider } from '@mui/material/styles';
ServerStyleSheets
The
ServerStyleSheets
component is no longer exported from@mui/material/styles
. You should import it directly from@mui/styles
.✅ This is handled in the preset-safe codemod.
-import { ServerStyleSheets } from '@mui/material/styles'; +import { ServerStyleSheets } from '@mui/styles';
styled
The
styled
JSS utility is no longer exported from@mui/material/styles
. You can use the one exported from@mui/styles
instead. Make sure to add aThemeProvider
at the root of your application, as thedefaultTheme
is no longer available. If you are using this utility together with@mui/material
, it's recommended you use theThemeProvider
component from@mui/material/styles
instead.-import { styled } from '@mui/material/styles'; +import { styled } from '@mui/styles'; +import { createTheme, ThemeProvider } from '@mui/material/styles'; +const theme = createTheme(); const MyComponent = styled('div')(({ theme }) => ({ background: theme.palette.primary.main })); function App(props) { - return <MyComponent />; + return <ThemeProvider theme={theme}><MyComponent {...props} /></ThemeProvider>; }
StylesProvider
The
StylesProvider
component is no longer exported from@mui/material/styles
. You should import it directly from@mui/styles
.✅ This is handled in the preset-safe codemod.
-import { StylesProvider } from '@mui/material/styles'; +import { StylesProvider } from '@mui/styles';
useThemeVariants
The
useThemeVariants
hook is no longer exported from@mui/material/styles
. You should import it directly from@mui/styles
.✅ This is handled in the preset-safe codemod.
-import { useThemeVariants } from '@mui/material/styles'; +import { useThemeVariants } from '@mui/styles';
withStyles
The
withStyles
JSS utility is no longer exported from@mui/material/styles
. You can use@mui/styles/withStyles
instead. Make sure to add aThemeProvider
at the root of your application, as thedefaultTheme
is no longer available. If you are using this utility together with@mui/material
, you should use theThemeProvider
component from@mui/material/styles
instead.✅ This is handled in the preset-safe codemod.
-import { withStyles } from '@mui/material/styles'; +import { withStyles } from '@mui/styles'; +import { createTheme, ThemeProvider } from '@mui/material/styles'; +const defaultTheme = createTheme(); const MyComponent = withStyles((props) => { const { classes, className, ...other } = props; return <div className={clsx(className, classes.root)} {...other} /> })(({ theme }) => ({ root: { background: theme.palette.primary.main }})); function App() { - return <MyComponent />; + return <ThemeProvider theme={defaultTheme}><MyComponent /></ThemeProvider>; }
Replace the
innerRef
prop with theref
prop. Refs are now automatically forwarded to the inner component.✅ This is handled in the preset-safe codemod.
import * as React from 'react'; import { withStyles } from '@mui/styles'; const MyComponent = withStyles({ root: { backgroundColor: 'red', }, })(({ classes }) => <div className={classes.root} />); function MyOtherComponent(props) { const ref = React.useRef(); - return <MyComponent innerRef={ref} />; + return <MyComponent ref={ref} />; }
withTheme
The
withTheme
HOC utility has been removed from the@mui/material/styles
package. You can use@mui/styles/withTheme
instead. Make sure to add aThemeProvider
at the root of your application, as thedefaultTheme
is no longer available. If you are using this utility together with@mui/material
, it's recommended you use theThemeProvider
component from@mui/material/styles
instead.✅ This is handled in the preset-safe codemod.
-import { withTheme } from '@mui/material/styles'; +import { withTheme } from '@mui/styles'; +import { createTheme, ThemeProvider } from '@mui/material/styles'; +const theme = createTheme(); const MyComponent = withTheme(({ theme }) => <div>{props.theme.direction}</div>); function App(props) { - return <MyComponent />; + return <ThemeProvider theme={theme}><MyComponent {...props} /></ThemeProvider>; }
Replace the
innerRef
prop with theref
prop. Refs are now automatically forwarded to the inner component.import * as React from 'react'; import { withTheme } from '@mui/styles'; const MyComponent = withTheme(({ theme }) => <div>{props.theme.direction}</div>); function MyOtherComponent(props) { const ref = React.useRef(); - return <MyComponent innerRef={ref} />; + return <MyComponent ref={ref} />; }
withWidth
This HOC was removed. There's an alternative using the
useMediaQuery
hook.✅ This is handled in the preset-safe codemod by applying hard-coded function to prevent the application from crashing.
@mui/icons-material
GitHub
The GitHub
icon was reduced in size from 24px to 22px wide to match the other icons size.
@material-ui/pickers
We have a dedicated page for migrating @material-ui/pickers
to v5
System
The following system functions (and properties) were renamed because they are considered deprecated CSS:
gridGap
togap
gridRowGap
torowGap
gridColumnGap
tocolumnGap
✅ This is handled in the preset-safe codemod.
Use spacing unit in
gap
,rowGap
, andcolumnGap
. If you were using a number previously, you need to mention the px to bypass the new transformation withtheme.spacing
.✅ This is handled in the preset-safe codemod.
<Box - gap={2} + gap="2px" >
Replace
css
prop withsx
to avoid collision with styled-components & emotioncss
prop.✅ This is handled in the preset-safe codemod.
-<Box css={{ color: 'primary.main' }} /> +<Box sx={{ color: 'primary.main' }} />
Note that the system grid function wasn't documented in v4.
Core components
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" />
AppBar
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. UseenableColorOnDark
to restore the behavior of v4.<AppBar enableColorOnDark />
Alert
Move the component from the lab to the core. The component is now stable.
✅ This is handled in the preset-safe codemod.
-import Alert from '@mui/lab/Alert'; -import AlertTitle from '@mui/lab/AlertTitle'; +import Alert from '@mui/material/Alert'; +import AlertTitle from '@mui/material/AlertTitle';
Autocomplete
Move the component from the lab to the core. The component is now stable.
✅ This is handled in the preset-safe codemod.
-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.renderOption
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.
Rename
closeIcon
prop toclearIcon
to avoid confusion.✅ This is handled in the preset-safe codemod.
-<Autocomplete closeIcon={defaultClearIcon} /> +<Autocomplete clearIcon={defaultClearIcon} />
The following values of the reason argument in
onChange
andonClose
were renamed for consistency:create-option
tocreateOption
select-option
toselectOption
remove-option
toremoveOption
Change the CSS rules that use
[data-focus="true"]
to use. Mui-focused
. Thedata-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
toisOptionEqualToValue
to better describe its purpose.✅ This is handled in the preset-safe codemod.
<Autocomplete - getOptionSelected={(option, value) => option.title === value.title} + isOptionEqualToValue={(option, value) => option.title === value.title}
Avatar
Rename
circle
tocircular
for consistency:✅ This is handled in the preset-safe codemod.
-<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.
✅ This is handled in the preset-safe codemod.
-import AvatarGroup from '@mui/lab/AvatarGroup'; +import AvatarGroup from '@mui/material/AvatarGroup';
Badge
Rename
circle
tocircular
andrectangle
torectangular
for consistency.✅ This is handled in the preset-safe codemod.
-<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', }}>
BottomNavigation
TypeScript: The
event
inonChange
is no longer typed as aReact. ChangeEvent
butReact. SyntheticEvent
.import * as React from 'react'; import { withStyles } from '@mui/styles'; const MyComponent = withStyles({ root: { backgroundColor: 'red', }, })(({ classes }) => !!crwd_bt_768_tb_dwrc!!); function MyOtherComponent(props) { const ref = React.useRef(); - return <MyComponent innerRef={ref} />; + return <MyComponent ref={ref} />; }
BottomNavigationAction
Remove the
span
element that wraps the children. Remove thewrapper
classKey too. More details about this change.<button class="MuiBottomNavigationAction-root"> - <span class="MuiBottomNavigationAction-wrapper"> {icon} <span class="MuiBottomNavigationAction-label"> {label} </span> - </span> </button>
Box
The
borderRadius
system prop value transformation has been changed. If it receives a number, it multiplies this value with thetheme.shape.borderRadius
value. Use a string to provide an explicitpx
value.✅ This is handled in the preset-safe codemod.
-<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. You can read this section for the "why" behind this new API.✅ This is handled in the preset-safe codemod.
<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:
✅ This is handled in the preset-safe codemod.
gridGap
togap
gridColumnGap
tocolumnGap
gridRowGap
torowGap
-<Box gridGap={1}> -<Box gridColumnGap={2}> -<Box gridRowGap={3}> +<Box gap={1}> +<Box columnGap={2}> +<Box rowGap={3}>
(Note that the system grid function wasn't documented in v4.)
The
clone
prop was removed because its behavior can be obtained by applying thesx
prop directly to the child if it is a MUI component.-<Box sx={{ border: '1px dashed grey' }} clone> - <Button>Save</Button> -</Box> +<Button sx={{ border: '1px dashed grey' }}>Save</Button>
The 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 MUI component.-<Box sx={{ border: '1px dashed grey' }}> - {(props) => <Button {...props}>Save</Button>} -</Box> +<Button sx={{ border: '1px dashed grey' }}>Save</Button>
For non-MUI 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>
Button
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.✅ This is handled in the preset-safe codemod.
<Button color="default"> +<Button>
If you prefer to use the
default
color in v4, take a look at this CodeSandboxspan
element that wraps children has been removed.label
classKey is also removed. More details about this change.<button class="MuiButton-root"> - <span class="MuiButton-label"> children - </span> </button>
Chip
Rename
default
variant tofilled
for consistency.✅ This is handled in the preset-safe codemod.
Since
filled
is the default value, the variant prop can be deleted:-<Chip variant="default"> +<Chip>
Checkbox
The switch color prop is now "primary" by default. To continue using the "secondary" color, you must explicitly indicate
secondary
. This brings the switch closer to the Material Design guidelines.- <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 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">
CircularProgress
The
static
variant has been renamed todeterminate
, and the previous appearance ofdeterminate
has been replaced by that ofstatic
. It was an exception to Material Design, and was removed from the specification.✅ This is handled in the preset-safe codemod.
-<CircularProgress variant="static" classes={{ static: 'className' }} /> +<CircularProgress variant="determinate" classes={{ determinate: 'className' }} />
NB: Se você já tinha customizado como "determinate", suas customizações provavelmente não são mais válidas. Por favor, remova-as.
Collapse
The
collapsedHeight
prop was renamedcollapsedSize
to support the horizontal direction.✅ This is handled in the preset-safe codemod.
-<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' }}>
CssBaseline
The component was migrated to use the
@mui/styled-engine
(emotion
orstyled-components
) instead ofjss
. 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 fromtheme.typography.body2
(0.875rem
) totheme.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', }, }, }, }, });
Dialog
The onE* transition props were removed. Use TransitionProps instead.
✅ This is handled in the preset-safe codemod.
<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 fromonClose
whenreason === 'backdropClick'
instead.✅ This is handled in the preset-safe codemod.
<Dialog - disableBackdropClick - onClose={handleClose} + onClose={(event, reason) => { + if (reason !== 'backdropClick') { + handleClose(event, reason); + } + }} />
Remove the
withMobileDialog
higher-order component. The hook API allows a simpler and more flexible solution:✅ This is handled in the preset-safe codemod by applying hard-coded function to prevent application crash, further fixes are required.
-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); // ... -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); // ...
Flatten DialogTitle DOM structure, remove
disableTypography
prop✅ This is handled in the preset-safe codemod.
-<DialogTitle disableTypography> - <Typography variant="h4" component="h2"> +<DialogTitle> + <Typography variant="h4" component="span"> > > My header > > </Typography>
Divider
Use border instead of background color. It 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; }
ExpansionPanel
Rename the
ExpansionPanel
components toAccordion
to use a more common naming convention:✅ This is handled in the preset-safe codemod.
-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>
TypeScript: The
event
inonChange
is no longer typed as aReact. ChangeEvent
butReact. SyntheticEvent
.-<Accordion onChange={(event: React. ChangeEvent<{}>, expanded: boolean) => {}} /> +<Accordion onChange={(event: React. SyntheticEvent, expanded: boolean) => {}} />
ExpansionPanelDetails
- Remove
display: flex
fromAccordionDetails
(formerlyExpansionPanelDetails
) as its too opinionated. Most developers expect a display block.
ExpansionPanelSummary
Rename
focused
tofocusVisible
for consistency:<AccordionSummary classes={{ - focused: 'custom-focus-visible-classname', + focusVisible: 'custom-focus-visible-classname', }} />
Remove
IconButtonProps
prop fromAccordionSummary
(formerlyExpansionPanelSummary
). The component renders a<div>
element instead of anIconButton
. The prop is no longer necessary.
Fab
Rename
round
tocircular
for consistency:✅ This is handled in the preset-safe codemod.
-<Fab variant="round"> +<Fab variant="circular">
span
element that wraps children has been removed.label
classKey is also removed. More details about this change.<button class="MuiFab-root"> - <span class="MuiFab-label"> {children} - </span> </button>
FormControl
Change the default variant from
standard
tooutlined
. Standard has been removed from the Material Design guidelines.✅ 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" />
FormControlLabel
- The
label
prop is now required. If you were using aFormControlLabel
without alabel
, you can replace it with just the value of thecontrol
prop.
-<FormControlLabel control={<Checkbox />} />
+<Checkbox />
Grid
Rename
justify
prop tojustifyContent
to align with the CSS property name.✅ This is handled in the preset-safe codemod.
-<Grid justify="center"> +<Grid justifyContent="center">
The props:
alignItems
alignContent
andjustifyContent
and theirclasses
and style overrides keys were 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 the system, not on theTypography
component itself. If you still wish to add overrides for them, you can use the `theme.components.✅ This is handled in the preset-safe codemod.
const theme = createTheme({ components: { MuiGrid: { - styleOverrides: { - "align-items-xs-flex-end": { - marginTop: '20px', - }, - }, + variants: { + props: { alignItems: "flex-end" }, + style: { + marginTop: '20px', + }, + }], }, }, });
GridList
Rename the
GridList
components toImageList
to align with the current Material Design naming.✅ This is handled in the preset-safe codemod.
Rename the GridList
spacing
prop togap
to align with the CSS attribute.Rename the GridList
cellHeight
prop torowHeight
.Add the
variant
prop to GridList.Rename the GridListItemBar
actionPosition
prop toposition
. (Note also the related classname changes.)Use CSS object-fit. For IE11 support either use a polyfill such as https://www.npmjs.com/package/object-fit-images, or 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> <img src="file.jpg" alt="Image title" /> - <GridListTileBar + <ImageListItemBar title="Title" subtitle="Subtitle" /> - </GridListTile> -</GridList> + </ImageListItem> +</ImageList>
Hidden
This component is deprecated because its functionality can be created with the
sx
prop or theuseMediaQuery
hook.✅ This is handled in the preset-safe codemod by applying fake
Hidden
component to prevent application crash, further fixes are required.Use the
sx
prop to replaceimplementation="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 replaceimplementation="js"
:-<Hidden implementation="js" xlUp><Paper /></Hidden> +const hidden = useMediaQuery(theme => theme.breakpoints.up('xl')); +return hidden ? null : <Paper />;
Icon
The default value of
fontSize
was changed fromdefault
tomedium
for consistency. In the unlikely event that you were using the valuedefault
, the prop can be removed:-<Icon fontSize="default">icon-name</Icon> +<Icon>icon-name</Icon>
IconButton
The default size's padding is reduced to
8px
which makes the default IconButton size of40px
. To get the old default size (48px
), usesize="large"
. The change was done to better match Google's products when Material Design stopped documenting the icon button pattern.✅ This is handled in the preset-safe codemod.
- <IconButton> + <IconButton size="large">
span
element that wraps children has been removed.label
classKey is also removed. More details about this change.<button class="MuiIconButton-root"> - <span class="MuiIconButton-label"> <svg /> - </span> </button>
Link
The default
underline
prop is changed from"hover"
to"always"
. To get the same behavior as in v4, applydefaultProps
in theme✅ This is handled in link-underline-hover codemod, read the details before running this codemod.
createTheme({ components: { MuiLink: { defaultProps: { underline: 'hover', }, }, }, });
Menu
The onE* transition props were removed. Use TransitionProps instead.
✅ This is handled in the preset-safe codemod.
<Menu - onEnter={onEnter} - onEntered={onEntered} - onEntering={onEntering} - onExit={onExit} - onExited={onExited} - onExiting={onExiting} + TransitionProps={{ + onEnter, + onEntered, + onEntering, + onExit, + onExited, + onExiting, + }} >
Note: 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 now displays below the anchor instead of on top of it. You can restore the previous behavior with:<Menu + anchorOrigin={{ + vertical: 'top', + horizontal: 'left', + }}
MenuItem
The
MenuItem
component inherits theButtonBase
component instead ofListItem
. The class names related to "MuiListItem-*" are removed and themingListItem
is no longer affectingMenuItem
.-<li className="MuiButtonBase-root MuiMenuItem-root MuiListItem-root"> +<li className="MuiButtonBase-root MuiMenuItem-root">
prop
listItemClasses
is removed, useclasses
instead.-<MenuItem listItemClasses={{...}}> +<MenuItem classes={{...}}>
Read more about MenuItem CSS API
Modal
Remove the
disableBackdropClick
prop because it is redundant. UseonClose
withreason === 'backdropClick'
instead.✅ This is handled in the preset-safe codemod.
<Modal - disableBackdropClick - onClose={handleClose} + onClose={(event, reason) => { + if (reason !== 'backdropClick') { + handleClose(event, reason); + } + }} />
Remove the
onEscapeKeyDown
prop because it is redundant. UseonClose
withreason === "escapeKeyDown"
instead.✅ This is handled in the preset-safe codemod.
<Modal - onEscapeKeyDown={handleEscapeKeyDown} + onClose={(event, reason) => { + if (reason === 'escapeKeyDown') { + handleEscapeKeyDown(event); + } + }} />
Remove
onRendered
prop. Depending on your use case either use a callback ref on the child element or an effect hook in the child component.
NativeSelect
Merge the
selectMenu
slot intoselect
. SlotselectMenu
was redundant. Theroot
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' }} />
OutlinedInput
Remove the
labelWidth
prop. Thelabel
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" />
Paper
Change the background opacity based on the elevation in dark mode. This change was done to follow the Material Design guidelines. You can revert it in the theme:
const theme = createTheme({ components: { MuiPaper: { + styleOverrides: { root: { backgroundImage: 'unset' } }, }, }, });
Pagination
Move the component from the lab to the core. The component is now stable.
✅ This is handled in the preset-safe codemod.
-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';
Rename
round
tocircular
for consistency:✅ This is handled in the preset-safe codemod.
-<Pagination shape="round"> -<PaginationItem shape="round"> +<Pagination shape="circular"> +<PaginationItem shape="circular">
Popover
The onE* transition props were removed. Use TransitionProps instead.
✅ This is handled in the preset-safe codemod.
<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.
Popper
Upgrade Popper.js from v1 to v2. This third-party library has introduced a lot of changes.
You can read their migration guide or the following summary: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()
Modifiers' API has changed a lot. There are too many changes to be covered here.
Portal
- Remove
onRendered
prop. Depending on your use case either use a callback ref on the child element or an effect hook in the child component.
Radio
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 />
The component doesn't have
. MuiIconButton-root
and. MuiIconButton-label
class names anymore, target. MuiButtonBase-root
instead.- <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">
Rating
Move the component from the lab to the core. The component is now stable.
✅ This is handled in the preset-safe codemod.
-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 noemptyIcon
prop, you can restore the previous behavior with:<Rating icon={customIcon} + emptyIcon={null} />
Rename
visuallyhidden
tovisuallyHidden
for consistency:<Rating classes={{ - visuallyhidden: 'custom-visually-hidden-classname', + visuallyHidden: 'custom-visually-hidden-classname', }} />
RootRef
This component was removed. You can get a reference to the underlying DOM node of our components via
ref
prop. The component relied onReactDOM.findDOMNode
which is✅ This is handled in the preset-safe codemod by applying fake ``RootRef` component to prevent application crash, further fixes are required.
> -
> -
+