diff --git a/change/@fluentui-react-12283c65-5330-4f04-9ce2-532900d9be76.json b/change/@fluentui-react-12283c65-5330-4f04-9ce2-532900d9be76.json new file mode 100644 index 0000000000000..71a91954cbca2 --- /dev/null +++ b/change/@fluentui-react-12283c65-5330-4f04-9ce2-532900d9be76.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "fix(ComboBox): fix(react-combobox): Remove _getAriaActiveDescendantValue, compute aria-activedescendantvalue in state, and update currentPendingValue when the options change.", + "packageName": "@fluentui/react", + "email": "esteban.230@hotmail.com", + "dependentChangeType": "patch" +} diff --git a/packages/react/etc/react.api.md b/packages/react/etc/react.api.md index d19d22a1b7d4b..eb40c50e0161f 100644 --- a/packages/react/etc/react.api.md +++ b/packages/react/etc/react.api.md @@ -3942,6 +3942,7 @@ export interface IComboBoxProps extends ISelectableDroppableTextProps ({ ...item, index })); + + // If currentOptions differs from the previous currentOptions we need to update the currentPendingValueValidIndex + // otherwise, it will be out of sync with the currentOptions. This can happen when the options are filtered. + if (!shallowCompare(prevProps.hoisted.currentOptions, currentOptions) && currentPendingValue) { + newCurrentPendingValueValidIndex = + this.props.allowFreeform || this.props.allowFreeInput + ? this._processInputChangeWithFreeform(currentPendingValue) + : this._updateAutocompleteIndexWithoutFreeform(currentPendingValue); + } + + let descendantText = undefined; + + if (isOpen && selectedIndices.length) { + descendantText = options[selectedIndices[0]]?.id ?? this._id + '-list' + selectedIndices[0]; + } else if (isOpen && this._hasFocus() && newCurrentPendingValueValidIndex !== -1) { + descendantText = + options[newCurrentPendingValueValidIndex].id ?? this._id + '-list' + newCurrentPendingValueValidIndex; + } + + if (descendantText !== this.state.ariaActiveDescendantValue) { + this.setState({ + ariaActiveDescendantValue: descendantText, + }); + } } public componentWillUnmount(): void { @@ -579,7 +612,7 @@ class ComboBoxInternal extends React.Component ({ ...item, index: i })) - - .filter( - option => - isNormalOption(option) && !option.disabled && option.text.toLocaleLowerCase().indexOf(updatedValue) === 0, - ); - - // If we found a match, update the state - if (items.length > 0) { - this._setPendingInfo(originalUpdatedValue, items[0].index, getPreviewText(items[0])); - } + const matchingIndex = this._updateAutocompleteIndexWithoutFreeform(updatedValue); // Schedule a timeout to clear the pending value after the timeout span this._autoCompleteTimeout = this._async.setTimeout(() => { this._autoCompleteTimeout = undefined; }, ReadOnlyPendingAutoCompleteTimeout); - return; + + return matchingIndex; } } - // If we get here, either autoComplete is off or we did not find a match with autoComplete on. + // If we get here, autoComplete is off. // Remember we are not allowing freeform, so at this point, if we have a pending valid value index // use that; otherwise use the selectedIndex const index = currentPendingValueValidIndex >= 0 ? currentPendingValueValidIndex : this._getFirstSelectedIndex(); @@ -927,6 +948,30 @@ class ComboBoxInternal extends React.Component ({ ...item, index: i })) + + .filter( + option => + isNormalOption(option) && !option.disabled && option.text.toLocaleLowerCase().indexOf(updatedValue) === 0, + ); + + // If we found a match, update the state + if (items.length > 0) { + this._setPendingInfo(originalUpdatedValue, items[0].index, getPreviewText(items[0])); + return items[0].index; + } + + return -1; } private _getFirstSelectedIndex(): number { @@ -2377,25 +2422,6 @@ class ComboBoxInternal extends React.Component ({ ...item, index })); - let descendantText = - isOpen && selectedIndices?.length - ? options[selectedIndices[0]].id ?? this._id + '-list' + selectedIndices[0] - : undefined; - if (isOpen && this._hasFocus() && currentPendingValueValidIndex !== -1) { - descendantText = options[currentPendingValueValidIndex].id ?? this._id + '-list' + currentPendingValueValidIndex; - } - return descendantText; - } - /** * Get the aria autocomplete value for the combo box * @returns 'inline' if auto-complete automatically dynamic, 'both' if we have a list of possible values to pick from