mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
improvement(ui): drop full-content hover tooltips (#6128)
* improvement(ui): drop full-content hover tooltips - remove the chunk-content tooltip in the KB chunks table (it forced the full chunk body on every truncated row) - remove the sub-block value tooltip on collapsed workflow blocks (whole prompts/code/JSON on hover) - replace the native `title` on subflow and note blocks with the clip-gated OverflowSpan - clip-gate the KB documents tags cell so it stops firing on fully visible tags - drop the dead tooltip on the resource header root title, which can never truncate * fix(workflow-renderer): default the optional note name for OverflowSpan
This commit is contained in:
+3
-5
@@ -33,7 +33,6 @@ import { ArrowUpLeft } from 'lucide-react'
|
||||
import { createPortal } from 'react-dom'
|
||||
import { TITLE_BAR_LANE_PT } from '@/components/page-header-bar'
|
||||
import { InlineRenameInput } from '@/app/workspace/[workspaceId]/components/inline-rename-input'
|
||||
import { FloatingOverflowText } from '@/app/workspace/[workspaceId]/components/resource/components/floating-overflow-text'
|
||||
|
||||
export interface DropdownOption {
|
||||
label: string
|
||||
@@ -195,10 +194,9 @@ export const ResourceHeader = memo(function ResourceHeader({
|
||||
<span className={cn(chipGeometryClass, 'inline-flex shrink-0 cursor-default')}>
|
||||
{TitleIcon && <TitleIcon className={chipContentIconClass} />}
|
||||
{titleLabel && (
|
||||
<FloatingOverflowText
|
||||
label={titleLabel}
|
||||
className='block whitespace-nowrap text-[var(--text-body)] text-sm'
|
||||
/>
|
||||
<span className='block whitespace-nowrap text-[var(--text-body)] text-sm'>
|
||||
{titleLabel}
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
)}
|
||||
|
||||
@@ -21,11 +21,7 @@ import type {
|
||||
SelectableConfig,
|
||||
SortConfig,
|
||||
} from '@/app/workspace/[workspaceId]/components'
|
||||
import {
|
||||
EMPTY_CELL_PLACEHOLDER,
|
||||
FloatingOverflowText,
|
||||
Resource,
|
||||
} from '@/app/workspace/[workspaceId]/components'
|
||||
import { EMPTY_CELL_PLACEHOLDER, Resource } from '@/app/workspace/[workspaceId]/components'
|
||||
import {
|
||||
ChunkContextMenu,
|
||||
ChunkEditor,
|
||||
@@ -948,13 +944,9 @@ export function Document({
|
||||
cells: {
|
||||
content: {
|
||||
content: (
|
||||
<FloatingOverflowText
|
||||
label={chunk.content}
|
||||
showWhen={previewContent !== chunk.content}
|
||||
className='block truncate text-[var(--text-primary)] text-sm'
|
||||
>
|
||||
<span className='block truncate text-[var(--text-primary)] text-sm'>
|
||||
<SearchHighlight text={previewContent} searchQuery={searchQuery} />
|
||||
</FloatingOverflowText>
|
||||
</span>
|
||||
),
|
||||
},
|
||||
index: {
|
||||
|
||||
@@ -18,9 +18,12 @@ import {
|
||||
chipContentLabelClass,
|
||||
chipVariants,
|
||||
cn,
|
||||
FloatingTooltip,
|
||||
isTextClipped,
|
||||
Loader,
|
||||
Tooltip,
|
||||
Trash,
|
||||
useFloatingTooltip,
|
||||
} from '@sim/emcn'
|
||||
import { Database, DatabaseX } from '@sim/emcn/icons'
|
||||
import { createLogger } from '@sim/logger'
|
||||
@@ -177,6 +180,39 @@ interface TagValue {
|
||||
value: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Tags cell for the documents table. Shows the joined tag values inline and
|
||||
* reveals the full `name: value` breakdown only when the inline text is
|
||||
* actually clipped — an un-truncated cell already says everything the tooltip
|
||||
* would.
|
||||
*/
|
||||
function DocumentTagsCell({ tags }: { tags: TagValue[] }) {
|
||||
const { state, handlers } = useFloatingTooltip(isTextClipped)
|
||||
|
||||
return (
|
||||
<>
|
||||
<span
|
||||
role='presentation'
|
||||
className='block max-w-full truncate text-[var(--text-secondary)] text-caption'
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onKeyDown={(e) => e.stopPropagation()}
|
||||
{...handlers}
|
||||
>
|
||||
{tags.map((tag) => tag.value).join(', ')}
|
||||
</span>
|
||||
<FloatingTooltip state={state} className='max-w-[240px]'>
|
||||
<div className='flex flex-col gap-0.5'>
|
||||
{tags.map((tag) => (
|
||||
<div key={tag.slot} className='truncate text-xs'>
|
||||
<span className='text-[var(--text-muted)]'>{tag.displayName}:</span> {tag.value}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</FloatingTooltip>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes tag values for a document
|
||||
*/
|
||||
@@ -1057,7 +1093,6 @@ export function KnowledgeBase({
|
||||
const DocIcon = ConnectorIcon || getDocumentIcon(doc.mimeType, doc.filename)
|
||||
|
||||
const tags = getDocumentTags(doc, tagDefinitions)
|
||||
const tagsDisplayText = tags.map((t) => t.value).join(', ')
|
||||
|
||||
const statusCell: ResourceCell =
|
||||
doc.processingStatus === 'failed' && doc.processingError
|
||||
@@ -1076,34 +1111,7 @@ export function KnowledgeBase({
|
||||
: { content: getStatusBadge(doc) }
|
||||
|
||||
const tagsCell: ResourceCell =
|
||||
tags.length === 0
|
||||
? { label: null }
|
||||
: {
|
||||
content: (
|
||||
<Tooltip.Root>
|
||||
<Tooltip.Trigger asChild>
|
||||
<span
|
||||
role='presentation'
|
||||
className='block max-w-full truncate text-[var(--text-secondary)] text-caption'
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onKeyDown={(e) => e.stopPropagation()}
|
||||
>
|
||||
{tagsDisplayText}
|
||||
</span>
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Content side='top' className='max-w-[240px]'>
|
||||
<div className='flex flex-col gap-0.5'>
|
||||
{tags.map((tag) => (
|
||||
<div key={tag.slot} className='truncate text-xs'>
|
||||
<span className='text-[var(--text-muted)]'>{tag.displayName}:</span>{' '}
|
||||
{tag.value}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Root>
|
||||
),
|
||||
}
|
||||
tags.length === 0 ? { label: null } : { content: <DocumentTagsCell tags={tags} /> }
|
||||
|
||||
return {
|
||||
id: doc.id,
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Streamdown } from 'streamdown'
|
||||
import 'streamdown/styles.css'
|
||||
import { cn, handleKeyboardActivation } from '@sim/emcn'
|
||||
import { getEmbedInfo } from '@sim/utils/media-embed'
|
||||
import { OverflowSpan } from '../lib/overflow-span'
|
||||
|
||||
const EMBED_SCALE = 0.78
|
||||
const EMBED_INVERSE_SCALE = `${(1 / EMBED_SCALE) * 100}%`
|
||||
@@ -217,15 +218,13 @@ export function NoteBlockView({
|
||||
|
||||
<div className='flex items-center justify-between border-[var(--divider)] border-b p-2'>
|
||||
<div className='flex min-w-0 flex-1 items-center'>
|
||||
<span
|
||||
<OverflowSpan
|
||||
value={name ?? ''}
|
||||
className={cn(
|
||||
'truncate font-medium text-md',
|
||||
!isEnabled && 'text-[var(--text-muted)]'
|
||||
)}
|
||||
title={name}
|
||||
>
|
||||
{name}
|
||||
</span>
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Badge, cn, handleKeyboardActivation } from '@sim/emcn'
|
||||
import { RepeatIcon, SplitIcon } from 'lucide-react'
|
||||
import { Handle, Position } from 'reactflow'
|
||||
import { HANDLE_POSITIONS } from '../dimensions'
|
||||
import { OverflowSpan } from '../lib/overflow-span'
|
||||
import { tileIconColorClass } from '../lib/tile-icon-color'
|
||||
import type { BlockRunStatus, DiffStatus } from '../types'
|
||||
|
||||
@@ -171,15 +172,13 @@ export function SubflowNodeView({
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<span
|
||||
<OverflowSpan
|
||||
value={blockName}
|
||||
className={cn(
|
||||
'truncate font-medium text-md',
|
||||
!isEnabled && 'text-[var(--text-muted)]'
|
||||
)}
|
||||
title={blockName}
|
||||
>
|
||||
{blockName}
|
||||
</span>
|
||||
/>
|
||||
</div>
|
||||
<div className='flex items-center gap-1'>
|
||||
{!isEnabled && <Badge variant='gray-secondary'>disabled</Badge>}
|
||||
|
||||
@@ -33,13 +33,14 @@ export function SubBlockRowView({ title, displayValue, isMonospace }: SubBlockRo
|
||||
className='min-w-0 truncate text-[var(--text-tertiary)] text-sm capitalize'
|
||||
/>
|
||||
{displayValue !== undefined && (
|
||||
<OverflowSpan
|
||||
value={displayValue}
|
||||
<span
|
||||
className={cn(
|
||||
'flex-1 truncate text-right text-[var(--text-primary)] text-sm',
|
||||
isMonospace && 'font-mono'
|
||||
)}
|
||||
/>
|
||||
>
|
||||
{displayValue}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user