From 977d06fa8826d491854b6f2a81335daa20418789 Mon Sep 17 00:00:00 2001 From: Sarah Higley Date: Mon, 30 Jan 2023 15:41:48 -0800 Subject: [PATCH 1/9] fix: checkbox/label pattern with role override results in duplicate input and label announcements --- .../react/src/components/Dropdown/Dropdown.base.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/react/src/components/Dropdown/Dropdown.base.tsx b/packages/react/src/components/Dropdown/Dropdown.base.tsx index dc043a9bd0633..20662f48e492e 100644 --- a/packages/react/src/components/Dropdown/Dropdown.base.tsx +++ b/packages/react/src/components/Dropdown/Dropdown.base.tsx @@ -346,7 +346,7 @@ class DropdownInternal extends React.Component 0; @@ -847,13 +847,14 @@ class DropdownInternal extends React.Component ); }; @@ -864,9 +865,13 @@ class DropdownInternal extends React.Component { + private _onRenderItemLabel = (item: IDropdownOption, id: string): JSX.Element | null => { const { onRenderOption = this._onRenderOption } = this.props; - return onRenderOption(item, this._onRenderOption); + return ( + + ); }; private _onPositioned = (positions?: ICalloutPositionedInfo): void => { From 72f507fffe551e78f0cf47b6a90ac7cbcfbc861a Mon Sep 17 00:00:00 2001 From: Sarah Higley Date: Mon, 30 Jan 2023 15:46:10 -0800 Subject: [PATCH 2/9] fix combobox checkbox/label pattern --- packages/react/src/components/ComboBox/ComboBox.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/react/src/components/ComboBox/ComboBox.tsx b/packages/react/src/components/ComboBox/ComboBox.tsx index 03eb5041dd6f8..c2d163d1faa83 100644 --- a/packages/react/src/components/ComboBox/ComboBox.tsx +++ b/packages/react/src/components/ComboBox/ComboBox.tsx @@ -1489,7 +1489,7 @@ class ComboBoxInternal extends React.Component { const { onRenderOption = this._onRenderOptionContent } = this.props; - const id = this._id; + const id = item.id ?? this._id + '-list' + item.index; const isSelected: boolean = this._isOptionSelected(item.index); const isChecked: boolean = this._isOptionChecked(item.index); const isIndeterminate: boolean = this._isOptionIndeterminate(item.index); @@ -1497,12 +1497,16 @@ class ComboBoxInternal extends React.Component onRenderOption(item, this._onRenderOptionContent); + const onRenderCheckboxLabel = () => ( + + ); const getOptionComponent = () => { return !this.props.multiSelect ? ( ) : ( Date: Mon, 30 Jan 2023 15:47:18 -0800 Subject: [PATCH 3/9] change file --- ...luentui-react-89173b86-4f03-440a-93e8-23c4c3569f3b.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 change/@fluentui-react-89173b86-4f03-440a-93e8-23c4c3569f3b.json diff --git a/change/@fluentui-react-89173b86-4f03-440a-93e8-23c4c3569f3b.json b/change/@fluentui-react-89173b86-4f03-440a-93e8-23c4c3569f3b.json new file mode 100644 index 0000000000000..931347c628e03 --- /dev/null +++ b/change/@fluentui-react-89173b86-4f03-440a-93e8-23c4c3569f3b.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "fix: Combobox/Dropdown multiselect checkbox+label pattern with role=option results in duplicate text", + "packageName": "@fluentui/react", + "email": "sarah.higley@microsoft.com", + "dependentChangeType": "patch" +} From 4591967b65b937ce0cd60d954d0f9ce81a39e905 Mon Sep 17 00:00:00 2001 From: Sarah Higley Date: Tue, 31 Jan 2023 09:41:35 -0800 Subject: [PATCH 4/9] update with suggestions --- packages/react/src/components/ComboBox/ComboBox.tsx | 2 +- .../react/src/components/Dropdown/Dropdown.base.tsx | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/react/src/components/ComboBox/ComboBox.tsx b/packages/react/src/components/ComboBox/ComboBox.tsx index c2d163d1faa83..87dce504ad815 100644 --- a/packages/react/src/components/ComboBox/ComboBox.tsx +++ b/packages/react/src/components/ComboBox/ComboBox.tsx @@ -1499,7 +1499,7 @@ class ComboBoxInternal extends React.Component ( ); diff --git a/packages/react/src/components/Dropdown/Dropdown.base.tsx b/packages/react/src/components/Dropdown/Dropdown.base.tsx index 20662f48e492e..c3d8cbbf4dbbc 100644 --- a/packages/react/src/components/Dropdown/Dropdown.base.tsx +++ b/packages/react/src/components/Dropdown/Dropdown.base.tsx @@ -796,6 +796,10 @@ class DropdownInternal extends React.Component ) : ( ); }; From 5b428d82e5795876ef23b66361150220f3e62822 Mon Sep 17 00:00:00 2001 From: Sarah Higley Date: Tue, 31 Jan 2023 14:57:44 -0800 Subject: [PATCH 5/9] update snapshots --- .../__snapshots__/ComboBox.test.tsx.snap | 72 +++++++++------- .../__snapshots__/Dropdown.test.tsx.snap | 84 +++++++++++-------- 2 files changed, 90 insertions(+), 66 deletions(-) diff --git a/packages/react/src/components/ComboBox/__snapshots__/ComboBox.test.tsx.snap b/packages/react/src/components/ComboBox/__snapshots__/ComboBox.test.tsx.snap index 802b78a6b8d3f..acd5e81edaf79 100644 --- a/packages/react/src/components/ComboBox/__snapshots__/ComboBox.test.tsx.snap +++ b/packages/react/src/components/ComboBox/__snapshots__/ComboBox.test.tsx.snap @@ -1641,6 +1641,7 @@ exports[`ComboBox Renders correctly when opened in multi-select mode 1`] = ` } > - + + Option 1 + +
- + + Option 2 + + diff --git a/packages/react/src/components/Dropdown/__snapshots__/Dropdown.test.tsx.snap b/packages/react/src/components/Dropdown/__snapshots__/Dropdown.test.tsx.snap index be458943aaa5e..908835e44e576 100644 --- a/packages/react/src/components/Dropdown/__snapshots__/Dropdown.test.tsx.snap +++ b/packages/react/src/components/Dropdown/__snapshots__/Dropdown.test.tsx.snap @@ -468,6 +468,7 @@ exports[`Dropdown multi-select Renders correctly when open 1`] = ` } > - + + 1 + +
- + + 2 + + From b293b73c5520426a35b7f2e761ca523919eca2e5 Mon Sep 17 00:00:00 2001 From: Sarah Higley Date: Tue, 31 Jan 2023 17:32:03 -0800 Subject: [PATCH 6/9] update implementation to not add extra element --- .../src/components/ComboBox/ComboBox.tsx | 26 ++++++++++++++----- .../src/components/Dropdown/Dropdown.base.tsx | 22 +++++++++++----- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/packages/react/src/components/ComboBox/ComboBox.tsx b/packages/react/src/components/ComboBox/ComboBox.tsx index 87dce504ad815..890c7378665ad 100644 --- a/packages/react/src/components/ComboBox/ComboBox.tsx +++ b/packages/react/src/components/ComboBox/ComboBox.tsx @@ -1487,6 +1487,11 @@ class ComboBoxInternal extends React.Component { const { onRenderOption = this._onRenderOptionContent } = this.props; const id = item.id ?? this._id + '-list' + item.index; @@ -1497,12 +1502,6 @@ class ComboBoxInternal extends React.Component ( - - ); - const getOptionComponent = () => { return !this.props.multiSelect ? ( {item.text}; }; + /* + * Render content of a multiselect item label. + * Text within the label is aria-hidden, to prevent duplicate input/label exposure + */ + private _onRenderMultiselectOptionContent = (item: IComboBoxOption): JSX.Element => { + const optionClassNames = getComboBoxOptionClassNames(this._getCurrentOptionStyles(item)); + return ( + + ); + }; + /** * Click handler for the menu items * to select the item and also close the menu diff --git a/packages/react/src/components/Dropdown/Dropdown.base.tsx b/packages/react/src/components/Dropdown/Dropdown.base.tsx index c3d8cbbf4dbbc..efcdabaf5ac3d 100644 --- a/packages/react/src/components/Dropdown/Dropdown.base.tsx +++ b/packages/react/src/components/Dropdown/Dropdown.base.tsx @@ -851,7 +851,7 @@ class DropdownInternal extends React.Component{item.text}; }; - /** Render custom label for drop down item */ - private _onRenderItemLabel = (item: IDropdownOption, id: string): JSX.Element | null => { - const { onRenderOption = this._onRenderOption } = this.props; + /* + * Render content of a multiselect item label. + * Text within the label is aria-hidden, to prevent duplicate input/label exposure + */ + private _onRenderMultiselectOption = (item: IDropdownOption): JSX.Element => { return ( - + ); }; + /** Render custom label for multiselect checkbox items */ + private _onRenderItemLabel = (item: IDropdownOption, id: string): JSX.Element | null => { + const { onRenderOption = this._onRenderMultiselectOption } = this.props; + return onRenderOption(item, this._onRenderMultiselectOption); + }; + private _onPositioned = (positions?: ICalloutPositionedInfo): void => { if (this._focusZone.current) { // Focusing an element can trigger a reflow. Making this wait until there is an animation From eb6b96c8577d1a62c1fc9857879ae10b8ac120e9 Mon Sep 17 00:00:00 2001 From: Sarah Higley Date: Tue, 31 Jan 2023 19:14:43 -0800 Subject: [PATCH 7/9] update snapshots --- .../src/components/ComboBox/ComboBox.tsx | 2 +- .../__snapshots__/ComboBox.test.tsx.snap | 66 +++++++--------- .../__snapshots__/Dropdown.test.tsx.snap | 78 +++++++++---------- 3 files changed, 67 insertions(+), 79 deletions(-) diff --git a/packages/react/src/components/ComboBox/ComboBox.tsx b/packages/react/src/components/ComboBox/ComboBox.tsx index 890c7378665ad..42a842b9ce4f4 100644 --- a/packages/react/src/components/ComboBox/ComboBox.tsx +++ b/packages/react/src/components/ComboBox/ComboBox.tsx @@ -1487,7 +1487,7 @@ class ComboBoxInternal extends React.Component - + Option 1 +
- + Option 2 + diff --git a/packages/react/src/components/Dropdown/__snapshots__/Dropdown.test.tsx.snap b/packages/react/src/components/Dropdown/__snapshots__/Dropdown.test.tsx.snap index 908835e44e576..94d2ec91a1b40 100644 --- a/packages/react/src/components/Dropdown/__snapshots__/Dropdown.test.tsx.snap +++ b/packages/react/src/components/Dropdown/__snapshots__/Dropdown.test.tsx.snap @@ -582,30 +582,27 @@ exports[`Dropdown multi-select Renders correctly when open 1`] = `  - + 1 +
- + 2 + From 75b1899fe6ea0fafbc493a3446b47994d349bda9 Mon Sep 17 00:00:00 2001 From: Sarah Higley Date: Tue, 31 Jan 2023 19:53:44 -0800 Subject: [PATCH 8/9] default dropdown to using item.id --- packages/react/src/components/Dropdown/Dropdown.base.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react/src/components/Dropdown/Dropdown.base.tsx b/packages/react/src/components/Dropdown/Dropdown.base.tsx index efcdabaf5ac3d..84e08ce47fcd3 100644 --- a/packages/react/src/components/Dropdown/Dropdown.base.tsx +++ b/packages/react/src/components/Dropdown/Dropdown.base.tsx @@ -798,7 +798,7 @@ class DropdownInternal extends React.Component Date: Wed, 1 Feb 2023 15:39:39 -0800 Subject: [PATCH 9/9] Apply suggestions from code review Co-authored-by: Ben Howell <48106640+behowell@users.noreply.github.com> --- packages/react/src/components/Dropdown/Dropdown.base.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react/src/components/Dropdown/Dropdown.base.tsx b/packages/react/src/components/Dropdown/Dropdown.base.tsx index 84e08ce47fcd3..b8f387f623b59 100644 --- a/packages/react/src/components/Dropdown/Dropdown.base.tsx +++ b/packages/react/src/components/Dropdown/Dropdown.base.tsx @@ -798,7 +798,7 @@ class DropdownInternal extends React.Component { + private _onRenderItemLabel = (item: IDropdownOption): JSX.Element | null => { const { onRenderOption = this._onRenderMultiselectOption } = this.props; return onRenderOption(item, this._onRenderMultiselectOption); };