# Listbox ## Basic example Listboxes are built using a combination of the `Listbox`, `ListboxButton`, `ListboxOptions`, `ListboxOption`, and `ListboxLabel` components. The `ListboxButton` will automatically open/close the `ListboxOptions` when clicked, and when the listbox is open, the list of items receives focus and is automatically navigable via the keyboard. ```svelte {selectedPerson.name} {#each people as person (person.id)} {person.name} {/each} ``` ## Styling [See here](general-concepts#component-styling) for some general notes on styling the components in this library. ### Active and selected items To style the active `ListboxOption`, you can use the `active` slot prop that it provides, which tells you whether or not that option is currently focused via the mouse or keyboard. To style the selected `ListboxOption`, you can use the `selected` slot prop that it provides, which tells you whether or not that option is the selected option (the one passed to the `value` prop of the ``) You can use these states to conditionally apply whatever active/focus styles you wish. ```svelte {selectedPerson.name} {#each people as person (person.id)} (active ? "active" : "")} let:selected > {#if selected} {/if} {person.name} {/each} ``` ## Using a custom label By default, the `Listbox` will use the `` contents as the label for screenreaders. If you'd like more control over what is announced to assistive technologies, use the `ListboxLabel` component: ```svelte Assignee: {selectedPerson.name} {#each people as person (person.id)} {person.name} {/each} ``` ## Showing/hiding the listbox By default, the `ListboxOptions` instance will be shown and hidden automatically based on the internal `open` state tracked by the `Listbox` component itself. If you'd rather handle this yourself (perhaps because you need to add an extra wrapper element for one reason or another), you can add a `static` prop to the `ListboxOptions` component to tell it to always render, and use the `open` slot prop provided by the `Listbox` to show or hide the listbox yourself. ```svelte {selectedPerson.name} {#if open}
{#each people as person (person.id)} {person.name} {/each}
{/if}
``` You can also choose to have the `Listbox` merely hide the `ListboxOptions` when the `Listbox` is closed, instead of removing it from the DOM entirely, by using the `unmount` prop. This may be useful for performance reasons if rendering the `ListboxOptions` is expensive. ```svelte {selectedPerson.name} {#each people as person (person.id)} {person.name} {/each} ``` ## Disabling an item Use the `disabled` prop to disable a `ListboxOption`. This will make it unselectable via mouse and keyboard navigation, and it will be skipped when pressing the up/down arrows. ```svelte {selectedPerson.name} {#each people as person (person.id)} {person.name} {/each} ``` ## Transitions To animate the opening and closing of the listbox, you can use [this library's Transition component](/docs/2.0/transition) or Svelte's built-in transition engine. See that page for a comparison. ### Using the `Transition` component To use the `Transition` component, all you need to do is wrap the `ListboxOptions` in a ``, and the transition will be applied automatically. ```svelte {selectedPerson.name} {#each people as person (person.id)} {person.name} {/each} ``` The components in this library communicate with each other, so the Transition will be managed automatically when the Listbox is opened/closed. If you require more control over this behavior, you may use a more explicit version: ```svelte {selectedPerson.name} {#each people as person (person.id)} {person.name} {/each} ``` ### Using Svelte transitions The last example above also provides a blueprint for using Svelte transitions: ```svelte {selectedPerson.name} {#if open}
{#each people as person (person.id)} {person.name} {/each}
{/if}
``` Make sure to use the `static` prop, or else the exit transitions won't work correctly. ## Horizontal options If you've styled your `ListboxOptions` to appear horizontally, use the `horizontal` prop on the `Listbox` component to enable navigating the items with the left and right arrow keys instead of up and down, and to update the `aria-orientation` attribute for assistive technologies. ```svelte {selectedPerson.name} {#each people as person (person.id)} {person.name} {/each} ``` ## Accessibility notes ### Focus management When a Listbox is toggled open, the `ListboxOptions` receives focus. Focus is trapped within the list of items until Escape is pressed or the user clicks outside the options. Closing the `Listbox` returns focus to the `ListboxButton`. ### Mouse interaction Clicking a `ListboxButton` toggles the options list open and closed. Clicking anywhere outside of the options list will close the listbox. ### Keyboard interaction When the `horizontal` prop is set, the `` and `` below become `` and ``: | Command | Description | | ----------------------------------------------------------------------------------- | ----------------------------------------------- | | `` / `` / `` / `` when `ListboxButton` is focused | Opens listbox and focuses the selected item | | `` when listbox is open | Closes listbox | | `` / `` when listbox is open | Focuses next/previous non-disabled option | | `` / `` when listbox is open | Focuses first/last non-disabled option | | `` / `` when listbox is open | Selects the focused option | | `` when listbox is open | Focuses next option that matches keyboard input | ### Other All relevant ARIA attributes are automatically managed. For a full reference on all accessibility features implemented in `Listbox`, see the ARIA spec on Listbox. ## Component API ### Listbox The main listbox component. | Prop | Default | Type | Description | | ------------ | ------- | --------- | ---------------------------------------------------------------------------------- | | `as` | `div` | `string` | The element the `Listbox` should render as | | `disabled` | `false` | `boolean` | Whether the entire `Listbox` and its children should be disabled | | `horizontal` | `false` | `boolean` | Whether the entire `Listbox` should be oriented horizontally instead of vertically | | `value` | -- | `T` | The selected value | | Slot prop | Type | Description | | ---------- | --------- | -------------------------------------- | | `disabled` | `boolean` | Whether or not the listbox is disabled | | `open` | `boolean` | Whether or not the listbox is open | ### ListboxButton The listbox's button. | Prop | Default | Type | Description | | ---- | -------- | -------- | ------------------------------------------------ | | `as` | `button` | `string` | The element the `ListboxButton` should render as | | Slot prop | Type | Description | | ---------- | --------- | -------------------------------------- | | `disabled` | `boolean` | Whether or not the listbox is disabled | | `open` | `boolean` | Whether or not the listbox is open | ### ListboxLabel A label that can be used for more control over the text your listbox will announce to screenreaders. Renders an element that is linked to the root `Listbox` via the `aria-labelledby` attribute and an autogenerated id. | Prop | Default | Type | Description | | ---- | ------- | -------- | ----------------------------------------------- | | `as` | `label` | `string` | The element the `ListboxLabel` should render as | | Slot prop | Type | Description | | ---------- | --------- | -------------------------------------- | | `disabled` | `boolean` | Whether or not the listbox is disabled | | `open` | `boolean` | Whether or not the listbox is open | ### ListboxOptions The component that directly wraps the list of options in your custom listbox. | Prop | Default | Type | Description | | --------- | ------- | --------- | ----------------------------------------------------------------------------------------------- | | `as` | `ul` | `string` | The element the `ListboxOptions` should render as | | `static` | `false` | `boolean` | Whether the element should ignore the internally managed open/closed state | | `unmount` | `true` | `boolean` | Whether the element should be unmounted, instead of just hidden, based on the open/closed state | Note that `static` and `unmount` cannot be used together. | Slot prop | Type | Description | | --------- | --------- | ---------------------------------- | | `open` | `boolean` | Whether or not the listbox is open | ### ListboxOption Used to wrap each item within your listbox. | Prop | Default | Type | Description | | ---------- | ------- | --------- | ------------------------------------------------------------------------------- | | `value` | -- | `T` | The option value | | `as` | `li` | `string` | The element the `ListboxOption` should render as | | `disabled` | `false` | `boolean` | Whether the option should be disabled for keyboard navigation and ARIA purposes | | Slot prop | Type | Description | | ---------- | --------- | -------------------------------------- | | `active` | `boolean` | Whether the option is active (focused) | | `selected` | `boolean` | Whether the option is selected | | `disabled` | `boolean` | Whether the option is disabled |