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
    • ListItem.List is a <ul> with role="list"; this stops some browsers from turning the list into plain text when the list style is reset. Rows are <li>, and a screen reader announces “list, 3 items”. Give it an aria-label when the page has more than one list.
    • Outside a list, ListItem renders a <div>; an <li> is only valid inside a <ul>.
    • With render, the <li> wraps the link or button, so the list structure stays valid. The link name is the row text: title, subtitle and meta.
    • On an interactive row selected sets aria-current="true". On a static row the selected state is visual only; do not show a static row as selected.
    • On an interactive row disabled sets aria-disabled="true" and tabindex="-1"; clicks are ignored.
    • Put navigation rows in <nav aria-label>. Do not use a button row as a toggle; aria-pressed is not set.
    Key Behaviour
    Tab A static row takes no focus. An interactive row is one stop; in a static row the separate button in trailing is its own stop.
    Enter Opens a link row; activates a button row.
    Space Activates a button row. A link does not respond to Space.

    Focus is on the link or button given through render. The ring is 2 px wide and 2 px away, and shows for keyboard focus only. The selected bar is not a focus indicator. A disabled row takes no focus.

    Example Read
    Link row “Settings Account and appearance, link”
    Selected link row “Settings Account and appearance, link, current”
    Static row “List item Secondary text”, in the list “1 of 3”
    Disabled link “Notifications, link, unavailable”

    A link name can get long. When the title is enough, move the subtitle to meta or to a separate static row.

    Text is at least 4.5:1 in every mode; values are computed from the bigbang output.

    Pair Light mode Dark mode
    color-text-default / color-surface-default 16.16:1 17.18:1
    color-text-subtle / color-surface-default 8.77:1 10.27:1
    color-text-default / color-surface-selected 15.05:1 13.98:1
    color-text-subtle / color-surface-selected 8.17:1 8.36:1
    color-border-selected / color-surface-selected (bar) 5.56:1 7.11:1
    color-focus-ring / color-surface-selected 5.56:1 7.11:1
    color-text-disabled / color-surface-default (disabled, exempt) 2.52:1 2.80:1

    The divider (color-border-subtle, 1.22:1) is decorative: rows are also separated by space. Disabled text falls under the inactive-component exception of WCAG 1.4.3.

    Criterion How ListItem meets it What the product team does
    1.3.1 Info and relationships The list is ul/li with role="list"; the selected row has aria-current. Name several lists with aria-label.
    1.4.1 Use of colour Selected is given by surface, bar and aria-current. Do not show a selected state with colour alone on a static row.
    1.4.3 Contrast (minimum) Text is at least 8.17:1. Do not change colours with className.
    1.4.11 Non-text contrast The focus ring and the bar are at least 5.56:1. -
    2.1.1 Keyboard An interactive row is a link or a button; Tab, Enter and (on a button) Space work. Do not make a row clickable with onClick; use render.
    2.4.4 Link purpose The link name is the title. Write a meaningful title.
    2.4.7 Focus visible The ring is around the row. Do not remove outline with className.
    2.5.8 Target size An sm row is at least 8 + 20 + 8 = 36 px tall. Keep buttons in trailing at 24 px or more (Button sm is 32 px).
    4.1.2 Name, role, value The link or button carries its own role; aria-current and aria-disabled give the state. Use a real a or button for render.