@@ -1023,6 +1023,7 @@ export default function Sidebar({ routeReveal }: { routeReveal: SidebarRouteReve
10231023 const [ renamingTitle , setRenamingTitle ] = useState ( "" ) ;
10241024 const settlingThreadKeysRef = useRef ( new Set < string > ( ) ) ;
10251025 const threadListRef = useRef < HTMLUListElement | null > ( null ) ;
1026+ const searchResultsListRef = useRef < HTMLUListElement | null > ( null ) ;
10261027 const dragLabelOffsetRef = useRef ( 0 ) ;
10271028 const listMotionRef = useRef < ReturnType < typeof createSidebarListMotion > | null > ( null ) ;
10281029 const [ dragState , setDragState ] = useState < {
@@ -1685,7 +1686,8 @@ export default function Sidebar({ routeReveal }: { routeReveal: SidebarRouteReve
16851686 } ) ;
16861687 } ;
16871688 const pointerOutsideThreadList = ( point : { x : number ; y : number } ) => {
1688- const bounds = threadListRef . current ?. getBoundingClientRect ( ) ;
1689+ // Search results replace the thread list, so only one of them is mounted.
1690+ const bounds = ( threadListRef . current ?? searchResultsListRef . current ) ?. getBoundingClientRect ( ) ;
16891691 return bounds !== undefined && ( point . x < bounds . left || point . x > bounds . right ) ;
16901692 } ;
16911693 const moveThreadContextDrag = ( point : { x : number ; y : number } ) => {
@@ -3101,57 +3103,66 @@ export default function Sidebar({ routeReveal }: { routeReveal: SidebarRouteReve
31013103 closeDelay = { 0 }
31023104 timeout = { 400 }
31033105 >
3104- < ul
3105- id = "sidebar-thread-search-results"
3106- role = "listbox"
3107- aria-label = "Thread search results"
3108- className = "flex flex-col gap-px"
3106+ < DndContext
3107+ sensors = { dndSensors }
3108+ autoScroll = { false }
3109+ onDragStart = { ( event ) => {
3110+ contextDragKeyRef . current = String ( event . active . id ) ;
3111+ } }
31093112 >
3110- { threadSearchResults . map ( ( thread , index ) => {
3111- const threadKey = scopedThreadKey (
3112- scopeThreadRef ( thread . environmentId , thread . id ) ,
3113- ) ;
3114- return (
3115- < SidebarSearchResultRow
3116- isSettled = { settledThreadKeys . has ( threadKey ) }
3117- key = { threadKey }
3118- thread = { thread }
3119- project = {
3120- projectByKey . get ( `${ thread . environmentId } :${ thread . projectId } ` ) ?? null
3121- }
3122- projectDisplayName = {
3123- projectDisplayNameByKey . get (
3124- `${ thread . environmentId } :${ thread . projectId } ` ,
3125- ) ?? null
3126- }
3127- environmentLabel = { environmentLabelById . get ( thread . environmentId ) ?? null }
3128- environmentMachine = {
3129- environmentMachineById . get ( thread . environmentId ) ?? "server"
3130- }
3131- providerEntryByInstanceId = {
3132- providerEntriesByEnvironment . get ( thread . environmentId ) ??
3133- EMPTY_PROVIDER_ENTRIES
3134- }
3135- isHighlighted = { activeSearchResultIndex === index }
3136- isRouteActive = { routeRowThreadKey === threadKey }
3137- resultId = { threadSearchResultId ( index ) }
3138- searchMatch = {
3139- threadSearchMatchByKey . get (
3140- threadSearchMatchKey ( {
3141- environmentId : thread . environmentId ,
3142- threadId : thread . id ,
3143- } ) ,
3144- ) ?? null
3145- }
3146- searchQuery = { threadSearchQuery }
3147- searchMatchQuery = { threadSearch . query }
3148- onHighlight = { ( ) => setActiveSearchResultIndex ( index ) }
3149- onSelect = { ( ) => selectThreadSearchResult ( thread ) }
3150- onFileDropThreads = { handleThreadFileDrop }
3151- />
3152- ) ;
3153- } ) }
3154- </ ul >
3113+ < ul
3114+ ref = { searchResultsListRef }
3115+ id = "sidebar-thread-search-results"
3116+ role = "listbox"
3117+ aria-label = "Thread search results"
3118+ className = "flex flex-col gap-px"
3119+ >
3120+ { threadSearchResults . map ( ( thread , index ) => {
3121+ const threadKey = scopedThreadKey (
3122+ scopeThreadRef ( thread . environmentId , thread . id ) ,
3123+ ) ;
3124+ return (
3125+ < SidebarSearchResultRow
3126+ isSettled = { settledThreadKeys . has ( threadKey ) }
3127+ key = { threadKey }
3128+ thread = { thread }
3129+ project = {
3130+ projectByKey . get ( `${ thread . environmentId } :${ thread . projectId } ` ) ?? null
3131+ }
3132+ projectDisplayName = {
3133+ projectDisplayNameByKey . get (
3134+ `${ thread . environmentId } :${ thread . projectId } ` ,
3135+ ) ?? null
3136+ }
3137+ environmentLabel = { environmentLabelById . get ( thread . environmentId ) ?? null }
3138+ environmentMachine = {
3139+ environmentMachineById . get ( thread . environmentId ) ?? "server"
3140+ }
3141+ providerEntryByInstanceId = {
3142+ providerEntriesByEnvironment . get ( thread . environmentId ) ??
3143+ EMPTY_PROVIDER_ENTRIES
3144+ }
3145+ isHighlighted = { activeSearchResultIndex === index }
3146+ isRouteActive = { routeRowThreadKey === threadKey }
3147+ resultId = { threadSearchResultId ( index ) }
3148+ searchMatch = {
3149+ threadSearchMatchByKey . get (
3150+ threadSearchMatchKey ( {
3151+ environmentId : thread . environmentId ,
3152+ threadId : thread . id ,
3153+ } ) ,
3154+ ) ?? null
3155+ }
3156+ searchQuery = { threadSearchQuery }
3157+ searchMatchQuery = { threadSearch . query }
3158+ onHighlight = { ( ) => setActiveSearchResultIndex ( index ) }
3159+ onSelect = { ( ) => selectThreadSearchResult ( thread ) }
3160+ onFileDropThreads = { handleThreadFileDrop }
3161+ />
3162+ ) ;
3163+ } ) }
3164+ </ ul >
3165+ </ DndContext >
31553166 </ TooltipProvider >
31563167 ) : (
31573168 < p
0 commit comments