Why Queue Music uses a custom dropdown for playlist selection
Queue Music began as a small project by Thomas Logan with backing from the Mozilla Foundation, and from the outset it was shaped by a clear principle: every control on the page must behave the same way for a person using a keyboard in Adelaide as it does for someone using VoiceOver in Parramatta. The native HTML select element looks simple on the surface, but its internal mechanics vary so much between browsers and mobile WebViews that building a reliable music player on top of it became risky. A custom dropdown, written with predictable WAI-ARIA semantics, lets the team pin down exactly how each interaction is announced and how focus moves after every keystroke.
In Australia, where the Australian Bureau of Statistics counts roughly 4.4 million people living with disability and where Vision Australia supports thousands of blind and low-vision clients, those small differences in component behaviour are not academic. A playlist selector that mislabels options, swallows key presses, or closes unexpectedly after a selection can mean the difference between an arvo of relaxed listening and a frustrating half-hour fighting the interface. The decision to write a custom widget grew out of this reality.
The keyboard navigation problem with native selects
The native select element has a hidden complexity that surprises most developers the first time they audit it. On Windows with NVDA, the control announces its options as a flat list, but on macOS with VoiceOver, the same code path produces a different verbosity setting and a different order of operations. Type-ahead support behaves differently in Firefox on Linux compared with Safari on iOS, and older Android browsers sometimes refuse to scroll past a certain number of visible options. For a keyboard-only user in a Brisbane office switching between playlists, these differences turn a simple task into a guessing game.
When Queue Music uses a custom listbox pattern, the team can guarantee that pressing the arrow keys always moves highlight by exactly one item, that Home and End jump to the boundaries of the list, and that Escape always returns focus to the trigger button. None of that is a guarantee with the native control, because the browser gets the final word on keystroke handling. This is a similar concern to the one covered in the track queue limit, where the team explained how unbounded input fields become unpredictable for assistive technology.
How custom controls improve screen reader announcements
A second layer of the problem is the announcement itself. Screen readers do not simply read the visible text of a select option; they append role information, state information, and sometimes position information. With a native select, that extra information is decided by the browser vendor and the screen reader manufacturer working together, which means the announcement can read as "Playlist selector, Focus, list, 1 of 4" on one platform and "Focus, combo box, collapsed" on another. For a listener on a Sydney bus, the inconsistency is exhausting.
The custom listbox in Queue Music applies a controlled labelling strategy so that every option is announced with the same prefix, the same state suffix, and the same positional cue. The trigger button is marked with aria-haspopup="listbox", each option carries aria-selected, and the live region updates only when the user actually changes the value. The roulette neighbourhood betting guide is unrelated content, but it sits in the same journal because Queue Music documents its interaction patterns alongside every other design note the project publishes.
Styling consistency across browsers and devices
Visual consistency is the third reason, and it is the one most sighted developers notice first. A native select renders with operating-system chrome on every platform, which means the same code looks like a Windows combo box in Perth, a macOS pop-up button in Melbourne, and an iOS wheel picker on a Queensland holiday. Trying to restyle the element is famously painful: setting a background colour often gets stripped on Safari, while setting padding gets ignored on Firefox. Users who switch between devices end up looking at four different interfaces for what is supposedly the same control.
A custom dropdown removes that problem entirely. Queue Music uses the same flat, high-contrast styling across all platforms, with a 44-pixel tap target to satisfy the Australian Human Rights Commission's guidance on touch targets and the WCAG 2.2 target size minimum. The trigger always looks like a button, the menu always looks like a menu, and the active option is always marked with both a colour change and a tick icon so that colour is not the only signal.
| Feature | Native HTML select | Queue Music custom dropdown |
|---|---|---|
| Keyboard handling | Varies by browser and OS | Fixed and predictable |
| Screen reader announcement | Vendor-determined | Project-controlled |
| Visual styling | OS-native appearance | Consistent across platforms |
| Touch target size | Often below 44 px | Always 44 px or larger |
| Type-ahead search | Inconsistent | Guaranteed behaviour |
| Maintenance burden | Low | Higher but justified |
Why ARIA live regions demand predictable behaviour
Live regions are another piece of the puzzle. Queue Music relies heavily on aria-live polite regions to announce playback changes, queue updates, and errors. When a native select is involved in a state change, browsers sometimes inject their own announcements into the same live region, which causes two messages to collide or one to be truncated. A custom component silences the browser's default announcements and lets only the application's polite region speak, which keeps the experience clean for users who depend on screen reader error announcements.
This matters most during playlist switching, where the application needs to announce the new playlist name, the number of tracks queued, and whether shuffle is on, all in a predictable order. Mixing those announcements with browser chatter would force a user in a noisy Hobart café to repeat the screen reader output several times to catch the details.
Trade-offs: the engineering effort behind custom widgets
Custom widgets are not free. Every screen reader update, every browser release, and every mobile operating system version can shift the assumptions the code is built on. The Queue Music project maintains a small test suite that exercises the dropdown with NVDA, JAWS, VoiceOver, and TalkBack, plus a set of automated focus-trap checks. That is more work than dropping a <select> into the markup, and the team is honest about the cost.
The trade-off still pays off because the alternative is shipping a component that works beautifully for one user and breaks silently for another. The same argument has been made in submissions to the Australian Communications and Media Authority on digital inclusion. Queue Music treats the dropdown as a long-term investment rather than a quick win, which is why the code receives the same scrutiny as the player's transport controls.
Listening to Australian users and updating the component
The custom dropdown did not appear fully formed. Early testers from the Australian Network on Disability and from local meetup groups in Fremantle flagged issues with focus return after selection, and a contributor from the University of Melbourne pointed out that the menu was trapping focus when the playlist list grew longer than eight items. Each of those reports fed into a revision: focus now returns to the trigger after every confirmation, the menu wraps gracefully at the document edges, and the listbox height is calculated against the viewport rather than against the parent container.
The project keeps an open channel for feedback through the journal, where users can flag regressions after browser updates. That loop matters because accessibility is not a checkbox; it is a moving target, and a custom component gives the team a chance to keep pace without waiting for a browser vendor to ship a fix.
Practical takeaways for accessibility builders
- Audit native controls on at least three screen reader and browser combinations before assuming they work.
- Treat ARIA live regions as a one-voice channel; prevent native controls from injecting competing announcements.
- Set a 44-pixel minimum touch target so the component remains usable on phones and tablets.
- Document the keyboard map in plain language, including what Home, End, Page Up, and Page Down do.
Common pitfalls when reproducing this pattern
- Forgetting to mark the trigger with
aria-expandedso screen readers cannot tell whether the menu is open. - Allowing focus to escape the listbox when the user reaches the last visible option.
- Reusing live regions for both polite and assertive announcements and creating race conditions.
- Treating the custom widget as a one-off rather than a reusable component with shared documentation.