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

unexpected focus results for tabindex + <dialog>.showModal() #1929

Open
danbeam opened this issue Oct 19, 2016 · 61 comments

Comments

@danbeam
Copy link

commented Oct 19, 2016

@domenic @esprehn @tkent-google @TakayoshiKochi

Hi,

As spec'd (as far as I can tell), <dialog> has a few cases where the tabindex + focus behavior is unintuitive to me.

Specs:
https://html.spec.whatwg.org/multipage/forms.html#dialog-focusing-steps
https://html.spec.whatwg.org/multipage/interaction.html#sequential-focus-navigation-order
https://html.spec.whatwg.org/multipage/interaction.html#negative-tabindex

First case:

<dialog>
  <div tabindex="-1">
    i don't wish to participate in the tab order,
    but am focused when showModal() is called
  </div>
</dialog>

Second case:

<dialog>
  <button tabindex="-1">
    i get focused on showModal() even with a negative tabindex
  </button>
</dialog>

Third case:

<dialog>
  <button tabindex="-1">
    i get focused on showModal() even with a negative tabindex
  </button>
  <div tabindex="0">
    i lose even through I participate in the tab order
  </div>
</dialog>

It's obviously possible to remove the tabindex="-1" in cases 2 and 3, but some frameworks (i.e. Polymer) use .tabIndex = 0/-1 as if it's the same as calling setAttribute('tabindex', '0') or removeAttribute('tabindex').

Additionally, there's no easy way to remove an element that is tabbable by default (i.e. <button>, <a href>) without the ability to specify tabindex="-1".

I think this generally boils down to spec lingo about the "tabindex focus flag" or being "focusable" when it should be more like being in the "sequential focus navigation order".

This leads to unexpected mismatches in behavior (at least in my mental modal) which actually manifested in Chrome's settings page.

Note: while this currently only affects Chrome, Mozilla seems to be kinda/sorta interested:
https://bugzilla.mozilla.org/show_bug.cgi?id=840640

@domenic

This comment has been minimized.

Copy link
Member

commented Oct 19, 2016

Could you explain what parts of the behavior are unintuitive to you, what spec lines lead to that behavior, and what behavior you think should happen instead?

@danbeam

This comment has been minimized.

Copy link
Author

commented Oct 19, 2016

https://html.spec.whatwg.org/multipage/interaction.html#specially-focusable

If the value is a negative integer
The user agent must set the element's tabindex focus flag, but should omit the element from the sequential focus navigation order.

If the value is a zero
The user agent must set the element's tabindex focus flag, should allow the element and any focusable areas that have the element as their DOM anchor to be reached using sequential focus navigation, following platform conventions to determine the element's relative position in the sequential focus navigation order.

the simplest interpretation of this text is: tabindex=0 means focusable, tabindex=-1 means unfocusable (regardless of tag name, with no ancestors or disabled involved).

in my fiddles: pressing Tab before <dialog>.showModal() is called has different results than after.

@domenic

This comment has been minimized.

Copy link
Member

commented Oct 19, 2016

Sorry, I'm still not really clear.

in my fiddles: pressing Tab before <dialog>.showModal() is called has different results than after.

So, you would expect it to have the same results whether or not a modal dialog is shown?

Which of the two results would you find more preferable?

@tkent-google

This comment has been minimized.

Copy link
Collaborator

commented Oct 20, 2016

Dan and I chatted before filing this, and I think Dan's main concern is that "dialog focusing steps" depends on DOM order, and is not manageable by tabindex attributes.

https://html.spec.whatwg.org/multipage/forms.html#dialog-focusing-steps

If there isn't one, then let control be the first non-inert focusable area in subject's control group.

https://html.spec.whatwg.org/multipage/interaction.html#control-group

Focusable areas in control groups are ordered relative to the tree order of their DOM anchors.

A solution would be

  • Make "dialog focusing steps" tabindex-aware, or
  • Expand "autofocus" attribute support to all elements
@danbeam

This comment has been minimized.

Copy link
Author

commented Oct 24, 2016

Expand "autofocus" attribute support to all elements

ehhh, that didn't sound so awesome when I spoke about it to @freshp86. I don't really understand what autofocus helps when an element isn't focusable (i.e. <div autofocus> as <div> is not focusable by default).

Make "dialog focusing steps" tabindex-aware

right, this is what I was hoping for. but really, just that <dialog> essentially works like it's own document (as far as focus is concerned).

@domenic

what i expect from fiddle 1:

  • step 0: click in blank space in result frame
  • step 1: press Tab
    • expectation 1: focus skips over <div tabindex="-1"> and to <button>show dialog</button>
  • step 2: click or press Enter while on <button>show dialog</button>, a dialog should show (in Chrome)
    • expectation 2: <div tabindex="-1"> cannot be focused, similarly to the <div tabindex="-1"> outside of the <dialog>
    • unexpected 1: the unfocusable <div tabindex="-1"> is focused (as seen by outline CSS)

i'll fill in more steps for 2 and 3, but same basic theme: pressing Tab in a document works differently than when opening a <dialog>, which essentially causes everything underneath it to become inert and restarts the focus logic with its contents. this is my mental modal at least (when a dialog is shown modally). please let me know if i'm just thinking of this incorrectly.

@domenic

This comment has been minimized.

Copy link
Member

commented Oct 24, 2016

OK, thanks for the background; I think I am starting to understand the problem. It seems like the conflict is essentially that tabindex="" is used to impact sequential focus navigation, but most of the focus mechanisms in the spec do not have to do with sequential focus navigation---that's only related to pressing TAB to sequentially tab through the document.

In particular, in fiddle1, the outside-the-dialog div is not focused at first because the whole browsing context is focused. And you cannot then focus it through pressing TAB, of course. But you can focus it by clicking on it. (Or by calling .focus(), or similar.)

When you open the dialog, the user agent then wants to move focus to the dialog. Since this isn't related to pressing TAB, we don't care about the tabindex="" attribute; we just use the normal focus rules that apply for clicking and for .focus().

I guess what might be strange is the choice to focus the first element of the dialog, instead of focusing the dialog as a whole. Focusing the dialog as a whole would match the behavior for the outer document, where we initially focus the browsing context instead of focusing the first focusable element inside of it.

My guess is that it was deemed more user-friendly to focus something inside the dialog. Maybe it is also complicated since "the dialog" is kind of part of both the outer document and the dialog focus control group; maybe if we focused the dialog then the rest of the spec would get confused about what to tab to next, or similar. (I'm less sure about that part, and it doesn't matter much.)

So I think there might be an inconsistency here, but I don't think extending tabindex="" to have meaning outside of sequential focus navigation is the right way to fix it.

@danbeam

This comment has been minimized.

Copy link
Author

commented Nov 18, 2016

My guess is that it was deemed more user-friendly to focus something inside the dialog.

That's possible, but for assistive technology users that's like deeming it "more user-friendly" to start scrolled half-way down the page (if you focus something half-way in the middle of the dialog's contents, that's where a screenreader likely shifts to).

Additionally, if there's a <button> at the bottom of a <dialog>, it actually does force scroll to it (example).

Also, focus rings are often just noise on mobile (other than maybe in editable areas i.e. <input>, <textarea>); not a ton of keyboard nav going on there.

I guess what might be strange is the choice to focus the first element of the dialog, instead of focusing the dialog as a whole. Focusing the dialog as a whole would match the behavior for the outer document, where we initially focus the browsing context instead of focusing the first focusable element inside of it.

YES. It would be way more sane, IMO, to just focus the dialog as a whole and respect autofocus if it exists. Just like in outer documents (AFAIK).

@domenic

This comment has been minimized.

Copy link
Member

commented Nov 24, 2016

If you're interested in changing Chromium in that fashion, I'm happy to change the spec too. Let me know?

@danbeam

This comment has been minimized.

Copy link
Author

commented Nov 29, 2016

I'm hacking around in Blink, but have some questions:

  1. should the <dialog> that we're calling show() or showModal() on receive focus events?
    note: <body> does when initially focused
  2. does this mean that <dialog> should be focusable by default?
    note: is often focusable in Blink, though user agent styles hide the outline
  3. I assume that document.activeElement should be the top-level <dialog> while 1+ <dialog>s are showing?
    note: I think there are issues with the current implementation
@TakayoshiKochi

This comment has been minimized.

Copy link
Member

commented Nov 29, 2016

In my opinion,

  1. Yes, it would receive focus event.
  2. The spec says "The tabindex attribute must not be specified on dialog elements.", but I'm not sure "by default" or not. Maybe <display>.tabIndex = -1 when it is not on the top-level, and <display>.tabIndex = 0 when it is.
  3. Yes, document.activeElement can only point to at most one element in a document.
@domenic

This comment has been minimized.

Copy link
Member

commented Dec 6, 2016

@danbeam thanks for digging them up.

If we were to make these changes, I'd say the answers to your three questions would be yes, yes, and yes.

However looking through that first long bug thread does make it seem to me like the more reasonable behavior is to focus the first control. Testing a few native apps they seem to all work that way too. Do you still think focusing the dialog is the best choice?

I was going to say, "maybe the best strategy is 1) autofocus; 2) first focusable control; 3) the dialog". But that is actually what the spec already does! The confusion in this thread is just about confusing "focusable" with "part of the sequential focus navigation order"; tabindex="-1" causes something to be focusable, but takes it out of the sequential focus navigation order. So given that we have this distinction, everything seems to be working pretty well to me; you just have to remember to not put tabindex="-1" on your divs, since doing so makes them focusable.

@danbeam

This comment has been minimized.

Copy link
Author

commented Dec 6, 2016

The confusion in this thread is just about confusing "focusable" with "part of the sequential focus navigation order";

But that's exactly the issue: someone probably would add tabindex="0" to affect initial focus (not just "sequential focus navigation order"). But they can't configure it in reverse, i.e. skipping over a default focusable element (what I tried to accomplish with <button tabindex="-1">). This asymmetry was the root of my misconception.

you just have to remember to not put tabindex="-1" on your divs

Yeah, I understand what you're saying, and we're (Chrome UI folks) probably having issues because we're using Shadow DOM, which intentionally hides a bunch of stuff (and currently doesn't work with the way that <dialog> considers its initial focus candidate, which is probably just a bug).


In general, I think there's a few things we (and the context) agree upon:

  1. valid [autofocus] should be respected
  2. the <dialog> should get focused when focusable (i.e. <dialog tabindex="0">)

What I'm not sure makes sense is:

  1. any focusable element (i.e. <a>) inside a <dialog> should be focused initially
    1. it seems like this should be configurable in some way, many have asked
  2. the main use case for <dialog> and what it brings to the web. I see a few possibilities:
    1. add a new level of modality, filtering events through a first (or only) responder for certain events or modes of browsing
    2. make an often replicated UI paradigm easier to create

Regarding 1. if we agree to let some validly opt out of the default behavior (initial focusing logic), maybe canceling a 'show' event via preventDefault() would be a natural fit? Or maybe [optionally] parameterizing show()/showModal()?

Regarding 2. I suspect that @Hixie, @cookiecrook, and @stevefaulkner went at eachother for many rounds because it wasn't insanely clear to them what <dialog> wants to accomplish. I interpreted (and hoped for) "add a new level of modality" because of the concept of inertness. The user agent styles (unspecified, I get that) of showModal() in Chrome match that of "common UI paradigm". It's all fairly muddy to me; I'm uncertain and fearful for the future of <dialog> because it hasn't received much usage or implementation support (I think its unclear purpose may be a partial cause).


tl;dr - the absolute best thing I could see happening is the ability to harness just inertness, maybe via an inert attribute or makeInert() imperative API. This allows folks access some of the underlying magic of <dialog> without forcing the default behavior when it doesn't suit well.

@domenic

This comment has been minimized.

Copy link
Member

commented Dec 6, 2016

Regarding 1. if we agree to let some validly opt out of the default behavior (initial focusing logic), maybe canceling a 'show' event via preventDefault() would be a natural fit? Or maybe [optionally] parameterizing show()/showModal()?

I like parameterizing show/showModal, among these. Although I'd appreciate more info on the use cases---I don't quite remember that showing up in the megathread, but maybe it escaped my brain...

the absolute best thing I could see happening is the ability to harness just inertness, maybe via an inert attribute or makeInert() imperative API.

Yeah, definitely! We're hoping for implementer interest in #1474, but haven't seen much yet :(.


So to recap our learnings, there are three separate but related concepts:

  1. Unfocusable vs. focusable
  2. In sequential tab order vs. not
  3. Inert vs. not

tabindex controls (1) and (2) together. Specifically, setting it to anything will control (1) by making the element focusable---but you cannot make the element unfocusable. And using -1 vs. 0 you can control (2).

The spec factors (3) separately from (1) and (2), but in practice they are tied together: the algorithms for focusing and sequentially navigating focus consult inertness, in addition to consulting focusability specifically and in-sequential-tab-order specifically. It might be an unobservable refactoring of the spec to say that all inert elements are unfocusable and not in sequential tab order. But probably there is some subtle difference; I wonder what it would be.


So. What should we do with this bug, given our new deeper understanding of focus? Maybe add a clarifying note delineating the difference between these three concepts, for one. But should we do any behavior changes? Maybe parameterizing show/showModal? Or just hope that #1474 gains ground and the issues can be solved there?

@minorninth

This comment has been minimized.

Copy link

commented Dec 6, 2016

I like the idea of changing the spec so that opening a dialog respects autofocus, and doesn't autofocus controls with tabindex=-1. Those seem consistent with the spirit of the original spec, and they're unlikely to break any existing code or tests.

I'm a bit hesitant to parameterize showModal because we're already having trouble getting buy-in to ship dialog in other browsers, so changing the API seems like it shouldn't be done unilaterally.

@danbeam

This comment has been minimized.

Copy link
Author

commented Dec 6, 2016

Adding an optional DialogShowParams dictionary to show()/showModal() is pretty straight-forward:
https://codereview.chromium.org/2560553002

Apparently easier than getting folks to agree on whether it should exist :).

@freshp86

This comment has been minimized.

Copy link

commented Dec 6, 2016

Speaking of the showModal() API changes, according to this spec, it should accept an optional parameter (MouseEvent or Element), which I don't think even Chrome has implemented (verified by the CL @danbeam linked above, I think). Perhaps we can kill two birds with one stone, by using the DialogShowParams proposed above and move the existing optional parameter to the dictionary?

@danbeam

This comment has been minimized.

Copy link
Author

commented Dec 6, 2016

Perhaps we can kill two birds with one stone, by using the DialogShowParams proposed above and move the existing optional parameter to the dictionary?

yep, that's why the proposal adds an optional dictionary (instead of just a boolean) -- there's a well-placed TODO in the code.

@danbeam

This comment has been minimized.

Copy link
Author

commented Dec 6, 2016

@domenic You asked for use cases.

We're targeting an action menu (code).

a
b

Our use case is functionally similar to a native context menu but we need to control the style. We don't wish to match platform style, so <menuitem> wouldn't work for us (even if it was implemented in Chrome).

A list of options shows up based on a user gesture. Tapping, clicking, or keyboard navigation within the action menu selects an item and performs an action. We wish for the menu to become "first responder" (get first crack at all UI events) until either an action is performed or the user expresses a desire to close the menu (perform no action) via keypress (Esc, Tab) or tap/click on the "scrim" (area outside the menu). This is similar to <select>, but is stateless (the selected item is not preserved / re-selected when the menu is re-opened).

The modal aspect of <dialog> is perfect for our purposes, as it's super hard to otherwise deal with events that a user might expect to close this menu (i.e. focus, click, tap, or scroll outside of the menu, especially with event re-targeting in Shadow DOM).

The Polymer team has tried to mimic inertness without <dialog> but have to do crazy stuff like look for through ancestry chains for scrollable nodes and attempt to block or detect scroll in a less sure-fire way than the UA can (we've had slews of bugs on about this, can dig up a list if you'd like).

@domenic

This comment has been minimized.

Copy link
Member

commented Dec 8, 2016

@minorninth

I like the idea of changing the spec so that opening a dialog respects autofocus,

It already does; no spec change needed

and doesn't autofocus controls with tabindex=-1.

As discussed in the rest of this thread, that doesn't make sense; tabindex=-1 means that the control is focusable, but not in sequential focus order. But sequential focus order is only used for pressing TAB, not for anything else (like determining what control should be initially focused in a dialog).

I'm a bit hesitant to parameterize showModal because we're already having trouble getting buy-in to ship dialog in other browsers, so changing the API seems like it shouldn't be done unilaterally.

Yeah, dialog is in a tough spot. I think conservative small changes like this make sense though, as long as nobody else objects.

@freshp86

Speaking of the showModal() API changes, according to this spec, it should accept an optional parameter

Maybe we should open an additional issue to discuss removing that, since nobody implements it. Unless Chrome wants to implement it? The use case @danbeam gives is a pretty clear-cut instance where an Element would be useful.

@danbeam

You asked for use cases.

This seems like a pretty good use case for non-modal dialogs in my opinion... I'm surprised you're using the modal version. I see how it makes event management easier but it seems like it'd be better if clicking/etc. outside the "dialog" had the usual effect, like it does with native context menus. At least on Windows (which I understand most Chrome users are on).

Anyway, I was specifically asking for use cases for not focusing the first focusable control. In your example, it seems like focusing "Make default" would be good, right? Or is the decision from the UI folks that it's better not to do so? I guess some quick testing of native context menus shows that they don't focus the first item usually, so that makes sense...

@freshp86

This comment has been minimized.

Copy link

commented Dec 8, 2016

Maybe we should open an additional issue to discuss removing that, since nobody implements it. Unless Chrome wants to implement it?

For the use case in question (implementing a popup action menu with dialog), the existing API, even if implemented, would not be sufficient. Just passing an Element to showModal() does not convey enough information on where exactly the dialog should be anchored to (top-left, top-right, bottom-left, bottom-right). Also, consider the corner case where the menu (dialog) would be near the edge of the screen, so its position should be tweaked to make it as much of it visible as possible. Essentially all the logic I describe above is what we currently do here.

Simply specifying an "anchor element" without a strategy on how to use that element's position is not sufficient I think.

I'm surprised you're using the modal version.

Non-modal version (our previous "action menu" implementation, which was not <dialog> based) suffers from other issues, mostly revolving around the fact that interacting with the rest of the page is undesirable until the popup action menu is dismissed.

it seems like it'd be better if clicking/etc. outside the "dialog" had the usual effect, like it does with native context menus.

Have not tried on Windows, but on Linux, the 1st click outside of the context menu is consumed for closing the menu, which matches the behavior of a modal <dialog>. This also matches the behavior of every mobile app with similar action menus I tried.

Anyway, I was specifically asking for use cases for not focusing the first focusable control.

Here is a screencast showing such a case, where a disabled custom element receives focus.

@domenic

This comment has been minimized.

Copy link
Member

commented Dec 8, 2016

For the use case in question (implementing a popup action menu with dialog), the existing API, even if implemented, would not be sufficient.

Right, that's why https://html.spec.whatwg.org/multipage/forms.html#%27anchor-point%27 is part of the feature.

Have not tried on Windows, but on Linux, the 1st click outside of the context menu is consumed for closing the menu

Yes, I noticed this discrepancy, but I assumed Chrome (desktop) would be building for 95% of its users using Windows, not the <1% using Linux.

Here is a screencast showing such a case, where a disabled custom element receives focus.

It seems like the real problem here is that the custom element is focusable in the first place. Presumably because you added a tabindex attribute to it. Why do that? All custom elements are by default not focusable, so there's nothing to be gained here.

@danbeam

This comment has been minimized.

Copy link
Author

commented Dec 8, 2016

Anyway, I was specifically asking for use cases for not focusing the first focusable control. In your example, it seems like focusing "Make default" would be good, right? Or is the decision from the UI folks that it's better not to do so? I guess some quick testing of native context menus shows that they don't focus the first item usually, so that makes sense...

It boils down to subtle differences between using a list box to perform an action vs select a value.

Select a value

When selecting a value (e.g. from an enumerable list), like in the case of <select>, it makes sense to show the currently selected value and preserve when re-opening the menu. This is what all platforms/browsers do (as far as I can tell).

<select> on Chrome for Windows:

<select> on Firefox for Windows:

<select> for IE (on Windows):

<select> on Chrome for Linux:

<select> on Firefox for Linux:

<select> on Chrome for Mac:

<select> on Chrome for Android:

Perform an action

In an action menu, an item is not preselected (nor preserved when re-opened).

<a href> context menu on Chrome for Windows:

<a href> context menu on Firefox for Windows:

<a href> context menu on IE (for Windows):

<a href> context menu on Chrome for Linux:

<a href> context menu on Firefox for Linux:

<a href> context menu on Chrome for Mac:

<a href> context menu on Chrome for Android:


Why does it matter?

Simply because I (and others) want to convey the right paradigm.

Unfortunately, in many of these UIs (and in Material Design, dropdown example), the focused state and the selected state (either selected value or action to perform) are identical. Why? ¯\_(ツ)_/¯ Less UI paradigms = better for users? Additionally, focus UIs are less useful on touch-only devices.

So, for our use case, if <dialog> focuses the first focusable item (and items in both should be focusable), it's harder to tell a dropdown from an action menu.

That's why it's a big deal to me (and all the places I gathered screenshots).

@domenic

This comment has been minimized.

Copy link
Member

commented Dec 9, 2016

Wow, thanks @danbeam for the detailed explanation! I agree it makes sense in such a menu-like use case to not select the first item. OK. That's a reasonably compelling reason to add such an option to show/showModal.

So, I can work on a spec change to do that. We need something that is false by default (unlike setInitialFocus); perhaps focusDialog.

Should we also remove the anchor ability, or is Chrome interested in doing that at some point? I'd lean toward removing it unless there are concrete plans in the next quarter or so; we can always add it back later.

@danbeam

This comment has been minimized.

Copy link
Author

commented Dec 9, 2016

Wow, thanks @danbeam for the detailed explanation! I agree it makes sense in such a menu-like use case to not select the first item. OK. That's a reasonably compelling reason to add such an option to show/showModal.

Huzzah!

So, I can work on a spec change to do that. We need something that is false by default (unlike setInitialFocus); perhaps focusDialog.

ignoreFocusableElements? skipFocus or skipFocusSteps?

Should we also remove the anchor ability, or is Chrome interested in doing that at some point? I'd lean toward removing it unless there are concrete plans in the next quarter or so; we can always add it back later.

On the chrome side, I don't see a bunch of priority being given to the anchor idea:
https://bugs.chromium.org/p/chromium/issues/detail?id=410346

domenic added a commit that referenced this issue Dec 9, 2016

Remove anchored positioning of <dialog>s
This was mentioned briefly in the discussion in #1929. <dialog> only has
one implementation currently, and that implementation is not planning to
implement the anchoring feature, per
https://bugs.chromium.org/p/chromium/issues/detail?id=410346.
@domenic

This comment has been minimized.

Copy link
Member

commented Dec 9, 2016

I put up #2157 to remove anchored positioning and thus clear the way for work on this option.

ignoreFocusableElements? skipFocus or skipFocusSteps?

Hmm. We want to focus the dialog itself if it's focusable, right?

We might also want to suggest that dialog elements be focusable areas by default.

@freshp86

This comment has been minimized.

Copy link

commented Dec 9, 2016

Given that JS does not support overloaded methods, I am afraid that committing to a showModal(opt_skipFocus) API might be too hard to change later. Can we consider the ShowParams approach which is more flexible?

There are a few things related to showing a dialog that should be specified at the time the dialog is shown (modality, initial focus behavior, end focus behavior, anchor element), and therefore those make sense to not be HTML attributes that can be modified after a dialog is shown. So instead of passing a single optional boolean to showModal, could we have something as follows?

show({
  modal: true, // defaults to false,
  skipInitialFocus: true, // defaults to false,
  restoreFocusOnClose: true, // defaults to false. Might be implemented in the future
  anchorElement: ..... // Might be added/implemented in the future
});

I just think this is more flexible, and since specs are harder to change (especially if multiple vendors have already implemented them), making it a bit more forward looking could be beneficial.

@domenic

This comment has been minimized.

Copy link
Member

commented Dec 9, 2016

Yes, we would definitely use an options object. I don't think anyone was proposing otherwise.

@domenic

This comment has been minimized.

Copy link
Member

commented Jan 12, 2017

I'd really encourage everyone to re-read the thread at https://www.w3.org/Bugs/Public/show_bug.cgi?id=23366 before repeating arguments that have been made there.

@stevefaulkner

This comment has been minimized.

Copy link
Contributor

commented Jan 13, 2017

I guess a workaround to maximise the accessibility and usability of a dialog due to spec constraints (if @danbeam's proposal is accepted) is to do something like this: override dialog role using role=presentation add a div with role=dialog set the flag and use .focus() to set initial focus on the <div role="dialog" tabindex="-1">

<dialog role="presentation">
<div role="dialog" tabindex="-1">
....
...
...
</div>
</dialog>

It's unfortunate that we have to ask developers to do more work bolting on semantics and behaviour to make HTML features accessible, but it's not uncommon.

@esprehn

This comment has been minimized.

Copy link

commented Jan 13, 2017

@domenic I did the code reviews for this feature, I was around when this was all debated.
I would also not say there's consensus, that thread was with an old spec editor and an engineer who doesn't work on dialog anymore, and was also had 4 years ago. People, opinions and the platform change. :)

I don't support this idea that we should add a "skipThePlatformThingIDontWant" flag to a brand new feature. We should just not do that in the first place. Authors should opt in for the more magical behavior (moving the focus), not out of the magical behavior.

@domenic

This comment has been minimized.

Copy link
Member

commented Jan 13, 2017

I think it's important for the platform to have good, accessible defaults that match user expectations. @stevefaulkner has one opinion on what those are, and others disagree and think the current focus behavior is the better default, as can be seen from that thread.

Regardless, it sounds like consensus has been lost on this feature, if Blink has transitioned their public position from in-favor to against. I will not invest any more work in it, but if you are willing to work with Mozilla on re-building consensus I'll accept and review a PR for your new version.

@cookiecrook

This comment has been minimized.

Copy link

commented Jan 13, 2017

@domenic wrote:

I'd really encourage everyone to re-read the thread at https://www.w3.org/Bugs/Public/show_bug.cgi?id=23366 before repeating arguments that have been made there.

I spent several hours refreshing myself on our old thread from 2013 and familiarizing myself with this one. I didn't consider those issues resolved at the time. Frankly it seemed that Ian was just being stubborn and patiently waiting us out so he could do what he wanted to do anyway. That's normally an effective negotiation strategy, except he objectively demonstrated he had no idea how screen readers worked.

As I mentioned in the W3C thread, one of the stated goals of WHATWG is to document what the browsers (and through association, assistive technology like screen readers) do today. Any changes should be incubated and adopted by vendors. Ian's goal to change the way screen readers behave with dialogs is technically possible, but it would take years of advocacy with dozens of vendors, most of which are not involved in the W3C or WHATWG. As such, he was guilty of advocacy through spec authoring, which is against the current goals of both W3C and WHATWG. I hope that was apparent. If not, I can clarify more.

Apple was in favor of some form of the first-control behavior as well; see https://www.w3.org/Bugs/Public/show_bug.cgi?id=23366#c22 and subsequent comments.

As the person who was quoted, I should clarify the context. At the time, <dialog> did not receive any focus notifications in any context. It was clear that the API as written would be inaccessible for years to come. We were offering any compromise in the hope that the WHATWG editors would not forego accessibility as a requirement.

Since that time, Steve and others have pointed out the negative consequences that focusing the first control would have on screen reader and mainstream users alike. I acknowledge those points and retract that initial proposal.

I've now come around to the proposal of 1. autofocus if applied. 2. otherwise focus the dialog itself. the <dialog> element should be focusable by default, and I'd add the following

User agent default styles should include:

dialog { outline: none; }

I would not normally recommend hiding focus on a focusable element, but I think the benefits outweigh any potential negatives.

  1. The visual presentation of dialogs generally make clear to most keyboard user that it focused, regardless of whether it has a native focus outline.
  2. No native platform dialogs show the visual outline on dialogs.
  3. Hiding the default outline will prevent some web authors from incorrectly making the dialog non-focusable in order to hide the outline.
  4. It's easy to override the outline in CSS, if the site author wants to use the native focus outline style.
@stevefaulkner

This comment has been minimized.

Copy link
Contributor

commented Jan 14, 2017

@domenic wrote:

@stevefaulkner has one opinion on what those are, and others disagree and think the current focus behavior is the better default, as can be seen from that thread

We appear to have support (apple @cookiecrook , firefox @MarcoZehe , chrome @esprehn, @danbeam ) for making dialog focusable by default unless autofocus is present on a control within the dialog. It would be helpful if the spec editors made the changes to reflect this.

@domenic

This comment has been minimized.

Copy link
Member

commented Jan 14, 2017

I'm concerned with the implementers of this feature in dialog, which are @danbeam and @nt1m. And as I said above,

I will not invest any more work in it, but if you are willing to work with Mozilla on re-building consensus I'll accept and review a PR for your new version.

@stevefaulkner

This comment has been minimized.

Copy link
Contributor

commented Jan 14, 2017

@domenic It is noted you wrote:

If you're interested in changing Chromium in that fashion, I'm happy to change the spec too. Let me know?

So i guess another route is to implement the supported behaviour and then the spec will change as a result. /cc @MarcoZehe

@domenic

This comment has been minimized.

Copy link
Member

commented Jan 14, 2017

Yes, that was before I wrote the sentence that I've now repeated twice.

@minorninth

This comment has been minimized.

Copy link

commented Jan 18, 2017

I'm excited about the growing consensus! Generally I'm very supportive of the idea of making the default to focus on the dialog itself and not the first focusable control, especially since it will be very easy for authors to simply add autofocus to a control they want to focus.

Sorry if I missed it above, but it wasn't clear to me if dialogs should be part of the tab order or not. I think that not makes more sense, but we should clarify a few things:

  1. What happens with non-modal dialogs? As far as I understand, it's perfectly legal to use ... to wrap non-modal dialogs or panes in a web app, and not use dialog.showModal(). What are the consequences of dialog being focusable now?
  2. What should HTMLDialogElement.tabIndex return, 0 or -1? Should dialogs participate in the tab order or not?
  3. The spec currently says that tabIndex shouldn't be used on dialogs. Do we need to change that? Is there any possible reason the author may want to change the tabIndex now?

My initial thought is that dialogs should behave as if tabIndex is -1, so they're focusable but not part of the tab order. Authors may want to use pointer-events: none if they use non-modal dialogs and don't want a mouse click to focus the dialog.

@stevefaulkner

This comment has been minimized.

Copy link
Contributor

commented Jan 19, 2017

@minorninth wrote:

My initial thought is that dialogs should behave as if tabIndex is -1, so they're focusable but not part of the tab order.

I believe that is the general agreement, yes /cc @MarcoZehe @cookiecrook
I think the same goes for non modal dialogs.

@danbeam

This comment has been minimized.

Copy link
Author

commented Jan 19, 2017

@minorninth @stevefaulkner yep, a default tabIndex of -1 for <dialog> made the most sense to me as well if we decide it should be focusable. that's what I ended up at previously.

@samthor

This comment has been minimized.

Copy link

commented Jan 24, 2017

I've had a go at implementing the focus proposal in the polyfill here, if anyone wanted to play around with it (...in Firefox/Safari where dialog is not implemented yet).

Q. Currently, clicking on the dialog backdrop in Chrome's native implementation, focuses the dialog if it has a tabindex. Should clicking the backdrop follow the proposed algorithm too (which occurs on show/showModal)?

@dbbk

This comment has been minimized.

Copy link

commented Oct 9, 2017

It's been almost a year since the last update on this, has there been any progress?

@danbeam

This comment has been minimized.

Copy link
Author

commented Oct 10, 2017

@esprehn and I no longer work on Chrome, so ¯\_(ツ)_/¯

@dpogue

This comment has been minimized.

Copy link

commented Oct 10, 2017

I believe the consensus was focusing the dialog by default, but the PR to add that to the spec has not been merged: w3c/html#773

@chaals

This comment has been minimized.

Copy link

commented May 16, 2018

Ping. Where is this issue at?

@TakayoshiKochi

This comment has been minimized.

Copy link
Member

commented May 16, 2018

I'll handle this case, in the course of fixing #2393 (#2171 is fixed now).

@domenic

This comment has been minimized.

Copy link
Member

commented May 16, 2018

No, we don't have implementer consensus on this change anymore. @danbeam and @esprehn have moved on from working on Chrome, and @nt1m has not worked on dialog in Firefox recently or replied to this thread. (And no other browser implements dialog.) Consensus needs to be rebuilt before this change can be made, otherwise we are just writing fiction that no implementer will follow and for which tests will fail.

@zcorpan zcorpan added the topic: focus label Sep 1, 2018

alice added a commit to alice/html that referenced this issue Jan 8, 2019

Remove anchored positioning of <dialog>s
This was mentioned briefly in the discussion in whatwg#1929. <dialog> only has
one implementation currently, and that implementation is not planning to
implement the anchoring feature, per
https://bugs.chromium.org/p/chromium/issues/detail?id=410346.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.