Files

9.5 KiB

name, description, metadata
name description metadata
material-ui Material-UI (MUI) v7 React component library - components, theming, customization, best practices
language audience
typescript developers

Overview

Material-UI (MUI) v7 is the latest version of the popular React component library implementing Google's Material Design. Use this skill when working with MUI components.

Current Version: v7.3.9

Installation

npm install @mui/material @emotion/react @emotion/styled

Peer Dependencies

{
  "peerDependencies": {
    "react": "^17.0.0 || ^18.0.0 || ^19.0.0",
    "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
  }
}

Icons

npm install @mui/icons-material

Roboto Font

npm install @fontsource/roboto

Import in entry point:

import '@fontsource/roboto/300.css';
import '@fontsource/roboto/400.css';
import '@fontsource/roboto/500.css';
import '@fontsource/roboto/700.css';

React 18 and Below

If using React 18 or below, set react-is override:

{
  "overrides": {
    "react-is": "^18.3.1"
  }
}

Quickstart

import Button from '@mui/material/Button';

export default function App() {
  return <Button variant="contained">Hello World</Button>;
}

Required Globals

Add to your app:

import { CssBaseline, ThemeProvider } from '@mui/material';

Viewport meta tag:

<meta name="viewport" content="initial-scale=1, width=device-width" />

Theming

Create Theme

import { createTheme } from '@mui/material/styles';

const theme = createTheme({
  palette: {
    mode: 'dark',
    primary: { main: '#1976d2' },
    secondary: { main: '#dc004e' },
  },
  typography: {
    fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif',
  },
  spacing: 8,
});

Apply Theme

import { ThemeProvider, CssBaseline } from '@mui/material';

function App({ children }) {
  return (
    <ThemeProvider theme={theme}>
      <CssBaseline />
      {children}
    </ThemeProvider>
  );
}

Dark Mode with CSS Variables

const theme = createTheme({
  cssVariables: {
    colorSchemeSelector: 'class',
  },
  colorSchemes: {
    light: true,
    dark: true,
  },
});

Use theme.vars.* for CSS variables:

const StyledDiv = styled('div')(({ theme }) => ({
  color: theme.vars.palette.text.primary,
}));

Color Scheme with useColorScheme

MUI v7 provides useColorScheme hook to manage color modes (light/dark/system) without explicit state management. Pair with a custom useMode hook for cleaner separation of concerns.

1. Create the theme with color schemes:

import { createTheme } from '@mui/material/styles';

const theme = createTheme({
  cssVariables: {
    colorSchemeSelector: 'class',
  },
  colorSchemes: {
    light: true,
    dark: true,
  },
  palette: {
    primary: { main: '#1976d2' },
    secondary: { main: '#dc004e' },
  },
});

2. Wrap your app with ThemeProvider:

import { ThemeProvider, CssBaseline } from '@mui/material';

function App() {
  return (
    <ThemeProvider theme={theme}>
      <CssBaseline />
      <YourApp />
    </ThemeProvider>
  );
}

3. Create a useMode hook for cleaner access:

// hooks/useMode.ts
import { useColorScheme } from '@mui/material/styles';

type Mode = 'light' | 'dark' | 'system';

export function useMode() {
  const { mode, setMode, systemMode } = useColorScheme();

  return {
    mode: mode === 'system' ? systemMode : mode,
    modeRaw: mode,
    setMode,
    isDark: (mode === 'system' ? systemMode : mode) === 'dark',
  };
}

4. Use in your TopBar component:

import { AppBar, Toolbar, Typography, IconButton } from '@mui/material';
import { useMode } from './hooks/useMode';
import LightMode from '@mui/icons-material/LightMode';
import DarkMode from '@mui/icons-material/DarkMode';
import SettingsBrightness from '@mui/icons-material/SettingsBrightness';

function TopBar() {
  const { modeRaw, setMode } = useMode();

  const cycleMode = () => {
    const modes: Array<'light' | 'dark' | 'system'> = ['light', 'dark', 'system'];
    const currentIndex = modes.indexOf(modeRaw);
    setMode(modes[(currentIndex + 1) % modes.length]);
  };

  return (
    <AppBar position="static">
      <Toolbar>
        <Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
          My App
        </Typography>
        <IconButton color="inherit" onClick={cycleMode}>
          {modeRaw === 'dark' ? <LightMode /> : modeRaw === 'light' ? <DarkMode /> : <SettingsBrightness />}
        </IconButton>
      </Toolbar>
    </AppBar>
  );
}

5. Use in any component:

import { useMode } from './hooks/useMode';
import { Box, Typography } from '@mui/material';

function Dashboard() {
  const { isDark, mode } = useMode();

  return (
    <Box sx={{ bgcolor: isDark ? 'grey.900' : 'grey.100', p: 2 }}>
      <Typography>Current mode: {mode}</Typography>
    </Box>
  );
}

Customization

1. One-off: sx Prop

<Button sx={{ width: 300, bgcolor: 'success.main' }}>
  Custom
</Button>

2. Nested Styles

<Slider sx={{ '& .MuiSlider-thumb': { borderRadius: 1 } }} />

3. Reusable: styled()

import Slider, { SliderProps } from '@mui/material/Slider';
import { styled } from '@mui/material/styles';

const SuccessSlider = styled(Slider)<SliderProps>(({ theme }) => ({
  color: theme.palette.success.main,
}));

4. Dynamic Props

interface CustomSliderProps extends SliderProps {
  success?: boolean;
}

const StyledSlider = styled(Slider, {
  shouldForwardProp: (prop) => prop !== 'success',
})<CustomSliderProps>(({ success, theme }) => ({
  ...(success && { color: theme.palette.success.main }),
}));

5. Global Theme Overrides

const theme = createTheme({
  components: {
    MuiButton: {
      defaultProps: { disableElevation: true },
      styleOverrides: {
        root: { textTransform: 'none' },
      },
    },
  },
});

Component Patterns

Slot Props (MUI v7 Standard)

<Accordion
  slots={{ transition: CustomTransition }}
  slotProps={{ transition: { unmountOnExit: true } }}
/>

Responsive Design

<Box sx={{
  display: 'flex',
  flexDirection: { xs: 'column', md: 'row' },
  gap: { xs: 1, md: 2 },
}} />

Grid (v2 - now just Grid)

import Grid from '@mui/material/Grid';

<Grid container spacing={2}>
  <Grid item xs={12} md={6}>Content</Grid>
</Grid>

Stack (Preferred over Box for Simple Layouts)

<Stack direction="row" spacing={2}>
  <Button>One</Button>
  <Button>Two</Button>
</Stack>

State Classes

Use for hover, focus, disabled, selected states:

  • .Mui-active, .Mui-checked, .Mui-disabled, .Mui-error, .Mui-expanded, .Mui-focusVisible, .Mui-focused, .Mui-readOnly, .Mui-required, .Mui-selected
<Button disabled className="CustomButton">
// Style: .CustomButton.Mui-disabled { ... }

Migration to v7

Key Changes

  1. Grid2 → Grid: Use import Grid from '@mui/material/Grid'
  2. Lab components: Import from @mui/material not @mui/lab
  3. createMuiTheme → createTheme
  4. InputLabel size="normal" → size="medium"
  5. Deep imports removed: Use import { createTheme } from '@mui/material/styles'
  6. Hidden component removed: Use sx prop or useMediaQuery

Codemods

npx @mui/codemod v7.0.0/grid-props <path>
npx @mui/codemod v7.0.0/lab-removed-components <path>
npx @mui/codemod v7.0.0/input-label-size-normal-medium <path>

Icons

Import individually for tree-shaking:

import Home from '@mui/icons-material/Home';
import Search from '@mui/icons-material/Search';

Use sx for sizing:

<Home sx={{ fontSize: 24, color: 'primary.main' }} />

Common Components

Component Use Case
Box Generic wrapper
Container Page layout
Stack Simple layouts
Grid Complex layouts
Button Actions
TextField Form inputs
Card Content containers
AppBar Navigation headers
Drawer Side navigation
Dialog Modals
Table Data grids
Chip Tags/labels
Typography Text styling
Avatar User images
Alert Notifications
Skeleton Loading states
Menu Dropdown menus
Tabs Tab navigation
Stepper Multi-step forms

Best Practices

  1. Use Theme - Define colors, typography, spacing globally
  2. Use sx for One-off - Quick style overrides
  3. Use styled() for Reusable - Create custom components
  4. Use Stack - Prefer over Box for simple layouts
  5. Use Grid (v2) - For complex responsive layouts
  6. Use CSS Variables - For better dev tools and dark mode
  7. Use Slot Props - MUI v7 standard for component customization
  8. TypeScript - MUI v7 requires TypeScript 4.9+
  9. Test - Use @mui/internal/test-utils for testing
  10. Top Bar with Color Scheme Switch - Use AppBar with Toolbar, Typography for title, and useColorScheme hook for theme toggle
import { AppBar, Toolbar, Typography, IconButton } from '@mui/material';
import { useColorScheme } from '@mui/material/styles';
import LightMode from '@mui/icons-material/LightMode';
import DarkMode from '@mui/icons-material/DarkMode';

function TopBar() {
  const { mode, setMode } = useColorScheme();

  return (
    <AppBar position="static">
      <Toolbar>
        <Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
          My App
        </Typography>
        <IconButton color="inherit" onClick={() => setMode(mode === 'dark' ? 'light' : 'dark')}>
          {mode === 'dark' ? <LightMode /> : <DarkMode />}
        </IconButton>
      </Toolbar>
    </AppBar>
  );
}