@@ -144,6 +144,7 @@ export function adjacentModelPickerProvider(input: {
144144}
145145
146146const EMPTY_MODEL_JUMP_LABELS = new Map < string , string > ( ) ;
147+ const MODEL_LIST_ESTIMATED_ITEM_SIZE = 52 ;
147148
148149function ModelListSeparator ( ) {
149150 return < div className = "h-0.5" /> ;
@@ -197,6 +198,7 @@ export const ModelPickerContent = memo(function ModelPickerContent(props: {
197198 const [ showBottomScrollFade , setShowBottomScrollFade ] = useState ( false ) ;
198199 const searchInputRef = useRef < HTMLInputElement > ( null ) ;
199200 const modelListRef = useRef < LegendListRef | null > ( null ) ;
201+ const pickerContentRef = useRef < HTMLDivElement > ( null ) ;
200202 const highlightedModelKeyRef = useRef < string | null > ( null ) ;
201203 const favorites = useClientSettings ( ( s ) => s . favorites ?? [ ] ) ;
202204 const activeEntry = props . instanceEntries . find (
@@ -699,6 +701,17 @@ export const ModelPickerContent = memo(function ModelPickerContent(props: {
699701 ) ,
700702 [ visibleModels ] ,
701703 ) ;
704+ const [ modelListContentSize , setModelListContentSize ] = useState (
705+ ( ) => filteredItemKeys . length * MODEL_LIST_ESTIMATED_ITEM_SIZE ,
706+ ) ;
707+ const [ searchHeight , setSearchHeight ] = useState ( 0 ) ;
708+ useLayoutEffect (
709+ ( ) => modelListRef . current ?. getState ( ) . listen ( "totalSize" , setModelListContentSize ) ,
710+ [ ] ,
711+ ) ;
712+ // Fit the list to its rows plus the combobox list `py-1` and LegendList `py-1.5`.
713+ const modelListHeight =
714+ filteredItemKeys . length === 0 ? 0 : `calc(${ modelListContentSize } px + var(--spacing) * 5)` ;
702715 const updateModelListScrollFades = useCallback ( ( ) => {
703716 const scrollElement = modelListRef . current ?. getScrollableNode ( ) ;
704717 if ( ! ( scrollElement instanceof HTMLElement ) ) {
@@ -815,7 +828,10 @@ export const ModelPickerContent = memo(function ModelPickerContent(props: {
815828 return (
816829 < TooltipProvider delay = { 0 } >
817830 < div
818- className = "relative flex h-screen max-h-86.5 w-screen max-w-90 flex-row overflow-hidden"
831+ ref = { pickerContentRef }
832+ className = "relative flex max-h-86.5 w-screen max-w-90 flex-row overflow-hidden"
833+ // Hold the height from when the search started; results scroll instead of resizing.
834+ style = { isSearching ? { height : searchHeight } : undefined }
819835 data-model-picker-content = "true"
820836 >
821837 { /* Sidebar */ }
@@ -890,7 +906,10 @@ export const ModelPickerContent = memo(function ModelPickerContent(props: {
890906 ref = { searchInputRef }
891907 placeholder = "Search models..."
892908 value = { searchQuery }
893- onChange = { ( e ) => setSearchQuery ( e . target . value ) }
909+ onChange = { ( e ) => {
910+ if ( ! isSearching ) setSearchHeight ( pickerContentRef . current ?. offsetHeight ?? 0 ) ;
911+ setSearchQuery ( e . target . value ) ;
912+ } }
894913 onKeyDown = { ( e ) => {
895914 if (
896915 showSidebar &&
@@ -944,7 +963,10 @@ export const ModelPickerContent = memo(function ModelPickerContent(props: {
944963 />
945964
946965 { /* Model list */ }
947- < div className = "relative min-h-0 flex-1 overflow-hidden pr-px" >
966+ < div
967+ className = "relative min-h-0 overflow-hidden pr-px"
968+ style = { { height : modelListHeight } }
969+ >
948970 < ComboboxListVirtualized >
949971 < LegendList < string >
950972 ref = { modelListRef }
@@ -1013,7 +1035,7 @@ export const ModelPickerContent = memo(function ModelPickerContent(props: {
10131035 />
10141036 ) ;
10151037 } }
1016- estimatedItemSize = { 52 }
1038+ estimatedItemSize = { MODEL_LIST_ESTIMATED_ITEM_SIZE }
10171039 drawDistance = { 480 }
10181040 recycleItems
10191041 contentContainerClassName = "pl-2 pr-px"
0 commit comments