diff --git a/web/chat/typeahead-tooltip.react.js b/web/chat/typeahead-tooltip.react.js --- a/web/chat/typeahead-tooltip.react.js +++ b/web/chat/typeahead-tooltip.react.js @@ -8,6 +8,7 @@ import type { InputState } from '../input/input-state'; import { + getTypeaheadOverlayScroll, getTypeaheadTooltipActions, getTypeaheadTooltipButtons, getTypeaheadTooltipPosition, @@ -36,6 +37,8 @@ setChosenPositionInOverlay, ] = React.useState(0); + const overlayRef = React.useRef(); + React.useEffect(() => { setChosenPositionInOverlay(0); }, [suggestedUsers]); @@ -143,6 +146,16 @@ inputState.setTypeaheadState, ]); + React.useEffect(() => { + const current = overlayRef.current; + if (current) { + current.scrollTop = getTypeaheadOverlayScroll( + current.scrollTop, + chosenPositionInOverlay, + ); + } + }, [chosenPositionInOverlay]); + if (suggestedUsers.length === 0) { return null; } @@ -153,7 +166,11 @@ }); return ( -
+
{tooltipButtons}
); diff --git a/web/utils/typeahead-utils.js b/web/utils/typeahead-utils.js --- a/web/utils/typeahead-utils.js +++ b/web/utils/typeahead-utils.js @@ -153,6 +153,30 @@ }); } +function getTypeaheadOverlayScroll( + currentScrollTop: number, + chosenActionPosition: number, +): number { + const upperButtonBoundary = chosenActionPosition * typeaheadStyle.rowHeight; + const lowerButtonBoundary = + (chosenActionPosition + 1) * typeaheadStyle.rowHeight; + + if (upperButtonBoundary < currentScrollTop) { + return upperButtonBoundary; + } else if ( + lowerButtonBoundary - typeaheadStyle.tooltipMaxHeight > + currentScrollTop + ) { + return ( + lowerButtonBoundary + + typeaheadStyle.tooltipVerticalPadding - + typeaheadStyle.tooltipMaxHeight + ); + } + + return currentScrollTop; +} + function getTypeaheadTooltipPosition( textarea: HTMLTextAreaElement, actionsLength: number, @@ -188,5 +212,6 @@ getCaretOffsets, getTypeaheadTooltipActions, getTypeaheadTooltipButtons, + getTypeaheadOverlayScroll, getTypeaheadTooltipPosition, };