Open robertlong opened 3 years ago
Assigning this to @mcroud for review and UI recommendation.
Hi @robertlong
Thanks for this! A few questions if I may. I'm trying to visualise the conundrum of managing focus between 3D world and 2D UI. In the image below have I captured the two options accurately?
Would method A prevent us from using tab as a means of cycling interactive objects in the 3D World? I've posed the question of tab use in 3D environments to #accessibility, perhaps someone has some advice on expected tab behaviour there. Perhaps keyboard users would have a fixed cursor allowing them to interact with objects by proximity or simply centralising them in their view, removing the need for tab in this manner?
Yes, I believe method A would prevent us from using tab to cycle 3D object selection. However, there is still the object list in the 2D UI. I think we want to bring most, if not all of the 3D UI into the 2D object menu. So, I think using the object list to navigate objects in the 3D world would work well. Same thing goes for people.
For B, I think we would need to break up the focus in the 3D world. If you had 100 objects in the world that wouldn't be very intuitive. As I understand it, you would use a list and navigate with the arrow keys when you have a lot of selectable items.
Perhaps we could introduce a hotkey to open and focus the objects/people list in method A. That way keyboard users could quickly navigate to selecting an object. Also, the fixed cursor would be great as well. I think it would be also be interesting to see if the option for a first person view with cursor lock on the canvas would be interesting to those users and the section of our userbase familiar with games. I think borrowing mechanics from a FPS control scheme would be a pretty understood method of placing a cursor in the middle of the screen while maintaining the ability to look and move around.
Yes! the Objects list is a very good shout!
I'm trying to source any existing research material or observations we may have with 3D/VR and keyboard usage. I'm afraid I haven't ventured far beyond typical keyboard usage on a website/app so on one hand I wouldn't want to weigh in with impulsive opinions, however I have spent a good chunk of today with the new UI on keyboard and did encounter moments where the behaviour was unexpected or I lost my place.
I don't see a deadline but I'm guessing that the immediate conundrum needs to be resolved prior to the new UI going live? I ask because this task seems like it could be part of a larger accessibility audit. With the obstacles I encountered I wonder if a heuristic evaluation would highlight pressing issues.
Stepping back to the problem at hand, the Object list is a terrific addition and using this with the "view" button (personal opinion, "go to" would feel more accurate to me) provides a lot of control and flexibility for future concepts.
Making this task more efficient for keyboard use feels like a good measure to me, so the hotkey for the Object list feels like a worthy addition.
After speaking with James Teh, we decided to push the rest of the accessibility efforts out a bit. We really need to get them right and not rush through it. We've made big strides already, but as you saw, these focus layers are necessary for things to work well. So let's not focus too hard on a tight deadline and instead focus on finding the correct implementation. I don't think there are huge remaining engineering problems. The design system as a whole is mostly accessible, but it falls apart when composed into larger flows due to this focus issue.
Agreed, with the object menu. That's an area of the UI I'd like to put more focus on in the future. Also, "View" was originally "Go To", I'm happy to switch it back.
Understood.
I wanted to know what the expected keyboard patterns would be for a user, so I found https://webaim.org/techniques/keyboard/#testing and began using Hubs to see if that might shed some light.
I took the mindset that if a canvas hotkey doesn’t impact or conflict with an access key for the current focused element then allow it to affect the canvas.
I tried to navigate the object list using the Up/Down arrow keys, it had no effect (not that up/down is mandatory in this scenario) but in the background I was moving in the 3D world. Similar with arrows keys and the main menu.
Learning of other accepted keyboard patterns, like using [J] and [K] for next and previous (Twitter/Tumblr/Google), I wondered whether treating the canvas as a separate layer to the UI may allow us to utilise more shortcuts in the future without fear of conflict or unexpected results for users.
Similar to a large application like Google Docs, perhaps we use Tab to move focus between the main sections of the app, and then use arrow keys to navigate inside those areas. I.e Tab moves between Canvas > Main menu > Object/People list. The arrow keys then traverse the items within those sections. This might also help us overcome traversing a large object list as we can “jump out” with a single tab press. Slack also allows this broad section jumping with Command + F6.
I know this is beyond what we are talking about here but expanding on the object list hotkey, maybe utilising the “/ ?” Key to bring up a simple shortcut menu as per other web apps would allow us to provide more specific key combinations to access certain features.
There are a good few people in DPX who would be very happy to participate in strategic discussions with Hubs on validating accessibility patterns when the time comes for a wider effort.
Removing P0 tag as this isn't a bug but is being prioritized for design and development.
Background
In the redesign, we're putting in the work to ensure that Hubs has excellent keyboard navigation support for accessibility. Currently, all of the new elements have proper focused element styling and tab index ordering is getting close to correct. However, one area we are severely lacking is trapping focus when a modal, popover, or other full screen element is visible.
From the WAI-ARIA Authoring Practices Document:
I've began to implement focus-layers in Hubs, but I've ran into a few design issues and I'd like to get some feedback on my implementation before continuing.
Focus Layers
The team at Discord have developed a library called focus-layers that helps implement these sorts of focus interactions in React. As a developer, I can add focus layers to components like Modals and Popovers and the focus will be isolated to those components. When the component unmounts (is removed from the DOM) that layer will be popped off the focus layer stack, my focus will return to the previously focused element in the parent layer, and I'll be able to focus items in the parent layer again. It's a great library that manages to simplify a really hard problem.
The redesign has quite a few components that trap focus. Here's a diagram of them:
Canvas
We can probably think of the canvas / 3D viewport as the bottom most focus layer or perhaps it's not really a focus layer at all. If it is thought of as a focus layer and if you have nothing focused in the UI, your keyboard input should go to it. If it's not a focus layer, then we can send all of the global keyboard shortcuts to the canvas so long as an input element like a text input isn't focused. This is somewhat complicated by the fact that we have bound the Tab, Space, Escape, and Arrow keys to actions in the 3D viewport.
Two solutions for this that I've come up with are:
The canvas element takes focus and 3D viewport hotkeys are only received when it is focused. This means we can avoid remapping most of these hotkeys. However we probably want to remove the keyboard mapping for tab so that users can change focus to elements in the UI root. Pressing the escape key in the UI root, tabbing to it, or clicking on the canvas would focus the canvas.
The canvas element takes focus, but the 3D viewport hotkeys are bound globally. The Tab and Spacebar keys would be unbound. Escape would be used in both the 3D and 2D context depending on what is in focus to. For example, it is used in to cancel drawing with the pen. The arrow keys would be bound to movement when the canvas is focused, or whenever we can detect that you are a "mouse user". Currently you start out as a mouse user and a keyboard user is detected when the user presses the tab key. Clicking anywhere on the page switches you back to a mouse user. With this method, you can use the arrow keys to move around in 3D space and still use them to scroll through lists, etc. The WASD keys are globally bound and can always be used to move around in 3D space.
UI Root
The UI Root component is, as it's name suggests, the root of the application. When you load a Hubs room and press tab, the first element that is focused, is the join room button.
In the above screenshot, the join room button is focused, and you can move focus to the bottom toolbar. For example the next focus item after the "Options" button is the "Invite" button in the bottom toolbar and the item after the "More" button in the bottom right, is the "People" button in the top right.
Once you are in the room, there are more items in that bottom toolbar that can be toggled or open popovers/sidebars.
Popover
The popover component traps focus when opened. Focus currently starts on the close button, but when properly implemented will focus the next element. Pressing tab repeatedly will eventually reach the end of the focusable elements in the popover and loop back around to the first focusable element. Pressing the escape key or unmounting the popover (triggered via the close button or another action) will untrap the focus.
Modal
Modals work the same way as popovers, except sometimes they can't be closed via the escape key.
Fullscreen Layout
The focus layer for the fullscreen layout component also works the same way as modals and popovers, but it always takes up the whole screen and obscures the rest of the content. The media browser, avatar editor, and preferences page are examples of this component.
Sidebar
The sidebar component only traps focus when it is full screen. On mobile devices or smaller browser windows, the sidebar is full screen and obscures the other content. Focusing elements outside the sidebar when it is fullscreen wouldn't make sense because you can't see these items, so we only enable the focus layer when it is fullscreen. When the focus is inside the sidebar, you can press escape to hide it or navigate backwards.
Summary and Action Items
Overall, focus layers allow for easy and correct keyboard navigation, but I could use more opinions on where they are used, how they are implemented, and for someone to check my understanding. I would especially like input from someone who has extensively used or studied interfaces that implement these patterns correctly, because I'm still pretty new to this.
The biggest design decision is how to handle the 3D viewport keybindings in combination with the standard keyboard navigation controls. I haven't fully thought through either of the two options I've proposed, but I think they are good starting points.
I'm going to pause on the technical work until we've had time to discuss the design, if anyone would like to see a demo, you can check out that branch or we could stand it up on our staging server. I'm happy to walk people through a demo.
┆Issue is synchronized with this Jira Task