Skip to content

Commit

Permalink
Fixed scrollIntoView in Combobox and Dropdown (#17074)
Browse files Browse the repository at this point in the history
* fix: fixed scrollIntoView

* fix: fixed code to use onHighlightedIndexChange

* fix: fixed const name

* test: fixed tests
  • Loading branch information
guidari authored Aug 1, 2024
1 parent d6b01b7 commit f22da5a
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 27 deletions.
2 changes: 1 addition & 1 deletion packages/react/src/components/ComboBox/ComboBox-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const prefix = 'cds';

describe('ComboBox', () => {
let mockProps;

window.HTMLElement.prototype.scrollIntoView = function () {};
beforeEach(() => {
mockProps = {
id: 'test-combobox',
Expand Down
17 changes: 15 additions & 2 deletions packages/react/src/components/ComboBox/ComboBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ const ComboBox = forwardRef(
(state, actionAndChanges) => {
const { type, changes } = actionAndChanges;
const { highlightedIndex } = changes;

switch (type) {
case InputBlur:
if (
Expand Down Expand Up @@ -607,11 +608,23 @@ const ComboBox = forwardRef(
setInputValue(inputValue || '');
setHighlightedIndex(indexToHighlight(inputValue));
},

onSelectedItemChange({ selectedItem }) {
onChange({ selectedItem });
},

onHighlightedIndexChange: ({ highlightedIndex }) => {
if (highlightedIndex! > -1 && typeof window !== undefined) {
const itemArray = document.querySelectorAll(
`li.${prefix}--list-box__menu-item[role="option"]`
);
const highlightedItem = itemArray[highlightedIndex!];
if (highlightedItem) {
highlightedItem.scrollIntoView({
behavior: 'smooth',
block: 'nearest',
});
}
}
},
initialSelectedItem: initialSelectedItem,
inputId: id,
stateReducer,
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/components/Dropdown/Dropdown-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ describe('Dropdown', () => {
});

describe('Component API', () => {
window.HTMLElement.prototype.scrollIntoView = function () {};
it('should accept a `ref` for the underlying button element', async () => {
const ref = React.createRef();
render(<Dropdown {...mockProps} ref={ref} />);
Expand Down
9 changes: 9 additions & 0 deletions packages/react/src/components/Dropdown/Dropdown.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,15 @@ const items = [
{
text: 'Option 5',
},
{
text: 'Option 6',
},
{
text: 'Option 7',
},
{
text: 'Option 8',
},
];

export const ExperimentalAutoAlign = () => (
Expand Down
42 changes: 19 additions & 23 deletions packages/react/src/components/Dropdown/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,10 @@ import {
size as floatingSize,
} from '@floating-ui/react';

const {
ToggleButtonKeyDownArrowDown,
ToggleButtonKeyDownArrowUp,
ToggleButtonKeyDownHome,
ToggleButtonKeyDownEnd,
ItemMouseMove,
MenuMouseLeave,
} = useSelect.stateChangeTypes as UseSelectInterface['stateChangeTypes'] & {
ToggleButtonClick: UseSelectStateChangeTypes.ToggleButtonClick;
};
const { ItemMouseMove, MenuMouseLeave } =
useSelect.stateChangeTypes as UseSelectInterface['stateChangeTypes'] & {
ToggleButtonClick: UseSelectStateChangeTypes.ToggleButtonClick;
};

const defaultItemToString = <ItemType,>(item?: ItemType | null): string => {
if (typeof item === 'string') {
Expand Down Expand Up @@ -326,25 +320,27 @@ const Dropdown = React.forwardRef(
const isObject = item !== null && typeof item === 'object';
return isObject && 'disabled' in item && item.disabled === true;
},
onHighlightedIndexChange: ({ highlightedIndex }) => {
if (highlightedIndex! > -1 && typeof window !== undefined) {
const itemArray = document.querySelectorAll(
`li.${prefix}--list-box__menu-item[role="option"]`
);
const highlightedItem = itemArray[highlightedIndex!];
if (highlightedItem) {
highlightedItem.scrollIntoView({
behavior: 'smooth',
block: 'nearest',
});
}
}
},
};
const dropdownInstanceId = useId();

function stateReducer(state, actionAndChanges) {
const { changes, props, type } = actionAndChanges;
const { highlightedIndex } = changes;
const { changes, type } = actionAndChanges;

switch (type) {
case ToggleButtonKeyDownArrowDown:
case ToggleButtonKeyDownArrowUp:
case ToggleButtonKeyDownHome:
case ToggleButtonKeyDownEnd:
if (highlightedIndex > -1) {
const itemArray = document.querySelectorAll(
`li.${prefix}--list-box__menu-item[role="option"]`
);
props.scrollIntoView(itemArray[highlightedIndex]);
}
return changes;
case ItemMouseMove:
case MenuMouseLeave:
return { ...changes, highlightedIndex: state.highlightedIndex };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const openMenu = async () => {

describe('FluidComboBox', () => {
let mockProps;

window.HTMLElement.prototype.scrollIntoView = function () {};
beforeEach(() => {
mockProps = {
id: 'test-fluidcombobox',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ describe('FluidDropdown', () => {
});

describe('Component API', () => {
window.HTMLElement.prototype.scrollIntoView = function () {};
it('should accept a `ref` for the underlying button element', async () => {
const ref = React.createRef();
render(<FluidDropdown {...mockProps} ref={ref} />);
Expand Down

0 comments on commit f22da5a

Please sign in to comment.