Listbox

Keep choices visible in a styled list. A selected choice stays visible; in multiple mode, each row uses the same checkmark treatment as Combobox suggestions. Click to choose, use arrow keys to move, and press Space to toggle a multiple choice.

Visible single choice

A visible list of choices. Arrow keys move the selection; click a row to choose it.

Choose a plan

Code

<link
  rel="component"
  href="@threadlabs/looma/components/ui-listbox/ui-listbox.html"
>

<div
  id="plan-label"
>Choose a plan</div>
<ui-listbox
  id="plan"
  name="plan"
  aria-labelledby="plan-label"
  rows="3"
  required
>
  <option
    value="basic"
  >Basic</option>
  <option
    value="team"
  >Team</option>
  <option
    value="enterprise"
  >Enterprise</option>
</ui-listbox>
<script setup>
  import { UiListbox } from "@threadlabs/looma";
</script>

<template>
  <div
    id="plan-label"
  >Choose a plan</div>
  <UiListbox
    id="plan"
    name="plan"
    aria-labelledby="plan-label"
    :rows="3"
    :required="true"
  >
    <option
      value="basic"
    >Basic</option>
    <option
      value="team"
    >Team</option>
    <option
      value="enterprise"
    >Enterprise</option>
  </UiListbox>
</template>
import { UiListbox } from "@threadlabs/looma";

export default function Example() {
  return <>
    <div
      id="plan-label"
    >Choose a plan</div>
    <UiListbox
      id="plan"
      name="plan"
      aria-labelledby="plan-label"
      rows={3}
      required
    >
      <option
        value="basic"
      >Basic</option>
      <option
        value="team"
      >Team</option>
      <option
        value="enterprise"
      >Enterprise</option>
    </UiListbox>
  </>;
}
/** @jsxImportSource preact */
import { UiListbox } from "@threadlabs/looma";

export default function Example() {
  return <>
    <div
      id="plan-label"
    >Choose a plan</div>
    <UiListbox
      id="plan"
      name="plan"
      aria-labelledby="plan-label"
      rows={3}
      required
    >
      <option
        value="basic"
      >Basic</option>
      <option
        value="team"
      >Team</option>
      <option
        value="enterprise"
      >Enterprise</option>
    </UiListbox>
  </>;
}
<script>
  import { UiListbox } from "@threadlabs/looma";
</script>

<div
  id="plan-label"
>Choose a plan</div>
<UiListbox
  id="plan"
  name="plan"
  aria-labelledby="plan-label"
  rows={3}
  required
>
  <option
    value="basic"
  >Basic</option>
  <option
    value="team"
  >Team</option>
  <option
    value="enterprise"
  >Enterprise</option>
</UiListbox>
import { Component } from "@angular/core";
import { UiListbox } from "@threadlabs/looma";

@Component({
  selector: "example-view",
  standalone: true,
  imports: [UiListbox],
  template: `
    <div
      id="plan-label"
    >Choose a plan</div>
    <div
      ui-listbox
      id="plan"
      [name]="'plan'"
      aria-labelledby="plan-label"
      [rows]="3"
      [required]="true"
    >
      <option
        value="basic"
      >Basic</option>
      <option
        value="team"
      >Team</option>
      <option
        value="enterprise"
      >Enterprise</option>
    </div>
  `,
})
export default class Example {}

Multiple choice

Checked rows show every selection. Click a row or press Space to toggle it.

Regions

Code

<link
  rel="component"
  href="@threadlabs/looma/components/ui-listbox/ui-listbox.html"
>

<div
  id="regions-label"
>Regions</div>
<ui-listbox
  id="regions"
  name="regions"
  aria-labelledby="regions-label"
  rows="4"
  multiple
>
  <option
    value="north"
    selected
  >North</option>
  <option
    value="south"
  >South</option>
  <option
    value="east"
  >East</option>
  <option
    value="west"
    selected
  >West</option>
</ui-listbox>
<script setup>
  import { UiListbox } from "@threadlabs/looma";
</script>

<template>
  <div
    id="regions-label"
  >Regions</div>
  <UiListbox
    id="regions"
    name="regions"
    aria-labelledby="regions-label"
    :rows="4"
    :multiple="true"
  >
    <option
      value="north"
      selected
    >North</option>
    <option
      value="south"
    >South</option>
    <option
      value="east"
    >East</option>
    <option
      value="west"
      selected
    >West</option>
  </UiListbox>
</template>
import { UiListbox } from "@threadlabs/looma";

export default function Example() {
  return <>
    <div
      id="regions-label"
    >Regions</div>
    <UiListbox
      id="regions"
      name="regions"
      aria-labelledby="regions-label"
      rows={4}
      multiple
    >
      <option
        value="north"
        selected
      >North</option>
      <option
        value="south"
      >South</option>
      <option
        value="east"
      >East</option>
      <option
        value="west"
        selected
      >West</option>
    </UiListbox>
  </>;
}
/** @jsxImportSource preact */
import { UiListbox } from "@threadlabs/looma";

export default function Example() {
  return <>
    <div
      id="regions-label"
    >Regions</div>
    <UiListbox
      id="regions"
      name="regions"
      aria-labelledby="regions-label"
      rows={4}
      multiple
    >
      <option
        value="north"
        selected
      >North</option>
      <option
        value="south"
      >South</option>
      <option
        value="east"
      >East</option>
      <option
        value="west"
        selected
      >West</option>
    </UiListbox>
  </>;
}
<script>
  import { UiListbox } from "@threadlabs/looma";
</script>

<div
  id="regions-label"
>Regions</div>
<UiListbox
  id="regions"
  name="regions"
  aria-labelledby="regions-label"
  rows={4}
  multiple
>
  <option
    value="north"
    selected
  >North</option>
  <option
    value="south"
  >South</option>
  <option
    value="east"
  >East</option>
  <option
    value="west"
    selected
  >West</option>
</UiListbox>
import { Component } from "@angular/core";
import { UiListbox } from "@threadlabs/looma";

@Component({
  selector: "example-view",
  standalone: true,
  imports: [UiListbox],
  template: `
    <div
      id="regions-label"
    >Regions</div>
    <div
      ui-listbox
      id="regions"
      [name]="'regions'"
      aria-labelledby="regions-label"
      [rows]="4"
      [multiple]="true"
    >
      <option
        value="north"
        selected
      >North</option>
      <option
        value="south"
      >South</option>
      <option
        value="east"
      >East</option>
      <option
        value="west"
        selected
      >West</option>
    </div>
  `,
})
export default class Example {}

API

Package: @threadlabs/looma · Native root: div

Attributes

NameDescriptionPropertyTypeDefaultAllowed values
disabledPrevents selection and form submission.disabledbooleanfalse—
invalidExposes invalid state to assistive technology and styling.invalidbooleanfalse—
multipleAllows several choices, each shown with a checkmark when selected.multiplebooleanfalse—
nameThe form field name used for each selected value.namestring—
requiredRequires at least one choice before form submission.requiredbooleanfalse—
rowsThe maximum number of choices visible before the list scrolls. Use at least two.rowsnumber5—
valueThe initial or externally set single selection. Authored selected options work when it is omitted.valuestring——
valuesThe initial or externally set selections in multiple mode. Authored selected options work when it is omitted.valueslist(string)——

Framework props

NameTypeDefaultAllowed values
disabledbooleanfalse—
invalidbooleanfalse—
multiplebooleanfalse—
namestring—
requiredbooleanfalse—
rowsnumber5—
valuestring——
valuesreadonly (string)[]——

Events

NameDetailDescription
changeobject
  • value: string
  • values: list(string) (required)
  • trigger: keyword (required)
Emitted when a toggleable control changes checked state.

Slots

NamePurpose
defaultDefault child content.

Design tokens

Set shared theme properties on a theme boundary. Component hooks apply only to their owning component.

Component tokens

TokenDeclared valuesFallback
--ui-listbox-border—var(--ui-control-border)
--ui-listbox-focus-shadow—var(--ui-focus-halo)
--ui-listbox-invalid-border—var(--ui-field-danger, var(--ui-danger))
--ui-listbox-radius—var(--ui-field-radius, var(--ui-radius-md))
--ui-listbox-surface—var(--ui-control-surface)

Shared tokens

TokenFallback
--ui-border-width—
--ui-control-border—
--ui-control-focus—
--ui-control-inset—
--ui-control-size-md—
--ui-control-surface—
--ui-control-surface-disabled—
--ui-danger—
--ui-disabled-text—
--ui-field-dangervar(--ui-danger)
--ui-field-radiusvar(--ui-radius-md)
--ui-focus-halo—
--ui-focus-ring—
--ui-focus-width—
--ui-line-height-md—
--ui-radius-md—
--ui-space-1—
--ui-text-primary—