Are you willing to submit a PR to fix? Yes
Requested priority: Normal
Products/sites affected: Yammer
Starting in 6.25.1, the behavior of a Dropdown with a placeholder has changed. Previously clicking to open it would not change the value, now it does.
The first value is selected.
The placeholder continues to show.
Hi @chrismohr, this was a by-design change, following W3C Accessibility guidelines for good screen reader experience. What is your scenario that is adversely impacted by this change? Perhaps we can augment some of the methods (e.g onChange) to differentiate between when the Dropdown auto selected an option from a placeholder or if it was a user action.
@cliffkoh, in any scenario where completion of the dropdown is optional, it is currently not possible for a keyboard navigation user to tab over the field without selecting a value. It also seems like a negative experience for mouse users who want to click to reveal the available options, but then decide they want to leave the field blank.
I'd be interested to hear more details about the accessibility guidelines that you were meeting with this change, also if you have more specific suggestions for a solution, I can submit an updated PR that meets all of our requirements here.
I edited the title of the issue to say 'focus' rather than 'click'.
Hi @cliffkoh - can you outline the original issue that was fixed here, and which specific WCAG item is being addressed? Generally speaking, focusing a control should not change the input value - this is to allow both keyboard and screenreader users to tab past the control to other controls without affecting it. I'm wondering if in the process of fixing some other issue, this regression was introduced?
As Chris outlines above, as a keyboard or screenreader user, if I tab through this control, it will have the side effect of picking the first value, which IMO should only take place if I select that value intentionally. That's not particularly user-friendly. Imagine if hovering the mouse over the control automatically selected the first value - that's somewhat analogous to what we're doing here.
I'm noticing that the people picker control also has a bug in this area - I'll open a separate issue on that.
So, the W3C accessibility spec recommends, but does not require selecting an option when it gets focus. The problem is that Fabric's Dropdown behaves like an opened Dropdown even when it is closed and in placeholder, in that you can press the arrow keys up and down to change the option. So as such, the Dropdown needs to specify via the aria-size
and aria-posInSet
attributes to inform the screen reader that despite there only being 1 element in the DOM, it is actually one option out of a larger set of options.
If the first option is not selected on the other hand, I do not know how to communicate organically (without hardcoding a non-localizable string in Fabric) that you can use the arrow keys to change the selected options - or the total number of selectable options.
Welcome suggestions/PRs where we get the best of both worlds :)
Issue re the people picker control - that one is a bit more severe, as tabbing through can end up selecting additional items each time the user passes through.
https://github.com/OfficeDev/office-ui-fabric-react/issues/5915
So, the W3C accessibility spec recommends, but does not require selecting an option when it gets focus
Can you point me towards this specific item?
the W3C accessibility spec recommends, but does not require selecting an option when it gets focus
FWIW, I'm aware of a suggestion for popup menus for the first item to receive focus when the menu is opened via keyboard; but that's expected since opening is triggered by an explicit user interaction. Focusing would not be expected to trigger this, though.
The problem is that Fabric's Dropdown behaves like an opened Dropdown even when it is closed
So it's sounding like a Fabric internals / implementation issue means that fixing one issue (at least this way) ends up introducing another as an unwanted side-effect, so is not actually by-design? (By design suggests that this is the intended/desired behavior here.)
https://www.w3.org/TR/wai-aria-practices-1.1/#listbox_kbd_interaction
Specifically
When a single-select listbox receives focus:
- If none of the options are selected before the listbox receives focus, the first option receives focus. Optionally, the first option may be automatically selected.
- If an option is selected before the listbox receives focus, focus is set on the selected option.
So I actually mis-spoke. Because the Fabric Dropdown behaves as a Dropdown even when collapsed (you can use the arrow keys to switch between options), focusing on the first option MEANS that the first option gets selected - there is no way to drop focus on the first option otherwise (the first option if not selected is not even rendered in DOM).
In other words, the current exhibited behavior is a requirement of the spec and not just a recommendation...
the current exhibited behavior is a requirement of the spec
I'm going to disagree with this. It is (a) a suggestion of the spec, but (b) that spec item applies to listboxes. This is not - from the end-user's POV - a listbox. It's a dropdown control.
It's seems to me that this behavior is still somehow the results of other internal details within Fabric, and not something that's required by WC3 spec, nor something expected by a keyboard user.
Having said all that though; I'm not quite sure how big a deal this specific issue is. I'd describe it as 'quirky' or slightly confusing rather than being inaccessible. Key issue though would be whether this control would be used in a scenario where a mouse user could leave it unselected to effect some behavior, but a keyboard user would not be able to do similar, as focusing it would always trigger a selection. That would probably be an inappropriate use of this control, though.
To a blind user/to all the screen readers, this is ultimately a component that behaves (and quacks and looks 馃檪) like a listbox when in single-selection mode and when collapsed. There is no concept of a "Dropdown" from a screen reader's POV.
The "internal detail" you speak of is a capability of the Dropdown where we allow pressing of arrow keys to change the selected option (because of that, so much extra work was needed to make sure we read out the new selected option). Would you argue that that is not a capability you expect of a Dropdown? We could of course always just remove that capability and that certainly is one way to be spec-compliant whilst preserving the placeholder - but we regress everyone who relies or expects that capability.
At the end of the day, I don't disagree that the placeholder being changed on focus is not a great UX for where the Dropdown is intended to be optional, but we kind of _have_ to do this (unless someone knows a better way to implement this). The screen reader experience in Chris's PR is for instance, immediately broken (it's not just quirky, it is incorrect - I don't just mean that we do not set focus on the first option, I mean that what is read by the screen reader is incorrect).
Here's a suggestion though: perhaps add in another checkbox before the Dropdown which enables/disables the Dropdown. If the user does not intend to fill in the optional field for the Dropdown, he does not check the checkbox, and vice versa.
Also tagging various accessibility champions from different teams (@philipzloh @cschlechty @jspurlin) in case they have something to add.
@chrismohr @BrendanMcK Here's an idea.. perhaps the Dropdown can have a mode where placeholder does not change when it gets focus (By default it isn't in this mode - it is an opt in). However, when it is in this mode, you can no longer press up/down to switch options. All the aria attributes would also change accordingly (e.g. will have aria-collapsed
but no aria-size
).
in any scenario where completion of the dropdown is optional, it is currently not possible for a keyboard navigation user to tab over the field without selecting a value. It also seems like a negative experience for mouse users who want to click to reveal the available options, but then decide they want to leave the field blank.
IMO this is using the correct component but approaching it from the wrong angle. "Decide they want to leave field blank" isn't something that is _only_ possibly done at the start. After already having selected an option, a user may "decide they want to leave the field blank". Then what? We need to build controls that are both standards-conformant and resilient to usage. Strong recommendation against the "leave this blank if you don't want to use it" thinking.
The safest (and conformant) way to do this is to provide an option called None that the user would know to mean "oh just kidding I don't want any of the provided options".
To a blind user/to all the screen readers [...]
But a sighted keyboard user has an inconsistent experience, since the keyboard model is that of a listbox, but the visuals are those of a dropdown.
So perhaps the underling issue here is Fabric deciding to model this as a listbox? Which may well be the right decision overall given other requirements. There maybe no good fix here; and from sighted keyboard user's pov, it's perhaps unexpected behavior, but not major.
While I wasn't involved in much of the development of the Dropdown component, I would venture to say that Fabric did not start out "modelling it after a listbox". In the W3C reference implementation of a single select listbox, you can not even use the arrow keys to change options when the listbox is collapsed (unlike the built in HTML <select>
). Instead, the net result of the Dropdown through all that development history is that it now has this capability, and in order to ensure that the component is accessible, we have to do what we have done.
I do think a middle ground exists in that we can make this contentious behavior (including the ability to use the arrow keys to change options while the Dropdown is collapsed) opt-in/opt-out. It would definitely add even more to the complexity in getting the accessibility right, but this might be the compromise we're looking for.
Thanks @cliffkoh, @BrendanMcK and @philipzloh for your insights. I'm relatively new to this area, and your thoughtful responses are helping me get up to speed.
I've beeing chewing on your replies and the W3C specs today, and heres where I'm at:
@philipzloh I agree that providing an option named "none", would likely be more resilient to usage, as the user would be able to select it even after selecting a value. I can't think of any strong arguments against this, just that it might be a bit aesthetically displeasing.
@cliffkoh I'm intrigued by the suggestion of introducing a new mode for this control. As you stated a couple of times, most of the challenge here is supporting the mode where we allow arrow keys to change options while the Dropdown is collapsed. (Maybe we can call this "quick change mode"?) I think it might be interesting to allow disabling this mode, and having the control behave more like a regular html select box, where the first press of up/down would reveal the options, and the second would move the focus, and then selection would be achieved with space/enter.
I'm also interested to hear if you know more about why quick change mode exists? Why was it built? Who relies on or expects this capability? How do they rely on it? I've gone through many other web component libraries today, and have yet to find another dropdown/select component that works like this. Any chance that this complexity/cost could be reduced by deprecating/eliminating this mode?
@chrismohr Thanks for your thoughtful reply. It seems you have a developed a good grasp of the factors at play here 馃檪 Unfortunately I do not personally know the history or context of it but we can probably find out who precisely added this in which PR if one digs through the file's history.
Regarding your comment on taking out quick change mode entirely, let me tag @JasonGore who is Fabric's primary SHIELD this week who can help drive us through the process to figure that out.
@chrismohr for point 3, have you tried all the other component libraries with a screen reader (Narrator on Edge)? 馃榿 Agree with you that there is no guidance for the kind of Dropdown we have, but it turns out that being standards compliant here results in a good experience for the visually impaired... (again also agree with you here that it is not without _some_ compromises - and that's really more because we support "quick change" rather than because we have a placeholder)
I haven't yet dug in too deep on the screen reader side of things. I'm on a mac, and did a bit with voice-over, and I think I see now how my PR could be seen to have a negative impact, but I don't yet have a strong grasp on the aria tags at play, and didn't evaluate how standards compliant the various libraries I looked at today are.
Also, I don't want to go around in circles, but when you assert that this is a good experience for the visually impaired, are you factoring in that they are also likely navigating with keyboard, and are most likely to be surprised by changing values as a result of them tabbing over a field? This seems like a big deal to me, but maybe I'm just having trouble letting go of the notion that a dropdown can be left blank?
Hi Chris, I guess you haven't tried it out yourself but here's a screen capture of the experience from above:
The visually impaired will indeed be primarily navigating via keyboard and as you can see above, every single interaction is via keyboard.
Right, I guess where we differ is that I see not being able to tab over a field without changing its value as a bad experience, but I'm hearing you characterize the overall experience as good. So I'm guessing that's because you don't value that as a capability, which is fair, given @philipzloh's point above.
Where I'm coming from, even though the selection is verbalized, I'm speculating that this would be surprising and undesirable to users, since it seems to diverge with how many dropdown/select components on the web behave.
Not trying to change any minds here, just trying to summarize where we're at.
Just to be clear, I completely agree with you that it is more intuitive (maybe much more) for people without disabilities if options do not change when it gets focus. That is how most Dropdown-like components work, or how I would intuitively expect it to work.
W.r.t. characterizing the experience as good, note that this is only as it pertains to the screen-reader experience for the visually impaired. As I have said above, as long as we have quick change, we will have to compromise one way or the other (either the auto selection from placeholder being potentially surprising for a person without visual impairment, or the component experience being completely broken for those with a visual impairment). Therefore, my suggestion to opt in to disable quick change mode entirely, thus enabling the best of both worlds.
(We could also just remove quick change entirely, or deprecate it, make it opt-in instead of the default - but this change has a much bigger impact that a somewhat larger discussion needs to be tabled around it - and this is what @JasonGore is helping to figure out).
@chrismohr BTW, I double-clicked into your assert above that the HTML <select>
does not allow quick change (that was surprising to me when I heard it). Upon further investigation, I have confirmed that both the Edge and Chrome <select>
offers the quick change capability. Only Safari's <select>
does not...
I imagine that it would be very unlikely that the proposal to remove quick change entirely would pass muster at Fabric Design. The best we can do here is where we allow an opt-in to a mode where quick change is disabled and therefore placeholder does not need to switch.
is this going to be fixed? or putting a props for disabling or enabling the auto selection of the first item?
Is this issue fixed?If not please provide any alternative solution.It will be helpful for us.
I'm diving back into this issue and trying to catch up with a long discussion.
Looking at the default <select>
behavior (which we are trying to model for all users), it automatically selects the first item in the list. There isn't a way to display a blank select.
One suggestion from stackoverflow is to disable and hide the first item, and use the first item as the display text.
This is something you could manually do today, right? Maybe this is the way we can move in the future? Make the placeholder the first, hidden item in the list, and make that the default selected item. This will allow us to provide an accesible experience while maintaining our desired functionality.
proposal:
Set 1st item of dropdown as placholder, disabled, selected, hidden. This way, nothing changes on focus, and dropdown only contains your items.
Described, it looks wrong. Using it, the behavior seems right. I would double check with James Jackson on this as well.
Make the placeholder the first, hidden item in the list, and make that the default selected item. This will allow us to provide an accesible experience while maintaining our desired functionality.
This is insufficient if you want to unselect everything. If you accidentally made a choice but no longer want to make any choice.
What I ended up doing is setting the very first element as placeholder - I know this is not good at all but no choice, I don't want to touch core code so everytime I update npm packages
I lose the stuff.
please fix this - like seriously this is a common sense to not choose an option on behalf of user.
I don't know, how this is misinterpreted during designing this framework
This is true. @micahgodbolt, we should look into this.
@javahemans Have you read the thread above carefully which explains the current behavior? The current behavior is standards compliant with https://www.w3.org/TR/wai-aria-practices-1.1/#listbox_kbd_interaction
I don't think native selects automatically fire an onChanged
event when select is opened. It does however happen with this version.
Just to provide a summary of the possible Feature work to alleviate this concern:
Option 1: Make the placeholder a selectable option
This will address both the spec conformance and accessibility concerns.
Option 2: Have an alternative mode for Dropdown where the Up/Down arrow keys always open the listbox of options (like what <select>
does on Mac OS), as opposed to just change it directly (like what <select>
does on Windows).
This way, the unexpanded single select Dropdown does not need to have role="listbox" and does not need to "set focus" on the first option (thereby selecting the first option as well).
Either options are potentially breaking changes and should be an explicit opt-in.
I have a workaround for it for those that are interested:
https://codepen.io/aamirj/pen/NoyRMz. Essentially, I have add a hidden option as the very first item in the dropdown.
Found this frustrating after upgrading my package to the latest version, suddenly all my Dropdowns were automatically triggering onChange on focus, which in my opinion is unexpected behavior especially in situations where you are doing something (like getting data from the server, or hiding / showing UI based on the option selected).
At the very least there should be a way to opt out of this behavior via a prop?
@Rocky-Moon Sorry to hear that. :( It is one of those catch-22 where the prior behavior really annoyed people who really care about or depend on accessibility, and the present behavior annoys people who were explicitly depending on the Dropdown to not do what it has to do (and who doesn't see standards compliance and accessibility as being as much of a priority).
The team is looking to rewrite Dropdown and ComboBox and will look to address this during that rewrite.. (most likely make the Dropdown behave more like a Combobox, just without the editing capability, and hence take on role=combobox
which has a different accessibility spec). Hence the feature work above for either of the two options is presently not something we'll take on. Pull requests are welcome however...
cc @micahgodbolt @dzearing @ecraig12345 @jdhuntington
Thanks for the response Cliff, totally understand - you're damned if you do and damned if you don't :)
Would be great to see this resolved. This is a hot fire mess for cascading dropdowns with API calls.
@joschect can you please fix? I agree that it's the wrong behavior. It should behave like this:
Any update on this issue ?
The spec linked through the thread is actually for keyboard interaction and states:
When a single-select listbox receives focus:
If none of the options are selected before the listbox receives focus, the first option receives focus. Optionally, the first option may be automatically selected.
but also states:
DOM focus (the active element) is functionally distinct from the selected state. For more details, see this description of differences between focus and selection.
So it makes no sense to select the first item and trigger the onChange event when focusing the dropown with the mouse. And it is debatable if this behavior should be there if focused with the keyboard.
Seems like bad UX to make decisions for the user interacting with the input.
The distinction here is that the role="listbox" is on the top-level single select dropdown (when collapsed). There is no way to focus on the first element without also selecting it :)
I greatly welcome an expansion on how you would achieve this separation of focus and selection in this scenario :) If there is such a way, we should definitely try to have someone get a PR to implement this.
With regards to an update on when a comprehensive fix (i.e. rework) for the problem will take place, an engineer (@joschect) has been assigned but the engineer has not been able to start on the work yet due to having other work items taking precedence in his priority queue so far. I'll let @joschect speak to how close he is to being able to start on the comprehensive fix.
Since it looks like the rewrite will not take place in Fabric v7 lifecycle, we have taken a stab at providing minimally a partial fix for this problem with #10755. Now, the Dropdown will only select the first option (and trigger onChange) ONLY if focus was landed on the Dropdown through keyboard events (e.g. tab navigation) to continue to confirm to W3C aria specs for listbox
.
For a sighted user using a mouse, we will retain the placeholder selection until the user makes an explicit selection.
:tada:This issue was addressed in #10755, which has now been successfully released as [email protected]
.:tada:
Handy links:
Most helpful comment
What I ended up doing is setting the very first element as placeholder - I know this is not good at all but no choice, I don't want to touch core code so everytime I update
npm packages
I lose the stuff.please fix this - like seriously this is a common sense to not choose an option on behalf of user.
I don't know, how this is misinterpreted during designing this framework