Home Assistant List Components
Use this skill when working with list containers or list items in the Home Assistant frontend. The new primitives replace the deprecated MWC-based ha-list, ha-md-list, ha-list-item, and ha-md-list-item.
Component Hierarchy
ha-row-item (base row layout — slots, spacing, disabled)
├── ha-list-item-base (non-interactive, role="listitem")
│ ├── ha-list-item-button (interactive, renders <a> or <button>)
│ └── ha-list-item-option (selectable, role="option", aria-selected)
ha-list-base (roving-tabindex container, role="list")
├── ha-list-nav (wraps in <nav> landmark, use with ha-list-item-button + href)
└── ha-list-selectable (role="listbox", owns selection state)
Container Selection
| Use case |
Container |
Items |
| Navigation list (links) |
ha-list-nav |
ha-list-item-button with href |
| Action list (buttons) |
ha-list-base |
ha-list-item-button without href |
| Single-select listbox |
ha-list-selectable |
ha-list-item-option |
| Multi-select listbox |
ha-list-selectable multi |
ha-list-item-option |
| Static display rows |
ha-list-base |
ha-list-item-base |
Slot Mapping (MWC to New)
| Old (MWC) |
New |
Notes |
| default slot (text) |
headline slot or .headline attribute |
Primary text |
slot="secondary" |
supporting-text slot or .supportingText attribute |
Secondary line |
slot="graphic" |
slot="start" |
Leading icon/avatar |
slot="meta" |
slot="end" |
Trailing content |
| — |
slot="content" |
Escape hatch: replaces entire middle column |
CSS Custom Properties
Container
--ha-list-gap — spacing between items (default 0)
--ha-list-padding — padding around the list (default 0)
Row
--ha-row-item-padding-block — vertical padding
--ha-row-item-padding-inline — horizontal padding
--ha-row-item-gap — gap between start/content/end
--ha-row-item-min-height — minimum row height (default 48px)
Focus
--ha-list-item-focus-radius — focus outline border-radius
--ha-list-item-focus-width — focus outline width (steady state)
--ha-list-item-focus-offset — focus outline offset
--ha-list-item-focus-background — background color on keyboard focus
Selection
--ha-list-item-selected-background — background when selected (appearance="line")
CSS Parts
All items expose: base, start, content, headline, supporting-text, end.
Additional parts:
ha-list-nav: nav (the <nav> wrapper), base (inner div)
ha-list-item-button: ripple
ha-list-item-option: ripple, checkbox
Events
ha-list-activated — from ha-list-base on Enter/Space. Detail: { index, item }.
ha-list-selected — from ha-list-selectable on selection change. Detail: { index, diff: { added, removed } }.
Migration Rules
From ha-list + ha-list-item (MWC)
- Identify interactivity: Does the item navigate (href), perform an action (click), allow selection, or just display info?
- Pick container: Navigation →
ha-list-nav. Selection → ha-list-selectable. Otherwise → ha-list-base.
- Pick item: Navigates →
ha-list-item-button with href. Action → ha-list-item-button without href. Selection → ha-list-item-option. Static → ha-list-item-base.
- Remap slots:
graphic → start, meta → end, text → headline/supporting-text.
- Remove MWC attributes:
twoline, hasMeta, hasGraphic, noninteractive, activated, graphic="icon" — these have no equivalent and are not needed.
- Replace event listeners:
@request-selected → use ha-list-selected on the container (for selectable) or @click / ha-list-activated for buttons.
Non-interactive rows inside ha-list-nav
Use ha-list-item-base (not ha-list-item-button) for rows that display info without a link or action but still need to live inside a nav list. These participate in the list layout but are excluded from roving tabindex.
Tooltip on non-interactive rows
ha-list-item-base accepts pointer events by default, so ha-tooltip hover works without needing interactive.
Reference Implementations
src/panels/config/components/ha-config-navigation-list.ts — ha-list-nav + ha-list-item-button
src/panels/config/devices/ha-config-device-page.ts — mixed ha-list-item-button + ha-list-item-base in ha-list-nav
gallery/src/pages/components/ha-list.markdown — canonical gallery documentation
Anti-patterns
- Do not use
ha-list-item-button for non-interactive display rows — use ha-list-item-base.
- Do not put
ha-list-item-option inside ha-list-nav — use ha-list-selectable.
- Do not handle selection in individual items —
ha-list-selectable owns selection state.
- Do not use
@click on ha-list-item-option for selection — listen to ha-list-selected on the container.
- Do not add
role attributes manually — the components set correct ARIA roles automatically.
1---2name: home-assistant-list-components3description: Home Assistant list component migration and usage guidance. Use when editing ha-list, ha-list-item, ha-md-list, or migrating to ha-list-nav, ha-list-selectable, ha-list-item-button, ha-list-item-option, or ha-list-item-base.4license: Apache-2.05---67# Home Assistant List Components89Use this skill when working with list containers or list items in the Home Assistant frontend. The new primitives replace the deprecated MWC-based `ha-list`, `ha-md-list`, `ha-list-item`, and `ha-md-list-item`.1011## Component Hierarchy1213```text14ha-row-item (base row layout — slots, spacing, disabled)15├── ha-list-item-base (non-interactive, role="listitem")16│ ├── ha-list-item-button (interactive, renders <a> or <button>)17│ └── ha-list-item-option (selectable, role="option", aria-selected)1819ha-list-base (roving-tabindex container, role="list")20├── ha-list-nav (wraps in <nav> landmark, use with ha-list-item-button + href)21└── ha-list-selectable (role="listbox", owns selection state)22```2324## Container Selection2526| Use case | Container | Items |27|----------|-----------|-------|28| Navigation list (links) | `ha-list-nav` | `ha-list-item-button` with `href` |29| Action list (buttons) | `ha-list-base` | `ha-list-item-button` without `href` |30| Single-select listbox | `ha-list-selectable` | `ha-list-item-option` |31| Multi-select listbox | `ha-list-selectable multi` | `ha-list-item-option` |32| Static display rows | `ha-list-base` | `ha-list-item-base` |3334## Slot Mapping (MWC to New)3536| Old (MWC) | New | Notes |37|-----------|-----|-------|38| default slot (text) | `headline` slot or `.headline` attribute | Primary text |39| `slot="secondary"` | `supporting-text` slot or `.supportingText` attribute | Secondary line |40| `slot="graphic"` | `slot="start"` | Leading icon/avatar |41| `slot="meta"` | `slot="end"` | Trailing content |42| — | `slot="content"` | Escape hatch: replaces entire middle column |4344## CSS Custom Properties4546### Container4748- `--ha-list-gap` — spacing between items (default `0`)49- `--ha-list-padding` — padding around the list (default `0`)5051### Row5253- `--ha-row-item-padding-block` — vertical padding54- `--ha-row-item-padding-inline` — horizontal padding55- `--ha-row-item-gap` — gap between start/content/end56- `--ha-row-item-min-height` — minimum row height (default `48px`)5758### Focus5960- `--ha-list-item-focus-radius` — focus outline border-radius61- `--ha-list-item-focus-width` — focus outline width (steady state)62- `--ha-list-item-focus-offset` — focus outline offset63- `--ha-list-item-focus-background` — background color on keyboard focus6465### Selection6667- `--ha-list-item-selected-background` — background when selected (appearance="line")6869## CSS Parts7071All items expose: `base`, `start`, `content`, `headline`, `supporting-text`, `end`.7273Additional parts:7475- `ha-list-nav`: `nav` (the `<nav>` wrapper), `base` (inner div)76- `ha-list-item-button`: `ripple`77- `ha-list-item-option`: `ripple`, `checkbox`7879## Events8081- `ha-list-activated` — from `ha-list-base` on Enter/Space. Detail: `{ index, item }`.82- `ha-list-selected` — from `ha-list-selectable` on selection change. Detail: `{ index, diff: { added, removed } }`.8384## Migration Rules8586### From `ha-list` + `ha-list-item` (MWC)87881. **Identify interactivity**: Does the item navigate (href), perform an action (click), allow selection, or just display info?892. **Pick container**: Navigation → `ha-list-nav`. Selection → `ha-list-selectable`. Otherwise → `ha-list-base`.903. **Pick item**: Navigates → `ha-list-item-button` with `href`. Action → `ha-list-item-button` without `href`. Selection → `ha-list-item-option`. Static → `ha-list-item-base`.914. **Remap slots**: `graphic` → `start`, `meta` → `end`, text → `headline`/`supporting-text`.925. **Remove MWC attributes**: `twoline`, `hasMeta`, `hasGraphic`, `noninteractive`, `activated`, `graphic="icon"` — these have no equivalent and are not needed.936. **Replace event listeners**: `@request-selected` → use `ha-list-selected` on the container (for selectable) or `@click` / `ha-list-activated` for buttons.9495### Non-interactive rows inside `ha-list-nav`9697Use `ha-list-item-base` (not `ha-list-item-button`) for rows that display info without a link or action but still need to live inside a nav list. These participate in the list layout but are excluded from roving tabindex.9899### Tooltip on non-interactive rows100101`ha-list-item-base` accepts pointer events by default, so `ha-tooltip` hover works without needing `interactive`.102103## Reference Implementations104105```text106src/panels/config/components/ha-config-navigation-list.ts — ha-list-nav + ha-list-item-button107src/panels/config/devices/ha-config-device-page.ts — mixed ha-list-item-button + ha-list-item-base in ha-list-nav108gallery/src/pages/components/ha-list.markdown — canonical gallery documentation109```110111## Anti-patterns112113- Do not use `ha-list-item-button` for non-interactive display rows — use `ha-list-item-base`.114- Do not put `ha-list-item-option` inside `ha-list-nav` — use `ha-list-selectable`.115- Do not handle selection in individual items — `ha-list-selectable` owns selection state.116- Do not use `@click` on `ha-list-item-option` for selection — listen to `ha-list-selected` on the container.117- Do not add `role` attributes manually — the components set correct ARIA roles automatically.