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
| Name | Description | Property | Type | Default | Allowed values |
|---|---|---|---|---|---|
disabled | Prevents selection and form submission. | disabled | boolean | false | — |
invalid | Exposes invalid state to assistive technology and styling. | invalid | boolean | false | — |
multiple | Allows several choices, each shown with a checkmark when selected. | multiple | boolean | false | — |
name | The form field name used for each selected value. | name | string | | — |
required | Requires at least one choice before form submission. | required | boolean | false | — |
rows | The maximum number of choices visible before the list scrolls. Use at least two. | rows | number | 5 | — |
value | The initial or externally set single selection. Authored selected options work when it is omitted. | value | string | — | — |
values | The initial or externally set selections in multiple mode. Authored selected options work when it is omitted. | values | list(string) | — | — |
Framework props
| Name | Type | Default | Allowed values |
|---|---|---|---|
disabled | boolean | false | — |
invalid | boolean | false | — |
multiple | boolean | false | — |
name | string | | — |
required | boolean | false | — |
rows | number | 5 | — |
value | string | — | — |
values | readonly (string)[] | — | — |
Events
| Name | Detail | Description |
|---|---|---|
change | object
| Emitted when a toggleable control changes checked state. |
Slots
| Name | Purpose |
|---|---|
default | Default child content. |
Design tokens
Set shared theme properties on a theme boundary. Component hooks apply only to their owning component.
Component tokens
| Token | Declared values | Fallback |
|---|---|---|
--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
| Token | Fallback |
|---|---|
--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-danger | var(--ui-danger) |
--ui-field-radius | var(--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 | — |