Skip to main content

List

Please refer to MUI's official docs for more details on component's usage guide and API documentation.

Basic List

Lists are a continuous group of text or images.



// MUI Imports
import List from '@mui/material/List'
import Divider from '@mui/material/Divider'
import ListItem from '@mui/material/ListItem'
import ListItemIcon from '@mui/material/ListItemIcon'
import ListItemText from '@mui/material/ListItemText'
import ListItemButton from '@mui/material/ListItemButton'

const ListBasic = () => {
return (
<>
<List component='nav' aria-label='main mailbox'>
<ListItem disablePadding>
<ListItemButton>
<ListItemIcon>
<i className='ri-mail-line text-xl' />
</ListItemIcon>
<ListItemText primary='Inbox' />
</ListItemButton>
</ListItem>
<ListItem disablePadding>
<ListItemButton>
<ListItemIcon>
<i className='ri-file-copy-line text-xl' />
</ListItemIcon>
<ListItemText primary='Draft' />
</ListItemButton>
</ListItem>
</List>
<Divider className='m-0' />
<List component='nav' aria-label='secondary mailbox'>
<ListItem disablePadding>
<ListItemButton>
<ListItemIcon>
<i className='ri-time-line text-xl' />
</ListItemIcon>
<ListItemText primary='Snoozed' />
</ListItemButton>
</ListItem>
<ListItem disablePadding>
<ListItemButton component='a' href='#simple-list' className='hover:text-inherit'>
<ListItemIcon>
<i className='ri-spam-2-line text-xl' />
</ListItemIcon>
<ListItemText primary='Spam' />
</ListItemButton>
</ListItem>
</List>
</>
)
}

export default ListBasic
Nested List


// React Imports
import { useState } from 'react'

// MUI Imports
import List from '@mui/material/List'
import Divider from '@mui/material/Divider'
import ListItem from '@mui/material/ListItem'
import Collapse from '@mui/material/Collapse'
import ListItemIcon from '@mui/material/ListItemIcon'
import ListItemText from '@mui/material/ListItemText'
import ListItemButton from '@mui/material/ListItemButton'

const ListNested = () => {
// States
const [open, setOpen] = useState<boolean>(true)

const handleClick = () => {
setOpen(!open)
}

return (
<>
<List component='nav' aria-label='main mailbox'>
<ListItem disablePadding>
<ListItemButton onClick={handleClick}>
<ListItemIcon>
<i className='ri-mail-line text-xl' />
</ListItemIcon>
<ListItemText primary='Inbox' />
<i className={open ? 'ri-arrow-up-s-line' : 'ri-arrow-down-s-line'} />
</ListItemButton>
</ListItem>
<Collapse in={open} timeout='auto' unmountOnExit>
<List component='div' disablePadding>
<ListItem disablePadding>
<ListItemButton className='pis-8'>
<ListItemIcon>
<i className='ri-time-line text-xl' />
</ListItemIcon>
<ListItemText primary='Scheduled' />
</ListItemButton>
</ListItem>
</List>
</Collapse>
<ListItem disablePadding>
<ListItemButton>
<ListItemIcon>
<i className='ri-file-copy-line text-xl' />
</ListItemIcon>
<ListItemText primary='Draft' />
</ListItemButton>
</ListItem>
</List>
<Divider className='m-0' />
<List component='nav' aria-label='secondary mailbox'>
<ListItem disablePadding>
<ListItemButton>
<ListItemIcon>
<i className='ri-time-line text-xl' />
</ListItemIcon>
<ListItemText primary='Snoozed' />
</ListItemButton>
</ListItem>
<ListItem disablePadding>
<ListItemButton>
<ListItemIcon>
<i className='ri-spam-2-line text-xl' />
</ListItemIcon>
<ListItemText primary='Spam' />
</ListItemButton>
</ListItem>
</List>
</>
)
}

export default ListNested
Dense List

Use dense prop with <List> component for dense list.

  • Inbox
  • Draft

  • Snoozed
  • Spam

// MUI Imports
import List from '@mui/material/List'
import Divider from '@mui/material/Divider'
import ListItem from '@mui/material/ListItem'
import ListItemIcon from '@mui/material/ListItemIcon'
import ListItemText from '@mui/material/ListItemText'
import ListItemButton from '@mui/material/ListItemButton'

const ListDense = () => {
return (
<>
<List dense>
<ListItem disablePadding>
<ListItemButton>
<ListItemIcon>
<i className='ri-mail-line text-xl' />
</ListItemIcon>
<ListItemText primary='Inbox' />
</ListItemButton>
</ListItem>
<ListItem disablePadding>
<ListItemButton>
<ListItemIcon>
<i className='ri-file-copy-line text-xl' />
</ListItemIcon>
<ListItemText primary='Draft' />
</ListItemButton>
</ListItem>
</List>
<Divider className='m-0' />
<List dense>
<ListItem disablePadding>
<ListItemButton>
<ListItemIcon>
<i className='ri-time-line' />
</ListItemIcon>
<ListItemText primary='Snoozed' />
</ListItemButton>
</ListItem>
<ListItem disablePadding>
<ListItemButton>
<ListItemIcon>
<i className='ri-spam-2-line text-xl' />
</ListItemIcon>
<ListItemText primary='Spam' />
</ListItemButton>
</ListItem>
</List>
</>
)
}

export default ListDense
List with Secondary Text

Use secondary prop with <ListItemText> component for secondary text.

  • Caroline Black
    Caroline Black

    Sweet dessert brownie.

  • Alfred Copeland
    Alfred Copeland

    Pudding pie tiramisu.

  • Celia Schneider
    Celia Schneider

    Muffin pie chupa chups.


// MUI Imports
import List from '@mui/material/List'
import Avatar from '@mui/material/Avatar'
import ListItem from '@mui/material/ListItem'
import IconButton from '@mui/material/IconButton'
import ListItemText from '@mui/material/ListItemText'
import ListItemAvatar from '@mui/material/ListItemAvatar'
import ListItemSecondaryAction from '@mui/material/ListItemSecondaryAction'

const ListSecondary = () => {
return (
<List>
<ListItem>
<ListItemAvatar>
<Avatar src='/images/avatars/2.png' alt='Caroline Black' />
</ListItemAvatar>
<ListItemText primary='Caroline Black' secondary='Sweet dessert brownie.' />
<ListItemSecondaryAction>
<IconButton edge='end'>
<i className='ri-add-line' />
</IconButton>
</ListItemSecondaryAction>
</ListItem>
<ListItem>
<ListItemAvatar>
<Avatar src='/images/avatars/1.png' alt='Alfred Copeland' />
</ListItemAvatar>
<ListItemText primary='Alfred Copeland' secondary='Pudding pie tiramisu.' />
<ListItemSecondaryAction>
<IconButton edge='end'>
<i className='ri-add-line' />
</IconButton>
</ListItemSecondaryAction>
</ListItem>
<ListItem>
<ListItemAvatar>
<Avatar src='/images/avatars/8.png' alt='Celia Schneider' />
</ListItemAvatar>
<ListItemText primary='Celia Schneider' secondary='Muffin pie chupa chups.' />
<ListItemSecondaryAction>
<IconButton edge='end'>
<i className='ri-add-line' />
</IconButton>
</ListItemSecondaryAction>
</ListItem>
</List>
)
}

export default ListSecondary
Selected List Item

Manage selected prop with the help of a state.

  • Caroline Black
    Caroline Black
  • Alfred Copeland
    Alfred Copeland
  • Celia Schneider
    Celia Schneider

// React Imports
import { useState } from 'react'

// MUI Imports
import List from '@mui/material/List'
import Avatar from '@mui/material/Avatar'
import ListItem from '@mui/material/ListItem'
import IconButton from '@mui/material/IconButton'
import ListItemText from '@mui/material/ListItemText'
import ListItemButton from '@mui/material/ListItemButton'
import ListItemAvatar from '@mui/material/ListItemAvatar'

const ListItemSelected = () => {
// States
const [selectedIndex, setSelectedIndex] = useState<number>(1)

const handleListItemClick = (index: number) => {
setSelectedIndex(index)
}

return (
<List>
<ListItem
disablePadding
secondaryAction={
<IconButton edge='end' onClick={e => e.stopPropagation()}>
<i className='ri-message-2-line text-xl' />
</IconButton>
}
>
<ListItemButton selected={selectedIndex === 0} onClick={() => handleListItemClick(0)}>
<ListItemAvatar>
<Avatar src='/images/avatars/2.png' alt='Caroline Black' />
</ListItemAvatar>
<ListItemText primary='Caroline Black' />
</ListItemButton>
</ListItem>
<ListItem
disablePadding
secondaryAction={
<IconButton edge='end' onClick={e => e.stopPropagation()}>
<i className='ri-message-2-line text-xl' />
</IconButton>
}
>
<ListItemButton selected={selectedIndex === 1} onClick={() => handleListItemClick(1)}>
<ListItemAvatar>
<Avatar src='/images/avatars/1.png' alt='Alfred Copeland' />
</ListItemAvatar>
<ListItemText primary='Alfred Copeland' />
</ListItemButton>
</ListItem>
<ListItem
disablePadding
secondaryAction={
<IconButton edge='end' onClick={e => e.stopPropagation()}>
<i className='ri-message-2-line text-xl' />
</IconButton>
}
>
<ListItemButton selected={selectedIndex === 2} onClick={() => handleListItemClick(2)}>
<ListItemAvatar>
<Avatar src='/images/avatars/8.png' alt='Celia Schneider' />
</ListItemAvatar>
<ListItemText primary='Celia Schneider' />
</ListItemButton>
</ListItem>
</List>
)
}

export default ListItemSelected
List with Checkbox
  • Caroline Black
    Caroline Black
  • Alfred Copeland
    Alfred Copeland
  • Celia Schneider
    Celia Schneider

// React Imports
import { useState } from 'react'

// MUI Imports
import List from '@mui/material/List'
import Avatar from '@mui/material/Avatar'
import ListItem from '@mui/material/ListItem'
import Checkbox from '@mui/material/Checkbox'
import ListItemText from '@mui/material/ListItemText'
import ListItemButton from '@mui/material/ListItemButton'
import ListItemAvatar from '@mui/material/ListItemAvatar'
import ListItemSecondaryAction from '@mui/material/ListItemSecondaryAction'

const ListWithCheckbox = () => {
// States
const [checked, setChecked] = useState<number[]>([0])

const handleToggle = (value: number) => () => {
const currentIndex = checked.indexOf(value)
const newChecked = [...checked]

if (currentIndex === -1) {
newChecked.push(value)
} else {
newChecked.splice(currentIndex, 1)
}

setChecked(newChecked)
}

return (
<List>
<ListItem disablePadding>
<ListItemButton onClick={handleToggle(0)}>
<ListItemAvatar>
<Avatar src='/images/avatars/2.png' alt='Caroline Black' />
</ListItemAvatar>
<ListItemText id='checkbox-list-label-0' primary='Caroline Black' />
<ListItemSecondaryAction>
<Checkbox
edge='end'
tabIndex={-1}
disableRipple
onChange={handleToggle(0)}
checked={checked.indexOf(0) !== -1}
inputProps={{ 'aria-labelledby': 'checkbox-list-label-0' }}
/>
</ListItemSecondaryAction>
</ListItemButton>
</ListItem>
<ListItem disablePadding>
<ListItemButton onClick={handleToggle(1)}>
<ListItemAvatar>
<Avatar src='/images/avatars/1.png' alt='Alfred Copeland' />
</ListItemAvatar>
<ListItemText id='checkbox-list-label-1' primary='Alfred Copeland' />
<ListItemSecondaryAction>
<Checkbox
edge='end'
tabIndex={-1}
disableRipple
onChange={handleToggle(1)}
checked={checked.indexOf(1) !== -1}
inputProps={{ 'aria-labelledby': 'checkbox-list-label-1' }}
/>
</ListItemSecondaryAction>
</ListItemButton>
</ListItem>
<ListItem disablePadding>
<ListItemButton onClick={handleToggle(2)}>
<ListItemAvatar>
<Avatar src='/images/avatars/8.png' alt='Celia Schneider' />
</ListItemAvatar>
<ListItemText id='checkbox-list-label-2' primary='Celia Schneider' />
<ListItemSecondaryAction>
<Checkbox
edge='end'
tabIndex={-1}
disableRipple
onChange={handleToggle(2)}
checked={checked.indexOf(2) !== -1}
inputProps={{ 'aria-labelledby': 'checkbox-list-label-2' }}
/>
</ListItemSecondaryAction>
</ListItemButton>
</ListItem>
</List>
)
}

export default ListWithCheckbox
List with Switch
  • Settings
  • Wi-Fi
  • Bluetooth
  • Location
  • Airplane Mode
  • Hotspot
  • Do not disturb

// React Imports
import { useState } from 'react'

// MUI Imports
import List from '@mui/material/List'
import Switch from '@mui/material/Switch'
import ListItem from '@mui/material/ListItem'
import ListItemText from '@mui/material/ListItemText'
import ListItemIcon from '@mui/material/ListItemIcon'
import ListSubheader from '@mui/material/ListSubheader'
import ListItemSecondaryAction from '@mui/material/ListItemSecondaryAction'

const ListWithSwitch = () => {
// States
const [checked, setChecked] = useState<string[]>(['wifi', 'location'])

const handleToggle = (value: string) => () => {
const currentIndex = checked.indexOf(value)
const newChecked = [...checked]

if (currentIndex === -1) {
newChecked.push(value)
} else {
newChecked.splice(currentIndex, 1)
}

setChecked(newChecked)
}

return (
<List subheader={<ListSubheader>Settings</ListSubheader>}>
<ListItem>
<ListItemIcon>
<i className='ri-wifi-line text-xl' />
</ListItemIcon>
<ListItemText primary='Wi-Fi' />
<ListItemSecondaryAction>
<Switch edge='end' checked={checked.indexOf('wifi') !== -1} onChange={handleToggle('wifi')} />
</ListItemSecondaryAction>
</ListItem>
<ListItem>
<ListItemIcon>
<i className='ri-bluetooth-line text-xl' />
</ListItemIcon>
<ListItemText primary='Bluetooth' />
<ListItemSecondaryAction>
<Switch edge='end' checked={checked.indexOf('bluetooth') !== -1} onChange={handleToggle('bluetooth')} />
</ListItemSecondaryAction>
</ListItem>
<ListItem>
<ListItemIcon>
<i className='ri-map-pin-line text-xl' />
</ListItemIcon>
<ListItemText primary='Location' />
<ListItemSecondaryAction>
<Switch edge='end' checked={checked.indexOf('location') !== -1} onChange={handleToggle('location')} />
</ListItemSecondaryAction>
</ListItem>
<ListItem>
<ListItemIcon>
<i className='ri-plane-line text-xl' />
</ListItemIcon>
<ListItemText primary='Airplane Mode' />
<ListItemSecondaryAction>
<Switch edge='end' checked={checked.indexOf('airplane') !== -1} onChange={handleToggle('airplane')} />
</ListItemSecondaryAction>
</ListItem>
<ListItem>
<ListItemIcon>
<i className='ri-hotspot-line text-xl' />
</ListItemIcon>
<ListItemText primary='Hotspot' />
<ListItemSecondaryAction>
<Switch edge='end' checked={checked.indexOf('hotspot') !== -1} onChange={handleToggle('hotspot')} />
</ListItemSecondaryAction>
</ListItem>
<ListItem>
<ListItemIcon>
<i className='ri-indeterminate-circle-line text-xl' />
</ListItemIcon>
<ListItemText primary='Do not disturb' />
<ListItemSecondaryAction>
<Switch
edge='end'
checked={checked.indexOf('do-not-disturb') !== -1}
onChange={handleToggle('do-not-disturb')}
/>
</ListItemSecondaryAction>
</ListItem>
</List>
)
}

export default ListWithSwitch
Sticky Subheader

<ListSubheader> is by default sticky.

    • I'm sticky 1
    • Item 1
    • Item 2
    • Item 3
    • I'm sticky 2
    • Item 1
    • Item 2
    • Item 3
    • I'm sticky 3
    • Item 1
    • Item 2
    • Item 3
    • I'm sticky 4
    • Item 1
    • Item 2
    • Item 3
    • I'm sticky 5
    • Item 1
    • Item 2
    • Item 3

// MUI Imports
import Box from '@mui/material/Box'
import List from '@mui/material/List'
import ListItem from '@mui/material/ListItem'
import ListItemText from '@mui/material/ListItemText'
import ListSubheader from '@mui/material/ListSubheader'

const ListStickySubheader = () => {
return (
<List subheader={<li />} className='overflow-auto relative max-bs-[300px]'>
{[1, 2, 3, 4, 5].map(sectionId => (
<Box component='li' key={`section-${sectionId}`} className='bg-backgroundPaper'>
<Box component='ul' className='p-0 bg-inherit'>
<ListSubheader>{`I'm sticky ${sectionId}`}</ListSubheader>
{[1, 2, 3].map(item => (
<ListItem key={`item-${sectionId}-${item}`}>
<ListItemText primary={`Item ${item}`} />
</ListItem>
))}
</Box>
</Box>
))}
</List>
)
}

export default ListStickySubheader
Users List
  • Caroline Black
    Caroline Black

    Online

    13 minutes ago

  • Alfred Copeland
    Alfred Copeland

    Away

    11 minutes ago

  • Celia Schneider
    Celia Schneider

    Offline

    9 minutes ago

  • Max Rogan
    Max Rogan

    In Meeting

    28 minutes ago


// MUI Imports
import Box from '@mui/material/Box'
import Avatar from '@mui/material/Avatar'
import Button from '@mui/material/Button'
import ListItem from '@mui/material/ListItem'
import { Theme, styled } from '@mui/material/styles'
import Typography from '@mui/material/Typography'
import List from '@mui/material/List'
import ListItemText from '@mui/material/ListItemText'
import ListItemAvatar from '@mui/material/ListItemAvatar'
import ListItemSecondaryAction from '@mui/material/ListItemSecondaryAction'
import type { ListProps } from '@mui/material/List'

const StyledList = styled(List)<ListProps>(({ theme }) => ({
'& .MuiListItem-container': {
border: `1px solid ${theme.palette.divider}`,
'&:first-of-type': {
borderTopLeftRadius: theme.shape.borderRadius,
borderTopRightRadius: theme.shape.borderRadius
},
'&:last-child': {
borderBottomLeftRadius: theme.shape.borderRadius,
borderBottomRightRadius: theme.shape.borderRadius
},
'&:not(:last-child)': {
borderBottom: 0
},
'& .MuiListItem-root': {
paddingRight: theme.spacing(24)
},
'& .MuiListItemText-root': {
marginTop: 0,
'& .MuiTypography-root': {
fontWeight: 500
}
}
}
}))

type User = {
name: string
avatarSrc: string
status: string
statusColor: string
lastActive: string
}

const userList: User[] = [
{
name: 'Caroline Black',
avatarSrc: '/images/avatars/2.png',
status: 'Online',
statusColor: 'success.main',
lastActive: '13 minutes ago'
},
{
name: 'Alfred Copeland',
avatarSrc: '/images/avatars/1.png',
status: 'Away',
statusColor: 'warning.main',
lastActive: '11 minutes ago'
},
{
name: 'Celia Schneider',
avatarSrc: '/images/avatars/8.png',
status: 'Offline',
statusColor: 'secondary.main',
lastActive: '9 minutes ago'
},
{
name: 'Max Rogan',
avatarSrc: '/images/avatars/5.png',
status: 'In Meeting',
statusColor: 'error.main',
lastActive: '28 minutes ago'
}
]

const ListUsers = () => {
return (
<StyledList disablePadding>
{userList.map((user, index) => (
<ListItem key={index}>
<ListItemAvatar>
<Avatar src={user.avatarSrc} alt={user.name} />
</ListItemAvatar>
<div>
<ListItemText primary={user.name} />
<div className='flex items-center flex-wrap'>
<Box className='mie-3 flex items-center gap-1' sx={{ '& i, & svg': { color: user.statusColor } }}>
<i className='ri-circle-fill text-[10px]' />
<Typography variant='body2'>{user.status}</Typography>
</Box>
<Typography variant='body2' color='text.disabled'>
{user.lastActive}
</Typography>
</div>
</div>
<ListItemSecondaryAction>
<Button variant='contained' size='small'>
Add
</Button>
</ListItemSecondaryAction>
</ListItem>
))}
</StyledList>
)
}

export default ListUsers
Progress List
  • React is a JavaScript library for building user interfaces
  • Bootstrap is an open source toolkit
  • Vue.js is the Progressive JavaScript Framework
  • Angular implements Functional Programming concepts
  • JavaScript is the programming language of the Web

// MUI Imports
import ListItem from '@mui/material/ListItem'
import { styled } from '@mui/material/styles'
import List from '@mui/material/List'
import ListItemAvatar from '@mui/material/ListItemAvatar'
import ListItemText from '@mui/material/ListItemText'
import LinearProgress from '@mui/material/LinearProgress'
import type { ListProps } from '@mui/material/List'

// Type Imports
import type { ThemeColor } from '@core/types'

// Component Imports
import CustomAvatar from '@core/components/mui/Avatar'

const StyledList = styled(List)<ListProps>(({ theme }) => ({
'& .MuiListItem-root': {
border: `1px solid ${theme.palette.divider}`,
'&:first-of-type': {
borderTopLeftRadius: theme.shape.borderRadius,
borderTopRightRadius: theme.shape.borderRadius
},
'&:last-child': {
borderBottomLeftRadius: theme.shape.borderRadius,
borderBottomRightRadius: theme.shape.borderRadius
},
'&:not(:last-child)': {
borderBottom: 0
},
'& .MuiListItem-root': {
paddingRight: theme.spacing(24)
},
'& .MuiListItemText-root': {
marginTop: 0,
'& .MuiTypography-root': {
fontWeight: 500
}
}
}
}))

type CourseListType = {
description?: string
progress?: number
color?: ThemeColor
icon?: string
}

const courseList: CourseListType[] = [
{
description: 'React is a JavaScript library for building user interfaces',
progress: 90,
color: 'info',
icon: 'ri-reactjs-fill'
},
{
description: 'Bootstrap is an open source toolkit',
progress: 75,
color: 'primary',
icon: 'ri-bootstrap-fill'
},
{
description: 'Vue.js is the Progressive JavaScript Framework',
progress: 85,
color: 'success',
icon: 'ri-vuejs-fill'
},
{
description: 'Angular implements Functional Programming concepts',
progress: 60,
color: 'error',
icon: 'ri-angularjs-fill'
},
{
description: 'JavaScript is the programming language of the Web',
progress: 70,
color: 'warning',
icon: 'ri-javascript-fill'
}
]

const ListProgress = () => {
return (
<StyledList>
{courseList.map((course, index) => {
return (
<ListItem key={index}>
<ListItemAvatar className='flex gap-5 items-center w-full'>
<CustomAvatar skin='light' color={course.color} variant='rounded' className='w-9 h-9'>
<i className={course.icon} />
</CustomAvatar>
<div className='w-full'>
<ListItemText primary={course.description}></ListItemText>
<LinearProgress value={course.progress} variant='determinate' color={course.color} />
</div>
</ListItemAvatar>
</ListItem>
)
})}
</StyledList>
)
}

export default ListProgress