patternfly-react
patternfly-react copied to clipboard
Update Basic Dropdown example to demonstrate focus management
The dropdown panel should trap focus when visible. This means that:
- When a user navigates using only a keyboard, focus can only move within the panel while the panel is visible
- When a user uses a screen reader, only the contents within the panel are visible to the screen reader while the panel is visible (i.e.
aria-hidden=“true”is applied to all other contents on the page).
There are two use cases for the Dropdown component which have different keyboard interaction behaviors:
- The primary use case is where clicking the Dropdown toggle produces a menu of actions.
- The keyboard interaction that’s expected is outlined in #1002.
- An alternate use cases we want to support is where the panel that displays could contain whatever the consumer defines (a form, paragraph text).
- The keyboard interaction that’s expected in this case is similar to what you’d expect with a modal or popover. For example:
- Esc key dismisses the panel - this behavior requires implementation, and is related to #1051
- Tab key shifts focus within elements in the panel - this behavior is provided automatically, but there are some cases that might require handling (refer to the Modal component as an example):
- If the last element has focus, hitting Tab will shift focus to the first focusable element in the panel
- If the first element has focus, hitting Shift+Tab will shift focus to the last focusable element in the panel
- Other keys that automatically work with native elements should still work as expected (e.g. Enter/Space for button elements)
- The keyboard interaction that’s expected in this case is similar to what you’d expect with a modal or popover. For example:
Some notes about this issue:
- Similar behavior was implemented for the modal in #1011. However, unlike the modal, the user should be able to click anywhere outside the panel/menu to dismiss the panel/menu (e.g. clicking the toggle or clicking some other area on the screen should dismiss it).
- "trapping focus" may or may not be required for the primary use case where arrow keys are used to navigate the menu items. Alternatively, another solution for trapping focus in this case might work better. The following is an implementation of a button menu that provides similar arrow key interaction, and also hides the page contents from the screen reader while the menu is visible: https://github.com/HugoGiraudel/react-menu-button
Thanks for creating this issue!
The following are use cases related to the dropdown component, with suggestions on how to handle focus. I’m not sure what our options are for these cases, so these are just suggestions. Please comment if you have other ideas.
- The menu element contains no clickable elements
- add
tabindex=“-1”to the menu element and apply focus to this element OR addtabindex=“-1”to the first child of the menu element and apply focus to this element - If possible, keep focus on the menu until the user hits Esc
- add
- The menu element contains menu items
- The first menu item receives focus. This was implemented in PR #815.
- The menu element contains elements other than menu items that are clickable
- have the consumer identify items in the menu that can receive focus, and place focus on the first item.
- trap focus so that only these elements can receive focus
Some notes about these use cases:
- Use cases 1 and 3 are similar cases that we would need to solve for popovers. Although with popovers, I think we would always have a X button, so maybe use case 3 is the only one like the popover.
- Reviewing what WAI ARIA authoring practices recommends for modals regarding initial focus placement might be helpful, and might be something we want to do here.
Finally, this might be a separate issue, but I wanted to go ahead and capture some notes here related to managing focus:
When reviewing the dropdown in different screen readers, we don't really trap focus (but I also haven't found any implementation of a modal that traps focus in the context of a screen reader). I included comments in #561 related to trapping focus. I think the one critical thing that's needed in order to truly capture focus is to separate the element that pops up (modal, menu, popover) from the rest of the web page contents in the DOM so that we can set pointer-events: none; and aria-hidden="true" on the <main> element of the page. But I'm not sure if these are valid options for components like Dropdown and Popover.
I created a codepen to test whether pointer-events: none; and aria-hidden="true" work as expected, and all three screen readers will ignore the contents inside <main> and only access the contents that are in the <div> after <main>.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
Update the example to demonstrate how to handle focus (https://patternfly-react.surge.sh/components/dropdown#basic-panel).
Closing this as the dropdown was deprecated