I make games. I often have the requirement to quickly build a dialog or a window of some kind. Using native HTMl here makes sense to me, so I'm implementing a bunch of components that implement the most common features I need in my UI.
Now they have to be accessible, so read well with screen readers, and be fully keyboard navigable. This includes things like lists, tab bars, menus, etc.
So here's the problem. I have some things that need to be inside a container. A list for example. So you have the list container, and then the list items inside it.
When you tab around, I want the container to be tabbable, not the list item. So you don't tab through the list, you tab to the list, and then use the arrows to move around.
Now here's the problem. When the container is tabbable, and not the list item, when you tab to the container, it either:
* reads something like "List title section" and then nothing, not even the item you have selected. Or
* Reads all the list items at once.
Either of those are not great obviously. Ideally, I'd like it to read the list title, then list, and then the selected item.
So the way I get it to do this is by detecting when you tab/focus the list container, and then immediately set the focus to the selected list item instead.
Now this works fantastic. You can tab around, and it automatically puts you right on the list item you have selected, and it even gets read.
But somehow, when you don't just tab around, but also shift tab around, this shift tab lands you back on the list container. And that automatically moves your focus back inside the list. So effectively, once you're in a list, you're trapped.
Does anyone have an idea how to get around this without doing ugly hacks like stealing tab and shift tab and implementing tab order myself? I want to use as many native browser features as possible so if there's another way to do this, please feel free to tell me.
#HTML #JavaScript #accessibility
Now they have to be accessible, so read well with screen readers, and be fully keyboard navigable. This includes things like lists, tab bars, menus, etc.
So here's the problem. I have some things that need to be inside a container. A list for example. So you have the list container, and then the list items inside it.
When you tab around, I want the container to be tabbable, not the list item. So you don't tab through the list, you tab to the list, and then use the arrows to move around.
Now here's the problem. When the container is tabbable, and not the list item, when you tab to the container, it either:
* reads something like "List title section" and then nothing, not even the item you have selected. Or
* Reads all the list items at once.
Either of those are not great obviously. Ideally, I'd like it to read the list title, then list, and then the selected item.
So the way I get it to do this is by detecting when you tab/focus the list container, and then immediately set the focus to the selected list item instead.
Now this works fantastic. You can tab around, and it automatically puts you right on the list item you have selected, and it even gets read.
But somehow, when you don't just tab around, but also shift tab around, this shift tab lands you back on the list container. And that automatically moves your focus back inside the list. So effectively, once you're in a list, you're trapped.
Does anyone have an idea how to get around this without doing ugly hacks like stealing tab and shift tab and implementing tab order myself? I want to use as many native browser features as possible so if there's another way to do this, please feel free to tell me.
#HTML #JavaScript #accessibility
Pitermach reshared this.
Talon
in reply to Talon • • •I feel rather silly for being stuck.
Talon
in reply to Talon • • •I could re-implement tab order manually. This would probably make it easier to hook up navigation to a game pad in the future, and I would want this, so maybe I'll have to do this anyway.
I could set the aria title/label of the list container to whichever list item you have selected. That way, when you focus the container, the screen reader will automatically read the right info. But this will still cause it to say "section" at the end, and that's rather ugly and I don't know how I feel about that.
James H
in reply to Talon • • •Talon
in reply to James H • • •Also, let's say we have a list. That list has different items. If the keyboard is free of web navigation keys, you could use the arrows, page up/down, or even search to filter the list, and once you have an item, you could press a key to trigger an action immediately on that item.
Let's imagine you're in a list of spells. You arrow around to find a spell. You press i, and it immediately reads out all the relevant info of that spell. Description, mana cost, cooldown, etc.
Talon
in reply to James H • • •James H
in reply to Talon • • •Talon
in reply to James H • • •Mikołaj Rotnicki
in reply to Talon • • •Talon
in reply to Mikołaj Rotnicki • • •Mikołaj Rotnicki
in reply to Talon • • •Good. So please show some code samples when you are ready.
@talon
Talon
in reply to Mikołaj Rotnicki • • •codepen.io/TalonTheDragon/pen/…
Steve
in reply to Talon • • •Talon
in reply to Steve • • •Steve
in reply to Talon • • •Peter Vágner
in reply to Talon • •Active aka selected item should always have tabIndex="1" all other items should have tabIndex="-1" and you have to implement your own cursor handling. This technique is called rovingTabIndex. This is usefull while creating treeview, listbox, popup menu, menu bar and whatever widget where navigating around controls inside a container. See this paragraph or the whole article for more details w3.org/WAI/ARIA/apg/practices/…
Talon
in reply to Peter Vágner • • •Talon
in reply to Peter Vágner • • •Peter Vágner likes this.
James Scholes
in reply to Peter Vágner • • •Peter Vágner likes this.
Talon
in reply to James Scholes • • •Peter Vágner
in reply to James Scholes • •James Scholes
in reply to Talon • • •You are fighting against the semantics that were provided for this purpose. If you want a listbox, build a listbox.
But, to answer your specific question, you could use a roving tabindex on your list items, so that only one of them is in the tab order at all times. Let's say the first list item has `tabindex="0"`, the list has an accessible name via `aria-label` or `aria-labelledby`, and the list is not in the tab order.
Users will tab to the first item, and the screen reader will hopefully announce the name and role of the list, plus the item they just tabbed to. When they hit Up/Down Arrow or other navigation keys, set `tabindex="-1" on the item they just came from, and `tabindex="0"` on the destination.
Note: you may need to explicitly add `role="list"` to the `<ul>`, or VoiceOver may just decide to ignore the semantics. This also may not be a good idea in general. As a point of reference, Slack's messages list uses this approach.
Talon
in reply to James Scholes • • •Listboxes are built using normal unordered lists and list items, so you have to implement this yourself. And tabbing into the list is where my trouble was. Roving tab index does exactly what I wanted.
Unless I'm completely wrong here.
James Scholes
in reply to James Scholes • • •Talon
in reply to James Scholes • • •James Scholes
in reply to Talon • • •Talon
in reply to James Scholes • • •Talon
in reply to James Scholes • • •