git clone https://github.com/NeverSight/learn-skills.dev
T=$(mktemp -d) && git clone --depth=1 https://github.com/NeverSight/learn-skills.dev "$T" && mkdir -p ~/.claude/skills && cp -r "$T/data/skills-md/agents-inc/skills/web-ui-mui" ~/.claude/skills/neversight-learn-skills-dev-web-ui-mui && rm -rf "$T"
data/skills-md/agents-inc/skills/web-ui-mui/SKILL.mdMUI (Material UI) Patterns
Quick Guide: MUI provides pre-styled React components implementing Material Design. Use
+createThemefor global theming,ThemeProviderprop for one-off styles,sxfor reusable styled components, andstyled()/slotsfor deep component customization. Prefer path imports in development for faster builds. Current: v7.x (March 2025) -- CSS layers support, standardized slot pattern, Grid v2 promoted, React 19 compatible. MUI X v8 for DataGrid, DatePicker, Charts.slotProps
<critical_requirements>
CRITICAL: Before Using This Skill
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
, named constants)import type
(You MUST wrap the app in
with a ThemeProvider
instance -- never use MUI components without a theme)createTheme()
(You MUST use path imports (
) in development for faster startup -- barrel imports (@mui/material/Button
) cause 6x slower dev builds)@mui/material
(You MUST use
/slots
for component inner-element customization -- slotProps
is deprecated in v7)componentsProps
(You MUST use
for dark mode conditional styles -- never use theme.applyStyles('dark', {...})
which causes flickering)theme.palette.mode === 'dark'
</critical_requirements>
Auto-detection: MUI, Material UI, @mui/material, @mui/system, @mui/icons-material, @mui/x-data-grid, @mui/x-date-pickers, createTheme, ThemeProvider, sx prop, styled, CssBaseline, useTheme, useMediaQuery, DataGrid, DatePicker, AppBar, Drawer, Dialog, Snackbar, TextField, Autocomplete, slotProps
When to use:
- Building React applications with pre-styled Material Design components
- Creating themed UIs with consistent design tokens (palette, typography, spacing)
- Implementing complex data views with DataGrid, DatePicker, or Charts (MUI X)
- Building admin dashboards, forms, and CRUD interfaces rapidly
When NOT to use:
- Headless/unstyled components needed (use a headless component library instead)
- Minimal bundle size is critical (MUI adds significant weight)
- Non-Material Design aesthetic required without heavy theme customization
- Server Components needed as primary rendering strategy (MUI components are client-only)
Key patterns covered:
- Theme setup, color schemes, and dark mode
- sx prop styling (theme-aware, responsive, callbacks)
- styled() API for reusable components
- Slots/slotProps for component customization (v7)
- Layout components (Grid, Stack, Box, Container)
- TypeScript theme augmentation
Detailed Resources:
- examples/core.md -- ThemeProvider, createTheme, CssBaseline, color schemes, dark mode toggle, TypeScript augmentation, Next.js integration, CSS layers
- examples/form-inputs.md -- TextField, Select, Autocomplete, slots/slotProps customization
- examples/layout.md -- Grid, Stack, Box, Container, responsive card grid
- examples/data-grid.md -- @mui/x-data-grid columns, pagination, custom rendering
- examples/feedback.md -- Dialog, Snackbar, Alert, Skeleton, CircularProgress
- examples/navigation.md -- AppBar, Drawer, Tabs, responsive dashboard layout
- examples/styling.md -- styled() API, sx prop patterns, dark mode styling, custom props
- reference.md -- Decision frameworks, anti-patterns, quick reference tables
<philosophy>
Philosophy
MUI implements Material Design as a comprehensive React component library. It provides:
- Design System: Complete palette, typography, spacing, shadows, and breakpoint tokens
- Pre-styled Components: 50+ components with consistent visual language
- Customization Layers: From simple
overrides to deep theme-level component restylingsx - Accessibility: Built-in ARIA attributes, keyboard navigation, and focus management
Core Principle: Theme drives everything. Define your design tokens in
createTheme(), and all components inherit consistent styling. Override at the component level with sx, styled(), or slots/slotProps.
MUI v7 Key Changes (March 2025):
- CSS layers support via
(integrates with utility-first CSS frameworks)enableCssLayer - Standardized
/slots
across all components (replacesslotProps
/components
)componentsProps - Grid v2 promoted to
(old Grid renamed toGrid
)GridLegacy - Lab components graduated to
(Alert, Skeleton, Autocomplete, etc.)@mui/material - Package layout updated for ESM/CJS dual support (no deep imports beyond one level)
- React 19 full compatibility
Pigment CSS Status: MUI's zero-runtime CSS-in-JS engine is currently on hold / alpha. Production apps should continue using the default Emotion-based styling engine.
</philosophy><patterns>
Core Patterns
Pattern 1: Theme Setup and Configuration
Every MUI app starts with
createTheme() and ThemeProvider. The theme defines all design tokens.
import { createTheme, ThemeProvider, CssBaseline } from "@mui/material"; const theme = createTheme({ palette: { primary: { main: "#1976d2" }, secondary: { main: "#9c27b0" }, }, typography: { fontFamily: '"Inter", "Roboto", "Helvetica", "Arial", sans-serif', button: { textTransform: "none" }, }, shape: { borderRadius: 8 }, spacing: 8, }); function App({ children }: { children: React.ReactNode }) { return ( <ThemeProvider theme={theme}> <CssBaseline /> {children} </ThemeProvider> ); } export { App };
Why good: Centralized design tokens, CssBaseline normalizes cross-browser styles, all children inherit theme
For production-ready theme with color schemes, dark mode, component overrides, and TypeScript augmentation, see examples/core.md.
Pattern 2: CSS Variables and Dark Mode
MUI v7 supports CSS variables natively. Use
colorSchemes for flicker-free light/dark mode.
const theme = createTheme({ cssVariables: { colorSchemeSelector: "data" }, colorSchemes: { light: { palette: { primary: { main: "#1976d2" } } }, dark: { palette: { primary: { main: "#90caf9" } } }, }, });
Toggle with the
useColorScheme hook:
import { useColorScheme } from "@mui/material/styles"; const { mode, setMode } = useColorScheme(); setMode(mode === "light" ? "dark" : "light");
Why good: CSS variables prevent flash of wrong theme on SSR, persists preference to localStorage
// BAD: Causes SSR flicker backgroundColor: theme.palette.mode === "dark" ? "#333" : "#fff"; // GOOD: Use applyStyles in styled() ...theme.applyStyles("dark", { backgroundColor: "#1a1a2e" });
For full dark mode toggle component, see examples/core.md.
Pattern 3: The sx Prop
The
sx prop is MUI's primary styling escape hatch. It accesses theme values, supports responsive breakpoints, and handles pseudo-selectors.
<Box sx={{ p: 3, // theme.spacing(3) = 24px bgcolor: "background.paper", // theme.palette.background.paper borderRadius: 1, // theme.shape.borderRadius * 1 boxShadow: 3, // theme.shadows[3] width: { xs: "100%", md: "50%" }, // Responsive "&:hover": { boxShadow: 6 }, }} />
Why good: Theme-aware shorthand properties, responsive without media queries
// BAD: Inline styles bypass theme <Box style={{ padding: 24, backgroundColor: "#1976d2" }}>
Why bad: Hardcoded values, no theme consistency, no responsive support, no dark mode awareness
For callback syntax and advanced sx patterns, see examples/styling.md.
Pattern 4: styled() API for Reusable Components
Use
styled() when you need a reusable component with theme-aware styles. Prefer sx for one-off styles.
import { styled } from "@mui/material/styles"; import Card from "@mui/material/Card"; const HOVER_ELEVATION = 8; const StyledCard = styled(Card)(({ theme }) => ({ padding: theme.spacing(3), borderRadius: theme.shape.borderRadius * 2, "&:hover": { boxShadow: theme.shadows[HOVER_ELEVATION] }, ...theme.applyStyles("dark", { backgroundColor: theme.palette.grey[900], }), })); export { StyledCard };
Why good: Reusable, theme-aware, dark mode handled with
applyStyles
For styled with custom props (
shouldForwardProp), gradient buttons, and more, see examples/styling.md.
Pattern 5: Slots and SlotProps (v7 Standard)
In MUI v7,
slots and slotProps are the standardized API for customizing component inner elements. The older components/componentsProps API is deprecated.
<Autocomplete slots={{ paper: Paper }} slotProps={{ paper: { elevation: 8, sx: { borderRadius: 2 } }, listbox: { sx: { maxHeight: 300 } }, }} renderInput={(params) => <TextField {...params} label="Framework" />} />
Why good: Standardized API across all MUI components, replaces deprecated patterns
// BAD: Deprecated in v7 <Autocomplete componentsProps={{ paper: { elevation: 8 } }} />
For callback slotProps and advanced customization, see examples/form-inputs.md.
Pattern 6: Layout Components
MUI provides
Box, Stack, Grid, and Container for layout. In v7, Grid is the former Grid2.
// Grid: 12-column responsive layout (v7 uses size prop) const SIDEBAR_COLUMNS = 4; const MAIN_COLUMNS = 8; <Grid container spacing={3}> <Grid size={{ xs: 12, md: SIDEBAR_COLUMNS }}><Sidebar /></Grid> <Grid size={{ xs: 12, md: MAIN_COLUMNS }}><MainContent /></Grid> </Grid> // Stack: single-axis layout with consistent spacing <Stack direction={{ xs: "column", sm: "row" }} spacing={2}> <Button variant="contained">Save</Button> <Button variant="outlined">Cancel</Button> </Stack> // Container: centered content with maxWidth <Container maxWidth="lg" sx={{ py: 4 }}>{children}</Container>
When to use each: Box (flex/sx wrapper), Stack (single axis), Grid (12-column), Container (page centering)
For product card grids, dashboard layouts, and more, see examples/layout.md.
Pattern 7: TypeScript Theme Augmentation
Extend MUI's theme type system when adding custom palette colors or typography variants.
// theme-augmentation.d.ts declare module "@mui/material/styles" { interface Palette { neutral: Palette["primary"]; } interface PaletteOptions { neutral?: PaletteOptions["primary"]; } } declare module "@mui/material/Button" { interface ButtonPropsColorOverrides { neutral: true; } }
Then use in theme and components:
const theme = createTheme({ palette: { neutral: { main: "#64748b", contrastText: "#fff" } }, }); <Button color="neutral" variant="contained">Neutral</Button>
Why good: Full type safety, IDE autocomplete for custom colors/variants
For complete augmentation with typography variants, see examples/core.md.
Pattern 8: Next.js App Router Integration
MUI requires
AppRouterCacheProvider from @mui/material-nextjs for proper SSR style injection.
// app/layout.tsx import { AppRouterCacheProvider } from "@mui/material-nextjs/v15-appRouter"; import { ThemeProvider } from "@mui/material/styles"; import CssBaseline from "@mui/material/CssBaseline"; function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="en"> <body> <AppRouterCacheProvider> <ThemeProvider theme={theme}> <CssBaseline /> {children} </ThemeProvider> </AppRouterCacheProvider> </body> </html> ); } export default RootLayout; // Next.js requires default export for layouts
Why good: Prevents style hydration mismatches, CSS layers enable predictable specificity with utility-first CSS
For CSS layers integration and Vite setup, see examples/core.md.
</patterns><performance>
Performance Optimization
Import Optimization
// GOOD: Path imports -- fast in development import Button from "@mui/material/Button"; import DeleteIcon from "@mui/icons-material/Delete"; // BAD: Barrel imports -- 6x slower dev startup import { Button } from "@mui/material"; import { Delete } from "@mui/icons-material";
Path imports skip barrel file parsing.
@mui/icons-material has 2000+ modules -- barrel imports force parsing all of them.
Exception: Next.js 13.5+ auto-optimizes via
optimizePackageImports.
Memoize Expensive Props
// GOOD: Columns outside component (stable reference) const columns: GridColDef[] = [ { field: "id", headerName: "ID", width: 90 }, ]; function Table({ rows }: { rows: User[] }) { return <DataGrid rows={rows} columns={columns} />; } // BAD: Inline columns cause re-render every parent render
Stable Slot References
// GOOD: Defined outside render const CustomPaper = (props: PaperProps) => <Paper {...props} elevation={8} />; <Autocomplete slots={{ paper: CustomPaper }} /> // BAD: Inline function causes remount every render <Autocomplete slots={{ paper: (props) => <Paper {...props} /> }} />
ESLint Rule for Import Enforcement
</performance>{ "rules": { "no-restricted-imports": [ "error", { "patterns": [ { "regex": "^@mui/[^/]+$", "message": "Use path imports: import Button from '@mui/material/Button'" } ] } ] } }
<decision_framework>
Decision Framework
Styling Approach
How many places will this style be used? +-- One place --> sx prop (inline, theme-aware) +-- Multiple places (same type) --> styled() (reusable, typed) +-- All instances of a component --> theme.components (global override) +-- Customize inner elements --> slots/slotProps
Layout Component Selection
What kind of layout? +-- Single axis (row or column) --> Stack +-- 12-column grid --> Grid +-- Centered page content --> Container +-- Flexible box with sx --> Box +-- Both axes + complex --> Grid (nested)
Component vs Custom Build
Does MUI have this component? +-- YES --> Use it | +-- Minor style changes --> sx prop | +-- Structural changes --> slots/slotProps | +-- Completely different behavior --> Build custom +-- NO --> Build custom +-- Simple interaction --> Base HTML + sx +-- Complex interaction --> Consider a headless component library
Color Scheme Strategy
Do you need dark mode? +-- YES --> Use colorSchemes in createTheme | +-- System preference only --> cssVariables: true | +-- Manual toggle --> useColorScheme hook | +-- Both --> colorSchemeSelector: "data" + useColorScheme +-- NO --> Single palette in createTheme
MUI X Component Selection
What data display do you need? +-- Tabular data | +-- Simple (< 100 rows, no editing) --> Table component | +-- Complex (sorting, filtering, pagination) --> DataGrid | +-- Large dataset (100K+ rows) --> DataGridPro (virtualized) +-- Date/time input --> DatePicker / DateTimePicker +-- Charts --> MUI X Charts +-- Tree structure --> TreeView
</decision_framework>
<integration>
Integration Notes
React 19: Full compatibility in MUI v7.
SSR Frameworks: Use
@mui/material-nextjs with AppRouterCacheProvider for Next.js App Router. See examples/core.md for setup.
CSS Layers: Enable with
enableCssLayer to integrate with utility-first CSS frameworks. Allows predictable specificity ordering.
Form Libraries: MUI
TextField works with any form library via inputRef for registration or controlled value/onChange props. Map validation errors to helperText and error props.
Styling Engine: Emotion is the default and only production-ready engine.
@emotion/react and @emotion/styled are required peer dependencies.
Package Ecosystem:
| Package | Purpose | Version |
|---|---|---|
| Core components (Button, TextField, etc.) | v7.x |
| sx prop, styled(), ThemeProvider | v7.x |
| 2000+ Material Design icons | v7.x |
| DataGrid (free tier) | v8.x |
| DataGrid Pro (sorting, filtering, etc.) | v8.x |
| DatePicker, TimePicker | v8.x |
| Bar, Line, Pie, Scatter charts | v8.x |
| TreeView component | v8.x |
| Next.js SSR integration | v7.x |
| Required peer dependency | v11.x |
| Required peer dependency | v11.x |
<red_flags>
RED FLAGS
High Priority Issues:
- Using
for conditional styles (causes SSR flicker -- usetheme.palette.mode === 'dark'
)theme.applyStyles('dark', {...}) - Missing
wrapper (components render with MUI defaults instead of your design tokens)ThemeProvider - Using barrel imports from
or@mui/material
(6x slower dev builds)@mui/icons-material - Inline object/function definitions in
prop (causes component remount every render)slots
Medium Priority Issues:
- Using deprecated
/components
instead ofcomponentsProps
/slots
(removed in future versions)slotProps - Using
instead of the newGridLegacy
component withGrid
propsize - Hardcoding colors/spacing instead of using theme tokens (
vs#1976d2
)primary.main - Using
prop instead ofstyle
(bypasses theme, no responsive support)sx - Deep importing beyond one level:
(broken in v7 ESM)@mui/material/styles/createTheme
Common Mistakes:
- Forgetting
(inconsistent cross-browser baseline styles)CssBaseline - Not memoizing DataGrid
array (causes unnecessary re-renders)columns - Using
for graduated components (Alert, Skeleton, etc. are now in@mui/lab
)@mui/material - Missing TypeScript augmentation for custom palette colors (no autocomplete, type errors at usage)
- Setting
manually on MUI components (conflicts with MUI's z-index scale)zIndex
Gotchas & Edge Cases:
- MUI components are client-only -- they require
in Next.js App Router pages, not just layout'use client'
prop arrays merge styles left-to-right; later items override earlier ones (useful for conditional styles)sx
theme value is a multiplier, not pixels:spacing
=spacing(2)
=2 * 8px
by default16pxGrid
prop in v7 replacessize
/xs
/sm
/md
/lg
individual props from Grid2xl
is a composed component (Input + InputLabel + FormHelperText) -- useTextField
to target the actual input elementslotProps.inputDialog
must not remount the Transition component -- keep it stable between rendersTransitionProps
returnsuseMediaQuery
during SSR -- design for mobile-first and handle the hydration mismatchfalse
is not tree-shakeable -- a large theme config doesn't increase bundle, but unused components still need tree shaking via path importscreateTheme
</red_flags>
<critical_reminders>
CRITICAL REMINDERS
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
, named constants)import type
(You MUST wrap the app in
with a ThemeProvider
instance -- never use MUI components without a theme)createTheme()
(You MUST use path imports (
) in development for faster startup -- barrel imports (@mui/material/Button
) cause 6x slower dev builds)@mui/material
(You MUST use
/slots
for component inner-element customization -- slotProps
is deprecated in v7)componentsProps
(You MUST use
for dark mode conditional styles -- never use theme.applyStyles('dark', {...})
which causes flickering)theme.palette.mode === 'dark'
Failure to follow these rules will cause SSR flickering, degraded dev performance, and deprecated API usage.
</critical_reminders>