---
name: migration
description: MUI version migration guides — v4→v5 and v5→v6 with codemods and patterns
triggers:
- migration
- upgrade
- migrate
- v4
- v5
- v6
- makeStyles
- codemod
allowed-tools:
- Read
- Glob
- Grep
- Bash
- Write
- Edit
globs:
- "*.tsx"
- "*.ts"
- "*.jsx"
- "*.js"
---
# MUI Version Migration
## v4 → v5 Migration
### Package Renames
```bash
# Uninstall v4 packages
npm uninstall @material-ui/core @material-ui/icons @material-ui/lab @material-ui/system
# Install v5 packages
npm install @mui/material @mui/icons-material @mui/lab @mui/system
npm install @emotion/react @emotion/styled # new required peer deps
# If using styled-components instead of emotion (less common):
npm install @mui/material @mui/styled-engine-sc styled-components
```
### Run the v5 Codemod
The codemod handles ~80% of the mechanical changes automatically.
```bash
# Run the v5 preset-safe codemod (safe subset — no breaking changes)
npx @mui/codemod v5.0.0/preset-safe src/
# Run on a single file
npx @mui/codemod v5.0.0/preset-safe src/components/MyComponent.tsx
# Run individual transforms
npx @mui/codemod v5.0.0/component-rename-prop src/
npx @mui/codemod v5.0.0/moved-lab-modules src/
npx @mui/codemod v5.0.0/optimal-imports src/
```
After running the codemod, review the diff carefully — some transformations may need manual adjustment.
### Import Path Changes
```tsx
// v4
import { makeStyles } from '@material-ui/core/styles';
import { createMuiTheme } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';
import TextField from '@material-ui/core/TextField';
// v5
import { styled } from '@mui/material/styles'; // replaces makeStyles
import { createTheme } from '@mui/material/styles'; // createMuiTheme → createTheme
import Button from '@mui/material/Button';
import TextField from '@mui/material/TextField';
```
### createTheme Changes
```tsx
// v4
import { createMuiTheme } from '@material-ui/core/styles';
const theme = createMuiTheme({
palette: {
primary: { main: '#1976d2' },
},
overrides: { // v4: overrides
MuiButton: {
root: { textTransform: 'none' },
},
},
props: { // v4: props
MuiButton: { disableRipple: true },
},
});
// v5
import { createTheme } from '@mui/material/styles';
const theme = createTheme({
palette: {
primary: { main: '#1976d2' },
},
components: { // v5: components (combines overrides + props)
MuiButton: {
defaultProps: { // was: props
disableRipple: true,
},
styleOverrides: { // was: overrides
root: {
textTransform: 'none',
},
},
},
},
});
```
### makeStyles → styled / sx
This is the most impactful change. JSS (`makeStyles`, `withStyles`) is replaced by Emotion.
#### Pattern 1: sx prop (simple, inline styles)
```tsx
// v4 with makeStyles
const useStyles = makeStyles((theme) => ({
root: {
padding: theme.spacing(2),
backgroundColor: theme.palette.background.paper,
borderRadius: theme.shape.borderRadius,
},
}));
function MyComponent() {
const classes = useStyles();
return
Content
;
}
// v5 with sx prop
function MyComponent() {
return (
Content
);
}
```
#### Pattern 2: styled() (reusable styled components)
```tsx
// v4 with makeStyles + clsx
const useStyles = makeStyles((theme) => ({
card: {
padding: theme.spacing(3),
border: `1px solid ${theme.palette.divider}`,
borderRadius: theme.shape.borderRadius * 2,
},
cardHighlighted: {
borderColor: theme.palette.primary.main,
backgroundColor: theme.palette.primary.light,
},
}));
function MyCard({ highlighted }: { highlighted: boolean }) {
const classes = useStyles();
return (
Content
);
}
// v5 with styled()
import { styled } from '@mui/material/styles';
const StyledCard = styled('div', {
shouldForwardProp: (prop) => prop !== 'highlighted',
})<{ highlighted?: boolean }>(({ theme, highlighted }) => ({
padding: theme.spacing(3),
border: `1px solid ${theme.palette.divider}`,
borderRadius: theme.shape.borderRadius * 2,
...(highlighted && {
borderColor: theme.palette.primary.main,
backgroundColor: theme.palette.primary.light,
}),
}));
function MyCard({ highlighted }: { highlighted: boolean }) {
return Content;
}
```
#### Pattern 3: tss-react (drop-in makeStyles replacement)
For large codebases where a full migration is impractical, `tss-react` provides a near-identical API:
```bash
npm install tss-react @emotion/react
```
```tsx
// Minimal diff from v4 makeStyles
import { makeStyles } from 'tss-react/mui';
const useStyles = makeStyles()((theme) => ({
root: {
padding: theme.spacing(2),
backgroundColor: theme.palette.background.paper,
},
}));
function MyComponent() {
const { classes } = useStyles();
return Content
;
}
```
### withStyles → styled
```tsx
// v4
const StyledButton = withStyles((theme) => ({
root: {
margin: theme.spacing(1),
},
label: {
color: theme.palette.primary.main,
},
}))(Button);
// v5
const StyledButton = styled(Button)(({ theme }) => ({
margin: theme.spacing(1),
'& .MuiButton-label': { // target internal class
color: theme.palette.primary.main,
},
}));
// Or better — use sx prop on Button directly
```
### color Prop Changes
```tsx
// v4 — color accepted any string
// v5 — 'default' removed; use 'inherit' or omit color
```
### System Props Removed from Most Components
In v5, system props (like `mt`, `p`, `bgcolor`) work on `Box` and `Stack` but not on
all components. Use the `sx` prop instead.
```tsx
// v4 — system props on Typography
Text
// v5 — use sx prop
Text
```
### Lab Component Moves
Several components graduated from `@mui/lab` to `@mui/material`:
| v4 lab | v5 core |
|--------|---------|
| `@material-ui/lab/Alert` | `@mui/material/Alert` |
| `@material-ui/lab/Autocomplete` | `@mui/material/Autocomplete` |
| `@material-ui/lab/Pagination` | `@mui/material/Pagination` |
| `@material-ui/lab/Rating` | `@mui/material/Rating` |
| `@material-ui/lab/Skeleton` | `@mui/material/Skeleton` |
| `@material-ui/lab/SpeedDial` | `@mui/material/SpeedDial` |
| `@material-ui/lab/ToggleButton` | `@mui/material/ToggleButton` |
### v4 → v5 Breaking Changes Checklist
- [ ] Replace `@material-ui/*` with `@mui/*`
- [ ] Add `@emotion/react` and `@emotion/styled` peer deps
- [ ] Replace `createMuiTheme` with `createTheme`
- [ ] Replace `theme.overrides` + `theme.props` with `theme.components`
- [ ] Replace all `makeStyles`/`withStyles` (JSS) with `styled`/`sx`/tss-react
- [ ] Remove `color="default"` — use `color="inherit"` or omit
- [ ] Update Lab imports to core for graduated components
- [ ] Replace `` with `sx={{ display: { xs: 'none', sm: 'block' } }}`
- [ ] Update `Box` system shorthand keys (some changed)
- [ ] Check all `className` overrides — internal class names changed in v5
---
## v5 → v6 Migration
### Run the v6 Codemod
```bash
# Run preset-safe (recommended first step)
npx @mui/codemod v6.0.0/preset-safe src/
# Run on specific directories
npx @mui/codemod v6.0.0/preset-safe src/components/ src/pages/
# Individual transforms (if preset-safe missed something)
npx @mui/codemod v6.0.0/grid-v2-props src/
npx @mui/codemod v6.0.0/sx-prop src/
```
### Grid v2 (Major Breaking Change)
Grid v2 is the default `Grid` in v6. The `item` prop is removed; use `size` instead.
The `xs`, `sm`, `md`, `lg`, `xl` props are replaced by a single `size` prop with an object.
```tsx
// v5 Grid
import Grid from '@mui/material/Grid';
// v6 Grid (Grid v2) — same import path, new API
import Grid from '@mui/material/Grid';
// Shorthand for full-width only
Full width
// Auto-grow
Fills remaining space
```
### Grid v2 — Offset
```tsx
// v5 — offset via empty grid items or negative margins
// spacer
// v6 — offset prop
// Responsive offset
```
### Slots Pattern Standardized
In v6, the `slots`/`slotProps` API is standardized across all MUI X components
(DatePicker, DataGrid, Charts). The old `components`/`componentsProps` API is removed.
```tsx
// v5 (deprecated in v6)
// v6 (required)
```
### Pigment CSS (Experimental in v6)
v6 introduces optional Pigment CSS — a build-time CSS extraction alternative to Emotion.
It enables zero-runtime styling (faster SSR, smaller bundles).
```bash
# Install Pigment CSS (optional — still experimental in v6)
npm install @mui/material-pigment-css @pigment-css/react
# Next.js setup
npm install @pigment-css/nextjs-plugin
```
```js
// next.config.js
const { withPigment } = require('@pigment-css/nextjs-plugin');
module.exports = withPigment({
// your next config
}, {
theme: require('./src/theme').default,
});
```
With Pigment CSS, `styled()` and `sx` are processed at build time — no Emotion runtime.
Server components can use styled components directly without `'use client'`.
### v5 → v6 Breaking Changes Checklist
- [ ] Update all packages: `npm install @mui/material@6 @mui/x-date-pickers@7 @mui/x-data-grid@7`
- [ ] Replace Grid v1 props (`item`, `xs`/`sm`/`md`) with Grid v2 `size` prop
- [ ] Replace `components`/`componentsProps` with `slots`/`slotProps` in all MUI X components
- [ ] Check `@mui/x-date-pickers` peer dep: now requires `dayjs` or another adapter explicitly
- [ ] `useMediaQuery` now requires a `theme` argument in some contexts — verify usages
- [ ] `Stack` `divider` spacing changed — verify visual output
- [ ] Review `@mui/x-data-grid` API: some column definition fields changed
---
## Incremental Migration Strategy
For large codebases (100+ components), do not migrate everything at once.
### Phase 1: Package and Config (1 day)
```bash
# 1. Update packages
npm uninstall @material-ui/core @material-ui/icons
npm install @mui/material @mui/icons-material @emotion/react @emotion/styled
# 2. Run codemods
npx @mui/codemod v5.0.0/preset-safe src/
# 3. Fix obvious import errors
# 4. Run the app; expect red errors — that's normal at this stage
```
### Phase 2: Theme Migration (1–2 days)
```tsx
// Migrate theme file first — everything depends on it
// Old: createMuiTheme with overrides/props
// New: createTheme with components.MuiXxx.styleOverrides/defaultProps
```
### Phase 3: Component-by-Component (ongoing)
Prioritize components that are:
1. Used most frequently (Button, TextField, etc.)
2. Already have a clear `sx`-based replacement
3. Self-contained (not deeply composed)
```tsx
// Migrate one component at a time:
// 1. Remove makeStyles import
// 2. Replace className={classes.xxx} with sx={...} or styled()
// 3. Run tests
// 4. Commit
```
### Phase 4: Remove JSS Entirely
```bash
# Once all makeStyles are removed:
npm uninstall @material-ui/styles
```
### Coexistence Strategy (v4 + v5 during migration)
```tsx
// Temporarily keep both packages during migration
// @material-ui/core for unmigrated components
// @mui/material for migrated components
// Wrap each style engine separately
import { StylesProvider } from '@material-ui/core/styles'; // v4 JSS
import { ThemeProvider } from '@mui/material/styles'; // v5 Emotion
function App() {
return (
{/* migrated components use v5 theme */}
{/* unmigrated components use v4 styles */}
);
}
```
## makeStyles → styled/sx Conversion Reference
| makeStyles pattern | v5 equivalent |
|-------------------|---------------|
| `padding: theme.spacing(2)` | `sx={{ p: 2 }}` |
| `margin: theme.spacing(1, 2)` | `sx={{ my: 1, mx: 2 }}` |
| `color: theme.palette.primary.main` | `sx={{ color: 'primary.main' }}` |
| `backgroundColor: theme.palette.grey[100]` | `sx={{ bgcolor: 'grey.100' }}` |
| `display: 'flex'` | `sx={{ display: 'flex' }}` |
| `[theme.breakpoints.up('sm')]: { ... }` | `sx={{ md: { ... } }}` |
| `'&:hover': { ... }` | `sx={{ '&:hover': { ... } }}` |
| `'& .MuiButton-root': { ... }` | `sx={{ '& .MuiButton-root': { ... } }}` |
| `theme.transitions.create('opacity')` | `styled()(({ theme }) => ({ transition: theme.transitions.create('opacity') }))` |
## Common Post-Migration Issues
**Styles not applying:**
- Check that `CssBaseline` is inside `ThemeProvider`
- Confirm `@emotion/react` and `@emotion/styled` are installed
- Ensure no JSS `StylesProvider` is conflicting
**TypeScript errors after codemod:**
- `makeStyles` return type changed — `classes` is now in a `{ classes }` object with tss-react
- `Theme` import moved from `@material-ui/core` to `@mui/material/styles`
- Some prop types narrowed (e.g., `color` no longer accepts `'default'`)
**SSR style flash (FOUC):**
- Missing Emotion cache setup — see the performance skill for full SSR config
- Ensure `createEmotionCache()` is called per request, not once globally
**Grid layout broken after v6 upgrade:**
- The `item` prop is removed — add `size` prop to every grid item
- Run `npx @mui/codemod v6.0.0/grid-v2-props src/` to automate this