@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
<dialog>
<div tabindex="-1">
i don't wish to participate in the tab order,
but am focused when showModal() is called
</div>
</dialog>
<dialog>
<button tabindex="-1">
i get focused on showModal() even with a negative tabindex
</button>
</dialog>
<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
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?
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.
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?
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
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:
<div tabindex="-1"> and to <button>show dialog</button><button>show dialog</button>, a dialog should show (in Chrome)<div tabindex="-1"> cannot be focused, similarly to the <div tabindex="-1"> outside of the <dialog><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.
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.
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).
If you're interested in changing Chromium in that fashion, I'm happy to change the spec too. Let me know?
I'm hacking around in Blink, but have some questions:
<dialog> that we're calling show() or showModal() on receive focus events?<body> does when initially focused<dialog> should be focusable by default?document.activeElement should be the top-level <dialog> while 1+ <dialog>s are showing?In my opinion,
focus event.<display>.tabIndex = -1 when it is not on the top-level, and <display>.tabIndex = 0 when it is.document.activeElement can only point to at most one element in a document.@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.
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:
[autofocus] should be respected<dialog> should get focused when focusable (i.e. <dialog tabindex="0">)What I'm not sure makes sense is:
<a>) inside a <dialog> should be focused initially<dialog> and what it brings to the web. I see a few possibilities: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.
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:
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?
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.
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 :).
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?
Perhaps we can kill two birds with one stone, by using the
DialogShowParamsproposed 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.
@domenic You asked for use cases.
We're targeting an action menu (code).


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).
@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...
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.
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.
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).
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.
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
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.
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.
Yes, we would definitely use an options object. I don't think anyone was proposing otherwise.
Hmm. We want to focus the dialog itself if it's focusable, right?
I think it'd be really confusing to disable only part of the focusing steps. Which ones would you keep? Would you ignore or respect:
[autofocus] on form controls<button>, <input>, <select>)[tabindex] customizers<dialog tabindex=0>with this "ignore some part of focus steps" flag present?
I can't really think of a _super_ simple way of explaining this to users. But if you've got a preferred subset of these actions and an epicly explanatory flag name up your sleeve, I'm all ears.
My opinion: we run the default steps, which basically try all possible routes for a useful initial focus, or none at all. This allows advanced users the ability to set (or not set) initial focus themselves.
We might also want to suggest that dialog elements be focusable areas by default.
This is still fairly easy to accomplish via <dialog tabindex=0> (or -1, as we've found 😉 ), but I could probably make <dialog> focusable by default if you'd like.
I think it'd be really confusing to disable only part of the focusing steps.
I don't think of it that way. Instead we just wouldn't run the usual dialog focus steps, and would run a single focus step: focus the dialog. Of course, this only works if we make dialogs focusable, which was the second part of my question. This is why my proposed flag name was focusDialog: true.
Focusing nothing works too though, if you don't think the above makes sense.
I don't think focusDialog is particularly clear in this context, because it's not clear that it's talking about only the <dialog> and not its contents.
<dialog> or its contents currently gets focused by default in many cases.
Compared to just calling show() or showModal() with no params, adding focusDialog: true sounds like it'll run more focusing steps (to me). Specifying focusDialog: false sounds like nothing will be focused.
OK. Maybe it's simpler to go with a switch that turns off all focusing behavior. skipFocusing: true?
I'll work on a PR in that case.
skipFocusing is a tad vague. Does it mean focusing is disabled for the whole dialog, forever, or what?
Anything wrong with skipInitialFocus ?
skipInitialFocus is fine by me, pretty sure i previously prototyped with that name.
@danbeam thanks for the ping, belatedly responding. default focus on a control when a dialog is displayed is poor UX and AX in cases where the dialog contains more than a short message and an OK button. Why? An example http://codepen.io/stevef/pen/ZBgNjg in cases where the focus on display moves to a control at the bottom of the dialog a few negative things happen:
Compare this with an example of the 'about' native (XUL) dialog in Firefox, when the dialog is opened, the dialog itself recieves focus; for the magnifier user the top left of the dialog is in the viewport, the focus rectangle (if set by the user), is visible around the dialog content. For the SR user as the focus is set on the dialog itslef rather than a control, the SR auto reads the content of the dialog from the start.
I suggest that instead of implementing a flag to override default focus on a control, change the spec so the dialog is focusable by default. A demo of this is here: http://s.codepen.io/stevef/debug/ZBgNjg achieved by using .focus() and tabindex="-1" and not having any focusable elements inside the dialog. By doing as suggested, the default behaviour will be the most UX/AX friendly. Rather than having developers jump through hoops to make it so.
That does seem like a pretty reasonable simplification and gives the author control over which widget to focus. The existing behavior where we crawl the DOM looking for the first thing to focus feels brittle to me, and I worry this is another thing to remember for developers: "Make sure to always pass skipInitialFocus when using <dialog>".
@domenic @danbeam Can we change it to do that?
@esprehn this is an argument with a long history; it'd be ideal to read through most of https://www.w3.org/Bugs/Public/show_bug.cgi?id=23366 before reopening it. (The argument for the current behavior is that it's more like how native dialogs behave.) I'm hesitant to try to rebuild consensus around @stevefaulkner's new proposal, especially given how it was rejected in the past (including by Blink implementers, see Blink's last comment in the mega-thread at https://www.w3.org/Bugs/Public/show_bug.cgi?id=23366#c34). 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.
On 6 January 2017 at 23:16, Domenic Denicola notifications@github.com
wrote:
especially given how it was rejected in the past
It was argued for by firefox and webkit implementers.
We now have a proposal to add extra complexity via skipInitialFocus to
overcome the limitations of the current design defined in the spec. My
suggestion removes the need for additional complexity by making the default
implementation work out of the box for users and web developers.
--
Regards
SteveF
Current Standards Work @W3C
http://www.paciellogroup.com/blog/2015/03/current-standards-work-at-w3c/
(The argument for the current behavior is that it's more like how native dialogs behave.) I'm hesitant to try to rebuild consensus around @stevefaulkner's new proposal
I would like to understand what the practical negative outcomes of my suggestion would be for users, web developers or implementers. Can you elaborate?
I don't pretend to know everybody's use cases or expectations for <dialog>.
I have no idea whether:
<dialog> (or the dialog itself) to be focused when shownfocus() right after show()/showModal()As I've already mentioned, I think expectations or paradigms associated with dialogs are unclear because of their long history and platform-specific differences.
I think it's a better use of time to crack this composite behavior open into composable parts to allow it to be configured to others' needs. There's a bunch of ways to do that.
This thread came up with DialogShowParams, which I implemented here:
https://codereview.chromium.org/2560553002/
And proposed here:
https://groups.google.com/a/chromium.org/d/msg/blink-dev/Tanq8NVTar0/jv27dxakEgAJ
https://groups.google.com/a/chromium.org/d/msg/blink-dev/PHwXLbOkH5M/0uFGZ7rBEwAJ
It's received mixed support from Blink folks (positive: @rbyers, @chrishtr, concern: @esprehn, @minorninth), positive from other Chrome folks (@freshp86, me), and generally positive from Mozilla (@smaug----, @nt1m).
If we can't agree to configure, I guess I'm on board with @stevefaulkner's proposal _because_ it suits the needs of my specific UI (which might ship before this gets solved at the current rate). I also agree that focus resembles scroll for screen readers users, and that moving focus to the middle of something is jarring (which the current behavior promotes).
I would also like to add my support for @stevefaulkner's and @danbeam's proposal to make the dialog focusable by default, simplifying the spec that way, instead of adding even more complexity to it. Why? Because as @danbeam mentions above, native dialogs already work differently on different platforms. On Windows, the paradigm has shifted in recent versions to be more like what is proposed now, since Microsoft seems to have recognized that their own dialogs have grown in complexity from the Windows 95 days, and accessibility needs to take this into account. On Mac, especially with VoiceOver on, focus largely depends on VoiceOver's point of focus anyway, and MacOS dialogs are equally more complex than simple "message + OK button" things. Moreover, speaking strictly as a screen reader user, speech is a very sequential medium. Being able to read a dialog top to bottom, especially when it gives me information and asks me a question or wants me to agree on something, is far more intuitive than having to skip up from the bottom (focusable element inside the dialog), which goes against the sequential nature of speech. Steve already mentioned magnification users. So there are a lot of user-centric arguments for simplifying the spec and making the <dialog> element focusable by default.
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 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.
@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.
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.
@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.
@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.
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.
@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
Yes, that was before I wrote the sentence that I've now repeated twice.
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:
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.
@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.
@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.
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)?
It's been almost a year since the last update on this, has there been any progress?
@esprehn and I no longer work on Chrome, so ¯\_(ツ)_/¯
I believe the consensus was focusing the dialog by default, but the PR to add that to the spec has not been merged: https://github.com/w3c/html/issues/773
Ping. Where is this issue at?
I'll handle this case, in the course of fixing #2393 (#2171 is fixed now).
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.
Most helpful comment
@domenic wrote:
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.
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 followingUser agent default styles should include:
I would not normally recommend hiding focus on a focusable element, but I think the benefits outweigh any potential negatives.