Accessibility & semantics

Chrome 150 hands composite-widget arrow keys to the browser

Chrome 150 hands composite-widget arrow keys to the browser

Every custom listbox, tablist, menu and toolbar you have ever shipped has come with the same hidden JavaScript bill. The keyboard behaviour a native <select> gets for free, arrow keys moving between options, Home and End jumping to the ends, Tab leaving the widget entirely, you have written yourself, every time, and hoped nothing regressed.

Per Adrian Roselli's write-up, Chrome 150 has landed an HTML attribute that tries to hand that job to the browser. focusgroup puts arrow-key roving focus inside a composite widget on the platform. Roselli has published a set of demos exercising it, and per the source there is no scripting in any of them.

The keyboard tax composite widgets keep paying

The shape of the pattern is always the same. One tab stop for the widget as a whole. Arrow keys move focus among its options. Home and End jump to the extremes. Screen-reader users rely on it. Sighted keyboard users rely on it. And, in practice, every project rebuilds it in JavaScript, ships bugs into it, and eventually rewrites it.

That is the tax focusgroup is trying to remove. You put the attribute on the container and the browser does the roving. Focus moves inside on arrows. Tab moves out. No listener, no counter, no keyboard-trap regression to chase in the next sprint.

What the demos actually exercise

Per the source, Roselli has run the attribute against the six composite ARIA widget roles the source names: listbox, menu, menubar, radiogroup, tablist and toolbar. Six roles, six demos, and the demos style themselves only enough to honour dark and light mode, focus rings, and text defaults. If the roving keyboard behaviour works, it works because of the attribute, not because a polyfill is quietly propping it up.

That is the value of running the tests this way. It isolates what the platform gives you from what your codebase has been giving you all along. What passes here is what a user on Chrome 150 gets from raw HTML.

Where the shape of the attribute bites

focusgroup is not opinion-free. Per the source, the axis of movement is based on the default visual display of the widget role. A listbox is treated as vertically stacked, so the browser wires up up and down arrows. That is the correct default for the common case.

It becomes the wrong default the moment you build a horizontal listbox of pill-shaped options, and per the source that is a real pattern the author calls out. If you use listbox for horizontal pills, the source is direct: you have to address the axis yourself. The attribute will not notice that your CSS put the options in a row.

That is not a bug. It is a design decision, and it is exactly the kind of decision the Open-UI work is still figuring out. Any composite widget where the direction of arrow-key movement does not match the role's default deserves a re-read before you reach for focusgroup.

The spec situation, plainly

Two facts from the source you should not skip.

First, focusgroup was proposed by Open-UI, and per the source the Open-UI explainer is currently the only place, inside or outside a spec, that documents how to use it. There is no WHATWG HTML section to cite. If you build against the attribute today, you are building against an explainer.

Second, per the source it is not yet in WHATWG HTML as anything more than a feature request. That is not a footnote. It is the reason the shape of the attribute can still change under you. Adopt with your eyes open.

Testing today, per the source, requires Chrome 150. Anyone on a browser without support will see the raw DOM: a container, some children, and no roving focus. Progressive enhancement is not optional here.

For your next composite widget

The verdict from the source is generous but conditional. focusgroup is a useful primitive, the platform finally picking up a job it should have owned all along, with a spec story still in draft and a browser story one engine deep.

For a PR that reaches for it:

  • Use the native element first. A real <select> or a <input type="radio"> in a real form still beats a scripted composite for most listbox and radiogroup jobs. Reach for focusgroup when there is no native equivalent.
  • Read the Open-UI explainer end to end. Per the source it is the current documentation for the attribute, and the current documentation will move.
  • Check the axis of movement against your visual layout. Horizontal listboxes, vertical toolbars: anything that fights the role's default is your problem to solve.
  • Ship a keyboard fallback for browsers that do not implement the attribute. Testing needs Chrome 150; the users who cannot yet test need something that works today.
  • Keep the ARIA role right. focusgroup moves focus. It does not tell the assistive tech what your widget is; the role still has to be there and still has to be correct.

The platform has taken a real chunk of the composite-widget tax off the table. Use it where the native element cannot go, and treat the rest of the widget with the same care you would have last week.

Source: Adrian Roselli (adrianroselli.com)

Related
Accessibility & semantics

Your `<nav>` label already says 'navigation'

Writing 'Primary navigation' on a `<nav>` makes a screen reader announce the word twice. The fix is to trust the landmark and let the label do its actual job.

June 26, 2026
Accessibility & semantics

`headingoffset` is not the outline algorithm coming back

Firefox has shipped `headingoffset` behind a flag. It quietly fixes a real pain point for reusable components, but it is not, and cannot be, the long-abandoned Document Outline Algorithm in disguise.

June 22, 2026
Accessibility & semantics

ariaNotify() is developer catnip. Treat it like alert().

The new WAI-ARIA 1.3 ariaNotify() method makes screen-reader announcements trivial to fire from JavaScript — which is exactly the problem. The case CSS-Tricks lays out is straightforward: reach for it only where a live region genuinely cannot do the job.

June 21, 2026