List
Flexible lists with content slots, selection, links, and visual variants
List renders collections of related content with consistent spacing and accessible interaction. It supports simple data-driven items, custom row rendering, leading and trailing content, links, selection, headers, footers, and visual variants.
See the live List showcase.
Basic usage
import { List } from '@mosmox/ui';
const items = [
{ key: 'one', title: 'First item', description: 'Supporting information' },
{ key: 'two', title: 'Second item', description: 'More supporting information' },
];
<List items={items} />Each item needs a stable key and title. description, content, leading, trailing, and meta are optional slots.
Complete data-driven item
Every slot accepts a ReactNode, so an item can contain text, icons, avatars, badges, links, or custom controls:
const projects = [
{
key: 'atlas',
title: 'Project Atlas',
description: 'Main product workspace',
content: 'Last updated today at 10:42',
leading: <Folder size={20} aria-hidden="true" />,
trailing: <MoreHorizontal size={20} aria-label="More actions" />,
meta: '12 files',
href: '/projects/atlas',
data: { status: 'active', ownerId: 42 },
},
];
<List items={projects} variant="card" />data is application data and is not rendered automatically. It is available to callbacks and custom renderers.
Variants and sizes
variant accepts plain, divided, bordered, or card. size accepts sm, default, or lg.
<List items={items} variant="divided" size="sm" />
<List items={items} variant="bordered" />
<List items={items} variant="card" size="lg" />gap changes the spacing between the list shell sections and can be a number of pixels or a CSS length.
Links and interaction
An item with href renders as an anchor. Use onItemClick for application actions. Interactive rows support keyboard activation with Enter and Space.
<List
items={[
{ key: 'docs', title: 'Documentation', href: '/docs' },
{ key: 'settings', title: 'Settings' },
]}
onItemClick={(item) => console.log(item.key)}
/>Set disabled: true on an item to prevent interaction and reduce its emphasis.
Selection
selectionMode can be none, single, or multiple. Controlled selection uses selectedKeys; uncontrolled selection starts from defaultSelectedKeys. onSelectionChange receives the next keys and the item that caused the change.
<List
items={items}
selectionMode="multiple"
selectedKeys={selectedKeys}
onSelectionChange={(keys) => setSelectedKeys(keys)}
variant="bordered"
/>Custom row rendering
Use renderItem when the standard slots are not enough. The renderer receives the item and its current state.
<List
items={items}
renderItem={(item, state) => (
<>
<strong>{state.selected ? 'Selected: ' : ''}{item.title}</strong>
<span>{item.description}</span>
</>
)}
/>The custom renderer replaces the default row content, but the List still supplies selection state, focus behavior, and row semantics.
Fully custom content
Use children when the rows do not fit the ListItem structure at all. In this mode, children takes precedence over items and you own the markup inside the list container:
<List variant="card">
<div className="custom-row">
<strong>Custom heading</strong>
<span>Any React structure can be placed here.</span>
<button type="button">Action</button>
</div>
<div className="custom-row">
<img src="/avatar.png" alt="" />
<span>Avatar, controls, and layout are fully custom.</span>
</div>
</List>Use renderItem instead when you want custom markup while keeping built-in row selection, keyboard behavior, links, and disabled states.
Header and footer
<List
header="Recent activity"
items={items}
footer={<button type="button">View all</button>}
/>ConfigProvider
Configure defaults for a subtree with components.list. Local props override provider values.
<ConfigProvider components={{ list: { variant: 'card', size: 'sm', gap: '12px' } }}>
<List items={items} />
</ConfigProvider>| Setting | Type | Default | Description |
|---|---|---|---|
gap | string | 8px | Spacing between header, rows, and footer. |
size | sm | default | lg | default | Default row density. |
variant | plain | divided | bordered | card | plain | Default list treatment. |
Local size, variant, and gap props take precedence over the provider defaults.
Built-in behavior and boundaries
List renders the records supplied to it. It does not provide pagination, an internal scroll area, infinite scroll, sorting, filtering, search, or virtualization. For large collections, paginate or window the data in the parent component and pass the visible records to items.
API Reference
List props
| Prop | Type | Default | Description |
|---|---|---|---|
items | ListItem<T>[] | [] | Data-driven rows. |
children | ReactNode | — | Custom list content; takes precedence over items. |
renderItem | (item, state) => ReactNode | — | Replaces default row content while preserving List row behavior. state contains selected, disabled, and index. |
header | ReactNode | — | Content above rows. |
footer | ReactNode | — | Content below rows. |
size | sm | default | lg | default | Row density. |
variant | plain | divided | bordered | card | plain | Visual treatment. |
selectionMode | none | single | multiple | none | Enables keyboard and pointer selection. |
selectedKeys | string[] | — | Controlled selected keys. |
defaultSelectedKeys | string[] | [] | Initial uncontrolled selection. |
onSelectionChange | (keys, item?) => void | — | Selection callback. |
onItemClick | (item, index) => void | — | Row activation callback. |
gap | number | string | provider value or 8px | Local spacing override; numbers are converted to pixels. |
ListItem fields
| Field | Type | Description |
|---|---|---|
key | string | Stable unique row key. |
title | ReactNode | Primary row content. |
description | ReactNode | Supporting text. |
content | ReactNode | Additional body content. |
leading | ReactNode | Icon, Avatar, or other leading visual. |
trailing | ReactNode | Action or status at the end of the row. |
meta | ReactNode | Compact metadata before trailing content. |
href | string | Makes the row an anchor. |
disabled | boolean | Prevents interaction. |
data | T | Application data associated with the row; not rendered automatically. |
All standard HTMLAttributes<HTMLDivElement> are supported on the List root.
Accessibility
Selection mode uses a listbox root and option rows with aria-selected. Interactive rows are keyboard accessible. Links remain native anchors, preserving browser navigation and expected link semantics.