Skip to content

Commit d5da7ef

Browse files
author
Theodore Li
committed
fix(ui): ensure new resource tab button is always visible
1 parent 70d8df5 commit d5da7ef

File tree

1 file changed

+97
-95
lines changed
  • apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/components/resource-tabs

1 file changed

+97
-95
lines changed

apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/components/resource-tabs/resource-tabs.tsx

Lines changed: 97 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)