eslint-plugin-mui-v7
v1.6.4
Published
ESLint plugin focused on Material-UI V6 to V7 breaking changes with educational error messages
Maintainers
Readme
eslint-plugin-mui-v7
ESLint plugin focused on Material-UI V6 to V7 breaking changes with educational error messages
Automatically detect code that BREAKS when migrating from MUI V6 to V7 and teach developers the correct way through helpful messages with emojis and examples!
🎯 Philosophy
This plugin focuses on breaking changes only - code that will actually break when upgrading to V7. We don't warn about best practices or style preferences, just things that will cause errors.
🎉 Complete Coverage: Detects 100% of all detectable MUI V7 breaking changes with 100% autofix support (8/8 rules)!
✨ Features
- ⚠️ Catch Grid2 usage - Grid2 was renamed to Grid in V7
- 🎯 Grid item prop detection - Grid doesn't use
itemprop anymore, usesizeinstead - ✨ Find moved @mui/lab components - Alert, Skeleton, Rating, etc. are now in @mui/material
- 🔄 Detect deprecated props - onBackdropClick, size="normal", Hidden/PigmentHidden components
- 🎨 Catch deprecated imports - createMuiTheme, experimentalStyled, StyledEngineProvider wrong location
- 📦 Deep imports detection - Deep imports break in V7 due to exports field
- 🔧 Components/componentsProps deprecation - Suggests slots/slotProps API
- 💡 Theme variables suggestion - Use
theme.vars.*for automatic dark mode support (optional) - 🔧 Auto-fix available for 8/8 rules (100%)! 🎯
📦 Installation
npm install --save-dev eslint-plugin-mui-v7📚 Complete Setup Tutorial
Step 1: Install the Plugin
Choose your package manager:
# npm
npm install --save-dev eslint-plugin-mui-v7
# yarn
yarn add -D eslint-plugin-mui-v7
# pnpm
pnpm add -D eslint-plugin-mui-v7Step 2: Configure ESLint
For ESLint 9+ (Flat Config) - Recommended ✨
Create or update your eslint.config.js file:
// eslint.config.js
import muiV7Plugin from 'eslint-plugin-mui-v7'
export default [
// Use the recommended preset (easiest option!)
muiV7Plugin.configs.recommended,
// Your other ESLint configs...
]That's it! The plugin is now configured with all breaking changes as errors and best practices as warnings.
For ESLint <9 (Legacy .eslintrc)
Create or update your .eslintrc.js file:
// .eslintrc.js
module.exports = {
plugins: ['mui-v7'],
rules: {
// Breaking changes - ERRORS
'mui-v7/no-grid2-import': 'error',
'mui-v7/no-grid-item-prop': 'error',
'mui-v7/no-lab-imports': 'error',
'mui-v7/no-deprecated-props': 'error',
'mui-v7/no-deprecated-imports': 'error',
'mui-v7/no-deep-imports': 'error',
// Best practices - WARNINGS
'mui-v7/prefer-slots-api': 'warn',
'mui-v7/prefer-theme-vars': 'warn',
},
}Step 3: Run ESLint on Your Code
Check your code for MUI V7 breaking changes:
# Check all files
npx eslint .
# Check specific directory
npx eslint src/
# Check and auto-fix issues
npx eslint . --fixStep 4: Review and Fix Issues
The plugin will show you:
- ❌ Errors - Code that WILL BREAK in MUI V7
- ⚠️ Warnings - Best practices and deprecated patterns
Most issues can be auto-fixed with --fix! 🎯
Step 5: Fix Remaining Issues Manually
For issues that can't be auto-fixed (like spread props), the plugin provides helpful messages:
❌ mui-v7/no-grid-item-prop
🎯 Grid in MUI V7 no longer uses the `item` prop!
🔧 Old way (V6):
<Grid item xs={12} sm={6}>
✅ New way (V7):
<Grid size={{ xs: 12, sm: 6 }}>
💡 The new syntax is cleaner and more powerful!Complete Example
Here's a complete eslint.config.js for a React + TypeScript + MUI project:
// eslint.config.js
import js from '@eslint/js'
import tseslint from 'typescript-eslint'
import reactPlugin from 'eslint-plugin-react'
import muiV7Plugin from 'eslint-plugin-mui-v7'
export default [
js.configs.recommended,
...tseslint.configs.recommended,
reactPlugin.configs.flat.recommended,
// Add MUI V7 plugin
muiV7Plugin.configs.recommended,
{
files: ['**/*.{js,jsx,ts,tsx}'],
languageOptions: {
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
},
},
]🚀 Quick Start
ESLint 9+ (Flat Config) - Recommended
// eslint.config.js
import muiV7Plugin from 'eslint-plugin-mui-v7'
export default [
muiV7Plugin.configs.recommended, // ✅ Apply all recommended rules
]Manual Configuration
// eslint.config.js
import muiV7Plugin from 'eslint-plugin-mui-v7'
export default [
{
plugins: {
'mui-v7': muiV7Plugin,
},
rules: {
// Breaking changes - ERRORS (código quebra)
'mui-v7/no-grid2-import': 'error',
'mui-v7/no-grid-item-prop': 'error',
'mui-v7/no-lab-imports': 'error',
'mui-v7/no-deprecated-props': 'error',
'mui-v7/no-deprecated-imports': 'error',
'mui-v7/no-deep-imports': 'error',
// Best practices - WARNINGS (sugestões)
'mui-v7/prefer-slots-api': 'warn',
'mui-v7/prefer-theme-vars': 'warn',
},
},
]ESLint <9 (Legacy Config)
// .eslintrc.js
module.exports = {
plugins: ['mui-v7'],
rules: {,
'mui-v7/no-grid2-import': 'error',
'mui-v7/no-grid-item-prop': 'error',
'mui-v7/no-lab-imports': 'error',
'mui-v7/no-deprecated-props': 'error',
'mui-v7/no-deprecated-imports': 'error',
'mui-v7/no-deep-imports': 'error',
'mui-v7/prefer-slots-api': 'warn',
'mui-v7/prefer-theme-vars': 'warn',
},
}📋 Rules
🚨 Breaking Changes (Errors)
These rules detect code that WILL BREAK in MUI V7.
mui-v7/no-grid2-import
Grid2 was renamed to Grid in V7.
// ❌ Breaks in V7
import Grid2 from '@mui/material/Grid2'
import { grid2Classes } from '@mui/material/Grid2'
// ✅ Recommended
import { Grid } from '@mui/material'
import { gridClasses } from '@mui/material'mui-v7/no-grid-item-prop ✨ IMPROVED in v1.3.0
Grid doesn't use item prop anymore, use size instead. Now with auto-fix!
// ❌ Breaks in V7
<Grid item xs={12} sm={6} md={4}>
Content
</Grid>
// ✅ Works in V7
<Grid size={{ xs: 12, sm: 6, md: 4 }}>
Content
</Grid>mui-v7/no-lab-imports
Components moved from @mui/lab to @mui/material.
// ❌ Breaks in V7
import { Alert } from '@mui/lab'
import { Skeleton } from '@mui/lab'
// ✅ Recommended
import { Alert } from '@mui/material'
import { Skeleton } from '@mui/material'Moved components: Alert, AlertTitle, Autocomplete, AvatarGroup, Pagination, PaginationItem, Rating, Skeleton, SpeedDial, SpeedDialAction, SpeedDialIcon, ToggleButton, ToggleButtonGroup
Still in @mui/lab: LoadingButton, Masonry, TabContext, TabList, TabPanel, Timeline (and related components)
Moved to MUI X: TreeView and TreeItem moved to @mui/x-tree-view (not @mui/material)
mui-v7/no-deprecated-props ✨ IMPROVED in v1.3.0
Detects props and components removed in V7.
// ❌ Dialog.onBackdropClick - REMOVED
<Dialog onBackdropClick={handleClick}>
// ❌ Modal.onBackdropClick - REMOVED (NEW!)
<Modal onBackdropClick={handleClick}>
// ✅ Use onClose with reason check
<Dialog onClose={(event, reason) => {
if (reason === 'backdropClick') {
// Your logic here
}
}}>
// ❌ InputLabel size="normal" - RENAMED
<InputLabel size="normal">
// ✅ Use size="medium" (with auto-fix!)
<InputLabel size="medium">
// ❌ Hidden component - REMOVED
<Hidden xlUp><Paper /></Hidden>
// ❌ PigmentHidden component - REMOVED (NEW!)
<PigmentHidden xlUp><Paper /></PigmentHidden>
// ✅ Use sx prop
<Paper sx={{ display: { xl: 'none' } }} />
// ✅ Or use useMediaQuery
const hidden = useMediaQuery(theme => theme.breakpoints.up('xl'))
return hidden ? null : <Paper />mui-v7/no-deprecated-imports ✨ IMPROVED in v1.5.1
Detects deprecated imports removed in V7.
// ❌ createMuiTheme - REMOVED
import { createMuiTheme } from '@mui/material/styles'
// ✅ Use createTheme (with auto-fix!)
import { createTheme } from '@mui/material/styles'
// ❌ experimentalStyled - REMOVED
import { experimentalStyled } from '@mui/material/styles'
// ✅ Use styled (with auto-fix!)
import { styled } from '@mui/material/styles'
// ❌ StyledEngineProvider from wrong location - REMOVED (NEW in v1.5.1!)
import { StyledEngineProvider } from '@mui/material'
// ✅ Import from correct location (with auto-fix!)
import { StyledEngineProvider } from '@mui/material/styles'mui-v7/no-deep-imports ✨ NEW in v1.4.0
Detects deep imports that break in V7 due to the exports field.
// ❌ Deep imports don't work anymore
import Button from '@mui/material/Button/Button'
// ✅ Use main entry point (with auto-fix!)
import { Button } from '@mui/material'💡 Best Practices (Warnings)
These are suggestions, not breaking changes.
mui-v7/prefer-slots-api ✨ NEW in v1.3.0
Recommends using slots/slotProps instead of components/componentsProps.
// ⚠️ Deprecated (still works but will be removed)
<TextField
components={{ Input: CustomInput }}
componentsProps={{ input: { className: 'custom' } }}
/>
// ✅ Recommended: New slots API
<TextField
slots={{ input: CustomInput }}
slotProps={{ input: { className: 'custom' } }}
/>mui-v7/prefer-theme-vars ✨ IMPROVED in v1.5.0
When using cssVariables: true, use theme.vars.* for better performance and automatic dark mode. Now with auto-fix!
// ⚠️ Works but doesn't change with dark mode automatically
const Custom = styled('div')(({ theme }) => ({
color: theme.palette.text.primary,
}))
// ✅ Better: Changes automatically with dark mode (with auto-fix!)
const Custom = styled('div')(({ theme }) => ({
color: theme.vars.palette.text.primary,
}))🎓 Example Messages
The plugin provides educational messages with emojis and examples:
🎯 Grid in MUI V7 no longer uses the `item` prop!
🔧 Old way (V6):
<Grid item xs={12} sm={6} md={4}>
✅ New way (V7):
<Grid size={{ xs: 12, sm: 6, md: 4 }}>
💡 The new syntax is cleaner and more powerful!
You can use: size, offset, responsive spacing, and more.🔧 Configuration Presets
recommended - Balanced (Default)
Breaking changes as errors, best practices as warnings.
import muiV7Plugin from 'eslint-plugin-mui-v7'
export default [
muiV7Plugin.configs.recommended,
]strict - Strict Mode
Everything as errors (including best practices).
import muiV7Plugin from 'eslint-plugin-mui-v7'
export default [
muiV7Plugin.configs.strict,
]🆕 What's New
v1.5.1 (2025-11-14) - Complete Coverage! ✅
Added
- ✨ StyledEngineProvider import detection in
no-deprecated-imports- Detects incorrect imports from
@mui/materialinstead of@mui/material/styles - Automatic fix to correct import location
- Completes 100% coverage of all detectable MUI V7 breaking changes!
- Detects incorrect imports from
Coverage Achievement
- ✅ 8/8 rules with autofix support (100%)
- ✅ 0 known false positives
v1.5.0 (2025-11-14) - 100% Autofix! 🎯
Added
- ✨ Autofix for
prefer-theme-vars: Automatically transformstheme.palette.*→theme.vars.palette.*- Works in styled components, sx props, template literals, and object expressions
- Safely handles edge cases (ternary conditionals, non-null assertions)
- Achieved 100% autofix coverage for all 10 rules! 🎯
v1.4.1 (2025-11-14) - Critical Bug Fix! 🔧
Fixed
- 🐛 Removed 12 false positives from
no-lab-importsrule:- Timeline components (7): Still in
@mui/lab, not moved to@mui/material - Tab components (3): TabContext, TabList, TabPanel still in
@mui/lab - TreeView components (2): Moved to
@mui/x-tree-view, not@mui/material
- Timeline components (7): Still in
v1.4.0 (2025-11-14) - New Rules! 🚀
Added
- ✨ no-deep-imports: Detects deep imports that break due to exports field (with auto-fix!)
Enhanced
- 🔧 no-grid-item-prop: Added safety check to prevent autofix when spread props are present
- 📝 Documentation: Added "Known Limitations" section explaining edge cases
v1.3.0 (2025-11-14) - Major Update! 🎉
New Rules
- ✨ no-deprecated-imports: Detects
createMuiThemeandexperimentalStyled(with auto-fix!) - ✨ prefer-slots-api: Recommends
slots/slotPropsovercomponents/componentsProps
Enhanced Rules
- 🔧 no-deprecated-props: Now detects
Modal.onBackdropClickandPigmentHiddencomponent - 🔧 no-deprecated-props: Auto-fix for
InputLabel size="normal"→size="medium" - 🔧 no-grid-item-prop: Smart auto-fix that converts breakpoint props to
sizeobject - 🔧 no-grid2-import: Improved fix that properly renames
Grid2→Gridandgrid2Classes→gridClasses
Code Quality
- ✅ Added comprehensive test suite with 50+ test cases
- 🛡️ Added optional chaining (
?.) for safer AST navigation - 📦 Updated package.json with proper test scripts
- 🔄 Updated to run tests before publishing (
prepublishOnly)
v1.2.1 (2025-10-30)
UX Improvements
- ✨ Enhanced
no-lab-importsto show all moved components in error messages - 📝 Before:
Este componente foi movido(showed only first component) - 🎯 Now:
3 componente(s) movido(s)with complete list:Alert, Autocomplete, Rating
v1.2.0 (2025-10-30)
Performance
- ⚡ Optimized
no-lab-imports: O(n×m) → O(n) using Set lookup instead of Array.includes - ⚡ Optimized
prefer-theme-vars: Added WeakMap cache for getText() calls to eliminate duplicate I/O - 🧹 Improved code readability with optional chaining and early returns
- 📊 Moved
MOVED_COMPONENTSto module scope to avoid recreation on every rule invocation
Internal
- 🏗️ Formalized AST traversal depth tracking with MAX_DEPTH constant
- 💾 Source text caching to prevent redundant file reads
⚠️ Known Limitations
This plugin has some limitations to ensure safe and reliable autofixes:
1. Spread Props are Not Auto-Fixed
When a component has spread props ({...props}), the autofix is disabled to avoid potential issues:
// ❌ Plugin detects the issue but WON'T auto-fix (safe!)
<Grid {...props} item xs={12}>Content</Grid>
// Why? If props contains { item: true, xs: 6 }, the spread would override our fixSolution: Fix manually or remove the spread props first.
2. Dynamic Props are Not Auto-Fixed
Complex expressions and variables are not auto-fixed:
// ❌ Plugin detects but WON'T auto-fix (safe!)
<Grid item xs={isMobile ? 12 : 6}>Content</Grid>
<Grid item xs={colSize}>Content</Grid>Solution: These require manual migration to size prop.
3. Cross-File Dependencies
The plugin cannot detect issues that span multiple files:
// File 1: component-props.ts
export const gridProps = { item: true, xs: 12 }
// File 2: Component.tsx - Plugin won't detect this!
<Grid {...gridProps}>Content</Grid>Solution: Run the plugin on all files and review spread props carefully.
4. Best Practices vs Breaking Changes
The plugin focuses on breaking changes only. Some MUI best practices are not enforced:
- ✅ Detects: Code that breaks in V7
- ❌ Doesn't detect: Deprecated but still working code (unless it's in the migration path)
🔗 For Complex Cases
For complex migrations, consider using MUI's official codemods:
# Official MUI codemods
npx @mui/codemod v7.0.0/grid-props <path>
npx @mui/codemod v7.0.0/lab-removed-components <path>This plugin complements the codemods by providing continuous validation!
🧪 Testing
Run the comprehensive test suite:
npm testWatch mode for development:
npm run test:watch🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
📄 License
MIT © Matheus Pimenta (Koda AI Studio)
🔗 Links
❤️ Credits
Created by Matheus Pimenta (Koda AI Studio) + Claude Code
Keywords: eslint, mui, material-ui, mui-v7, react, typescript, linter, code-quality, migration, breaking-changes
