ListGroup

The ListGroup component provides an organized list structure with items, dividers, and sections for displaying grouped content.

Basics

Compose a vertical list by nesting ListGroupItem elements inside a ListGroup. Use the variant prop to switch between default, bordered, and flush styles.

Loading demo…

import { ListGroup, ListGroupItem } from '@plocks/ui'; export function Demo() { return ( <ListGroup variant="bordered" style={{ width: '100%', maxWidth: 360 }}> <ListGroupItem>Overview</ListGroupItem> <ListGroupItem>Analytics</ListGroupItem> <ListGroupItem>Reports</ListGroupItem> <ListGroupItem>Settings</ListGroupItem> </ListGroup> ); }

Two-line rows

Pass label and description for a stacked row. These take precedence over children, which renders as a single line of text and so cannot hold a layout block. description is optional — a label on its own reads the same as children, and mixing both row shapes in one group stays aligned.

Loading demo…

import { ListGroup, ListGroupItem } from '@plocks/ui'; export function Demo() { return ( <ListGroup variant="bordered" style={{ width: '100%', maxWidth: 360 }}> <ListGroupItem label="Download your data" description="A ZIP bundle of your profile, library, and history" /> <ListGroupItem label="Privacy" description="Control who sees your activity" /> <ListGroupItem label="About" /> </ListGroup> ); }

Variants

Compare the default, bordered, and flush group surfaces with identical rows.

Loading demo…

import { Column, ListGroup, ListGroupItem, Text } from '@plocks/ui'; const variants = ['default', 'bordered', 'flush'] as const; export function Demo() { return ( <Column gap="lg" fullWidth> {variants.map(variant => ( <Column key={variant} gap="xs" fullWidth> <Text fw="semibold">{variant}</Text> <ListGroup variant={variant}> <ListGroupItem>Overview</ListGroupItem> <ListGroupItem>Settings</ListGroupItem> </ListGroup> </Column> ))} </Column> ); }

Trailing value

value renders muted text at the end of the row, before endSection. A two-line row already claims the free space, so its value sits flush right on its own; a single-line row only takes its natural width, so the value is what gets pushed to the edge and endSection follows it.

Loading demo…

import { Badge, ListGroup, ListGroupItem } from '@plocks/ui'; export function Demo() { return ( <ListGroup variant="bordered" style={{ width: '100%', maxWidth: 360 }}> <ListGroupItem label="Username" value="@ada" /> <ListGroupItem label="Language" description="App language" value="English" /> <ListGroupItem value="2 unread" endSection={<Badge>New</Badge>}> Inbox </ListGroupItem> </ListGroup> ); }
Scan to open this page on your phoneplocks.dev/ui/ListGroup