@@ -273,103 +273,105 @@ export function ResourceTabs({
273273 < p > Collapse</ p >
274274 </ Tooltip . Content >
275275 </ Tooltip . Root >
276- < div
277- ref = { scrollNodeRef }
278- className = { cn (
279- 'flex min-w-0 flex-1 items-center overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden' ,
280- RESOURCE_TAB_GAP_CLASS
281- ) }
282- onDragOver = { ( e ) => {
283- e . preventDefault ( )
284- startEdgeScroll ( e . clientX )
285- } }
286- onDrop = { handleDrop }
287- >
288- { resources . map ( ( resource , idx ) => {
289- const config = getResourceConfig ( resource . type )
290- const displayName = nameLookup . get ( `${ resource . type } :${ resource . id } ` ) ?? resource . title
291- const isActive = activeId === resource . id
292- const isHovered = hoveredTabId === resource . id
293- const isDragging = draggedIdx === idx
294- const showGapBefore =
295- dropGapIdx === idx &&
296- draggedIdx !== null &&
297- draggedIdx !== idx &&
298- draggedIdx !== idx - 1
299- const showGapAfter =
300- idx === resources . length - 1 &&
301- dropGapIdx === resources . length &&
302- draggedIdx !== null &&
303- draggedIdx !== idx
276+ < div className = { cn ( 'flex min-w-0 flex-1 items-center' , RESOURCE_TAB_GAP_CLASS ) } >
277+ < div
278+ ref = { scrollNodeRef }
279+ className = { cn (
280+ 'flex min-w-0 items-center overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden' ,
281+ RESOURCE_TAB_GAP_CLASS
282+ ) }
283+ onDragOver = { ( e ) => {
284+ e . preventDefault ( )
285+ startEdgeScroll ( e . clientX )
286+ } }
287+ onDrop = { handleDrop }
288+ >
289+ { resources . map ( ( resource , idx ) => {
290+ const config = getResourceConfig ( resource . type )
291+ const displayName = nameLookup . get ( `${ resource . type } :${ resource . id } ` ) ?? resource . title
292+ const isActive = activeId === resource . id
293+ const isHovered = hoveredTabId === resource . id
294+ const isDragging = draggedIdx === idx
295+ const showGapBefore =
296+ dropGapIdx === idx &&
297+ draggedIdx !== null &&
298+ draggedIdx !== idx &&
299+ draggedIdx !== idx - 1
300+ const showGapAfter =
301+ idx === resources . length - 1 &&
302+ dropGapIdx === resources . length &&
303+ draggedIdx !== null &&
304+ draggedIdx !== idx
304305
305- return (
306- < div key = { resource . id } className = 'relative flex shrink-0 items-center' >
307- { showGapBefore && (
308- < div className = '-translate-x-1/2 -translate-y-1/2 pointer-events-none absolute top-1/2 left-0 z-10 h-[16px] w-[2px] rounded-full bg-[var(--text-subtle)]' />
309- ) }
310- < Tooltip . Root >
311- < Tooltip . Trigger asChild >
312- < Button
313- variant = 'subtle'
314- draggable
315- onDragStart = { ( e ) => handleDragStart ( e , idx ) }
316- onDragOver = { ( e ) => handleDragOver ( e , idx ) }
317- onDragLeave = { handleDragLeave }
318- onDragEnd = { handleDragEnd }
319- onMouseDown = { ( e ) => {
320- if ( e . button === 1 && chatId ) {
321- e . preventDefault ( )
322- handleRemove ( e , resource )
323- }
324- } }
325- onClick = { ( ) => onSelect ( resource . id ) }
326- onMouseEnter = { ( ) => setHoveredTabId ( resource . id ) }
327- onMouseLeave = { ( ) => setHoveredTabId ( null ) }
328- className = { cn (
329- 'group relative shrink-0 bg-transparent px-[8px] py-[4px] pr-[22px] text-[12px] transition-opacity duration-150' ,
330- isActive && 'bg-[var(--surface-4)]' ,
331- isDragging && 'opacity-30'
332- ) }
333- >
334- { config . renderTabIcon ( resource , 'mr-[6px] h-[14px] w-[14px]' ) }
335- { displayName }
336- { ( isHovered || isActive ) && chatId && (
337- < span
338- role = 'button'
339- tabIndex = { - 1 }
340- onClick = { ( e ) => handleRemove ( e , resource ) }
341- onKeyDown = { ( e ) => {
342- if ( e . key === 'Enter' )
343- handleRemove ( e as unknown as React . MouseEvent , resource )
344- } }
345- className = '-translate-y-1/2 absolute top-1/2 right-[4px] flex items-center justify-center rounded-[4px] p-[1px] hover:bg-[var(--surface-5)]'
346- aria-label = { `Close ${ displayName } ` }
347- >
348- < svg
349- className = 'h-[10px] w-[10px] text-[var(--text-icon)]'
350- viewBox = '0 0 24 24'
351- fill = 'none'
352- stroke = 'currentColor'
353- strokeWidth = '2.5'
354- strokeLinecap = 'round'
355- strokeLinejoin = 'round'
306+ return (
307+ < div key = { resource . id } className = 'relative flex shrink-0 items-center' >
308+ { showGapBefore && (
309+ < div className = '-translate-x-1/2 -translate-y-1/2 pointer-events-none absolute top-1/2 left-0 z-10 h-[16px] w-[2px] rounded-full bg-[var(--text-subtle)]' />
310+ ) }
311+ < Tooltip . Root >
312+ < Tooltip . Trigger asChild >
313+ < Button
314+ variant = 'subtle'
315+ draggable
316+ onDragStart = { ( e ) => handleDragStart ( e , idx ) }
317+ onDragOver = { ( e ) => handleDragOver ( e , idx ) }
318+ onDragLeave = { handleDragLeave }
319+ onDragEnd = { handleDragEnd }
320+ onMouseDown = { ( e ) => {
321+ if ( e . button === 1 && chatId ) {
322+ e . preventDefault ( )
323+ handleRemove ( e , resource )
324+ }
325+ } }
326+ onClick = { ( ) => onSelect ( resource . id ) }
327+ onMouseEnter = { ( ) => setHoveredTabId ( resource . id ) }
328+ onMouseLeave = { ( ) => setHoveredTabId ( null ) }
329+ className = { cn (
330+ 'group relative shrink-0 bg-transparent px-[8px] py-[4px] pr-[22px] text-[12px] transition-opacity duration-150' ,
331+ isActive && 'bg-[var(--surface-4)]' ,
332+ isDragging && 'opacity-30'
333+ ) }
334+ >
335+ { config . renderTabIcon ( resource , 'mr-[6px] h-[14px] w-[14px]' ) }
336+ { displayName }
337+ { ( isHovered || isActive ) && chatId && (
338+ < span
339+ role = 'button'
340+ tabIndex = { - 1 }
341+ onClick = { ( e ) => handleRemove ( e , resource ) }
342+ onKeyDown = { ( e ) => {
343+ if ( e . key === 'Enter' )
344+ handleRemove ( e as unknown as React . MouseEvent , resource )
345+ } }
346+ className = '-translate-y-1/2 absolute top-1/2 right-[4px] flex items-center justify-center rounded-[4px] p-[1px] hover:bg-[var(--surface-5)]'
347+ aria-label = { `Close ${ displayName } ` }
356348 >
357- < path d = 'M18 6 6 18M6 6l12 12' />
358- </ svg >
359- </ span >
360- ) }
361- </ Button >
362- </ Tooltip . Trigger >
363- < Tooltip . Content side = 'bottom' >
364- < p > { displayName } </ p >
365- </ Tooltip . Content >
366- </ Tooltip . Root >
367- { showGapAfter && (
368- < div className = '-translate-y-1/2 pointer-events-none absolute top-1/2 right-0 z-10 h-[16px] w-[2px] translate-x-1/2 rounded-full bg-[var(--text-subtle)]' />
369- ) }
370- </ div >
371- )
372- } ) }
349+ < svg
350+ className = 'h-[10px] w-[10px] text-[var(--text-icon)]'
351+ viewBox = '0 0 24 24'
352+ fill = 'none'
353+ stroke = 'currentColor'
354+ strokeWidth = '2.5'
355+ strokeLinecap = 'round'
356+ strokeLinejoin = 'round'
357+ >
358+ < path d = 'M18 6 6 18M6 6l12 12' />
359+ </ svg >
360+ </ span >
361+ ) }
362+ </ Button >
363+ </ Tooltip . Trigger >
364+ < Tooltip . Content side = 'bottom' >
365+ < p > { displayName } </ p >
366+ </ Tooltip . Content >
367+ </ Tooltip . Root >
368+ { showGapAfter && (
369+ < div className = '-translate-y-1/2 pointer-events-none absolute top-1/2 right-0 z-10 h-[16px] w-[2px] translate-x-1/2 rounded-full bg-[var(--text-subtle)]' />
370+ ) }
371+ </ div >
372+ )
373+ } ) }
374+ </ div >
373375 { chatId && (
374376 < AddResourceDropdown
375377 workspaceId = { workspaceId }
0 commit comments