Skip to content
BigBang

Popular

    ↑↓Navigate↵OpenEscClose
    TR

    Components

    ListItem

    One row of a list: a leading visual, a title and subtitle, and meta or an action at the end.

    Storybook
    Storybook
    Source
    Source

    The example below loads live from Storybook; open it in Storybook for the controls.

    Live example, StorybookOpen in Storybook

    A ListItem has a leading visual (leading), a title, a subtitle (subtitle), short information at the end (meta) and an action or badge (trailing). The default row is static: it does not change on hover and is not a tab stop. Put rows in ListItem.List; the list is a <ul> and the rows are <li>.

    • User 1Secondary text
      Today
    import { Avatar, ListItem } from '@bigbang/ui';
    export default function Default() {
    return (
    <ListItem.List className="w-full max-w-md" aria-label="List">
    <ListItem
    title="User 1"
    subtitle="Secondary text"
    meta="Today"
    leading={<Avatar name="User 1" decorative />}
    />
    </ListItem.List>
    );
    }

    size sets the block padding: sm is 8 px, md is 12 px, lg is 16 px. lg also sets the title to 16 px. Give the list divided for separator lines. variant="outline" draws a border around the row and variant="muted" tints it.

    • SmallSecondary text
    • MediumSecondary text
    • LargeSecondary text
    import { Icon, ListItem } from '@bigbang/ui';
    export default function Sizes() {
    return (
    <ListItem.List divided className="w-full max-w-md" aria-label="List">
    <ListItem size="sm" title="Small" subtitle="Secondary text" leading={<Icon name="settings" tone="subtle" />} />
    <ListItem size="md" title="Medium" subtitle="Secondary text" leading={<Icon name="settings" tone="subtle" />} />
    <ListItem size="lg" title="Large" subtitle="Secondary text" leading={<Icon name="settings" tone="subtle" />} />
    </ListItem.List>
    );
    }

    With render the whole row is one target: render={<a href="…" />}. On hover, press and focus the row is tinted with motion.stateLayer; keyboard focus shows a 2 px ring. selected marks the current page: a selected surface, a 2 px bar at the inline start and aria-current="true".

    import { Icon, ListItem } from '@bigbang/ui';
    export default function Links() {
    return (
    <nav aria-label="Account" className="w-full max-w-md">
    <ListItem.List>
    <ListItem
    title="Profile"
    leading={<Icon name="user" tone="subtle" />}
    trailing={<Icon name="chevron-right" tone="subtle" />}
    render={<a href="#profile" />}
    />
    <ListItem
    title="Settings"
    subtitle="Account and appearance"
    leading={<Icon name="settings" tone="subtle" />}
    trailing={<Icon name="chevron-right" tone="subtle" />}
    selected
    render={<a href="#settings" />}
    />
    <ListItem
    title="Notifications"
    subtitle="Email and app"
    leading={<Icon name="bell" tone="subtle" />}
    trailing={<Icon name="chevron-right" tone="subtle" />}
    render={<a href="#notifications" />}
    />
    </ListItem.List>
    </nav>
    );
    }

    When a row needs a button, keep the row static and put a Button in trailing. When the row is clickable, trailing must not hold a link or a button: nested interactive elements are invalid. The button is its own tab stop.

    • First itemSecondary text
    • Second itemSecondary text
    • Third itemSecondary text
    import { Button, Icon, ListItem } from '@bigbang/ui';
    export default function TrailingAction() {
    return (
    <ListItem.List divided className="w-full max-w-md" aria-label="List">
    {['First item', 'Second item', 'Third item'].map((title) => (
    <ListItem
    key={title}
    title={title}
    subtitle="Secondary text"
    leading={<Icon name="file" tone="subtle" />}
    trailing={
    <Button size="sm" variant="tertiary">
    Edit
    </Button>
    }
    />
    ))}
    </ListItem.List>
    );
    }

    disabled greys the row out. An interactive row leaves the tab order and ignores clicks (aria-disabled="true").

    import { Icon, ListItem } from '@bigbang/ui';
    export default function Disabled() {
    return (
    <ListItem.List className="w-full max-w-md" aria-label="List">
    <ListItem
    title="Settings"
    subtitle="Account and appearance"
    leading={<Icon name="settings" />}
    render={<a href="#settings" />}
    />
    <ListItem
    title="Notifications"
    subtitle="Email and app"
    leading={<Icon name="bell" />}
    disabled
    render={<a href="#notifications" />}
    />
    </ListItem.List>
    );
    }

    ListItem takes every colour from surface, text and border tokens.

    import { Icon, ListItem } from '@bigbang/ui';
    export default function Links() {
    return (
    <nav aria-label="Account" className="w-full max-w-md">
    <ListItem.List>
    <ListItem
    title="Profile"
    leading={<Icon name="user" tone="subtle" />}
    trailing={<Icon name="chevron-right" tone="subtle" />}
    render={<a href="#profile" />}
    />
    <ListItem
    title="Settings"
    subtitle="Account and appearance"
    leading={<Icon name="settings" tone="subtle" />}
    trailing={<Icon name="chevron-right" tone="subtle" />}
    selected
    render={<a href="#settings" />}
    />
    <ListItem
    title="Notifications"
    subtitle="Email and app"
    leading={<Icon name="bell" tone="subtle" />}
    trailing={<Icon name="chevron-right" tone="subtle" />}
    render={<a href="#notifications" />}
    />
    </ListItem.List>
    </nav>
    );
    }