List

Shared primitive for option lists. Used internally by Select, Dropdown (combobox), MultiSelect, Menu, the Phone input's country picker, and Datepicker's month/year selects. The slots, modes, and keyboard behaviour documented below are what each of those consumers inherits.

a11y (built in): LB.List applies the roles itself — role="listbox" (or menu under data-lb-list-mode="menu") on the items container, role="option"/menuitem per item, aria-multiselectable in multi mode, aria-disabled mirrored from the item's disabled class at mount, and aria-selected kept in sync on every toggle; auto-inserted separators get role="separator" like the authored ones. Keyboard is ↑/↓ (wrapping), Home/End and Enter/Space to select, and it skips disabled and filtered-out items — on a filterable list the same keys are bound to the search field so you can type and arrow without re-tabbing. Items are given stable ids and each highlight move fires lb-list-active-change, so the owning combobox (Command Palette) points aria-activedescendant at the active option while focus stays in the input — the list never steals it.

Usage: Root .lb-list on a <ul> (or <div>). Items are .lb-list__item — <li>, <button>, or <a>. Opt-in keyboard + selection behaviour with data-lb-list; set mode via data-lb-list-mode="single|multi|menu". Filterable lists add data-lb-list-filterable. The container is not focusable on its own — put tabindex="0" and an aria-label on it when the list itself is the tab stop, as the demos below do.


Simple

Plain items. No interactions unless wired. Use when rendering read-only lists (recent activity, navigation options).

  • Apple
  • Banana
  • Cherry
  • Grape (sold out)
  • Mango

With icons

Leading icon slot (.lb-list__icon). Useful for category lists, country pickers, or menus with visual hints.

  • Account settings
  • Preferences
  • Sign out

Single-select

Arrow keys navigate, Enter/Space selects, Home/End jump. Dispatches lb-list-select with { value, item }. Tab into the list to try it.

  • Apple
  • Banana
  • Cherry
  • Grape (sold out)
  • Mango

Last selected: banana

Multi-select

Checkbox on each item. Clicking toggles, keyboard Enter toggles. Dispatches lb-list-select; consumers call list.getSelected(). This demo also opts into data-lb-list-sort-selected — selected items float to the top with an auto-separator, alphabetical within each group; order stays stable while you toggle (re-sorts only on mount + list.refresh()).

  • Cheese
  • Olives
  • Basil
  • Pepperoni
  • Truffle (unavailable)

Selected: basil, cheese

Filterable

Pinned search input at top filters items by textContent substring. Keyboard nav stays on the search input so you can type + arrow-select without re-tabbing. Empty result renders .lb-list__no-results. Uses our regular .lb-input + data-lb-clearable so the X button is the same custom component used everywhere else in the DS.

  • Germany+49
  • France+33
  • Italy+39
  • Japan+81
  • South Korea+82
  • Mexico+52
  • Netherlands+31
  • Norway+47
  • Poland+48
  • Sweden+46
  • United States+1
No countries match

Stacked items (label + subtext)

Use .lb-list__stack instead of .lb-list__label when you need a primary + secondary line (team members, contacts, search results).

  • AG Avery Greenavery.green@letbe.design
  • NI Noor Ibrahimnoor.i@letbe.design
  • KT Kai Tanakakai.t@letbe.design

Menu-style (separator + danger + hint)

For action-menu styling. data-lb-list-mode="menu" swaps the roles to menu/menuitem and moves a highlight class — it never moves focus and does not handle Esc; use Menu for a popup menu with focus management. Add .lb-list__separator between groups, --danger for destructive, .lb-list__hint for keyboard shortcuts.

  • New file⌘ N
  • Open…⌘ O
  • Save⌘ S
  • Export…
  • Delete⌫