Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Components: Refactor Popover to focus content wrapper on open #5595

Closed
wants to merge 14 commits into from

Conversation

aduth
Copy link
Member

@aduth aduth commented Mar 13, 2018

Closes #5559
Reverts #5318

This pull request seeks to refactor the Popover component to be smarter about its focus-on-mount behavior, removing any distinction between keyboard and click interaction (removes react-click-outside as a dependency!), and hopefully making awareness of this prop less of a prerequisite (e.g. Tooltip no longer needs to assign, because there are no tabbables anyways).

Further, it leverages this behavior to enhance the Dropdown to "focus to first" when pressing Arrow Down (also Enter, Space). This works when the button is focused, either by keyboard or click.

Testing instructions:

Verify that upon clicking or focusing a dropdown button (e.g. "More Options"), you can press Enter/Down/Space to activate the first item in the menu.

Verify that there are no regressions in the dismissal of popovers, whether by shifting focus by tab or clicking elsewhere on the page.

@aduth aduth added [Focus] Accessibility (a11y) Changes that impact accessibility and need corresponding review (e.g. markup changes). [Feature] UI Components Impacts or related to the UI component system labels Mar 13, 2018
@aduth aduth requested a review from afercia March 13, 2018 20:28
@aduth aduth modified the milestones: 2.4, 2.5 Mar 14, 2018
@mtias
Copy link
Member

mtias commented Mar 14, 2018

In menus with sections like:

image

The arrows are restricted to the elements of the section.

@mtias
Copy link
Member

mtias commented Mar 14, 2018

Testing on the main ellipsis menu: the first arrow press scrolls the window, should try to stop that event.

@aduth
Copy link
Member Author

aduth commented Mar 14, 2018

In menus with sections like: The arrows are restricted to the elements of the section.

Yes, this is the behavior from master, and shouldn't be impacted by changes here. I'm not quite sure what the intended effect is here, but I figured to address separately if updates are needed.

Testing on the main ellipsis menu: the first arrow press scrolls the window, should try to stop that event.

I'm having trouble reproducing this. Anything notable about your setup?

@aduth
Copy link
Member Author

aduth commented Mar 14, 2018

I did note one perhaps strange behavior:

  • Click button
  • Press down arrow
  • Click button
  • Expected: Menu dismissed
  • Actual: Menu dismissed, but then immediately reopened

@mtias
Copy link
Member

mtias commented Mar 14, 2018

I'm having trouble reproducing this. Anything notable about your setup?

  • Make sure you have a scrolling container (open sidebar and dev console, for example).
  • Click on ellipsis menu.
  • Press down arrow.

@mtias
Copy link
Member

mtias commented Mar 14, 2018

Yes, this is the behavior from master, and shouldn't be impacted by changes here. I'm not quite sure what the intended effect is here, but I figured to address separately if updates are needed.

I would expect to jump to the next section using the arrows. Fine to address separately.

@aduth
Copy link
Member Author

aduth commented Mar 16, 2018

Testing on the main ellipsis menu: the first arrow press scrolls the window, should try to stop that event.

Fixed in 4f60c52.

event.stopPropagation();

// Prevent scroll on arrow press.
if ( event.keyCode === SPACE ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Space?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😞 1902a65

@afercia
Copy link
Contributor

afercia commented Mar 21, 2018

I've quickly tested, will double check, but seems to me this approach won't work when a screen reader is running, for the same reasons explained in #5559 (comment)

In short: screen readers intercept key presses and they pass them back to the browsers only in some circumstances, see details in the comment inked above.

@aduth can you confirm this approach depends on the keydown used here? https://github.com/WordPress/gutenberg/pull/5595/files#diff-d0ee2b28a3a71ab67d15d27fd2663e38R156

Has this been tested with a screen reader running? With VoiceOver, please use Control-Option-Space to activate the button. On Windows, you can use NVDA with Firefox and use Spacebar or Enter to activate the button.

@aduth
Copy link
Member Author

aduth commented Mar 21, 2018

I've run through this in VoiceOver: When effectively clicking the button by pressing Ctrl-Option-Space, the menu opens and the first item is not focused. However, with the intended changes here (also impacting any cursor user), the user can then proceed to navigate into the menu by pressing Down on the keyboard. In testing this behavior against Mac native UI controls (the system bar and finder button dropdowns), the interaction is the same: Ctrl-Option-Space activates the menu but does not transition into the first item; the user navigates to the first item by pressing Down.

@afercia
Copy link
Contributor

afercia commented Mar 21, 2018

However, with the intended changes here (also impacting any cursor user), the user can then proceed to navigate into the menu by pressing Down on the keyboard.

VoiceOver has its own peculiar interaction model, and I see the Down arrow works. That wouldn't be the behavior users expect though, because the whole thing is not announced as a "menu".

Regardless, I've just finished testing on Windows with:

  • Firefox ESR + NVDA 2018.1
  • IE11 and JAWS 2018

The Down arrow doesn't work. When pressing it, focus goes to the post "Add title". I guess the reason is always the same: the browser is unaware that keydown event has happened.

I'm sorry, it just doesn't work with screen readers.

@aduth
Copy link
Member Author

aduth commented Mar 21, 2018

Debugging this, it doesn't appear to be related to any changes here, but rather a result of key handling in NavigableContainer. Even in master on Windows Firefox, pressing Down cycles through buttons in the toolbar. I believe this is the behavior you're seeing.

Not sure yet why this is unique to Windows.

@afercia
Copy link
Contributor

afercia commented Mar 21, 2018

I'd suggest to dump to the console that keydown event and test with Firefox on Windows with and without NVDA running. I guess that event doesn't fire at all with NVDA running.

@aduth aduth force-pushed the update/popover-focus-mount branch from 9b851cc to bbd56ff Compare March 21, 2018 22:13
@aduth
Copy link
Member Author

aduth commented Mar 21, 2018

I'm beginning to get a bit of a better grasp at understanding what's happening here. I'm finding it hard to verify in a virtualized environment, but I believe the behavior with arrows acting as tab transitions (and bypassing DOM events) is intentional based on NVDA's browse and focus modes. Digging into the source (open source 🎉), I find that it uses the role attribute to determine whether pass-through of events should always occur (source, ARIA role mapping). It appears the behavior of the popup menu may qualify (specification is a bit ambiguous) as NVDA's ROLE_POPUPMENU (ARIA role="menu") and, indeed, adding this attribute restores the expected behavior of arrow down. This can be seen with the latest commit bbd56ff.

I'll spend some more time looking at this tomorrow. If we can find a suitable role which qualifies for event pass-through (be it menu or other), we may want to consider how we can apply this more broadly as a default for dropdown menus (since I'd assume this should apply to more than just "More Menu").

@afercia
Copy link
Contributor

afercia commented Mar 21, 2018

@aduth there wasn't the need to check the NVDA source :) That's what I've tried to explain and it's standard behavior for Windows screen readers. VoiceOver is, in a way, sort of an exception.

From #5559 (comment)

DOM events (especially keyboard events) may not work the way one would expect. This happens especially with keyboard events attached to elements that are not focusable or don't have a specific ARIA role ... and the keydown / keyup events attached to document don't fire at all. This is expected with screen readers, not a bug.

From #5595 (comment)

In short: screen readers intercept key presses and they pass them back to the browsers only in some circumstances

However, I do think we should not add a role. Specifically, menu is a dangerous role and a it's bit ambiguous, as you pointed out. The interaction should be as native as possible. The Popover is sort of a modal, and should be handled as such: move focus to it when it opens, constrain tabbing into it (see #5242 ). Any deviation from the recommended patterns and expected behaviors increases the chances to introduce huge barriers for assistive technologies users. We should just keep things simple.

I'd also like to remind the whole Popover issue started a few months ago, when the a11y recommendation was to keep the initial implementation. At that time the Popover was placed in the source immediately after the toggle; that was ideal because the natural tab order was preserved. Then, with the "portal" implementation and following changes, the Popover content is now moved very far in the source. At this point it really needs to have focus management in the most simple way: please let's just focus the first focusable element. This also means the Popover should always have some focusable content.

I'd also like to anticipate to all the team we (the accessibility team) are starting receiving feedback from users and also from some very specialized people currently attending CSUN 2018, and the feedback is not so great, so far. We're planning to publish all this feedback so everyone can get a sense of how much it is difficult to use this UI even for the most simple tasks. I'd strongly recommend, as I've always done, to try to keep things simple and as close to native as possible.

@aduth
Copy link
Member Author

aduth commented Mar 22, 2018

there wasn't the need to check the NVDA source :) That's what I've tried to explain

Sometimes it is easier to go direct to the source than to try to infer where there are gaps in the explanation.

I'd also like to remind the whole Popover issue started a few months ago, when the a11y recommendation was to keep the initial implementation.

The change to render popovers into a slot was not chosen arbitrarily. Reverting to rendering the popover contents in-place will result in a whole other set of bugs and inconsistencies. You can demonstrate this yourself with a simple change to revert back to the original behavior, and begin to observe its many subtle and unexpected effects:

diff --git a/components/popover/index.js b/components/popover/index.js
index bc542840e..08cc54933 100644
--- a/components/popover/index.js
+++ b/components/popover/index.js
@@ -330,7 +330,7 @@ class Popover extends Component {
 }
 
 Popover.contextTypes = {
-	getSlot: noop,
+	// getSlot: noop,
 };
 
 Popover.Slot = () => <Slot bubblesVirtually name={ SLOT_NAME } />;

And it's not a matter of the other bugs being the more easily addressed issues than recreating accessible behaviors via slotted rendering. There's simply no known solution to issues affecting stacking context with relation to popovers being shown above other elements on the page (and any such solution may require entire refactors of the administrative markup and CSS, potentially breaking plugins in the process) and unavoidable future bugs and maintenance headaches caused by inadvertent cascade of CSS. Even beyond this, it still wouldn't just work with keyboard behaviors because, for performance reasons, the popover content isn't within the DOM until it's expected to be shown, to avoid rendering and reconciling the potential thousands of nodes that could be made visible at any given point in time.

At this point it really needs to have focus management in the most simple way: please let's just focus the first focusable element.

Why is it assumed that focusing the first item is the expected behavior when activating a menu? You're pleading to revert to the previous behavior, but by all accounts the previous behavior was simply not correct, and nowhere close to the native interaction we seek to achieve. For what you consider merely a styling issue I'd also direct fault as not being an expected native behavior.

In what is being proposed by this pull request, I am going by the specification here:

With focus on the button:

  • Enter: opens the menu and places focus on the first menu item.
  • Space: Opens the menu and places focus on the first menu item.
  • (Optional) Down Arrow: opens the menu and moves focus to the first menu item.
  • (Optional) Up Arrow: opens the menu and moves focus to the last menu item.

By this definition, it is wrong to focus the first menu item except when the button is already focused while one of the listed keyboard interactions is made.

I'd strongly recommend, as I've always done, to try to keep things simple and as close to native as possible.

The intent of this pull request was not to introduce further complexity. Quite the opposite in-fact, it exists to simplify existing behaviors, remove all distinctions between cursor and keyboard users, and to emulate the native experience as closely as possible.

That we're discussing the behavior of specific software incompatibilities is not unexpected in the course of a review. But it appears to me you've approached this pull request with dismissal from the onset, presumably on the basis that the previous implementation was more "simple" or "native", of which I firmly believe it was neither.

Sometimes it requires that we do things wrong (and I wholly admit that #5318 was a bad change) to realize that there are more significant underlying flaws in the system. It would perpetuate the fragility that these issues introduce to merely gloss over them with a simple revert and ignore. This is also why I go out of my way to explicitly invite your feedback via a request for review, as I did 7 days before the merge of #5318, and here 8 days before your comment at #5559 (comment), to avoid these current situations of exhausted pessimism.

That all being said, if it's going to take a few more iterations before we get it right, I'd be totally fine with proceeding with a revert like that in #5732 in the interim.

@afercia
Copy link
Contributor

afercia commented Mar 22, 2018

Quickly googling can be faster than inspecting source code :)

Understanding screen reader interaction modes
https://tink.uk/understanding-screen-reader-interaction-modes/
by Léonie Watson

Why is it assumed that focusing the first item is the expected behavior when activating a menu?

Because the "more" Popover is not a menu, it's a modal :) In terms of expected behaviors by assistive technologies, a "menu" is similar to a desktop application menu, which is different from the "more" think or the "Content structure" thing.

That we're discussing the behavior of specific software incompatibilities is not unexpected in the course of a review.

I'd argue they're not incompatibilities. Gutenberg is supposed to support standard behaviors of assistive technologies and to be device independent.

But it appears to me you've approached this pull request with dismissal from the onset, presumably on the basis that the previous implementation was more "simple" or "native", of which I firmly believe it was neither.

That's because the approach proposed here just doesn't work with screen readers. The right direction to solve this kind of issues is not adding new layers of complexity (and I'm not speaking about code but about interaction), but rather simplifying interaction.

Regardless, using keyboard events on non focusable element without a role is a bad practice (jsx-a11y warns for this, right?) and doesn't work. Playing with down arrow, or tab, or whatever, leads to behaviors that are completely unexpected by users. I hope to be able to let the team read the reports we're receiving soon, to get a sense of how implementing unexpected interactions completely confuses users.

I still think the simplest solution is to just move focus within the Popover, together with #5242. Even better, if the decision was up to me, I'd treat this kind of Popovers like real modals using something like react-modal.

Existed prior to refactoring to track events (#2321, #931).

Causes conflict where intentional tabs away from the mounted element would revert focus back to the element (twice tab to dismiss a tooltip'd element)
@aduth aduth force-pushed the update/popover-focus-mount branch from bbd56ff to d0d8d6f Compare March 26, 2018 14:38
Otherwise race conditions where toolbar setting change occurs simultaneous to remainder of test actions.
While we need to exclude Tooltips from this behavior, which ought to otherwise described by appropriate ARIA attributes, we need to support screen readers which will navigate non-focusable content.
@aduth
Copy link
Member Author

aduth commented Mar 26, 2018

I've revisited this pull request this morning after sitting on it for a few days.

I agree that with consideration of #5242 (or more accurately, #2306), there's a need to mimic the tabbing behavior such that it is faithful to as though the popup were to occur in markup immediately following the focused triggering item, even if rendered elsewhere via Slot/Fill. For this reason, the latest changes revert back to the previous behavior where focus is transitioned to the popover on open.

However, focus is transitioned to the content wrapper, not the first tabbable child. The behavior of focusing the first tabbable item is one unique to the dropdown. I respectfully disagree that this is not a menu, at least so far as conceptually modeling its behaviors based upon relevant specifications. Considering modals more generally, particularly those with more complex content, I don't think this focus-first-tabbable behavior would be expected for any user. Imagine a modal with several paragraphs of text followed by a button. Would it not be the case that someone using NVDA would expect to be able to navigate through those paragraphs via browse mode upon opening the modal? Forcefully shifting focus to the button immediately upon open would be quite unexpected.

Aside: For what it's worth, React Modal — also implemented with portals — sets focus to a .ReactModal__Content--after-open[tabindex="-1"] after a popover is shown (Demo)

Previous revisions of this pull request detected the presence of a tabbable before shifting focus to the popover, with the (presumed incorrect) assumption that there's no sense in focusing the dialog if there is no focusable content within. However, in mind of various screen readers' browse modes, I assume this is a wrong assumption, as the user may need to navigate even through the non-focusable content.

This really only existed to simplify implementations such as Tooltip, where it's not expected we should want to transition focus where the tooltips are shown (otherwise causing two tab stops, an issue that's been seen on at least one occasion in the past). Since a tooltip needs custom handling to associate its relation to the tooltip'd element correctly, we should probably want this to be less simple, so as to ensure the developer is mindful of these considerations. See also #2369, though from what I can tell, the implementation for tooltips is still incomplete. While IconButton applies an aria-label, not all use of Tooltips is with icon button, so we should want it to be baked into the Tooltip component itself.

I've run through this again in a number of different contexts (cursor, keyboard only, keyboard with NVDA & VoiceOver), and all seems to be working as I'd expect. One potential uncertainty is what behavior should be expected in NVDA when in browse mode, focus is on the button, and the user presses "Down". Here (and in #5732), it moves to the next element in the tab sequence. This is because the button doesn't qualify to receive the keyboard events. It could, as with the previous commit applying role="menu" 84e78a3. This was since reverted, under the assumption that the current behavior is expected in browse mode. From what I can tell, this is also consistent with the behavior in various WAI-ARIA examples ([1], [2], [3], [4], [5]).

Please let me know if you have any feedback on these latest changes. I appreciate your patience and, if it's any consolation, this entire process has been incredibly educational for me personally.

@aduth aduth changed the title Components: Refactor Popover to focus by presence of tabbable Components: Refactor Popover to focus content wrapper on open Mar 26, 2018
@aduth
Copy link
Member Author

aduth commented Mar 26, 2018

Just noticed you mentioned the same issue with Tooltip implementation at #5756 (comment) 😄

@aduth aduth modified the milestones: 2.5, 2.6 Mar 28, 2018
@afercia
Copy link
Contributor

afercia commented Apr 3, 2018

Tested a bit and seems to not work as expected, not sure if something has changed.

Without a screen reader running, Windows 10, Firefox ESR:
Pressing Enter on the More Options button:

screenshot 97

  • the menu doesn't open
  • instead, the sidebar gets toggled (basically, it activates the first button inside the menu, even if the menu doesn't open)

With a screen reader running: Windows 10, Firefox ESR, NVDA 2018.1:

screenshot 96

  • focus is moved to the menu wrapper
  • instead, focus should be moved to the first menu item

Worth reminding:

  • the default mode for Windows screen readers is "browse mode"
  • when a button is focused, screen readers are still in browse mode
  • when a screen reader is running, pressing Enter or Spacebar on a button fires a click event
  • in all the 5 ARIA examples of menus linked above, focus goes to the first menu item

That said, I appreciate the effort made here but I'm still not convinced why there should be a different behavior when using a keyboard and when using a mouse. Seems to me this "double behavior" introduces a layer of complexity that is prone to be misused, probably fragile to maintain over time, and difficult to explain to developers who will to reuse this component.

If the intent is to make focus style not "linger" on the first menu item, than I'd tend to think it's a styling issue that should be solved with CSS and not with an extra-layer of code complexity. In this regard, even if as a person who specializes in accessibility I can only repeat that focus should always be visible even when using a mouse, I'd suggest to try a new approach. There's :focus-visible for this: it's landing soon in Chrome and already working in Firefox. I'd tend to consider this an acceptable compromise, especially because based on native browsers features.

More importantly: seems to me we should clearly distinguish what a menu is, as opposed to other Popover usage for non-menus (let's call these "modals"). I'm not sure the Popover component can be used with the same interaction model for both menus and modals, because the interaction model assistive technologies expect is different.

Menus:
they have a role="menu" and contain only menu items with a role="menuitem". Optionally, they can contain a "separator", nothing else.
https://www.w3.org/TR/wai-aria-1.1/#menu
https://www.w3.org/TR/wai-aria-1.1/#menuitem
https://www.w3.org/TR/wai-aria-1.1/#separator
https://www.w3.org/TR/wai-aria-practices-1.1/#menubutton
https://www.w3.org/TR/wai-aria-practices-1.1/#menu
(plus the ARIA Authoring Practices examples linked above)

In Gutenberg, the following are clearly menus:

screen shot 2018-04-03 at 15 29 21

When they open, focus should go to the first menu item, that's it.

Other Popover usages in Gutenberg are more similar to "modals" because they don't exclusively contain menu items, for example:

screen shot 2018-04-03 at 15 35 57

Thinking also at a recent conversation on Slack about using the Popover for modals and screen "take-overs", Id think either the Popover should have a different behavior to handle the "modals" or there should be a dedicated component. Modals are... complicated 😬

Traditionally, in ARIA terms a "modal" is a "dialog" that consists prevalently of interactive content. Think at a confirm dialog or a mini-form. That's the reason why NVDA switched to "forms mode" when entering a modal. In this traditional model, all the recommendation from this post applied:
Advanced ARIA Tip #2: Accessible modal dialogs
https://www.marcozehe.de/2015/02/05/advanced-aria-tip-2-accessible-modal-dialogs/

However, some important things have changed in ARIA 1.1 and in NVDA. Specifically, the definition for dialog has slightly changed in ARIA 1.1 and as a consequence NVDA doesn't switch to forms mode any longer. See
https://www.nvaccess.org/files/nvda/releases/2017.4/nvda_2017.4_changes.html
Web dialogs in Firefox and Chrome web browsers now automatically use browse
Mode, unless inside of a web application.
nvaccess/nvda#4493
nvaccess/nvda#4493 (comment)
nvaccess/nvda#7433

Basically this means "modals" are now supposed to contain also non-interactive content, for example big chunks of text, and users can explore content as they usually do in browse mode. What this does mean for us? It means that now for modals the best option is to focus the modal wrapper, as long as it has an aria-labelledby pointing to a visible title or an aria-label. This usage is very similar to one fo the interaction behaviors proposed in this PR. I wonder fi this switch between a "menu" behavior and a "modal" behavior could be controlled with a prop or if the best option is a separate component.

Worth noting the current recommendation in case of long content within a modal is to make the first element (such as a heading) focusable. See
https://www.w3.org/TR/wai-aria-practices-1.1/#dialog_modal

If content is large enough that focusing the first interactive element could cause the beginning of content to scroll out of view, it is advisable to add tabindex=-1 to a static element at the top of the dialog, such as the dialog title or first paragraph, and initially focus that element.

This was the traditional answer to your question @aduth, but I think we should be pragmatic and focusing the wrapper (the same element which has role=dialog and either aria-labelledby or aria-label) seems a more solid (and testable?) solution.

@youknowriad youknowriad modified the milestones: 2.6, 2.7 Apr 5, 2018
@aduth
Copy link
Member Author

aduth commented Apr 11, 2018

It's certainly not a goal to reenforce any segregation of interaction device. I'm looking at it purely from a perspective of impact of behavior on various states of focus. My current understanding is that ideally for these menus:

  • Clicking (even "clicks" from screen reader browse mode) should focus the button and toggle the dialog (open/close).
  • Enter & Space from a focused button toggles the dialog and focuses within if now open.
  • Arrow Down from a focused button opens the dialog (if not already open) and focuses within.
  • Generally the behavior of the dropdown should be as though it were in a tab sequence immediately following the anchor element (particularly relevant for screen reader "browse" mode navigation while button is currently focused and the menu visible).

You're right to point out that these are made challenging by various factors, mostly stemming from impact of portals on default tab flow. Ultimately, I agree we'd be best served to move forward as implementing the "simple" approach, and only iterating based upon solid end-to-end tests which can verify all of the expected behaviors.

in all the 5 ARIA examples of menus linked above, focus goes to the first menu item

Yeah, looking more closely at this, I see the click behavior is dependent upon whether the menu is already opened, and the behavior of the menu is such that hovering opens the menu, so clicking with a pointer device (vs. screen reader) is guaranteed to occur while the menu is already visible, and so focus doesn't transition to the first item. I'd be curious how an example would look for a toggle menu which doesn't open on hover, but rather on click.

Reflecting on the discussion from last week's editor meeting, I no longer hold the opinion that Popover needs to encompass all these behaviors and rather that individual abstracted components should correspond to the specific behaviors. I still think Popover can serve as a base, and we do already have components representing the various behaviors, but some adjustments to the implementations and documentation need to be made to reflect what's expected from each.

Roughly, mapping components to behaviors, I see:

  • Popover
    • role=dialog (?)
      • With requirements therein (aria-label or aria-describedby heading): Does this mean all Popover use should require a label describing the dialog?
    • Shifts focus to self (wrapper, heading) when made visible
    • Traps focus (related: Consider to implement a generic "constrain tabbing" functionality #4621)
    • Closes on escape, or focus transitioned outside
    • Returns focus to element which had it upon having been focused
    • Example: Full-screen takeover
  • Dropdown inherits behavior of Popover, plus:
    • Is visibly oriented relative to an anchor node
    • Example: Table of contents, inserter, date scheduling, tooltip
    • How does Tooltip interact with the focusing behavior? We don't want two tab stops, but this conflicts with Popover focus shifting. This is handled currently by passing a focusOnMount={ false } to the Popover, but I'm wondering if we could determine this programmatically (one of the goals of this pull request). What is it about a tooltip that allows us to not have it be focusable directly? (Some relation of aria-label and its own content being matched?)
  • DropdownMenu inherits behavior of Dropdown, plus:
    • role=menu
      • Only elements allowed in this role (separators, menu items), enforced via its own existing controls prop
    • Shifts focus to first tabbable item
    • Arrow navigable (builds-in NavigableContainers behavior)
    • Example: Editor menu, block more options menu, block transforms menu

A large number of these characteristics are already present in the above components (and through various refactors, the relations themselves). Based on this overview, I'm inclined to close this pull request and identified these as immediate action items:

  • Merge Make Popover initial focus work with screen readers. #5732 to fix screen reader browse mode focus behavior
  • Implement end-to-end tests verifying expected keyboard behaviors
    • I'd love if we could find a way to incorporate screen readers into these tests
  • Move "relative orientation" from Popover to Dropdown
  • Split Popover focus behavior to distinguish between focusing wrapper (in Popover) and first tabbable (move to DropdownMenu)
    • Can be adapted from this pull request
  • Require label for Popover
  • Popover focus trapping
  • Refactor Popover to avoid react-click-outside
    • Can be adapted from this pull request
  • Some refactor of Tooltip (most importantly applying aria-label consistently, but ideally also avoiding opt-out to focus behaviors and build-in logic to Popover instead)
  • Change block options menu to use DropdownMenu
    • May relate to the issue you noted in your latest comment with sidebar opening
  • Later: Iterate on implementations of Popover, Dropdown, DropdownMenu to align more with the "idealized" behaviors listed above, only once end-to-end tests can protect against unintended regressions

Let me know if you have any corrections to the above. I understand a large chunk of this text is repeated from various comments and proposals, and is summarized for completeness' sake.

@karmatosed
Copy link
Member

I would like to add something that also would benefit from focus issues being resolved: #5595. We have reports of the focus causing issue here and they are very worth considering in this. I'm adding here to avoid having multiple places for the same subject.

@aduth
Copy link
Member Author

aduth commented Apr 11, 2018

@karmatosed Did you mean to link to another issue? The number is that of this pull request 😄

Based on reference, do you mean #4871 ? Certainly related, though the plan is to close this pull request, so if we need to track it, it should be done so separately, either in #4871 or new issue(s) for those not accounted for in above intentions. In particular, I could use some help with focus style design iterations, and to my knowledge this is not tracked.

@aduth
Copy link
Member Author

aduth commented Apr 11, 2018

Closing with intention to split out tasks noted in #5595 (comment)

@aduth aduth closed this Apr 11, 2018
@aduth aduth deleted the update/popover-focus-mount branch April 11, 2018 19:04
@karmatosed
Copy link
Member

Ha crumbs yes: #4871.

@afercia
Copy link
Contributor

afercia commented Apr 16, 2018

Quick note about the modal label:

Any modal dialog should be labelled:

  • if the modal content has a visible heading or title, then use aria-labelledby="some-ID-here" on the element with role="dialog" to target the visible title
  • otherwise, use an aria-label="Some title here" on the element with role="dialog"

Reference:
https://www.w3.org/TR/wai-aria-1.1/#dialog
Authors SHOULD provide a dialog label, which can be done with the aria-label or aria-labelledby attribute.

See also the examples in the ARIA authoring practices:
https://www.w3.org/TR/wai-aria-practices/#dialog_modal

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] UI Components Impacts or related to the UI component system [Focus] Accessibility (a11y) Changes that impact accessibility and need corresponding review (e.g. markup changes).
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants