Skip to content

Containment

Lists

Rows of text and controls: one to three lines, leading and trailing content, selectable, and segmented items.

Examples

Static list

One to three lines with leading and trailing content. Static lists need no JavaScript.

  • Ali Connors Product designer
  • Team lead Sandra Adams Engineering 12
  • All contacts
React HTML
import { Icon, List, ListItem } from '@kyralabs/m3exp-web/react';

export default function Static() {
  return (
    <List aria-label="Contacts">
      <ListItem leadingContent={<Icon name="person" />} supportingContent="Product designer">
        Ali Connors
      </ListItem>
      <ListItem
        leadingContent={<Icon name="person" />}
        overlineContent="Team lead"
        supportingContent="Engineering"
        trailingContent="12"
      >
        Sandra Adams
      </ListItem>
      <ListItem
        leadingContent={<Icon name="group" />}
        trailingContent={<Icon name="chevron_right" />}
      >
        All contacts
      </ListItem>
    </List>
  );
}
<ul class="m3e-list" aria-label="Contacts">
  <li class="m3e-list-item">
    <span class="m3e-list-item__leading"
      ><span class="m3e-icon" aria-hidden="true">person</span></span
    >
    <span class="m3e-list-item__content">
      <span class="m3e-list-item__headline">Ali Connors</span>
      <span class="m3e-list-item__supporting">Product designer</span>
    </span>
  </li>
  <li class="m3e-list-item">
    <span class="m3e-list-item__leading"
      ><span class="m3e-icon" aria-hidden="true">person</span></span
    >
    <span class="m3e-list-item__content">
      <span class="m3e-list-item__overline">Team lead</span>
      <span class="m3e-list-item__headline">Sandra Adams</span>
      <span class="m3e-list-item__supporting">Engineering</span>
    </span>
    <span class="m3e-list-item__trailing">12</span>
  </li>
  <li class="m3e-list-item">
    <span class="m3e-list-item__leading"
      ><span class="m3e-icon" aria-hidden="true">group</span></span
    >
    <span class="m3e-list-item__content"
      ><span class="m3e-list-item__headline">All contacts</span></span
    >
    <span class="m3e-list-item__trailing"
      ><span class="m3e-icon" aria-hidden="true">chevron_right</span></span
    >
  </li>
</ul>

Run the HTML version (CSS classes only).

Single selection

An interactive list is a listbox with one tab stop: arrow keys move, Space or Enter selects. A radio button shows which option is selected.

The live demo runs with JavaScript. Its code is below.

React HTML
import { List, ListItem } from '@kyralabs/m3exp-web/react';

export default function Selectable() {
  return (
    <List aria-label="Pets" selectionMode="single" defaultSelectedKeys={['dog']}>
      <ListItem id="cat" selectionControl="radio">
        Cat
      </ListItem>
      <ListItem id="dog" selectionControl="radio">
        Dog
      </ListItem>
      <ListItem id="rabbit" selectionControl="radio">
        Rabbit
      </ListItem>
    </List>
  );
}
<m3e-list label="Pets" selection-mode="single">
  <div class="m3e-list-item" data-value="cat">
    <span class="m3e-list-item__leading">
      <span class="m3e-radio-button">
        <input class="m3e-radio-button__input" type="radio" />
        <span class="m3e-radio-button__icon" aria-hidden="true"></span>
        <span class="m3e-radio-button__state" aria-hidden="true"></span>
      </span>
    </span>
    <span class="m3e-list-item__content"><span class="m3e-list-item__headline">Cat</span></span>
  </div>
  <div class="m3e-list-item" data-value="dog" aria-selected="true">
    <span class="m3e-list-item__leading">
      <span class="m3e-radio-button">
        <input class="m3e-radio-button__input" type="radio" />
        <span class="m3e-radio-button__icon" aria-hidden="true"></span>
        <span class="m3e-radio-button__state" aria-hidden="true"></span>
      </span>
    </span>
    <span class="m3e-list-item__content"><span class="m3e-list-item__headline">Dog</span></span>
  </div>
  <div class="m3e-list-item" data-value="rabbit">
    <span class="m3e-list-item__leading">
      <span class="m3e-radio-button">
        <input class="m3e-radio-button__input" type="radio" />
        <span class="m3e-radio-button__icon" aria-hidden="true"></span>
        <span class="m3e-radio-button__state" aria-hidden="true"></span>
      </span>
    </span>
    <span class="m3e-list-item__content"><span class="m3e-list-item__headline">Rabbit</span></span>
  </div>
</m3e-list>

Run the HTML version (custom elements, no framework).

Multiple selection

Checkboxes as indicators, and a disabled option (disabledKeys, or aria-disabled on the element's option). The option is the control: its checkbox is inert and follows aria-selected.

The live demo runs with JavaScript. Its code is below.

React HTML
import { List, ListItem } from '@kyralabs/m3exp-web/react';

export default function Multiple() {
  return (
    <List
      aria-label="Toppings"
      selectionMode="multiple"
      defaultSelectedKeys={['basil', 'olives']}
      disabledKeys={['anchovies']}
    >
      <ListItem id="basil" selectionControl="checkbox" supportingContent="Fresh">
        Basil
      </ListItem>
      <ListItem id="mushrooms" selectionControl="checkbox">
        Mushrooms
      </ListItem>
      <ListItem id="olives" selectionControl="checkbox">
        Olives
      </ListItem>
      <ListItem id="anchovies" selectionControl="checkbox" supportingContent="Sold out">
        Anchovies
      </ListItem>
    </List>
  );
}
<m3e-list label="Toppings" selection-mode="multiple">
  <div class="m3e-list-item" data-value="basil" aria-selected="true">
    <span class="m3e-list-item__leading">
      <span class="m3e-checkbox">
        <input class="m3e-checkbox__input" type="checkbox" />
        <span class="m3e-checkbox__box" aria-hidden="true">
          <svg class="m3e-checkbox__mark" focusable="false">
            <path class="m3e-checkbox__stroke" d="M0 0H48" />
            <path class="m3e-checkbox__stroke" d="M0 0H48" />
          </svg>
        </span>
        <span class="m3e-checkbox__state" aria-hidden="true"></span>
      </span>
    </span>
    <span class="m3e-list-item__content">
      <span class="m3e-list-item__headline">Basil</span>
      <span class="m3e-list-item__supporting">Fresh</span>
    </span>
  </div>
  <div class="m3e-list-item" data-value="mushrooms">
    <span class="m3e-list-item__leading">
      <span class="m3e-checkbox">
        <input class="m3e-checkbox__input" type="checkbox" />
        <span class="m3e-checkbox__box" aria-hidden="true">
          <svg class="m3e-checkbox__mark" focusable="false">
            <path class="m3e-checkbox__stroke" d="M0 0H48" />
            <path class="m3e-checkbox__stroke" d="M0 0H48" />
          </svg>
        </span>
        <span class="m3e-checkbox__state" aria-hidden="true"></span>
      </span>
    </span>
    <span class="m3e-list-item__content">
      <span class="m3e-list-item__headline">Mushrooms</span>
    </span>
  </div>
  <div class="m3e-list-item" data-value="olives" aria-selected="true">
    <span class="m3e-list-item__leading">
      <span class="m3e-checkbox">
        <input class="m3e-checkbox__input" type="checkbox" />
        <span class="m3e-checkbox__box" aria-hidden="true">
          <svg class="m3e-checkbox__mark" focusable="false">
            <path class="m3e-checkbox__stroke" d="M0 0H48" />
            <path class="m3e-checkbox__stroke" d="M0 0H48" />
          </svg>
        </span>
        <span class="m3e-checkbox__state" aria-hidden="true"></span>
      </span>
    </span>
    <span class="m3e-list-item__content">
      <span class="m3e-list-item__headline">Olives</span>
    </span>
  </div>
  <div class="m3e-list-item" data-value="anchovies" aria-disabled="true">
    <span class="m3e-list-item__leading">
      <span class="m3e-checkbox">
        <input class="m3e-checkbox__input" type="checkbox" />
        <span class="m3e-checkbox__box" aria-hidden="true">
          <svg class="m3e-checkbox__mark" focusable="false">
            <path class="m3e-checkbox__stroke" d="M0 0H48" />
            <path class="m3e-checkbox__stroke" d="M0 0H48" />
          </svg>
        </span>
        <span class="m3e-checkbox__state" aria-hidden="true"></span>
      </span>
    </span>
    <span class="m3e-list-item__content">
      <span class="m3e-list-item__headline">Anchovies</span>
      <span class="m3e-list-item__supporting">Sold out</span>
    </span>
  </div>
</m3e-list>

Run the HTML version (custom elements, no framework).

Switches

A switch takes the trailing slot by default (selectionControlPosition moves it).

The live demo runs with JavaScript. Its code is below.

React HTML
import { Icon, List, ListItem } from '@kyralabs/m3exp-web/react';

export default function Switches() {
  return (
    <List aria-label="Connections" selectionMode="multiple" defaultSelectedKeys={['wifi']}>
      <ListItem id="wifi" leadingContent={<Icon name="wifi" />} selectionControl="switch">
        Wi-Fi
      </ListItem>
      <ListItem id="bluetooth" leadingContent={<Icon name="bluetooth" />} selectionControl="switch">
        Bluetooth
      </ListItem>
      <ListItem
        id="hotspot"
        leadingContent={<Icon name="wifi_tethering" />}
        selectionControl="switch"
        supportingContent="Share this phone's connection"
      >
        Hotspot
      </ListItem>
    </List>
  );
}
<m3e-list label="Connections" selection-mode="multiple">
  <div class="m3e-list-item" data-value="wifi" aria-selected="true">
    <span class="m3e-list-item__leading"
      ><span class="m3e-icon" aria-hidden="true">wifi</span></span
    >
    <span class="m3e-list-item__content">
      <span class="m3e-list-item__headline">Wi-Fi</span>
    </span>
    <span class="m3e-list-item__trailing">
      <span class="m3e-switch">
        <input class="m3e-switch__input" type="checkbox" role="switch" />
        <span class="m3e-switch__track" aria-hidden="true">
          <span class="m3e-switch__handle"><span class="m3e-switch__state"></span></span>
        </span>
      </span>
    </span>
  </div>
  <div class="m3e-list-item" data-value="bluetooth">
    <span class="m3e-list-item__leading"
      ><span class="m3e-icon" aria-hidden="true">bluetooth</span></span
    >
    <span class="m3e-list-item__content">
      <span class="m3e-list-item__headline">Bluetooth</span>
    </span>
    <span class="m3e-list-item__trailing">
      <span class="m3e-switch">
        <input class="m3e-switch__input" type="checkbox" role="switch" />
        <span class="m3e-switch__track" aria-hidden="true">
          <span class="m3e-switch__handle"><span class="m3e-switch__state"></span></span>
        </span>
      </span>
    </span>
  </div>
  <div class="m3e-list-item" data-value="hotspot">
    <span class="m3e-list-item__leading"
      ><span class="m3e-icon" aria-hidden="true">wifi_tethering</span></span
    >
    <span class="m3e-list-item__content">
      <span class="m3e-list-item__headline">Hotspot</span>
      <span class="m3e-list-item__supporting">Share this phone's connection</span>
    </span>
    <span class="m3e-list-item__trailing">
      <span class="m3e-switch">
        <input class="m3e-switch__input" type="checkbox" role="switch" />
        <span class="m3e-switch__track" aria-hidden="true">
          <span class="m3e-switch__handle"><span class="m3e-switch__state"></span></span>
        </span>
      </span>
    </span>
  </div>
</m3e-list>

Run the HTML version (custom elements, no framework).

Segmented items

Items on their own surfaces, 2dp apart, with actions (onAction).

The live demo runs with JavaScript. Its code is below.

React HTML
import { Icon, List, SegmentedListItem } from '@kyralabs/m3exp-web/react';

export default function Segmented() {
  return (
    <List
      aria-label="Settings"
      onAction={(key) => {
        console.log(key);
      }}
    >
      <SegmentedListItem
        id="wifi"
        leadingContent={<Icon name="wifi" />}
        supportingContent="Home network"
      >
        Wi-Fi
      </SegmentedListItem>
      <SegmentedListItem
        id="bluetooth"
        leadingContent={<Icon name="bluetooth" />}
        supportingContent="Off"
      >
        Bluetooth
      </SegmentedListItem>
      <SegmentedListItem
        id="battery"
        leadingContent={<Icon name="battery_full" />}
        supportingContent="82%"
      >
        Battery
      </SegmentedListItem>
    </List>
  );
}
<m3e-list label="Settings">
  <div class="m3e-list-item m3e-list-item--segmented" data-value="wifi">
    <span class="m3e-list-item__leading"
      ><span class="m3e-icon" aria-hidden="true">wifi</span></span
    >
    <span class="m3e-list-item__content">
      <span class="m3e-list-item__headline">Wi-Fi</span>
      <span class="m3e-list-item__supporting">Home network</span>
    </span>
  </div>
  <div class="m3e-list-item m3e-list-item--segmented" data-value="bluetooth">
    <span class="m3e-list-item__leading"
      ><span class="m3e-icon" aria-hidden="true">bluetooth</span></span
    >
    <span class="m3e-list-item__content">
      <span class="m3e-list-item__headline">Bluetooth</span>
      <span class="m3e-list-item__supporting">Off</span>
    </span>
  </div>
  <div class="m3e-list-item m3e-list-item--segmented" data-value="battery">
    <span class="m3e-list-item__leading"
      ><span class="m3e-icon" aria-hidden="true">battery_full</span></span
    >
    <span class="m3e-list-item__content">
      <span class="m3e-list-item__headline">Battery</span>
      <span class="m3e-list-item__supporting">82%</span>
    </span>
  </div>
</m3e-list>

Run the HTML version (custom elements, no framework).

API

React

<List>

A list (COMPONENT_SPEC §20). Static by default: the m3e-css <ul class="m3e-list"> of <ListItem> / <SegmentedListItem> <li>s. With selectionMode (or onAction) it is an interactive list (owner decision M8 #13): React Aria useListBox / useOption (a listbox of options with aria-selected: single and multiple selection, typeahead, Home / End, arrows that wrap; Right / Left move like Down / Up), the DOM <m3e-list> renders. Items with a selectionControl show their state in an inert checkbox, radio button or switch.

Why useListBox and not GridList: every option is one control (Compose's selectable / checkable rows, m3.material.io's listbox); a grid is for rows with several actions, which Compose's nested-control sample (a trailing IconButton) is the only case of and which a listbox cannot hold without nested interactive elements.

Prop Type Default Description
children required ReactNode <ListItem> / <SegmentedListItem> elements (static lists may hold other <li>s too).
selectionMode "none" | "single" | "multiple" Interactive list selection (React Aria listbox, owner decision M8 #13): single (Compose's selectable items) or multiple (checkable items). Without it, and without onAction, the list is a static <ul>.
selectedKeys 'all' | Iterable<Key> | undefined
defaultSelectedKeys 'all' | Iterable<Key> | undefined
disallowEmptySelection boolean | undefined
disabledKeys Iterable<Key> | undefined
aria-label string | undefined
aria-labelledby string | undefined
aria-describedby string | undefined
id string | undefined
className string | undefined
onAction ((key: Key) => void) | undefined Actionable options (Compose's clickable items): click or Enter. Makes the list interactive.
onSelectionChange ((keys: Selection) => void) | undefined

<ListItem>

The expressive list item (COMPONENT_SPEC §20; Compose ListItem(content = …)): headline (the children), overline, supporting text, leading and trailing content; one, two or three lines. In a static <List> it is an <li class="m3e-list-item">; in an interactive <List selectionMode> (or with onAction) it is a React Aria option with the state layer, focus ring, selected colors and the fast-spatial shape morph.

With headlineContent instead of children it is the legacy item (deprecated, D4).

Prop Type Default Description
id Key The item's key in an interactive <List> (else the element's key).
children ReactNode The headline (Compose's content).
textValue string | undefined The item's text for typeahead, when children is not a string.
isDisabled boolean | undefined Disabled: translucent content; in an interactive list it cannot be focused or selected.
isDragged boolean | undefined The dragged style (ReorderListTokens; owner decision M8 #14): style only, no drag logic.
selectionControl "checkbox" | "radio" | "switch" A checkbox, radio button or switch that shows the option's selected state in an interactive list (Compose's samples: onClick = null). The option is the control; the indicator is inert.
selectionControlPosition 'leading' | 'trailing' | undefined leading The slot the selection control takes. Default leading (checkbox, radio), trailing (switch).
leadingContent ReactNode Before the text: an <Icon>, an avatar, an image (.m3e-list-item__avatar / __image).
trailingContent ReactNode After the text: an <Icon>, trailing supporting text, a control in a static list.
overlineContent ReactNode Above the headline (label small).
supportingContent ReactNode Below the headline (body medium).
threeLine boolean | undefined Three-line layout (88dp, slots at the top) for multi-line supporting text, which Compose measures and CSS cannot (an overline with supporting text is three-line already).

Also accepts HTML attributes not listed here.

<SegmentedListItem>

A segmented list item (Compose SegmentedListItem): Surface by default (owner decision M8 #12), 2dp apart; the list's first and last items take the 16dp outer corners. Same props and behavior as <ListItem>.

Prop Type Default Description
id Key The item's key in an interactive <List> (else the element's key).
children ReactNode The headline (Compose's content).
textValue string | undefined The item's text for typeahead, when children is not a string.
isDisabled boolean | undefined Disabled: translucent content; in an interactive list it cannot be focused or selected.
isDragged boolean | undefined The dragged style (ReorderListTokens; owner decision M8 #14): style only, no drag logic.
selectionControl "checkbox" | "radio" | "switch" A checkbox, radio button or switch that shows the option's selected state in an interactive list (Compose's samples: onClick = null). The option is the control; the indicator is inert.
selectionControlPosition 'leading' | 'trailing' | undefined leading The slot the selection control takes. Default leading (checkbox, radio), trailing (switch).
leadingContent ReactNode Before the text: an <Icon>, an avatar, an image (.m3e-list-item__avatar / __image).
trailingContent ReactNode After the text: an <Icon>, trailing supporting text, a control in a static list.
overlineContent ReactNode Above the headline (label small).
supportingContent ReactNode Below the headline (body medium).
threeLine boolean | undefined Three-line layout (88dp, slots at the top) for multi-line supporting text, which Compose measures and CSS cannot (an overline with supporting text is three-line already).

Also accepts HTML attributes not listed here.

Custom elements

<m3e-list>

import '@kyralabs/m3e-elements/list.js';

<m3e-list label="Pets" selection-mode="single">…items…</m3e-list>: an interactive list (COMPONENT_SPEC §20; owner decisions M8 #13 and #15). Renders the m3e-css .m3e-list contract inside itself (the host is display: contents) and moves its children, .m3e-list-items in the m3e-css markup (data-value keys them; aria-selected="true" / aria-disabled="true" set the initial state), into it. It exists for what CSS cannot do (m3e-elements ListLayout; m3e-react's <List selectionMode> renders the same DOM with React Aria):

  • a role="listbox" of options with one tab stop, arrow keys that wrap (Down / Right next, Up / Left previous), Home / End and typeahead;
  • selection (selection-mode="single" | "multiple"): click, Space or Enter toggles an option, a checkbox, radio button or switch inside it shows the state; selection-change (detail: { values, value }, cancelable: preventDefault() keeps the selection);
  • selection-mode="none" (the default): actionable options (Compose's clickable ListItem); click or Enter emits action (detail: { value }).

Static lists need no element: <ul class="m3e-list"> of <li class="m3e-list-item">.

Attributes: label (the listbox's accessible name), selection-mode (selection is its deprecated name, since 1.8; removed in 2.0), disallow-empty-selection. Property selectedValues (string[]).

Attribute Property Type Notes
label label string
selection-mode selectionMode ListSelectionMode none (default) | single | multiple (React's selectionMode).
selection selection ListSelectionMode Deprecated. Since 1.8: use selectionMode (selection-mode). Removed in 2.0. The selection mode.
disallow-empty-selection disallowEmptySelection boolean
Event Detail Description
selection-change ListSelectionChangeDetail The selection changes; cancelable.
action ListActionDetail An option was activated (selection-mode="none").

CSS

list.css

@import '@kyralabs/m3e-css/list.css';

Lists (COMPONENT_SPEC §20): the expressive list item, segmented list items, interactive (selectable / checkable / clickable) items, the dragged style and the legacy list item (@deprecated, D4). Static lists need no JavaScript:

<ul class="m3e-list">
  <li class="m3e-list-item">
    <span class="m3e-list-item__leading"><span class="m3e-icon" aria-hidden="true">person</span></span>
    <span class="m3e-list-item__content">
      <span class="m3e-list-item__overline">Overline</span>          (optional)
      <span class="m3e-list-item__headline">Headline</span>
      <span class="m3e-list-item__supporting">Supporting text</span> (optional)
    </span>
    <span class="m3e-list-item__trailing">100+</span>                (optional)
  </li>
</ul>
  • Lines: one by default; two with an overline or supporting text; three with both, or with
--three-line (Compose's ListItemType: multi-line supporting text, which CSS cannot detect).
  • Segmented: .m3e-list-item--segmented items (SegmentedListItem). The list spaces them by
SegmentedGap and its first / last items take the outer corners (only at rest).
  • Interactive: .m3e-list-item--interactive on a focusable item (Compose's clickable,
selectable and checkable overloads): a listbox's options (<m3e-list> / m3e-react <List
selectionMode>, role="option" + aria-selected), or a link / button row. State layer, focus
ring and the shape morph; [aria-selected='true'] selected colors and shape; [aria-disabled]
disabled.
  • Indicators: a checkbox, radio button or switch (m3e-css markup) in a slot shows an option's
state: wrap it in an element with `inert` (the option is the control; Compose's samples pass
onClick = null), and the JS layers keep its input's `checked` in step with aria-selected.
  • Dragged: [data-dragged] (ReorderListTokens; owner decision M8 #14). Style only.
  • Disabled static items: .m3e-list-item--disabled (a listitem takes no aria-disabled).
  • Content helpers: .m3e-list-item__avatar (40dp, letters or an image), __image (56dp),
__video (100 × 56dp; --large 114 × 64dp): ListTokens sizes and shapes.
100 custom properties it reads
Custom property Default
--m3e-comp-checkbox-box-padding 2px
--m3e-comp-checkbox-state-layer-size 40px
--m3e-comp-divider-thickness 1px
--m3e-comp-list-item-baseline-leading-space 16px
--m3e-comp-list-item-baseline-padding-end 16px
--m3e-comp-list-item-baseline-padding-start 16px
--m3e-comp-list-item-baseline-padding-vertical 8px
--m3e-comp-list-item-baseline-shape var(--m3e-sys-shape-corner-none)
--m3e-comp-list-item-baseline-three-line-padding-vertical 12px
--m3e-comp-list-item-baseline-trailing-space 16px
--m3e-comp-list-item-color-duration var(--m3e-sys-motion-spring-default-effects-duration)
--m3e-comp-list-item-color-easing var(--m3e-sys-motion-spring-default-effects-easing)
--m3e-comp-list-item-container-color var(--m3e-sys-color-surface)
--m3e-comp-list-item-container-color-selected var(--m3e-sys-color-secondary-container)
--m3e-comp-list-item-elevation-duration var(--m3e-sys-motion-spring-fast-spatial-duration)
--m3e-comp-list-item-elevation-easing var(--m3e-sys-motion-spring-fast-spatial-easing)
--m3e-comp-list-item-headline-content-color var(--m3e-sys-color-on-surface)
--m3e-comp-list-item-headline-content-color-disabled color-mix(in srgb, var(--m3e-sys-color-on-surface) calc(0.38 * 100%), transparent)
--m3e-comp-list-item-headline-content-color-dragged var(--m3e-sys-color-on-tertiary-container)
--m3e-comp-list-item-headline-content-color-selected var(--m3e-sys-color-on-secondary-container)
--m3e-comp-list-item-headline-style-font var(--m3e-sys-typescale-body-large-font)
--m3e-comp-list-item-headline-style-line-height var(--m3e-sys-typescale-body-large-line-height)
--m3e-comp-list-item-headline-style-size var(--m3e-sys-typescale-body-large-size)
--m3e-comp-list-item-headline-style-tracking var(--m3e-sys-typescale-body-large-tracking)
--m3e-comp-list-item-headline-style-weight var(--m3e-sys-typescale-body-large-weight)
--m3e-comp-list-item-large-leading-video-height 64px
--m3e-comp-list-item-large-leading-video-width 114px
--m3e-comp-list-item-leading-avatar-color var(--m3e-sys-color-primary-container)
--m3e-comp-list-item-leading-avatar-label-color var(--m3e-sys-color-on-primary-container)
--m3e-comp-list-item-leading-avatar-shape var(--m3e-sys-shape-corner-full)
--m3e-comp-list-item-leading-avatar-size 40px
--m3e-comp-list-item-leading-content-color var(--m3e-sys-color-on-surface-variant)
--m3e-comp-list-item-leading-content-color-disabled color-mix(in srgb, var(--m3e-sys-color-on-surface) calc(0.38 * 100%), transparent)
--m3e-comp-list-item-leading-content-color-dragged var(--m3e-sys-color-on-tertiary-container)
--m3e-comp-list-item-leading-content-color-selected var(--m3e-sys-color-on-secondary-container)
--m3e-comp-list-item-leading-image-expressive-shape var(--m3e-sys-shape-corner-small)
--m3e-comp-list-item-leading-image-height 56px
--m3e-comp-list-item-leading-image-width 56px
--m3e-comp-list-item-leading-style-font var(--m3e-sys-typescale-title-medium-font)
--m3e-comp-list-item-leading-style-line-height var(--m3e-sys-typescale-title-medium-line-height)
--m3e-comp-list-item-leading-style-size var(--m3e-sys-typescale-title-medium-size)
--m3e-comp-list-item-leading-style-tracking var(--m3e-sys-typescale-title-medium-tracking)
--m3e-comp-list-item-leading-style-weight var(--m3e-sys-typescale-title-medium-weight)
--m3e-comp-list-item-leading-video-shape var(--m3e-sys-shape-corner-small)
--m3e-comp-list-item-morph-duration var(--m3e-sys-motion-spring-fast-spatial-duration)
--m3e-comp-list-item-morph-easing var(--m3e-sys-motion-spring-fast-spatial-easing)
--m3e-comp-list-item-one-line-min-height 56px
--m3e-comp-list-item-overline-content-color var(--m3e-sys-color-on-surface-variant)
--m3e-comp-list-item-overline-content-color-disabled color-mix(in srgb, var(--m3e-sys-color-on-surface) calc(0.38 * 100%), transparent)
--m3e-comp-list-item-overline-content-color-dragged var(--m3e-sys-color-on-tertiary-container)
--m3e-comp-list-item-overline-content-color-selected var(--m3e-sys-color-on-secondary-container)
--m3e-comp-list-item-overline-style-font var(--m3e-sys-typescale-label-small-font)
--m3e-comp-list-item-overline-style-line-height var(--m3e-sys-typescale-label-small-line-height)
--m3e-comp-list-item-overline-style-size var(--m3e-sys-typescale-label-small-size)
--m3e-comp-list-item-overline-style-tracking var(--m3e-sys-typescale-label-small-tracking)
--m3e-comp-list-item-overline-style-weight var(--m3e-sys-typescale-label-small-weight)
--m3e-comp-list-item-padding-bottom 10px
--m3e-comp-list-item-padding-end 16px
--m3e-comp-list-item-padding-start 16px
--m3e-comp-list-item-padding-top 10px
--m3e-comp-list-item-segmented-container-color var(--m3e-sys-color-surface)
--m3e-comp-list-item-segmented-gap 2px
--m3e-comp-list-item-segmented-shape var(--m3e-sys-shape-corner-large)
--m3e-comp-list-item-shadow var(--m3e-sys-elevation-level0-shadow)
--m3e-comp-list-item-shadow-dragged var(--m3e-sys-elevation-level4-shadow)
--m3e-comp-list-item-shape var(--m3e-sys-shape-corner-extra-small)
--m3e-comp-list-item-shape-dragged var(--m3e-sys-shape-corner-large)
--m3e-comp-list-item-shape-focused var(--m3e-sys-shape-corner-large)
--m3e-comp-list-item-shape-hovered var(--m3e-sys-shape-corner-medium)
--m3e-comp-list-item-shape-pressed var(--m3e-sys-shape-corner-large)
--m3e-comp-list-item-shape-selected var(--m3e-sys-shape-corner-large)
--m3e-comp-list-item-small-leading-video-height 56px
--m3e-comp-list-item-small-leading-video-width 100px
--m3e-comp-list-item-space 12px
--m3e-comp-list-item-supporting-content-color var(--m3e-sys-color-on-surface-variant)
--m3e-comp-list-item-supporting-content-color-disabled color-mix(in srgb, var(--m3e-sys-color-on-surface) calc(0.38 * 100%), transparent)
--m3e-comp-list-item-supporting-content-color-dragged var(--m3e-sys-color-on-tertiary-container)
--m3e-comp-list-item-supporting-content-color-selected var(--m3e-sys-color-on-secondary-container)
--m3e-comp-list-item-supporting-style-font var(--m3e-sys-typescale-body-medium-font)
--m3e-comp-list-item-supporting-style-line-height var(--m3e-sys-typescale-body-medium-line-height)
--m3e-comp-list-item-supporting-style-size var(--m3e-sys-typescale-body-medium-size)
--m3e-comp-list-item-supporting-style-tracking var(--m3e-sys-typescale-body-medium-tracking)
--m3e-comp-list-item-supporting-style-weight var(--m3e-sys-typescale-body-medium-weight)
--m3e-comp-list-item-three-line-min-height 88px
--m3e-comp-list-item-trailing-content-color var(--m3e-sys-color-on-surface-variant)
--m3e-comp-list-item-trailing-content-color-disabled color-mix(in srgb, var(--m3e-sys-color-on-surface) calc(0.38 * 100%), transparent)
--m3e-comp-list-item-trailing-content-color-dragged var(--m3e-sys-color-on-tertiary-container)
--m3e-comp-list-item-trailing-content-color-selected var(--m3e-sys-color-on-secondary-container)
--m3e-comp-list-item-trailing-style-font var(--m3e-sys-typescale-label-small-font)
--m3e-comp-list-item-trailing-style-line-height var(--m3e-sys-typescale-label-small-line-height)
--m3e-comp-list-item-trailing-style-size var(--m3e-sys-typescale-label-small-size)
--m3e-comp-list-item-trailing-style-tracking var(--m3e-sys-typescale-label-small-tracking)
--m3e-comp-list-item-trailing-style-weight var(--m3e-sys-typescale-label-small-weight)
--m3e-comp-list-item-two-line-min-height 72px
--m3e-comp-minimum-interactive-component-size 48px
--m3e-comp-radio-button-icon-size 20px
--m3e-comp-radio-button-padding 2px
--m3e-comp-radio-button-state-layer-size 40px
--m3e-comp-reorder-list-item-container-color var(--m3e-sys-color-tertiary-container)
--m3e-comp-switch-track-height 32px

Sources

Values come from androidx Compose Material3 1.5.0-beta01 at 19991f2c and from m3.material.io, as cited below from COMPONENT_SPEC §20 and the m3e-css sources.

ListTokens.kt / ReorderListTokens.kt@19991f2c plus the ListItem.kt / ListItemDefaults.kt values Compose renders (components/list-defaults.css; SOURCES register #37). Expressive item: 16dp sides, 10dp top / bottom (ListItemDefaults.ContentPadding), 12dp after the leading and before the trailing slot; min heights 56 / 72 / 88dp for one / two / three lines (two: an overline or supporting text; three: both, or multi-line supporting text, --three-line); three-line content aligns to the top (the 60dp InteractiveListVerticalAlignmentBreakpoint), shorter content is centred. Headline body large on-surface, overline label small, supporting body medium, trailing text label small, leading / trailing / overline / supporting on-surface-variant; leading avatar 40dp (primary container, title medium), image 56dp, video 100 × 56 / 114 × 64dp (ListTokens; Compose leaves sizes to the content, so icons keep the 24dp Icon default). Containers: Surface (ListItemDefaults.colors()), segmented Surface too (segmentedColors(); owner decision M8 #12: the docs demo passes surface container like Compose's samples), 2dp apart (SegmentedGap). Selected: secondary container with on-secondary-container content. Dragged: ReorderListTokens (tertiary container / on-tertiary-container), Level4 shadow, raised (zIndex 1). Disabled: the enabled container, content at 38 % (translucent copy(alpha)). Colors pick by enabled, selected and dragged only: hover, focus and press change no color (the state layer, in the content color, only; owner decision M8 #3). Legacy item: CornerNone, 8dp vertical padding (12dp three-line, slots at the top), 16dp sides and slot spacing.

list.css sources

(compose/material3 @ 19991f2c, ListItem.kt / ListItemDefaults.kt; values in list.css / list-defaults.css / reorder-list.css, lines in PARITY.md):

  • InteractiveListItem (ListItem.kt L1462-1660): contentPadding ListItemDefaults.ContentPadding (16 / 10dp), the leading slot padded InteractiveListInternalSpacing (12dp) at its end and the trailing slot at its start; overline, content, supporting stacked; min heights 56 / 72 / 88dp by ListItemType (isExpressiveListItemHeightBasedOnTextLinesFixEnabled = true); centred until the content area reaches InteractiveListVerticalAlignmentBreakpoint ((88 + 72) / 2 − 20 = 60dp), then top-aligned: two-line items (52dp) centre, three-line items (68dp) and a 64dp video sit at the top. Slot text: headline bodyLarge, overline / trailing labelSmall, supporting bodyMedium, leading titleMedium (avatar letters).
  • The background and clip on the animated shape, merged semantics; when clickable the minimum interactive size and combinedClickable with ripple(focusRingShape = shape): the state layer in the content color (LocalContentColor), the focus ring on the item's shape (drawn inward: segmented items are 2dp apart).
  • shapeForInteraction (ListItemDefaults.kt L1136-1161): pressed > dragged > selected > focused > hovered > rest (4dp rest, 12dp hovered, 16dp otherwise), each corner animated on FastSpatial (overshoots under the expressive scheme): registered radii transitioned with the spring's linear() here; m3e-react springs them (interruptible, [data-spring]). Focused = keyboard focus (:focus-visible; Android touch input does not focus).
  • segmentedShapes (L449-507): the first item's top corners, the last item's bottom corners and a single item's four take ListTokens.ContainerShape (16dp) in the rest shape only.
  • Colors (ListItemColors: disabled > dragged > selected > default, L751-L837) on DefaultEffects; disabled content translucent (copy(alpha)) on the enabled container; segmentedColors() = ItemSegmentedContainerColor (Surface; owner decision M8 #12). Hover, focus and press change no color: the state layer only (owner decision M8 #3).
  • Dragged: ReorderListTokens colors and shape, ListItemDefaults.elevation(draggedElevation) Level4 on FastSpatial, raised above its neighbours (zIndex 1).
  • Indicators: a Checkbox / RadioButton / Switch without a handler drops its minimum interactive size (Checkbox.kt L560-584, RadioButton.kt L154-180, Switch.kt L136-176): the footprint is the box (18dp), the 2dp-padded 20dp circle or the 52 × 32dp track. A live control in a static item keeps a 48dp hit area over the item's padding (Compose: the slot padding counts towards LocalMinimumInteractiveComponentSize).
  • Legacy ListItem (L139-228, ListItemLayout L877-1214): a Surface in ListItemDefaults.shape (CornerNone), 16dp sides, 8dp vertical padding (three-line 12dp with the slots at the top), 16dp after the leading and before the trailing slot; no states.