Claude
Skills
Sign in
Back

components

Included with Lifetime
$97 forever

MUI core component patterns and best practices

Design

What this skill does


# MUI Core Components Reference

## Input Components

### TextField

The most common form input. Wraps `FormControl`, `InputLabel`, `OutlinedInput`/`FilledInput`/`Input`,
and `FormHelperText` in one component.

```tsx
import TextField from '@mui/material/TextField';
import InputAdornment from '@mui/material/InputAdornment';

// Standard usage
<TextField
  label="Email address"
  type="email"
  variant="outlined"          // 'outlined' | 'filled' | 'standard'
  size="small"                // 'small' | 'medium'
  fullWidth
  required
  value={email}
  onChange={(e) => setEmail(e.target.value)}
  error={!!emailError}
  helperText={emailError || 'We will never share your email'}
  InputProps={{
    startAdornment: <InputAdornment position="start"><EmailIcon /></InputAdornment>,
  }}
  inputProps={{ maxLength: 100, 'aria-label': 'email address' }}
/>

// Multiline / textarea
<TextField
  label="Description"
  multiline
  rows={4}
  // or: minRows={2} maxRows={8} for auto-grow
  fullWidth
/>
```

### Autocomplete

Combines a text input with a dropdown for both free-form and constrained selection.

```tsx
import Autocomplete from '@mui/material/Autocomplete';
import Chip from '@mui/material/Chip';
import CircularProgress from '@mui/material/CircularProgress';

// Static options
<Autocomplete
  options={countries}
  getOptionLabel={(option) => option.label}
  isOptionEqualToValue={(option, value) => option.code === value.code}
  value={selectedCountry}
  onChange={(_, newValue) => setSelectedCountry(newValue)}
  renderInput={(params) => (
    <TextField {...params} label="Country" />
  )}
/>

// Multiple selection with chips
<Autocomplete
  multiple
  options={tags}
  value={selectedTags}
  onChange={(_, newValue) => setSelectedTags(newValue)}
  renderTags={(value, getTagProps) =>
    value.map((option, index) => (
      <Chip label={option} {...getTagProps({ index })} key={option} />
    ))
  }
  renderInput={(params) => (
    <TextField {...params} label="Tags" placeholder="Add tag" />
  )}
/>

// Async / server-side options
const [open, setOpen] = React.useState(false);
const [options, setOptions] = React.useState([]);
const [loading, setLoading] = React.useState(false);

<Autocomplete
  open={open}
  onOpen={() => { setOpen(true); fetchOptions(); }}
  onClose={() => setOpen(false)}
  options={options}
  loading={loading}
  renderInput={(params) => (
    <TextField
      {...params}
      label="Search users"
      InputProps={{
        ...params.InputProps,
        endAdornment: (
          <>
            {loading && <CircularProgress size={20} />}
            {params.InputProps.endAdornment}
          </>
        ),
      }}
    />
  )}
/>
```

### Select

```tsx
import Select from '@mui/material/Select';
import MenuItem from '@mui/material/MenuItem';
import FormControl from '@mui/material/FormControl';
import InputLabel from '@mui/material/InputLabel';
import Checkbox from '@mui/material/Checkbox';
import ListItemText from '@mui/material/ListItemText';

<FormControl fullWidth size="small">
  <InputLabel id="role-label">Role</InputLabel>
  <Select
    labelId="role-label"
    label="Role"
    value={role}
    onChange={(e) => setRole(e.target.value)}
  >
    <MenuItem value="admin">Administrator</MenuItem>
    <MenuItem value="editor">Editor</MenuItem>
    <MenuItem value="viewer">Viewer</MenuItem>
  </Select>
</FormControl>

// Multiple select with checkboxes
<Select
  multiple
  value={selectedRoles}
  onChange={handleChange}
  renderValue={(selected) => (
    <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5 }}>
      {selected.map((value) => <Chip key={value} label={value} size="small" />)}
    </Box>
  )}
>
  {roles.map((role) => (
    <MenuItem key={role} value={role}>
      <Checkbox checked={selectedRoles.includes(role)} />
      <ListItemText primary={role} />
    </MenuItem>
  ))}
</Select>
```

### Checkbox, Radio, Switch

```tsx
import Checkbox from '@mui/material/Checkbox';
import Radio from '@mui/material/Radio';
import RadioGroup from '@mui/material/RadioGroup';
import Switch from '@mui/material/Switch';
import FormControlLabel from '@mui/material/FormControlLabel';

// Checkbox with indeterminate state
<Checkbox
  checked={allSelected}
  indeterminate={someSelected && !allSelected}
  onChange={handleSelectAll}
/>

// Radio group
<RadioGroup value={alignment} onChange={(e) => setAlignment(e.target.value)}>
  <FormControlLabel value="left" control={<Radio />} label="Left" />
  <FormControlLabel value="center" control={<Radio />} label="Center" />
  <FormControlLabel value="right" control={<Radio />} label="Right" />
</RadioGroup>

// Switch
<FormControlLabel
  control={
    <Switch checked={darkMode} onChange={(e) => setDarkMode(e.target.checked)} />
  }
  label="Dark mode"
/>
```

### Slider and Rating

```tsx
import Slider from '@mui/material/Slider';
import Rating from '@mui/material/Rating';

// Range slider
<Slider
  value={priceRange}
  onChange={(_, newValue) => setPriceRange(newValue as number[])}
  valueLabelDisplay="auto"
  min={0}
  max={1000}
  step={10}
  marks={[
    { value: 0, label: '$0' },
    { value: 500, label: '$500' },
    { value: 1000, label: '$1000' },
  ]}
/>

// Star rating
<Rating
  value={rating}
  onChange={(_, newValue) => setRating(newValue)}
  precision={0.5}
  size="large"
/>
```

---

## Display Components

### Typography

```tsx
import Typography from '@mui/material/Typography';

// Semantic element with visual variant
<Typography variant="h1" component="h2">Page title</Typography>

// Caption with ellipsis
<Typography
  variant="body2"
  color="text.secondary"
  noWrap
  sx={{ maxWidth: 200 }}
>
  Long text that will be truncated
</Typography>

// Paragraph with bottom margin
<Typography variant="body1" gutterBottom>
  First paragraph with bottom margin.
</Typography>
```

### Chip

```tsx
import Chip from '@mui/material/Chip';
import Avatar from '@mui/material/Avatar';

<Chip label="Active" color="success" size="small" />
<Chip label="Draft" variant="outlined" onDelete={handleDelete} />
<Chip
  avatar={<Avatar alt="User" src="/user.jpg" />}
  label="Jane Smith"
  onClick={handleClick}
  clickable
/>
```

### Avatar and Badge

```tsx
import Avatar from '@mui/material/Avatar';
import AvatarGroup from '@mui/material/AvatarGroup';
import Badge from '@mui/material/Badge';

// Avatar with fallback initials
<Avatar src="/user.jpg" alt="John Doe">JD</Avatar>

// Avatar group with overflow count
<AvatarGroup max={4}>
  {users.map((u) => <Avatar key={u.id} src={u.avatar} alt={u.name} />)}
</AvatarGroup>

// Notification badge on icon
<Badge badgeContent={unreadCount} color="error" max={99}>
  <NotificationsIcon />
</Badge>

// Online indicator dot
<Badge
  overlap="circular"
  anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
  variant="dot"
  color="success"
>
  <Avatar src="/user.jpg" />
</Badge>
```

### Tooltip

```tsx
import Tooltip from '@mui/material/Tooltip';

<Tooltip title="Delete this item" placement="top" arrow>
  <IconButton aria-label="delete"><DeleteIcon /></IconButton>
</Tooltip>

// Tooltip on disabled element (needs a wrapping span)
<Tooltip title="You don't have permission">
  <span>
    <Button disabled>Restricted action</Button>
  </span>
</Tooltip>
```

### Alert

```tsx
import Alert from '@mui/material/Alert';
import AlertTitle from '@mui/material/AlertTitle';

<Alert severity="warning" variant="filled" onClose={handleClose}>
  <AlertTitle>Warning</AlertTitle>
  Your subscription expires in 3 days.
</Alert>

// severity: 'error' | 'warning' | 'info' | 'success'
// variant: 'standard' | 'filled' | 'outlined'
```

### Table

```tsx
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
import Paper from '@mui/material/Paper';

<TableContai

Related in Design