keep node viewer avatars visible with long titles

Move the viewer avatar list outside the truncated title area so long node titles do not clip avatars. Add a regression test covering long titles with active viewers.
This commit is contained in:
hjlarry 2026-04-14 11:58:28 +08:00
parent 7e044fc602
commit fa259ce2e3
2 changed files with 36 additions and 3 deletions

View File

@ -10,12 +10,17 @@ const mockUseNodePluginInstallation = vi.fn()
const mockHandleNodeIterationChildSizeChange = vi.fn()
const mockHandleNodeLoopChildSizeChange = vi.fn()
const mockUseNodeResizeObserver = vi.fn()
const mockUseCollaboration = vi.fn()
vi.mock('@/app/components/workflow/hooks', () => ({
useNodesReadOnly: () => ({ nodesReadOnly: false }),
useToolIcon: () => undefined,
}))
vi.mock('@/app/components/workflow/collaboration/hooks/use-collaboration', () => ({
useCollaboration: (...args: unknown[]) => mockUseCollaboration(...args),
}))
vi.mock('@/app/components/workflow/hooks/use-inspect-vars-crud', () => ({
default: () => ({
hasNodeInspectVars: mockHasNodeInspectVars,
@ -98,6 +103,7 @@ describe('BaseNode', () => {
vi.clearAllMocks()
mockHasNodeInspectVars.mockReturnValue(false)
mockUseNodeResizeObserver.mockReset()
mockUseCollaboration.mockReturnValue({ nodePanelPresence: {} })
mockUseNodePluginInstallation.mockReturnValue({
shouldDim: false,
isChecking: false,
@ -215,4 +221,32 @@ describe('BaseNode', () => {
expect(mockHandleNodeLoopChildSizeChange).toHaveBeenCalledWith('node-2')
expect(mockUseNodeResizeObserver).toHaveBeenCalledTimes(2)
})
it('should keep viewer avatars outside the truncated title area', () => {
const longTitle = 'This is a very long node title that should truncate before it clips the viewer avatars'
mockUseCollaboration.mockReturnValue({
nodePanelPresence: {
'node-1': {
'client-1': {
userId: 'viewer-1',
username: 'Zed',
avatar: null,
clientId: 'client-1',
timestamp: Date.now(),
},
},
},
})
renderWorkflowComponent(
<BaseNode id="node-1" data={toNodeData(createData({ title: longTitle }))}>
<div>Body</div>
</BaseNode>,
)
const titleContainer = screen.getByTitle(longTitle)
expect(titleContainer).toHaveClass('min-w-0', 'grow', 'truncate')
expect(titleContainer?.nextElementSibling).toHaveClass('shrink-0')
expect(screen.getByText('Z')).toBeInTheDocument()
})
})

View File

@ -268,10 +268,9 @@ const BaseNode: FC<BaseNodeProps> = ({
toolIcon={toolIcon}
/>
<div
title={data.title}
className="mr-1 flex grow items-center truncate text-text-primary system-sm-semibold-uppercase"
className="mr-1 flex min-w-0 grow items-center text-text-primary system-sm-semibold-uppercase"
>
<div>
<div title={data.title} className="min-w-0 grow truncate">
{data.title}
</div>
{viewingUsers.length > 0 && (