
Mui
- 951 installs
- 29.9k repo stars
- Updated July 27, 2026
- davila7/claude-code-templates
mui is a Claude Code skill that provides Material-UI v7 component, sx prop, theme, and responsive patterns for developers who build type-safe React UIs and need guidance through v7 breaking changes from v6.
About
mui is a comprehensive skill from davila7/claude-code-templates for building React applications with Material-UI v7, released March 2025. It covers component usage, the sx prop styling system, theme integration, responsive design, and MUI-specific utilities with type-safe patterns. Developers reach for mui when styling with sx, migrating from MUI v6 breaking changes, wiring themes, or composing accessible layouts with one of the most widely used React UI libraries. The skill helps agents apply consistent MUI v7 conventions instead of mixing deprecated APIs or ad hoc CSS. Use mui during feature UI work, design-system alignment, or refactors touching MUI imports and theme tokens.
- Comprehensive patterns for MUI v7 components including Box, Grid, Paper, Typography, Button, Card and Dialog
- Guidance on the sx prop styling system and theme customization for consistent, type-safe React UIs
- Responsive design patterns using MUI's breakpoint system and mobile-first layouts
- Migration support for the breaking changes introduced in Material-UI v7 from v6
- MUI-specific utilities and hooks such as useTheme and useMediaQuery
Mui by the numbers
- 951 all-time installs (skills.sh)
- +20 installs in the week ending Jul 28, 2026 (Skillselion tracking)
- Ranked #384 of 2,277 Frontend Development skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Jul 28, 2026 (Skillselion catalog sync)
npx skills add https://github.com/davila7/claude-code-templates --skill muiAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 951 |
|---|---|
| repo stars | ★ 29.9k |
| Security audit | 3 / 3 scanners passed |
| Last updated | July 27, 2026 |
| Repository | davila7/claude-code-templates ↗ |
How do you build UIs with MUI v7?
Get reliable patterns and guidance when building React UIs with Material-UI v7.
Who is it for?
React developers adopting Material-UI v7 who need sx prop, theme, and migration guidance from v6 breaking changes.
Skip if: Vue, Svelte, or Tailwind-only projects that do not use Material-UI React components.
When should I use this skill?
The user builds or refactors React UI with Material-UI v7 components, sx prop styling, themes, or responsive MUI layouts.
What you get
MUI v7 React components with sx styling, theme tokens, and responsive layout patterns
- MUI v7 component implementations
- Theme and sx styling configuration
By the numbers
- Targets Material-UI v7 released March 2025
Files
MUI v7 Patterns
Purpose
Material-UI v7 (released March 2025) patterns for component usage, styling with sx prop, theme integration, and responsive design.
Note: MUI v7 breaking changes from v6:
- Deep imports no longer work - use package exports field
onBackdropClickremoved from Modal - useonCloseinstead- All components now use standardized
slotsandslotPropspattern - CSS layers support via
enableCssLayerconfig (works with Tailwind v4)
When to Use This Skill
- Styling components with MUI sx prop
- Using MUI components (Box, Grid, Paper, Typography, etc.)
- Theme customization and usage
- Responsive design with MUI breakpoints
- MUI-specific utilities and hooks
---
Quick Start
Basic MUI Component
import { Box, Typography, Button, Paper } from '@mui/material';
import type { SxProps, Theme } from '@mui/material';
const styles: Record<string, SxProps<Theme>> = {
container: {
p: 2,
display: 'flex',
flexDirection: 'column',
gap: 2,
},
header: {
mb: 3,
fontSize: '1.5rem',
fontWeight: 600,
},
};
function MyComponent() {
return (
<Paper sx={styles.container}>
<Typography sx={styles.header}>
Title
</Typography>
<Button variant="contained">
Action
</Button>
</Paper>
);
}---
Styling Patterns
Inline Styles (< 100 lines)
For components with simple styling, define styles at the top:
import type { SxProps, Theme } from '@mui/material';
const componentStyles: Record<string, SxProps<Theme>> = {
container: {
p: 2,
display: 'flex',
flexDirection: 'column',
},
header: {
mb: 2,
color: 'primary.main',
},
button: {
mt: 'auto',
alignSelf: 'flex-end',
},
};
function Component() {
return (
<Box sx={componentStyles.container}>
<Typography sx={componentStyles.header}>Header</Typography>
<Button sx={componentStyles.button}>Action</Button>
</Box>
);
}Separate Styles File (>= 100 lines)
For complex components, create separate style file:
// UserProfile.styles.ts
import type { SxProps, Theme } from '@mui/material';
export const userProfileStyles: Record<string, SxProps<Theme>> = {
container: {
p: 3,
maxWidth: 800,
mx: 'auto',
},
header: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
mb: 3,
},
// ... many more styles
};
// UserProfile.tsx
import { userProfileStyles as styles } from './UserProfile.styles';
function UserProfile() {
return <Box sx={styles.container}>...</Box>;
}---
Common Components
Layout Components
// Box - Generic container
<Box sx={{ p: 2, bgcolor: 'background.paper' }}>
Content
</Box>
// Paper - Elevated surface
<Paper elevation={2} sx={{ p: 3 }}>
Content
</Paper>
// Container - Centered content with max-width
<Container maxWidth="lg">
Content
</Container>
// Stack - Flex container with spacing
<Stack spacing={2} direction="row">
<Item />
<Item />
</Stack>Grid System
import { Grid } from '@mui/material';
// 12-column grid
<Grid container spacing={2}>
<Grid item xs={12} md={6}>
Left half
</Grid>
<Grid item xs={12} md={6}>
Right half
</Grid>
</Grid>
// Responsive grid
<Grid container spacing={3}>
<Grid item xs={12} sm={6} md={4} lg={3}>
Card
</Grid>
{/* Repeat for more cards */}
</Grid>Typography
<Typography variant="h1">Heading 1</Typography>
<Typography variant="h2">Heading 2</Typography>
<Typography variant="body1">Body text</Typography>
<Typography variant="caption">Small text</Typography>
// With custom styling
<Typography
variant="h4"
sx={{
color: 'primary.main',
fontWeight: 600,
mb: 2,
}}
>
Custom Heading
</Typography>Buttons
// Variants
<Button variant="contained">Contained</Button>
<Button variant="outlined">Outlined</Button>
<Button variant="text">Text</Button>
// Colors
<Button variant="contained" color="primary">Primary</Button>
<Button variant="contained" color="secondary">Secondary</Button>
<Button variant="contained" color="error">Error</Button>
// With icons
import { Add as AddIcon } from '@mui/icons-material';
<Button startIcon={<AddIcon />}>Add Item</Button>---
Theme Integration
Using Theme Values
import { useTheme } from '@mui/material';
function Component() {
const theme = useTheme();
return (
<Box
sx={{
p: 2,
bgcolor: theme.palette.primary.main,
color: theme.palette.primary.contrastText,
borderRadius: theme.shape.borderRadius,
}}
>
Themed box
</Box>
);
}Theme in sx Prop
<Box
sx={{
// Access theme in sx
color: 'primary.main', // theme.palette.primary.main
bgcolor: 'background.paper', // theme.palette.background.paper
p: 2, // theme.spacing(2)
borderRadius: 1, // theme.shape.borderRadius
}}
>
Content
</Box>
// Callback for advanced usage
<Box
sx={(theme) => ({
color: theme.palette.primary.main,
'&:hover': {
color: theme.palette.primary.dark,
},
})}
>
Hover me
</Box>---
Responsive Design
Breakpoints
// Mobile-first responsive values
<Box
sx={{
width: {
xs: '100%', // 0-600px
sm: '80%', // 600-900px
md: '60%', // 900-1200px
lg: '40%', // 1200-1536px
xl: '30%', // 1536px+
},
}}
>
Responsive width
</Box>
// Responsive display
<Box
sx={{
display: {
xs: 'none', // Hidden on mobile
md: 'block', // Visible on desktop
},
}}
>
Desktop only
</Box>Responsive Typography
<Typography
sx={{
fontSize: {
xs: '1rem',
md: '1.5rem',
lg: '2rem',
},
lineHeight: {
xs: 1.5,
md: 1.75,
},
}}
>
Responsive text
</Typography>---
Forms
import { TextField, Stack, Button } from '@mui/material';
<Box component="form" onSubmit={handleSubmit}>
<Stack spacing={2}>
<TextField
label="Email"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
fullWidth
required
error={!!errors.email}
helperText={errors.email}
/>
<Button type="submit" variant="contained">Submit</Button>
</Stack>
</Box>---
Common Patterns
Card Component
import { Card, CardContent, CardActions, Typography, Button } from '@mui/material';
<Card>
<CardContent>
<Typography variant="h5" component="div">
Title
</Typography>
<Typography variant="body2" color="text.secondary">
Description
</Typography>
</CardContent>
<CardActions>
<Button size="small">Learn More</Button>
</CardActions>
</Card>Dialog/Modal
import { Dialog, DialogTitle, DialogContent, DialogActions, Button } from '@mui/material';
<Dialog open={open} onClose={handleClose}>
<DialogTitle>Confirm Action</DialogTitle>
<DialogContent>
Are you sure you want to proceed?
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Cancel</Button>
<Button onClick={handleConfirm} variant="contained">
Confirm
</Button>
</DialogActions>
</Dialog>Loading States
import { CircularProgress, Skeleton } from '@mui/material';
// Spinner
<Box sx={{ display: 'flex', justifyContent: 'center', p: 3 }}>
<CircularProgress />
</Box>
// Skeleton
<Stack spacing={1}>
<Skeleton variant="text" width="60%" />
<Skeleton variant="rectangular" height={200} />
<Skeleton variant="text" width="40%" />
</Stack>---
MUI-Specific Hooks
useMuiSnackbar
import { useMuiSnackbar } from '@/hooks/useMuiSnackbar';
function Component() {
const { showSuccess, showError, showInfo } = useMuiSnackbar();
const handleSave = async () => {
try {
await saveData();
showSuccess('Saved successfully');
} catch (error) {
showError('Failed to save');
}
};
return <Button onClick={handleSave}>Save</Button>;
}---
Icons
import { Add as AddIcon, Delete as DeleteIcon } from '@mui/icons-material';
import { Button, IconButton } from '@mui/material';
<Button startIcon={<AddIcon />}>Add</Button>
<IconButton onClick={handleDelete}><DeleteIcon /></IconButton>---
Best Practices
1. Type Your sx Props
import type { SxProps, Theme } from '@mui/material';
// ✅ Good
const styles: Record<string, SxProps<Theme>> = {
container: { p: 2 },
};
// ❌ Avoid
const styles = {
container: { p: 2 }, // No type safety
};2. Use Theme Tokens
// ✅ Good: Use theme tokens
<Box sx={{ color: 'primary.main', p: 2 }} />
// ❌ Avoid: Hardcoded values
<Box sx={{ color: '#1976d2', padding: '16px' }} />3. Consistent Spacing
// ✅ Good: Use spacing scale
<Box sx={{ p: 2, mb: 3, mt: 1 }} />
// ❌ Avoid: Random pixel values
<Box sx={{ padding: '17px', marginBottom: '25px' }} />---
Additional Resources
For more detailed patterns, see:
- styling-guide.md - Advanced styling patterns
- component-library.md - Component examples
- theme-customization.md - Theme setup
MUI v7 Patterns Skill
A comprehensive skill for working with Material-UI v7 components, styling, and best practices in React applications.
Purpose
This skill provides guidance and patterns for building React applications with Material-UI v7 (released March 2025). It covers component usage, the sx prop styling system, theme integration, responsive design, and MUI-specific utilities.
MUI is one of the most popular React UI libraries, and v7 introduced several breaking changes from v6. This skill helps developers navigate these changes while following consistent, type-safe patterns.
When to Use
Use this skill when you are:
- Styling components with the sx prop - Need guidance on MUI's styling approach
- Working with MUI components - Using Box, Grid, Paper, Typography, Button, Card, Dialog, and other MUI components
- Customizing themes - Setting up or modifying MUI themes
- Building responsive layouts - Using MUI's breakpoint system for mobile-first design
- Using MUI utilities and hooks - Working with useTheme, useMediaQuery, or custom MUI hooks
- Migrating from MUI v6 - Understanding v7 breaking changes
Trigger phrases:
- "style with sx prop"
- "MUI component"
- "Material-UI"
- "theme customization"
- "MUI responsive design"
- "MUI Grid layout"
How It Works
1. Identify the MUI task - Recognize when MUI patterns are relevant to the current work 2. Apply appropriate patterns - Use the correct styling approach based on component complexity 3. Leverage theme tokens - Use MUI's built-in theme values instead of hardcoded styles 4. Ensure type safety - Apply proper TypeScript types for sx props 5. Build responsively - Use MUI's breakpoint system for adaptive layouts
Key Features
MUI v7 Breaking Changes Awareness
The skill includes guidance on v7-specific changes:
- Deep imports no longer work (use package exports)
onBackdropClickremoved from Modal (useonCloseinstead)- Standardized
slotsandslotPropspattern for all components - CSS layers support via
enableCssLayerconfig (Tailwind v4 compatible)
Styling Patterns
Two approaches based on component complexity:
- Inline styles (< 100 lines) - Define styles at component top
- Separate styles file (>= 100 lines) - Create
ComponentName.styles.ts
Complete Component Coverage
- Layout: Box, Paper, Container, Stack
- Grid system: 12-column responsive grid
- Typography: All variants with custom styling
- Forms: TextField, validation, error states
- Feedback: Dialog, Snackbar, Loading states
- Navigation: Cards, Buttons, Icons
Theme Integration
- Direct theme value access in sx prop
- useTheme hook for programmatic access
- Callback syntax for complex theme-dependent styles
Responsive Design
- Mobile-first breakpoint system (xs, sm, md, lg, xl)
- Responsive prop values for any CSS property
- Conditional display based on screen size
Usage Examples
Basic Component with sx Prop
import { Box, Typography, Button, Paper } from '@mui/material';
import type { SxProps, Theme } from '@mui/material';
const styles: Record<string, SxProps<Theme>> = {
container: {
p: 2,
display: 'flex',
flexDirection: 'column',
gap: 2,
},
header: {
mb: 3,
fontSize: '1.5rem',
fontWeight: 600,
},
};
function MyComponent() {
return (
<Paper sx={styles.container}>
<Typography sx={styles.header}>Title</Typography>
<Button variant="contained">Action</Button>
</Paper>
);
}Responsive Layout
<Box
sx={{
width: {
xs: '100%', // 0-600px
sm: '80%', // 600-900px
md: '60%', // 900-1200px
lg: '40%', // 1200px+
},
display: {
xs: 'none', // Hidden on mobile
md: 'block', // Visible on desktop
},
}}
>
Responsive content
</Box>Grid System
import { Grid } from '@mui/material';
<Grid container spacing={3}>
<Grid item xs={12} sm={6} md={4} lg={3}>
<Card>...</Card>
</Grid>
<Grid item xs={12} sm={6} md={4} lg={3}>
<Card>...</Card>
</Grid>
</Grid>Theme-Aware Styling
<Box
sx={(theme) => ({
color: theme.palette.primary.main,
bgcolor: 'background.paper',
p: 2,
'&:hover': {
color: theme.palette.primary.dark,
},
})}
>
Theme-integrated content
</Box>Prerequisites
- React 18 or later
- Material-UI v7 packages installed:
@mui/material@mui/icons-material(for icons)- TypeScript (recommended for type safety)
Output
This skill produces:
- Type-safe component code using MUI patterns
- Properly structured style definitions
- Responsive, theme-integrated layouts
- Accessible UI components following MUI conventions
Best Practices
1. Always Type Your sx Props
import type { SxProps, Theme } from '@mui/material';
const styles: Record<string, SxProps<Theme>> = {
container: { p: 2 },
};2. Use Theme Tokens Over Hardcoded Values
// Good
<Box sx={{ color: 'primary.main', p: 2 }} />
// Avoid
<Box sx={{ color: '#1976d2', padding: '16px' }} />3. Use MUI Spacing Scale
// Good - Uses theme.spacing()
<Box sx={{ p: 2, mb: 3, mt: 1 }} />
// Avoid - Random pixel values
<Box sx={{ padding: '17px', marginBottom: '25px' }} />4. Organize Styles by Component Complexity
- Small components: Define styles at the top of the file
- Large components: Create separate
ComponentName.styles.tsfile
5. Use Semantic Color Names
Access palette colors by their semantic names:
primary.main,primary.light,primary.darksecondary.main,error.main,warning.maintext.primary,text.secondarybackground.paper,background.default
Additional Resources
The skill includes supplementary documentation:
resources/styling-guide.md- Advanced styling patternsresources/component-library.md- Extended component examplesresources/theme-customization.md- Theme setup and customization
Related Documentation
MUI Component Library
Layout Components
Box
The fundamental building block:
<Box
component="section"
sx={{
display: 'flex',
flexDirection: 'column',
gap: 2,
p: 3,
bgcolor: 'background.paper',
borderRadius: 2
}}
>
<Typography variant="h5">Section Title</Typography>
<Typography variant="body1">Content goes here</Typography>
</Box>Container
Centers content with max-width:
<Container maxWidth="lg" sx={{ py: 4 }}>
{/* Content automatically centered and constrained */}
</Container>Grid (v2)
Responsive grid layout:
import Grid from '@mui/material/Grid2';
<Grid container spacing={2}>
<Grid xs={12} sm={6} md={4}>
<Card>Item 1</Card>
</Grid>
<Grid xs={12} sm={6} md={4}>
<Card>Item 2</Card>
</Grid>
<Grid xs={12} sm={6} md={4}>
<Card>Item 3</Card>
</Grid>
</Grid>Stack
One-dimensional layout with spacing:
<Stack direction="row" spacing={2} alignItems="center">
<Avatar src={user.avatar} />
<Typography>{user.name}</Typography>
<Chip label={user.role} />
</Stack>Data Display
Typography
Text with theme variants:
<Typography variant="h1" component="h1" gutterBottom>
Main Heading
</Typography>
<Typography variant="body1" color="text.secondary">
Body text with secondary color
</Typography>
<Typography variant="caption" sx={{ fontWeight: 'bold' }}>
Bold caption
</Typography>Card
Content container:
<Card>
<CardMedia
component="img"
height="200"
image="/image.jpg"
alt="Description"
/>
<CardContent>
<Typography variant="h5" component="h2">
Card Title
</Typography>
<Typography variant="body2" color="text.secondary">
Card description text
</Typography>
</CardContent>
<CardActions>
<Button size="small">Learn More</Button>
<Button size="small">Share</Button>
</CardActions>
</Card>List
Structured content lists:
<List>
<ListItem disablePadding>
<ListItemButton onClick={handleClick}>
<ListItemIcon>
<InboxIcon />
</ListItemIcon>
<ListItemText
primary="Inbox"
secondary="5 new messages"
/>
</ListItemButton>
</ListItem>
<Divider />
<ListItem>
<ListItemAvatar>
<Avatar src="/avatar.jpg" />
</ListItemAvatar>
<ListItemText
primary="John Doe"
secondary="Online"
/>
</ListItem>
</List>Table
Data tables:
<TableContainer component={Paper}>
<Table>
<TableHead>
<TableRow>
<TableCell>Name</TableCell>
<TableCell>Email</TableCell>
<TableCell align="right">Actions</TableCell>
</TableRow>
</TableHead>
<TableBody>
{rows.map((row) => (
<TableRow key={row.id} hover>
<TableCell>{row.name}</TableCell>
<TableCell>{row.email}</TableCell>
<TableCell align="right">
<IconButton size="small">
<EditIcon />
</IconButton>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>Input Components
TextField
Text input with validation:
<TextField
label="Email"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
error={!!emailError}
helperText={emailError}
fullWidth
required
/>Select
Dropdown selection:
<FormControl fullWidth>
<InputLabel>Country</InputLabel>
<Select
value={country}
onChange={(e) => setCountry(e.target.value)}
label="Country"
>
<MenuItem value="us">United States</MenuItem>
<MenuItem value="uk">United Kingdom</MenuItem>
<MenuItem value="ca">Canada</MenuItem>
</Select>
</FormControl>Checkbox & Switch
Boolean inputs:
<FormControlLabel
control={<Checkbox checked={agreed} onChange={handleChange} />}
label="I agree to the terms"
/>
<FormControlLabel
control={<Switch checked={enabled} onChange={handleToggle} />}
label="Enable notifications"
/>Radio Group
Single selection:
<FormControl>
<FormLabel>Payment Method</FormLabel>
<RadioGroup value={payment} onChange={(e) => setPayment(e.target.value)}>
<FormControlLabel value="card" control={<Radio />} label="Credit Card" />
<FormControlLabel value="paypal" control={<Radio />} label="PayPal" />
<FormControlLabel value="crypto" control={<Radio />} label="Cryptocurrency" />
</RadioGroup>
</FormControl>Autocomplete
Searchable select:
<Autocomplete
options={options}
getOptionLabel={(option) => option.label}
value={value}
onChange={(event, newValue) => setValue(newValue)}
renderInput={(params) => (
<TextField {...params} label="Search" placeholder="Type to search..." />
)}
/>Buttons
Button Variants
<Stack direction="row" spacing={2}>
<Button variant="contained">Contained</Button>
<Button variant="outlined">Outlined</Button>
<Button variant="text">Text</Button>
</Stack>Button with Icons
<Button
variant="contained"
startIcon={<SaveIcon />}
onClick={handleSave}
>
Save Changes
</Button>
<IconButton color="primary">
<DeleteIcon />
</IconButton>
<Fab color="primary" sx={{ position: 'fixed', bottom: 16, right: 16 }}>
<AddIcon />
</Fab>Feedback Components
Alert
Status messages:
<Alert severity="success" onClose={handleClose}>
Operation completed successfully!
</Alert>
<Alert severity="error" icon={<ErrorIcon />}>
An error occurred. Please try again.
</Alert>Snackbar
Toast notifications:
<Snackbar
open={open}
autoHideDuration={6000}
onClose={handleClose}
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
>
<Alert onClose={handleClose} severity="success">
Changes saved!
</Alert>
</Snackbar>Dialog
Modal dialogs:
<Dialog open={open} onClose={handleClose} maxWidth="sm" fullWidth>
<DialogTitle>Confirm Delete</DialogTitle>
<DialogContent>
<DialogContentText>
Are you sure you want to delete this item? This action cannot be undone.
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Cancel</Button>
<Button onClick={handleDelete} color="error" variant="contained">
Delete
</Button>
</DialogActions>
</Dialog>CircularProgress & LinearProgress
Loading indicators:
<CircularProgress />
<CircularProgress size={20} />
<CircularProgress variant="determinate" value={progress} />
<LinearProgress />
<LinearProgress variant="determinate" value={progress} />
<LinearProgress color="secondary" />Skeleton
Content placeholders:
<Stack spacing={1}>
<Skeleton variant="text" width="60%" height={40} />
<Skeleton variant="rectangular" width="100%" height={200} />
<Skeleton variant="circular" width={40} height={40} />
</Stack>Navigation
AppBar & Toolbar
Application header:
<AppBar position="static">
<Toolbar>
<IconButton edge="start" color="inherit">
<MenuIcon />
</IconButton>
<Typography variant="h6" sx={{ flexGrow: 1 }}>
App Title
</Typography>
<IconButton color="inherit">
<AccountCircle />
</IconButton>
</Toolbar>
</AppBar>Drawer
Side navigation:
<Drawer
anchor="left"
open={open}
onClose={handleClose}
>
<Box sx={{ width: 250 }} role="presentation">
<List>
<ListItem button onClick={() => navigate('/dashboard')}>
<ListItemIcon><DashboardIcon /></ListItemIcon>
<ListItemText primary="Dashboard" />
</ListItem>
<ListItem button onClick={() => navigate('/settings')}>
<ListItemIcon><SettingsIcon /></ListItemIcon>
<ListItemText primary="Settings" />
</ListItem>
</List>
</Box>
</Drawer>Tabs
Tabbed navigation:
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
<Tabs value={tab} onChange={handleChange}>
<Tab label="Overview" />
<Tab label="Details" />
<Tab label="Settings" />
</Tabs>
</Box>
<TabPanel value={tab} index={0}>
Overview content
</TabPanel>Breadcrumbs
Navigation trail:
<Breadcrumbs>
<Link underline="hover" color="inherit" href="/">
Home
</Link>
<Link underline="hover" color="inherit" href="/products">
Products
</Link>
<Typography color="text.primary">Electronics</Typography>
</Breadcrumbs>Utility Components
Tooltip
Helpful hints:
<Tooltip title="Delete item" arrow placement="top">
<IconButton>
<DeleteIcon />
</IconButton>
</Tooltip>Popover
Floating content:
<Popover
open={open}
anchorEl={anchorEl}
onClose={handleClose}
anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
>
<Box sx={{ p: 2 }}>
<Typography>Popover content</Typography>
</Box>
</Popover>Menu
Context menus:
<Menu
anchorEl={anchorEl}
open={open}
onClose={handleClose}
>
<MenuItem onClick={handleEdit}>
<ListItemIcon><EditIcon /></ListItemIcon>
<ListItemText>Edit</ListItemText>
</MenuItem>
<MenuItem onClick={handleDelete}>
<ListItemIcon><DeleteIcon /></ListItemIcon>
<ListItemText>Delete</ListItemText>
</MenuItem>
</Menu>Chip
Compact information:
<Stack direction="row" spacing={1}>
<Chip label="Active" color="success" />
<Chip label="Pending" color="warning" />
<Chip
label="Admin"
onDelete={handleDelete}
deleteIcon={<CloseIcon />}
/>
</Stack>Badge
Notification indicators:
<Badge badgeContent={4} color="error">
<MailIcon />
</Badge>
<Badge variant="dot" color="success">
<Avatar src="/avatar.jpg" />
</Badge>Avatar
User images:
<Stack direction="row" spacing={2}>
<Avatar src="/avatar.jpg" />
<Avatar sx={{ bgcolor: 'primary.main' }}>JD</Avatar>
<Avatar variant="square" src="/logo.png" />
<AvatarGroup max={3}>
<Avatar src="/user1.jpg" />
<Avatar src="/user2.jpg" />
<Avatar src="/user3.jpg" />
<Avatar src="/user4.jpg" />
</AvatarGroup>
</Stack>Form Example
Complete form with validation:
<Box component="form" onSubmit={handleSubmit} sx={{ maxWidth: 600 }}>
<Stack spacing={3}>
<TextField
label="Full Name"
required
fullWidth
error={!!errors.name}
helperText={errors.name}
/>
<TextField
label="Email"
type="email"
required
fullWidth
error={!!errors.email}
helperText={errors.email}
/>
<FormControl fullWidth>
<InputLabel>Role</InputLabel>
<Select label="Role" value={role} onChange={(e) => setRole(e.target.value)}>
<MenuItem value="user">User</MenuItem>
<MenuItem value="admin">Admin</MenuItem>
</Select>
</FormControl>
<FormControlLabel
control={<Checkbox checked={agreed} onChange={(e) => setAgreed(e.target.checked)} />}
label="I agree to the terms and conditions"
/>
<Stack direction="row" spacing={2} justifyContent="flex-end">
<Button variant="outlined" onClick={handleCancel}>
Cancel
</Button>
<Button type="submit" variant="contained" disabled={!agreed}>
Submit
</Button>
</Stack>
</Stack>
</Box>MUI Styling Guide
The sx Prop
The sx prop is the primary styling method in MUI v7+:
<Box
sx={{
p: 2, // padding: theme.spacing(2)
mb: 3, // marginBottom: theme.spacing(3)
bgcolor: 'primary.main', // theme.palette.primary.main
color: 'white',
borderRadius: 1, // theme.shape.borderRadius
'&:hover': {
bgcolor: 'primary.dark'
}
}}
/>Theme-Aware Values
// Spacing (multiplied by theme.spacing, default 8px)
sx={{ p: 2 }} // padding: 16px
// Colors from palette
sx={{ bgcolor: 'primary.main', color: 'text.secondary' }}
// Breakpoints
sx={{
width: { xs: '100%', sm: '50%', md: '33%' }
}}
// Typography variants
sx={{ typography: 'h4' }} // Applies theme.typography.h4Responsive Styles
<Box
sx={{
display: { xs: 'block', md: 'flex' },
flexDirection: { xs: 'column', md: 'row' },
gap: { xs: 1, sm: 2, md: 3 },
p: { xs: 2, sm: 3, md: 4 }
}}
/>Pseudo-Selectors and Nested Styles
<Button
sx={{
'&:hover': {
bgcolor: 'primary.dark'
},
'&:disabled': {
opacity: 0.5
},
'& .MuiButton-startIcon': {
mr: 1
}
}}
/>Dynamic Styles
interface CardProps {
isActive: boolean;
priority: 'low' | 'medium' | 'high';
}
function Card({ isActive, priority }: CardProps) {
return (
<Paper
sx={{
borderLeft: 4,
borderColor: isActive ? 'success.main' : 'grey.300',
bgcolor: priority === 'high' ? 'error.light' : 'background.paper',
opacity: isActive ? 1 : 0.7
}}
/>
);
}Global Styles with GlobalStyles
import { GlobalStyles } from '@mui/material';
<GlobalStyles
styles={{
body: {
margin: 0,
padding: 0
},
'*': {
boxSizing: 'border-box'
},
'.custom-scrollbar::-webkit-scrollbar': {
width: 8
}
}}
/>Styled Components API
For reusable styled components:
import { styled } from '@mui/material/styles';
const StyledCard = styled(Card)(({ theme }) => ({
padding: theme.spacing(2),
borderRadius: theme.shape.borderRadius * 2,
backgroundColor: theme.palette.background.paper,
transition: theme.transitions.create(['transform', 'box-shadow']),
'&:hover': {
transform: 'translateY(-4px)',
boxShadow: theme.shadows[8]
}
}));
// With props
interface StyledButtonProps {
variant: 'primary' | 'secondary';
}
const StyledButton = styled(Button)<StyledButtonProps>(({ theme, variant }) => ({
backgroundColor: variant === 'primary'
? theme.palette.primary.main
: theme.palette.secondary.main,
color: theme.palette.primary.contrastText,
'&:hover': {
backgroundColor: variant === 'primary'
? theme.palette.primary.dark
: theme.palette.secondary.dark
}
}));Theme Overrides
import { createTheme } from '@mui/material/styles';
const theme = createTheme({
components: {
MuiButton: {
styleOverrides: {
root: {
borderRadius: 8,
textTransform: 'none',
fontWeight: 600
},
containedPrimary: {
boxShadow: 'none',
'&:hover': {
boxShadow: 'none'
}
}
},
defaultProps: {
disableRipple: true
}
},
MuiCard: {
styleOverrides: {
root: {
borderRadius: 12,
boxShadow: '0 2px 8px rgba(0,0,0,0.1)'
}
}
}
}
});CSS Variables (MUI v7+)
// In theme configuration
const theme = createTheme({
cssVariables: true
});
// Use in sx prop
<Box sx={{ color: 'var(--mui-palette-primary-main)' }} />
// Use in CSS
.custom-element {
background-color: var(--mui-palette-background-paper);
padding: var(--mui-spacing-2);
}Common Patterns
Card with Hover Effect
<Card
sx={{
p: 3,
transition: 'all 0.3s',
'&:hover': {
transform: 'scale(1.02)',
boxShadow: 4
}
}}
/>Gradient Background
<Box
sx={{
background: (theme) =>
`linear-gradient(45deg, ${theme.palette.primary.main} 30%, ${theme.palette.secondary.main} 90%)`,
color: 'white'
}}
/>Sticky Header
<AppBar
sx={{
position: 'sticky',
top: 0,
zIndex: (theme) => theme.zIndex.drawer + 1
}}
/>Flexbox Layouts
<Box
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
gap: 2
}}
/>Performance Tips
- Use sx prop for dynamic styles - Better tree-shaking
- Use styled() for static reusable components - Better performance
- Avoid inline functions in sx - Can cause re-renders
- Leverage theme tokens - Consistent and performant
// ❌ Bad: Inline function in sx
<Box sx={() => ({ p: 2 })} />
// ✅ Good: Direct object
<Box sx={{ p: 2 }} />
// ✅ Good: Memoized function for complex logic
const getSx = useMemo(() => ({ p: 2, /* complex logic */ }), [deps]);
<Box sx={getSx} />Debugging Styles
// Inspect theme in console
<Box sx={(theme) => {
console.log('Theme:', theme);
return { p: 2 };
}} />
// Use sx as array for conditional styles
<Box sx={[
{ p: 2 },
isActive && { bgcolor: 'primary.main' },
isDisabled && { opacity: 0.5 }
]} />MUI Theme Customization
Creating a Custom Theme
import { createTheme, ThemeProvider } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
const theme = createTheme({
palette: {
mode: 'light',
primary: {
main: '#1976d2',
light: '#42a5f5',
dark: '#1565c0',
contrastText: '#fff'
},
secondary: {
main: '#9c27b0',
light: '#ba68c8',
dark: '#7b1fa2',
contrastText: '#fff'
},
error: {
main: '#d32f2f'
},
warning: {
main: '#ed6c02'
},
info: {
main: '#0288d1'
},
success: {
main: '#2e7d32'
}
},
typography: {
fontFamily: '"Inter", "Roboto", "Helvetica", "Arial", sans-serif',
h1: {
fontSize: '2.5rem',
fontWeight: 600
},
h2: {
fontSize: '2rem',
fontWeight: 600
},
button: {
textTransform: 'none',
fontWeight: 600
}
},
shape: {
borderRadius: 8
},
spacing: 8
});
function App() {
return (
<ThemeProvider theme={theme}>
<CssBaseline />
{/* Your app */}
</ThemeProvider>
);
}Dark Mode Support
const getTheme = (mode: 'light' | 'dark') => createTheme({
palette: {
mode,
...(mode === 'light'
? {
// Light mode colors
primary: { main: '#1976d2' },
background: {
default: '#f5f5f5',
paper: '#ffffff'
}
}
: {
// Dark mode colors
primary: { main: '#90caf9' },
background: {
default: '#121212',
paper: '#1e1e1e'
}
})
}
});
function App() {
const [mode, setMode] = useState<'light' | 'dark'>('light');
const theme = useMemo(() => getTheme(mode), [mode]);
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<IconButton onClick={() => setMode(m => m === 'light' ? 'dark' : 'light')}>
{mode === 'light' ? <DarkModeIcon /> : <LightModeIcon />}
</IconButton>
{/* Your app */}
</ThemeProvider>
);
}Typography Customization
const theme = createTheme({
typography: {
fontFamily: '"Inter", sans-serif',
fontSize: 14,
fontWeightLight: 300,
fontWeightRegular: 400,
fontWeightMedium: 500,
fontWeightBold: 700,
h1: {
fontSize: '3rem',
fontWeight: 700,
lineHeight: 1.2,
letterSpacing: '-0.01562em'
},
h2: {
fontSize: '2.5rem',
fontWeight: 700,
lineHeight: 1.3
},
body1: {
fontSize: '1rem',
lineHeight: 1.5,
letterSpacing: '0.00938em'
},
button: {
fontSize: '0.875rem',
fontWeight: 600,
textTransform: 'none',
letterSpacing: '0.02857em'
}
}
});Component Style Overrides
const theme = createTheme({
components: {
MuiButton: {
styleOverrides: {
root: {
borderRadius: 8,
padding: '8px 16px',
boxShadow: 'none',
'&:hover': {
boxShadow: 'none'
}
},
contained: {
'&:hover': {
transform: 'translateY(-2px)',
transition: 'transform 0.2s'
}
}
},
defaultProps: {
disableElevation: true
}
},
MuiCard: {
styleOverrides: {
root: {
borderRadius: 12,
boxShadow: '0 2px 8px rgba(0,0,0,0.1)'
}
}
},
MuiTextField: {
defaultProps: {
variant: 'outlined',
size: 'medium'
},
styleOverrides: {
root: {
'& .MuiOutlinedInput-root': {
borderRadius: 8
}
}
}
},
MuiChip: {
styleOverrides: {
root: {
borderRadius: 6,
fontWeight: 500
}
}
}
}
});Breakpoints
const theme = createTheme({
breakpoints: {
values: {
xs: 0,
sm: 600,
md: 960,
lg: 1280,
xl: 1920
}
}
});
// Usage
<Box
sx={{
width: {
xs: '100%', // 0-599px
sm: '80%', // 600-959px
md: '60%', // 960-1279px
lg: '50%' // 1280px+
}
}}
/>Spacing
const theme = createTheme({
spacing: 8 // Base unit: 8px
});
// Usage: theme.spacing(2) = 16px
<Box sx={{ p: 2, m: 3 }} /> // padding: 16px, margin: 24pxCustom Palette Colors
declare module '@mui/material/styles' {
interface Palette {
tertiary: Palette['primary'];
}
interface PaletteOptions {
tertiary?: PaletteOptions['primary'];
}
}
const theme = createTheme({
palette: {
primary: {
main: '#1976d2'
},
secondary: {
main: '#9c27b0'
},
tertiary: {
main: '#ff9800',
light: '#ffb74d',
dark: '#f57c00',
contrastText: '#000'
}
}
});
// Usage
<Button color="tertiary">Tertiary Button</Button>Shadows
const theme = createTheme({
shadows: [
'none',
'0 2px 4px rgba(0,0,0,0.1)',
'0 4px 8px rgba(0,0,0,0.12)',
'0 8px 16px rgba(0,0,0,0.14)',
// ... up to shadows[24]
]
});
// Usage
<Paper elevation={2} /> // Uses shadows[2]Z-Index Layers
const theme = createTheme({
zIndex: {
mobileStepper: 1000,
speedDial: 1050,
appBar: 1100,
drawer: 1200,
modal: 1300,
snackbar: 1400,
tooltip: 1500
}
});Transitions
const theme = createTheme({
transitions: {
duration: {
shortest: 150,
shorter: 200,
short: 250,
standard: 300,
complex: 375,
enteringScreen: 225,
leavingScreen: 195
},
easing: {
easeInOut: 'cubic-bezier(0.4, 0, 0.2, 1)',
easeOut: 'cubic-bezier(0.0, 0, 0.2, 1)',
easeIn: 'cubic-bezier(0.4, 0, 1, 1)',
sharp: 'cubic-bezier(0.4, 0, 0.6, 1)'
}
}
});
// Usage
<Box
sx={{
transition: (theme) =>
theme.transitions.create(['transform', 'background-color'], {
duration: theme.transitions.duration.standard
})
}}
/>Complete Theme Example
import { createTheme } from '@mui/material/styles';
const theme = createTheme({
palette: {
mode: 'light',
primary: {
main: '#2563eb',
light: '#60a5fa',
dark: '#1e40af',
contrastText: '#ffffff'
},
secondary: {
main: '#7c3aed',
light: '#a78bfa',
dark: '#5b21b6',
contrastText: '#ffffff'
},
error: {
main: '#dc2626'
},
warning: {
main: '#f59e0b'
},
info: {
main: '#0ea5e9'
},
success: {
main: '#10b981'
},
background: {
default: '#f8fafc',
paper: '#ffffff'
},
text: {
primary: '#0f172a',
secondary: '#64748b'
}
},
typography: {
fontFamily: '"Inter", "Segoe UI", "Roboto", sans-serif',
fontSize: 14,
h1: {
fontSize: '3rem',
fontWeight: 700,
lineHeight: 1.2
},
h2: {
fontSize: '2.25rem',
fontWeight: 700,
lineHeight: 1.3
},
h3: {
fontSize: '1.875rem',
fontWeight: 600,
lineHeight: 1.4
},
h4: {
fontSize: '1.5rem',
fontWeight: 600,
lineHeight: 1.5
},
h5: {
fontSize: '1.25rem',
fontWeight: 600,
lineHeight: 1.6
},
h6: {
fontSize: '1rem',
fontWeight: 600,
lineHeight: 1.6
},
button: {
textTransform: 'none',
fontWeight: 600,
fontSize: '0.875rem'
}
},
shape: {
borderRadius: 10
},
spacing: 8,
components: {
MuiButton: {
styleOverrides: {
root: {
borderRadius: 8,
padding: '10px 20px',
fontWeight: 600,
boxShadow: 'none',
'&:hover': {
boxShadow: 'none'
}
},
contained: {
'&:hover': {
transform: 'translateY(-1px)',
boxShadow: '0 4px 12px rgba(0,0,0,0.15)'
}
}
},
defaultProps: {
disableElevation: true
}
},
MuiCard: {
styleOverrides: {
root: {
borderRadius: 12,
boxShadow: '0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24)',
'&:hover': {
boxShadow: '0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23)'
}
}
}
},
MuiTextField: {
defaultProps: {
variant: 'outlined'
},
styleOverrides: {
root: {
'& .MuiOutlinedInput-root': {
borderRadius: 8,
'&:hover .MuiOutlinedInput-notchedOutline': {
borderColor: '#2563eb'
}
}
}
}
},
MuiChip: {
styleOverrides: {
root: {
borderRadius: 6,
fontWeight: 500,
height: 28
}
}
},
MuiAppBar: {
styleOverrides: {
root: {
boxShadow: '0 1px 3px rgba(0,0,0,0.12)'
}
}
}
}
});
export default theme;Theme Provider Setup
// src/theme.ts - Export your theme
export { default as theme } from './theme';
// src/main.tsx or src/index.tsx
import { ThemeProvider } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
import theme from './theme';
root.render(
<StrictMode>
<ThemeProvider theme={theme}>
<CssBaseline />
<App />
</ThemeProvider>
</StrictMode>
);Accessing Theme in Components
import { useTheme } from '@mui/material/styles';
function MyComponent() {
const theme = useTheme();
return (
<Box
sx={{
color: theme.palette.primary.main,
padding: theme.spacing(2),
borderRadius: theme.shape.borderRadius
}}
/>
);
}Theme Nesting
import { createTheme, ThemeProvider, useTheme } from '@mui/material/styles';
function NestedTheme() {
const outerTheme = useTheme();
const innerTheme = createTheme({
...outerTheme,
palette: {
...outerTheme.palette,
mode: 'dark'
}
});
return (
<ThemeProvider theme={innerTheme}>
<Box sx={{ bgcolor: 'background.default', p: 2 }}>
Dark section within light app
</Box>
</ThemeProvider>
);
}{
"mui": {
"type": "domain",
"enforcement": "suggest",
"priority": "high",
"promptTriggers": {
"keywords": [
"mui",
"material-ui",
"material ui",
"@mui/material",
"@mui/icons-material",
"@mui/system",
"sx prop",
"mui theme",
"ThemeProvider",
"createTheme",
"useTheme",
"styled",
"Box",
"Typography",
"Button",
"TextField",
"Card",
"Dialog",
"Drawer",
"AppBar",
"Grid",
"Stack",
"Paper",
"Container",
"IconButton",
"Chip",
"Avatar",
"Alert",
"Snackbar",
"Menu",
"MenuItem",
"Select",
"Checkbox",
"Radio",
"Switch",
"Tabs",
"Autocomplete"
],
"intentPatterns": [
"style.*with.*mui",
"use.*mui.*component",
"create.*mui.*theme",
"customize.*mui",
"add.*material.*ui.*component",
"implement.*mui.*dialog",
"create.*mui.*form",
"setup.*mui.*theme",
"use.*mui.*icon",
"add.*mui.*(button|card|dialog|form|menu)"
]
},
"fileTriggers": {
"pathPatterns": [
"**/*.styles.ts",
"**/*.styles.tsx",
"**/components/**/*.tsx",
"**/components/**/*.ts",
"**/theme.ts",
"**/theme.tsx",
"**/theme/**/*.ts"
],
"contentPatterns": [
"import.*@mui/material",
"import.*@mui/icons-material",
"import.*@mui/system",
"from '@mui/material'",
"sx=\\{",
"<Box",
"<Typography",
"createTheme\\(",
"ThemeProvider",
"useTheme\\(\\)",
"styled\\("
]
}
}
}
Related skills
How it compares
Use mui over generic React UI skills when the stack is Material-UI v7 and agents must follow sx, theme, and v6-to-v7 migration rules.
FAQ
Which MUI version does the mui skill target?
The mui skill targets Material-UI v7, released March 2025. It documents component usage, sx prop styling, theme integration, responsive design, and utilities while addressing breaking changes developers face migrating from MUI v6.
When should the mui skill be used?
The mui skill applies when building or refactoring React apps with Material-UI v7—styling via sx, wiring themes, composing responsive layouts, or navigating v7 API changes with type-safe patterns instead of deprecated v6 approaches.
Is Mui safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.