I'd like to implement a listbox widget using the current web components specs. Moreover, the resulting listbox should conform to the ARIA standard. Instantiating the listbox widget should be as simple as:
<x-listbox>
<x-option>Option 1</x-option>
<x-option>Option 2</x-option>
</x-listbox>
For purposes of cleanliness and encapsulation, everything else should be rendered in shadow dom. To implement this widget, two custom elements, <x-listbox>
and <x-option>
are registered. The top-level element of the shadow dom of <x-listbox>
is a <div>
that carries the role=listbox
and the aria-activedescendent
attributes for accessibility (I don't want these attributes on the <x-listbox>
element because they are implementation details.)
In order for aria-activedescendent
to work, one needs ids on the option elements. Putting ids directly on the <x-option>
elements won't work out of two reasons: Firstly, it would pollute the id namespace of the document that uses the listbox widget. Secondly and even more importantly, ids do not work across shadow boundaries (which is one purpose of the shadow dom), so the ids of the options have to live in the same shadow dom as the <div>
with the aria-activedescendent
attribute.
A solution for this would be to surround each <x-option>
that is rendered as content inside the shadow dom of <x-listbox>
with another <div>
(belonging to that shadow dom), on which an id can be put.
My question is: Is this the right way to go and how to implement this using the custom element and shadow dom web apis?