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

fix: standalone Listbox updates activedescendant correctly #31415

Open
wants to merge 11 commits into
base: master
Choose a base branch
from

Conversation

smhigley
Copy link
Contributor

@smhigley smhigley commented May 17, 2024

Related to #31140 and #31235

Essentially this moves the initial activeDescendantController setting logic from useComboboxBaseState to useListbox, so it runs when the listbox is first renders instead of based on the change in open state.

That both makes combobox/dropdown aria-activedescendant logic a bit more straightforward (the attribute is set if the referenced option exists), and also makes a standalone listbox work.

It also moves a couple option lookup functions to the context, so that Listbox can access them (previously the getOptionById logic in onFocus wasn't working when not a standalone widget, since it didn't have access to the parent combobox's option collection).

Previous Behavior

The original issue was that listbox did not set the initial activedescendant. The first fix to that issue did so on focus, but that caused issues when clicking also set focus (and reset the activedescendant, potentially causing scroll & jumping).

New Behavior

There's no reason Listbox should not always have aria-activedescendant set while it's present on the page, so this change moves the initial activedescendant logic from the combobox (which handled it when opened) to the listbox (which handles it when initially rendered).

There is a very subtle difference between the two, since the Listbox is rendered when the Combobox/Dropdown trigger gains focus, but before it is opened. This causes a minor difference in when aria-activedescendant is set, but does not cause any practical drawbacks to screen reader users. Some early ARIA combobox pattern work was based around the idea that aria-activedescendant would always be set, so screen readers already handle logic on whether to read the activedescendant based on aria-expanded.

@fabricteam
Copy link
Collaborator

fabricteam commented May 17, 2024

📊 Bundle size report

Package & Exports Baseline (minified/GZIP) PR Change
react-combobox
Combobox (including child components)
100.496 kB
33.156 kB
101.45 kB
33.342 kB
954 B
186 B
react-combobox
Dropdown (including child components)
101.129 kB
33.096 kB
102.088 kB
33.285 kB
959 B
189 B
react-timepicker-compat
TimePicker
103.487 kB
34.632 kB
104.444 kB
34.803 kB
957 B
171 B
Unchanged fixtures
Package & Exports Size (minified/GZIP)
react-accordion
Accordion (including children components)
100.003 kB
30.524 kB
react-alert
Alert
78.817 kB
22.543 kB
react-avatar
Avatar
49.299 kB
15.837 kB
react-avatar
AvatarGroup
20.107 kB
7.973 kB
react-avatar
AvatarGroupItem
63.316 kB
20.017 kB
react-breadcrumb
@fluentui/react-breadcrumb - package
114.486 kB
31.821 kB
react-button
Button
37.103 kB
10.784 kB
react-button
CompoundButton
43.514 kB
12.074 kB
react-button
MenuButton
41.884 kB
12.132 kB
react-button
SplitButton
49.896 kB
13.724 kB
react-button
ToggleButton
53.03 kB
12.543 kB
react-card
Card - All
101.184 kB
29.049 kB
react-card
Card
94.218 kB
27.333 kB
react-card
CardFooter
14.354 kB
5.795 kB
react-card
CardHeader
16.618 kB
6.555 kB
react-card
CardPreview
14.418 kB
5.931 kB
react-datepicker-compat
DatePicker Compat
220.038 kB
62.373 kB
react-dialog
Dialog (including children components)
99.303 kB
29.994 kB
react-menu
Menu (including children components)
152.023 kB
45.98 kB
react-menu
Menu (including selectable components)
154.709 kB
46.477 kB
react-message-bar
MessageBar (all components)
24.411 kB
9.114 kB
react-persona
Persona
56.19 kB
17.726 kB
react-popover
Popover
127.766 kB
40.096 kB
react-toast
Toast (including Toaster)
99.625 kB
30.033 kB
🤖 This report was generated against 8820c131f5b6d0509c2781f741b07932f37a4ff5

@fabricteam
Copy link
Collaborator

fabricteam commented May 17, 2024

Perf Analysis (@fluentui/react-components)

No significant results to display.

All results

Scenario Render type Master Ticks PR Ticks Iterations Status
Avatar mount 634 653 5000
Button mount 282 309 5000
Field mount 1139 1144 5000
FluentProvider mount 695 697 5000
FluentProviderWithTheme mount 83 84 10
FluentProviderWithTheme virtual-rerender 36 34 10
FluentProviderWithTheme virtual-rerender-with-unmount 73 76 10
MakeStyles mount 855 850 50000
Persona mount 1745 1696 5000
SpinButton mount 1359 1365 5000
SwatchPicker mount 1489 1540 5000

@@ -0,0 +1,7 @@
{
Copy link
Collaborator

Choose a reason for hiding this comment

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

🕵 fluentuiv9 Open the Visual Regressions report to inspect the affected screenshots

Avatar Converged 2 screenshots
Image Name Diff(in Pixels) Image Type
Avatar Converged.badgeMask.normal.chromium.png 5 Changed
Avatar Converged.badgeMask - RTL.normal.chromium.png 0 Removed

@@ -104,9 +104,12 @@ export function useButtonTriggerSlot(
searchString.current = '';
}, 500);

if (open) {
moveToNextMatchingOptionWithSameCharacterHandling();
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This change is because of the difference in the activedescendant being set when the listbox is rendered, before being opened. The first press of a letter should only open the listbox, and not also move to the second option starting with that letter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants