Listbox role state in React
Tags: react, typescript, javascript, ux
Published: 2021-01-29 22:26:35

# Background

Over at [Process Street](https://www.process.st/) we're on the tail end of an integration with [Algolia](https://www.algolia.com/) to manage global search functionality.

Working on a [shape up](https://basecamp.com/shapeup) style team with two people on the back-end, one on design, and one on the front-end (me), we had a little over two weeks to implement a [small batch](https://basecamp.com/shapeup/2.2-chapter-08#team-and-project-sizes) pitch to get global search rolled out.

Once we got the feature working, we got some feedback.

> I wish I could use keyboard commands to go up and down the list and then hit enter to go to that link.

Totally makes sense. A UX instinct we have from the many modals we interact with like [Apple's Spotlight](https://support.apple.com/en-gb/HT204014), [Alfred](https://www.alfredapp.com/), and most [Algolia-powered](https://www.algolia.com/doc/?q=react) search modals.

We're using [Chakra UI](https://chakra-ui.com/) to implement our design system and power our new features. I assumed that there would be a preconfigured way to use keyboard controls on a modal. Alas, nothing in the [modal docs](https://chakra-ui.com/docs/overlay/modal) hinted at keyboard controls for a list.

It didn't take long for me to realize I had concluded hastily that Chakra would have that behavior out of the box. The fact that a modal contains a list of items is _my_ choice as the consumer of the modal. A modal isn't designed just for lists.

So then I thought:

> Wait a second, how is Chakra's own documentation search modal implemented?

Inspecting the modal with dev tools quickly revealed an [ARIA](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) role I had never even heard of: the [listbox](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/listbox_role). Digging [even further](https://github.com/chakra-ui/chakra-ui/blob/develop/website/src/components/algolia-search.tsx#L136), I found that Chakra is using a third-party listbox implementation from Algolia's [DocSearch](https://docsearch.algolia.com/) project. DocSearch doesn't fit Process Street's proprietary use case, so I decided to dig in and manage our own listbox.

A listbox is like an "ejected" `select` component. It's an interface for choosing one or more options from a list. Surprisingly, I didn't find much written on implementing these from scratch in React or in other JS ecosystems. Therefore, I stitched together a few different resources to create a hook that manages the effects and state for a `listbox` component.

# The shiny code

I think for certain problems, it's better to share the code and context than to package it up as yet-another-npm-module that requires upkeep.

Here is a sandbox with the hook's implementation and test.

{% codesandbox use-listbox-state-fzobe %}

Maybe Chakra would be open to adding this hook to their library 😉.

Thank you! Happy problem solving ✌️

---

### Sources

* [MDN listbox page](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/listbox_role)
* [W3C best practices](https://w3c.github.io/aria-practices/examples/listbox/listbox-scrollable.html)