-
Notifications
You must be signed in to change notification settings - Fork 374
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
In Shadow DOM v1, tabIndex=-1 makes all elements inside the shadow tree to be no tab-focusable #774
Comments
Is this with a shadow tree or not? |
With a shadow tree. Also note that this behavior changed from Shadow DOM v0 to v1. See minimal examples at https://bugs.chromium.org/p/chromium/issues/detail?id=896624#c5 (the examples use Polymer, but they can be made without Polymer as well if it helps). |
In that case this is really about delegatesFocus and the various focus related issues already on file: whatwg/html#2013. |
I guess I don't understand how delegatesFocus is supposed to work and why the introduction of delegatesFocus changed tabIndex's semantics. I read #399 changed tabIndex's semantics because we wanted a feature "make everything of this custom element/shadow tree non-tab-focsable"? But isn't that what delegatesFocus=false does for us? My intuition:
The shadow host could then be a <div> where Shadow DOM content overflows (a scrollable div). Still, an author could decide to eject the <div> from the tab order but leave its [shadow] content in. |
Your intuition matches mine, but I haven't looked at focus in a while. What goes amiss? |
Because of #399, an author can not decide to eject the host <div> from the tab order but leave its [shadow] content in. |
That issue doesn't seem to consider |
/cc @hayatoito @annevk According to the comment at https://bugs.chromium.org/p/chromium/issues/detail?id=896624#c15, and the tests at https://cs.chromium.org/chromium/src/third_party/WebKit/LayoutTests/shadow-dom/focus-navigation-with-delegatesFocus.html?l=106-138, |
The original change at r608013 caused WebUI regressions, some of which are unclear on how to fix because of a separate issue with tabindex -1 and Custom Elements, WICG/webcomponents#774. Need to address WebUI affected cases, before the flag is re-enabled by defalut. Bug: 907284 Change-Id: Ie8a41df1df663d25cf06a0ed6ae42ac80512df0c Reviewed-on: https://chromium-review.googlesource.com/c/1347429 Commit-Queue: Demetrios Papadopoulos <[email protected]> Reviewed-by: Dave Tapuska <[email protected]> Cr-Commit-Position: refs/heads/master@{#610218}
@freshp86, yeah, I think that is intentionally done in v1. if the shadow host has -1 tab index, any node in a shadow root is skipped, as far as I can read. |
I want to stress that the semantics described by @hayatoito is what we believe is the right model. This should not be about <template>
<input tabindex="1" />
</template> That should never disrupt the page, no matter what, it is bound to whatever tabindex value its host has, independently of the |
@caridy: Thanks for this explanation, it does make sense. There is still the following problem though: The combination of the described
Is that not considered a valid use case? Are authors forced to always wrap their contents with a div and add tabindex -1 to achieve that? @hugoholgersson: Are the scrolling containers changes based on a spec or is it just matching Firefox's behavior but not explicitly specced? Perhaps treating shadowRoots differently in the "keyboard accessible scroll containers" implementation is the right approach here? Such that they are not added in the tab order silently?
Just a thought about this: Perhaps providing a way for consumers of a component to modify this behavior would alleviate this problem? Even if an author created a "bad" component, consumers could "fix" that behavior on their end, for example |
@freshp86 The current HTML spec does not require tab-focusable scrollers but I hope WebKit and Edge pick it up so we can spec it (it has clear accessibility benefits). |
@caridy there's a difference between enabling elements inside a shadow tree being "tab-focusable" and letting that tree override the tab order of the light tree, no? |
I don't think we want this, it is basically inversion of control on something that is an internal implementation detail.
That's a very interesting question. I haven't play much with tab-focusable elements in light dom, maybe @davidturissini and @SiTaggart has some opinions here, but my intuition here is:
Side note: in our platform, this is not a problem because we intentionally only allow tabindex=0 and -1 in all authored web components, and only high-privilege code (usually app level code) can bend that rules (e.g.: panels and such that might require some specific behavior). |
To me, I may wish to have a programmatically focusable custom element host, with focusable children. I would achieve that by placing It shouldn't also remove all subtree items from being focusable too, even if they are in that hosts shadow. That should be left up to delegateFocus IMO |
This issue is titled about custom elements, but seems to actually be about Shadow DOM. I have a lot of standard divs that are shadow hosts. The divs have lots of input elements in their shadow tree. Sometimes I want to assign programmatic focus to the shadow host itself, in order to control where the next tab/shift-tab will send the user and allow mouse focus. So I set manually tabIndex=-1 on the shadow host div. In v0 that worked great, the same as standard DOM. In v1, all of the input elements inside the shadow host are removed from the tab order. document.body.appendChild(document.createElement('input'));
document.body.appendChild(document.createElement('input'));
const shadowHost = document.createElement('div');
shadowHost.textContent = 'shadow';
document.body.appendChild(shadowHost);
shadowHost.tabIndex = -1;
const shadowRoot = shadowHost.attachShadow({mode: 'open'});
shadowRoot.appendChild(document.createElement('slot'));
shadowRoot.appendChild(document.createElement('input')); I wanted to make my div more focusable, and it ends up removing tab order from all of its children?! |
I think I understand how @TakayoshiKochi wanted to circumvent this problem: @JoelEinbinder, what if you set That should both make your shadow host div appear tab- and click-focusable; the div will immediately forward focus to its shadow tree's tab order's first element*. Read his explanation about delegatesFocus for the details. * The shadow tree's tab order's last element, when Shift+TAB focus the shadow host div. |
It seems wrong that it would be impossible to make a custom element programmatically focusable and not in the user tab flow, without removing the entire shadow tree from tab flow. If I explicitly set |
Setting Using |
That is not true. It doesn't make the element not focusable, it removes it from the tab order. Clicking still moves focus, and assistive technology can still focus the element. tabIndex=-1 is a weird quirk of the web. But making a shadow root shouldn't transfer me to a new world where focus works completely differently. |
Finally is it any solution for it? |
When experimental web platform features are enabled, the blink KeyboardFocusableScrollers feature is enabled. This causes scrollable container to become keyboard-focusable. See: https://bugs.chromium.org/p/chromium/issues/detail?id=907284 Even trickier, setting tabindex to -1 on a web component causes everything inside of it to become untabbable. See: WICG/webcomponents#774 So the solution in this case is to wrap up the action-group component with a plain old div with tabIndex -1, and let that div handle the overflow/scrolling instead.
When experimental web platform features are enabled, the blink KeyboardFocusableScrollers feature is enabled. This causes scrollable container to become keyboard-focusable. See: https://bugs.chromium.org/p/chromium/issues/detail?id=907284 Even trickier, setting tabindex to -1 on a web component causes everything inside of it to become untabbable. See: WICG/webcomponents#774 So the solution in this case is to wrap up the action-group component with a plain old div with tabIndex -1, and let that div handle the overflow/scrolling instead.
Previously the screenreader readout was done by removing all rows except the selected row from the tab flow by setting tabindex = -1, but this broke tabbing through the other non-selected rows. This method was not breaking tab flow in the gr-file-list because the rows are not using shadow DOMs. see WICG/webcomponents#774 This change restores all rows to the tab flow by always setting tabindex to 0, and maintains the screenreader readout by focusing the row when it gets selected. Verified with VoiceOver on Mac OS. Release-Notes: skip Google-Bug-Id: b/235477335 Change-Id: I48ef40f18ce061e50ef71bd4df0cf311a25e683b
An inconsistency in Shadow DOM v1 has started to confuse web developers:
From crbug.com/906729:
Custom Element: tabIndex -1 removes "tab focusability" for everything inside the custom element.
A [scrollable] <div>: tabIndex -1 removes "tab focusability" for the [scrollable] <div> itself but not its content.
The text was updated successfully, but these errors were encountered: