Skip to content

Commit

Permalink
chore(combobox): fix highlighted index bug
Browse files Browse the repository at this point in the history
  • Loading branch information
andioneto committed Oct 11, 2021
1 parent fa6b019 commit 01c278c
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 25 deletions.
30 changes: 17 additions & 13 deletions packages/paste-core/components/combobox/src/Combobox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ const Combobox = React.forwardRef<HTMLInputElement, ComboboxProps>(

// Only virtualize non-grouped items
// Not virtualizing grouped items because we cannot accessibly define position within nested sets (e.g. "groups")
const rowVirtualizer = useVirtual({
const {scrollToIndex, virtualItems, totalSize} = useVirtual({
size: items.length,
parentRef,
// 36 is a magic number that represents the comboboxItem height in px
Expand All @@ -82,16 +82,14 @@ const Combobox = React.forwardRef<HTMLInputElement, ComboboxProps>(
const defaultState = useComboboxPrimitive({
initialSelectedItem,
items,
onHighlightedIndexChange: (changes: UseComboboxPrimitiveStateChange<string>) => {
const currentHighlight = defaultState.highlightedIndex ?? 0;
const newHighlight = changes.highlightedIndex ?? currentHighlight;
if (rowVirtualizer) {
rowVirtualizer.scrollToIndex(newHighlight);
}
if (onHighlightedIndexChange) {
onHighlightedIndexChange(changes);
}
},
onHighlightedIndexChange: React.useCallback(
(changes: UseComboboxPrimitiveStateChange<string>) => {
if (onHighlightedIndexChange) {
onHighlightedIndexChange(changes);
}
},
[onHighlightedIndexChange]
),
onInputValueChange,
onIsOpenChange,
onSelectedItemChange,
Expand All @@ -112,6 +110,12 @@ const Combobox = React.forwardRef<HTMLInputElement, ComboboxProps>(
isOpen,
} = state || defaultState;

React.useEffect(() => {
if (highlightedIndex !== undefined && typeof scrollToIndex === 'function' && highlightedIndex > -1) {
scrollToIndex(highlightedIndex);
}
}, [highlightedIndex, scrollToIndex]);

if (
getComboboxProps === undefined ||
getInputProps === undefined ||
Expand Down Expand Up @@ -173,8 +177,8 @@ const Combobox = React.forwardRef<HTMLInputElement, ComboboxProps>(
optionTemplate={optionTemplate}
groupItemsBy={groupItemsBy}
groupLabelTemplate={groupLabelTemplate}
totalSize={rowVirtualizer.totalSize}
virtualItems={rowVirtualizer.virtualItems}
totalSize={totalSize}
virtualItems={virtualItems}
/>
</ComboboxListbox>
{helpText && (
Expand Down
31 changes: 19 additions & 12 deletions packages/paste-core/components/combobox/stories/index.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,16 +125,15 @@ DefaultCombobox.story = {
name: 'Combobox',
};

const ItemToString = ({name}): string => name;
const ItemToString = ({name}: {name: string}): string => name;

export const VirtualizedCombobox = (): React.ReactNode => {
const itemsForVirtualCombobox = createLargeArray((index) => index.toString());
const itemsForVirtualCombobox = React.useMemo(() => createLargeArray((index) => (index as number).toString()), []);

return (
<Box width="20%">
<Combobox
initialIsOpen
itemToString={(item) => item}
items={itemsForVirtualCombobox}
labelText="Select a virtualized item"
helpText="This large list is virtualized"
Expand All @@ -148,18 +147,22 @@ VirtualizedCombobox.story = {
};

export const VirtualizedCombobox1 = (): React.ReactNode => {
const itemsForVirtualCombobox = createLargeArray((index) => ({
name: `Item ${index}`,
subtext: 'Virtualized combobox from Twilio Paste',
}));
const itemsForVirtualCombobox = React.useMemo(
() =>
createLargeArray((index) => ({
name: `Item ${index as number}`,
subtext: 'Virtualized combobox from Twilio Paste',
})),
[]
);

return (
<Box width="20%">
<Combobox
initialIsOpen
itemToString={ItemToString}
items={itemsForVirtualCombobox}
optionTemplate={({name, subtext}): string => `${name} - ${subtext}`}
optionTemplate={({name, subtext}: {name: string; subtext: string}): string => `${name} - ${subtext}`}
labelText="Select a virtualized item"
helpText="This large list is virtualized"
/>
Expand All @@ -172,10 +175,14 @@ VirtualizedCombobox1.story = {
};

export const VirtualizedCombobox2 = (): React.ReactNode => {
const itemsForVirtualCombobox = createLargeArray((index) => ({
name: `Item ${index}`,
subtext: 'Virtualized combobox from Twilio Paste',
}));
const itemsForVirtualCombobox = React.useMemo(
() =>
createLargeArray((index) => ({
name: `Item ${index as number}`,
subtext: 'Virtualized combobox from Twilio Paste',
})),
[]
);
return (
<Box width="20%">
<Combobox
Expand Down

0 comments on commit 01c278c

Please sign in to comment.