List
Lists are continuous, vertical indexes of text or images that are normally interactable.
Simple List
A list can be created using the List
and ListItem
components.
- Item 1
- Item 2
- Item 3
import { List } from "@react-md/core/list/List";
import { ListItem } from "@react-md/core/list/ListItem";
import { type ReactElement } from "react";
export default function SimpleListExample(): ReactElement {
return (
<List>
<ListItem>Item 1</ListItem>
<ListItem>Item 2</ListItem>
<ListItem>Item 3</ListItem>
</List>
);
}
Adding Click Handlers
Each list item will normally have an onClick
event handler to trigger an
action.
- Item 1
- Item 2
"use client";
import { List } from "@react-md/core/list/List";
import { ListItem } from "@react-md/core/list/ListItem";
import { type ReactElement } from "react";
export default function AddingClickHandlersExample(): ReactElement {
return (
<List>
<ListItem
onClick={() => {
// do something
}}
>
Item 1
</ListItem>
<ListItem
onClick={() => {
// do something
}}
>
Item 2
</ListItem>
</List>
);
}
Different Sizes
The ListItem
has different heights available and defaults to automatically
determining the height based on the provided props but can be manually set as
well. Check out the following examples to see the heights in action.
- Auto (Default)
- Normal
- Medium
- Large
- Extra Large
import { List } from "@react-md/core/list/List";
import { ListItem } from "@react-md/core/list/ListItem";
import { type ReactElement } from "react";
export default function DifferentSizesExample(): ReactElement {
return (
<List>
<ListItem height="auto">Auto (Default)</ListItem>
<ListItem height="normal">Normal</ListItem>
<ListItem height="medium">Medium</ListItem>
<ListItem height="large">Large</ListItem>
<ListItem height="extra-large">Extra Large</ListItem>
</List>
);
}
Adding Secondary Text
A ListItem
normally contains primary content (children
) and optionally
secondary content using the secondaryText
prop. The secondary text will gain
the --rmd-text-secondary-color
and use trailing ellipsis for long text. When
the secondaryText
prop exists, the height
will be automatically set to
"extra-large"
.
- Main Content TextSecondary content text
- Main Content TextSecondary content text
- Lorem ipsum dolor sit amet, consectetur adipiscing elit.Phasellus accumsan auctor neque, eu dignissim ex.
Multiple Lines of Secondary Text
The secondaryText
can also span multiple lines by enabling the multiline
prop. The default behavior will be to allow two lines of text and use
-webkit-line-clamp
to truncate the trailing text with ellipsis. The number of lines can be
configured by the core.$list-item-multiline-clamp Sass variable or
using the core.list-set-var(item-multiline-clamp, NEW_SIZE) mixin.
- Brunch this weekend?I'll be in your neighborhood sometimes this week. Would you like to try brunch this weekend?
- Summer BBQWish I could come, but I'm out of town this weekend
List Item Addons
The ListItem
also supports rendering addons before and after the children
,
primaryText
, and secondaryText
using the leftAddon
and rightAddon
props.
The addon will default to being icon sized and positioned vertically centered
with the rest of the content.
- Left Addon
- Right Addon
- Left and Right AddonBut also secondary text
import { List } from "@react-md/core/list/List";
import { ListItem } from "@react-md/core/list/ListItem";
import FavoriteIcon from "@react-md/material-icons/FavoriteIcon";
import VolumeOffOutlinedIcon from "@react-md/material-icons/VolumeOffOutlinedIcon";
import VolumeUpOutlinedIcon from "@react-md/material-icons/VolumeUpOutlinedIcon";
import { type ReactElement } from "react";
export default function ListItemAddonsExample(): ReactElement {
return (
<List>
<ListItem leftAddon={<FavoriteIcon />}>Left Addon</ListItem>
<ListItem rightAddon={<VolumeOffOutlinedIcon />}>Right Addon</ListItem>
<ListItem
leftAddon={<VolumeUpOutlinedIcon />}
rightAddon={<VolumeOffOutlinedIcon />}
secondaryText="But also secondary text"
>
Left and Right Addon
</ListItem>
</List>
);
}
Disabling Left Addon Spacing
When there is a leftAddon
, there will normally be additional margin-right
applied so that the content align nicely with a hamburger menu and title in an
AppBar
. This additional spacing can be removed by enabling
disableLeftAddonSpacing
.
- Left Addon
- Left Addon No Spacing
import { AppBar } from "@react-md/core/app-bar/AppBar";
import { AppBarTitle } from "@react-md/core/app-bar/AppBarTitle";
import { Button } from "@react-md/core/button/Button";
import { ICON_CONFIG } from "@react-md/core/icon/config";
import { List } from "@react-md/core/list/List";
import { ListItem } from "@react-md/core/list/ListItem";
import FavoriteIcon from "@react-md/material-icons/FavoriteIcon";
import VolumeUpOutlinedIcon from "@react-md/material-icons/VolumeUpOutlinedIcon";
import { type ReactElement } from "react";
export default function DisablingLeftAddonSpacingExample(): ReactElement {
return (
<div>
<AppBar>
<Button buttonType="icon" aria-label="Menu">
{ICON_CONFIG.menu}
</Button>
<AppBarTitle keyline="nav">Title</AppBarTitle>
</AppBar>
<List>
<ListItem leftAddon={<FavoriteIcon />}>Left Addon</ListItem>
<ListItem leftAddon={<VolumeUpOutlinedIcon />} disableLeftAddonSpacing>
Left Addon No Spacing
</ListItem>
</List>
</div>
);
}
Avatar Addons
When an addon should be an Avatar instead of an icon, set
the leftAddonType
or rightAddonType
to "avatar"
to modify the positioning.
- Left Avatar
- Right Avatar with some additional text
- Icon-Sized Left Avatar
- PhotosJan 04, 2019
import { Avatar } from "@react-md/core/avatar/Avatar";
import { List } from "@react-md/core/list/List";
import { ListItem } from "@react-md/core/list/ListItem";
import FolderIcon from "@react-md/material-icons/FolderIcon";
import InfoOutlineIcon from "@react-md/material-icons/InfoOutlineIcon";
import { type ReactElement } from "react";
export default function AvatarAddonsExample(): ReactElement {
return (
<List>
<ListItem leftAddon={<Avatar>A</Avatar>} leftAddonType="avatar">
Left Avatar
</ListItem>
<ListItem rightAddon={<Avatar>A</Avatar>} rightAddonType="avatar">
Right Avatar with some additional text
</ListItem>
<ListItem
leftAddon={
<Avatar size="icon" color="purple">
I
</Avatar>
}
>
Icon-Sized Left Avatar
</ListItem>
<ListItem
leftAddon={
<Avatar color="blue">
<FolderIcon />
</Avatar>
}
leftAddonType="avatar"
secondaryText="Jan 04, 2019"
rightAddon={<InfoOutlineIcon />}
>
Photos
</ListItem>
</List>
);
}
Media Addons
When an addon should be an image or something around 3.5rem
(56px
), set the
leftAddonType
or rightAddonType
to "media"
. The media size and spacing can
be configured by the core.$list-item-media-size and
core.$list-item-media-spacing Sass variables.
- Left Media
- Right Media
- See your video? You're a legend!Scott Stirling. The Man. The Myth. The Legend.
import { List } from "@react-md/core/list/List";
import { ListItem } from "@react-md/core/list/ListItem";
import StarIcon from "@react-md/material-icons/StarIcon";
import { type ReactElement } from "react";
export default function MediaAddonsExample(): ReactElement {
return (
<List>
<ListItem
leftAddon={<img src="https://i.pravatar.cc/56?img=1" alt="" />}
leftAddonType="media"
>
Left Media
</ListItem>
<ListItem
rightAddon={<img src="https://i.pravatar.cc/56?img=4" alt="" />}
rightAddonType="media"
>
Right Media
</ListItem>
<ListItem
leftAddon={<img src="https://i.pravatar.cc/56?img=8" alt="" />}
leftAddonType="media"
rightAddon={<StarIcon />}
secondaryText="Scott Stirling. The Man. The Myth. The Legend."
multiline
>
{"See your video? You're a legend!"}
</ListItem>
</List>
);
}
Large Media Addons
The ListItem
also supports large media that are 6.25rem
(100px
) wide by
setting the leftAddonType
or rightAddonType
to "large-media"
. The width
of the large media can be configured by the
core.$list-item-media-large-size Sass variable.
- Left Large Media
- Left Large MediaWith secondary text
- Right Large Media
- Right Large MediaWith secondary text
import { List } from "@react-md/core/list/List";
import { ListItem } from "@react-md/core/list/ListItem";
import { type ReactElement } from "react";
export default function LargeMediaAddonsExample(): ReactElement {
return (
<List>
<ListItem
leftAddon={<img src="https://picsum.photos/100/56?image=800" alt="" />}
leftAddonType="large-media"
>
Left Large Media
</ListItem>
<ListItem
leftAddon={<img src="https://picsum.photos/100/56?image=803" alt="" />}
leftAddonType="large-media"
secondaryText="With secondary text"
>
Left Large Media
</ListItem>
<ListItem
rightAddon={<img src="https://picsum.photos/100/56?image=700" alt="" />}
rightAddonType="large-media"
>
Right Large Media
</ListItem>
<ListItem
rightAddon={<img src="https://picsum.photos/100/56?image=738" alt="" />}
rightAddonType="large-media"
secondaryText="With secondary text"
>
Right Large Media
</ListItem>
</List>
);
}
Disabled List Item
The ListItem
can be disabled by enabling the disabled
prop which applies the
--rmd-text-disabled-color
and prevents user interaction. Since the text color
doesn't apply to addons, the disabledOpacity
prop can also be displayed to
apply opacity to the entire ListItem
instead to show it has been disabled.
- Disabled Item
- Disabled Item (Opacity)
- Disabled Item
- Disabled Item (Opacity)
import { List } from "@react-md/core/list/List";
import { ListItem } from "@react-md/core/list/ListItem";
import FavoriteIcon from "@react-md/material-icons/FavoriteIcon";
import { type ReactElement } from "react";
export default function DisabledListItemExample(): ReactElement {
return (
<List>
<ListItem disabled>Disabled Item</ListItem>
<ListItem disabled disabledOpacity>
Disabled Item (Opacity)
</ListItem>
<ListItem disabled leftAddon={<FavoriteIcon />}>
Disabled Item
</ListItem>
<ListItem disabled disabledOpacity leftAddon={<FavoriteIcon />}>
Disabled Item (Opacity)
</ListItem>
</List>
);
}
Noninteractive List
If the ListItem
should be used to only display data, set the role
to
"presentation"
removing all interaction behavior.
- Item 1
- Item 2
- Item 3
import { List } from "@react-md/core/list/List";
import { ListItem } from "@react-md/core/list/ListItem";
import { type ReactElement } from "react";
export default function NoninteractiveListExample(): ReactElement {
return (
<List>
<ListItem role="presentation">Item 1</ListItem>
<ListItem role="presentation">Item 2</ListItem>
<ListItem role="presentation">Item 3</ListItem>
</List>
);
}
Default List Styles
The List
and ListItem
components remove the default <ol>
and <ul>
styling, accessibility, and behavior to behave like a collection of actions
(buttons). If the default list styles should be used, replace the top-level
<ol>
or <ul>
with the Typography
component instead so all items gain the
same typography.
- Read this list
- Do something else
- Maybe read a book?
- Or go on a hike?
- Cook dinner?
- Celebrate
import { Typography } from "@react-md/core/typography/Typography";
import { type ReactElement } from "react";
export default function DefaultListStylesExample(): ReactElement {
return (
<Typography as="ol">
<li>Read this list</li>
<li>Do something else</li>
<ul>
<li>Maybe read a book?</li>
<li>Or go on a hike?</li>
<li>Cook dinner?</li>
</ul>
<li>Celebrate</li>
</Typography>
);
}
List Item Children
Since the ListItem
has some nice functionality of separating content with
addons, it might be tempting to use the ListItem
for layouts instead of
interactions. This is not recommended for accessibility because most semantics
are removed from the List
and ListItem
components. Instead, use the Box
(or a flex
container) and ListItemChildren
components for presentational
data.
import { Box } from "@react-md/core/box/Box";
import { ListItemChildren } from "@react-md/core/list/ListItemChildren";
import FavoriteIcon from "@react-md/material-icons/FavoriteIcon";
import InfoOutlineIcon from "@react-md/material-icons/InfoOutlineIcon";
import { type ReactElement } from "react";
export default function ListItemChildrenExample(): ReactElement {
return (
<Box align="start" stacked disablePadding>
<Box style={{ "--rmd-box-gap": 0 }} disablePadding>
<ListItemChildren leftAddon={<FavoriteIcon />}>
This is my favorite!
</ListItemChildren>
</Box>
<div style={{ display: "flex" }}>
<ListItemChildren
leftAddon={<InfoOutlineIcon />}
rightAddon={<FavoriteIcon />}
secondaryText="Gotcha!"
>
Never mind, this might actually be my favorite!
</ListItemChildren>
</div>
</Box>
);
}