SHIFT + D

Listbox

Updated on September 7, 2024Source codeTests

useListbox is a composable that implements the UI logic needed for a reactive, accessible listbox interface.

It follows WAI-ARIA authoring practices and allows you to easily customize accessibility features.

Features

Here's a breakdown of all the features offered by useListbox:

Feature
Details
Listbox basics
  • Supports single, multiple, and no selection
  • Compatible with assistive technology
  • Typeahead—with optional fuzzy matching—to quickly transfer focus
  • Supports enabled/disabled option state, even if that state changes reactively with user interaction
  • Support for complex options, with help from the useLabels extension
Reactivity
  • Focused option and selected option(s) are tracked and controlled reactively
  • Via the return object, you can read and watch reactive references to the focused option and selected option(s)
  • Via the return object, you can access methods that intelligently mutate the focused option and selected option(s)
  • Keyboard interactions adjust their behavior based on reactive changes to options' enabled/disabled state
  • Reactively disabled options are automatically deselected
  • Focused option and selected option(s) automatically update if option elements are reactively reordered
ARIA attribute management
  • role
  • aria-orientation
  • aria-multiselectable
  • aria-selected
  • aria-disabled
  • aria-owns
Keyboard interaction
  • Arrow keys transfer focus to the next or previous eligible option (up and down for vertical listboxes, left and right for horizontal listboxes)
  • Keyboard interaction is compatible with listboxes whose options are divided into multiple groups.
  • Home, End, and Command/Control + arrow transfers focus to the first or last eligible option
  • mousedown, touchstart, Space and Enter select the focused option, if it's eligible and not selected
  • mousedown, touchstart, Space and Enter deselect the focused option, if it's selected
  • esc deselects all options
Keyboard interaction for multiselectable listboxes
  • Shift + arrow adds the next or previous eligible option to the selection
  • Shift + Command/Control + arrow adds all preceding or all following eligible options to the selection
  • Command/Control + A selects all eligible options

Example

Single select

Example source code

Dost
Educate Girls
Food 4 Education
Imagine Worldwide
Lively Minds
Luminos Fund
Peepul
Rising Academies
Rocket Learning
SmartStart
Taleemabad
Ubongo
Aceli Africa
Avunja
CassVita
Digital Green
Farmerline
Hello Tractor
Kheyti
Pula
PxD
West African Rice Company
Bridges to Prosperity
Chancen International
Medha
Amani Global Works
Development Media International
Friendship Bench
Healthy Learners
Integrate Health
Intelehealth
Last Mile Health
Lwala
Muso
Nexleaf Analytics
No Means No Worldwide
Noora Health
PIVOT
Particles for Humanity
Sanku
SaveLIFE Foundation
Semilla Nueva
Shamiri Institute
0
0

Multiselect

Example source code

Create a listbox

To create a listbox, call the useListbox function, which accepts one optional options object as its only parameter.

<!-- MyComponent.vue -->
<template>...</template>

<script setup>
import { useListbox } from '@baleada/vue-features'

const listbox = useListbox([options])
</script>

Here's a breakdown of the options object:

Property
Type
Required
Default
Description
multiselectable
Boolean
no
false
Indicates whether or not the listbox supports multiple selections.
initialSelected
Number, Array
no
0

The index-based position of the option that should be initially selected.

For multiselectable listboxes, initialSelected can also be an array of index-based positions for multiple selected options.

ability
StatusOption
no
() => 'enabled'

A status option that should resolve to enabled for each enabled option, and disabled for each disabled option.

useListbox uses this information to decide which options are eligible to receive focus and/or be selected.

orientation
String
no
horizontal
Indicates the orientation of the listbox. For horizontal listboxes, left and right arrow keys will transfer focus, and for vertical listboxes, up and down arrow keys will transfer focus.
selectsOnFocus
Boolean
no
true
Indicates whether or not options should be selected as soon as they are focused
loops
Boolean
no
true
Indicates whether or not your listbox should "loop around" to the beginning of the list after reaching the end, and vice versa.
disabledOptionsReceiveFocus
Boolean
no
true

Indicates whether or not your listbox can transfer focus to disabled options.

If you set disabledOptionsReceiveFocus to false, you should be confident that assistive tech users don't need or want to read the labels of disabled options, or that they have another way to access that content.

Note that even when disabledOptionsReceiveFocus is true, it's never possible to select disabled options.

toCandidate(param)
Function
no
({ element }) => element.textContent

A callback function that helps your listbox's typeahead feature retrieve searchable text from each option.

When the end user starts typing a query, your listbox will iterate through the listbox options, calling toCandidate for each one to retrieve the "search candidate" text.

toCandidate receives one argument: an object with an element property and an index property. element holds the listbox option's actual DOM element, and index holds the option's index-based position in your array of options.

queryMatchThreshold
Number
no
1

Configures fuzzy matching for the typeahead feature.

queryMatchThreshold should be a number from 0 to 1. When queryMatchThreshold is 1, your listbox's typeahead will only transfer focus to an option that is an exact match for the typeahead's query. A numbers less than 1 will be increasingly less strict, ignoring slight typos and query mistakes when it transfers focus.

needsAriaOwns
Boolean
no
false

Indicates whether or not your listbox needs to manage the aria-owns attribute automatically.

needsAriaOwns should only be true if the structure of your HTML markup does not define a clear relationship between the listbox root element and the listbox options.

Use your listbox

useListbox returns a listbox—an object with tools you can use to connect useListbox's UI logic to your markup.

Here's a breakdown of that object:

Property
Type
Description
root
Function

A single element API object.

root.ref should be bound to the DOM element that serves as your listbox's root.

options
Function

A multiple element API object.

Pass the index-based position (Number) of the current option as the only argument for options.ref, and its returned function ref should be bound to the DOM element that serves as that option.

It's recommended that you render the options with v-for, get the index from your v-for statement, and bind the function ref to the v-for element.

focused
Ref (Number)
A reactive reference to the index-based position of the currently focused option
selected
Ref (Number), Ref (Array)

A reactive reference to the index-based position of the currently selected option

For multiselectable listboxes, selected will be an array of numbers, indicating the index-based positions of all selected options, in the order they were selected.

is
Object

An object with two properties: focused and selected.

Each property holds a method that requires an index (Number) as its only parameter.

Given the index, is.focused returns a boolean indicating whether or not that option is focused, and is.selected returns a boolean indicating whether or not that option is selected.

is.focused and is.selected read from reactive references, so their boolean return values are fully reactive when used in Vue templates, watchers, and computed references.

getStatuses(index)
Function

A function that requires an index (Number) as its only parameter, and returns a three-item array indicating the statuses (Strings) of the option at that index.

The first item will be focused or blurred, the second item will be selected or deselected and the third item will be enabled or disabled.

focus
Object

An object containing all the methods described in the eligible focus guide.

You can use these methods to programmatically transfer focus in a smarter way, taking enabled/disabled state and other customizable conditions into account.

select
Functions

An object containing all the methods described in the eligible picking guide.

You can use these methods to programmatically select options in a smarter way, taking enabled/disabled state and other customizable conditions into account.

Note that if you have a multiselectable listbox you can optionally pass an array of index-based positions to the select.exact method to programmatically select multiple eligible options.

deselect(indexOrIndices)
Function

A function that deselects an option.

For single select listboxes, deselect does not accept any parameters.

For multiselect listboxes, you can either pass a single index-based position (Number) to deselect one option, or pass an array of indices to deselect multiple options, or pass no arguments to deselect all currently selected options.

Here's a more complete example of how to use your listbox and bind the various function refs:

<!-- MyComponent.vue -->
<template>
  <div :ref="listbox.root.ref()">
    <div
      v-for="(option, index) in options"
      :key="option"
      :ref="listbox.options.ref(index)"
    >
      {{ option }}
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { useListbox } from '@baleada/vue-features'

const options = ref([
  'Educate Girls',
  'Kheyti',
  'One Heart Worldwide',
])

const listbox = useListbox()
</script>

Extend the listbox

The following extensions are compatible with your textbox:

LinkMenubar

Edit doc on GitHub

ON THIS PAGE

ListboxFeaturesExampleSingle selectMultiselectCreate a listboxUse your listboxExtend the listbox