mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-09 23:17:59 -05:00
improvement: code subblock, action bar, connections (#2024)
* improvement: action bar, connections * fix: code block draggable resize
This commit is contained in:
@@ -74,10 +74,10 @@ export const ActionBar = memo(
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'-right-20 absolute top-0',
|
||||
'flex flex-col items-center',
|
||||
'-top-[46px] absolute right-0',
|
||||
'flex flex-row items-center',
|
||||
'opacity-0 transition-opacity duration-200 group-hover:opacity-100',
|
||||
'gap-[6px] rounded-[10px] bg-[var(--surface-3)] p-[6px]'
|
||||
'gap-[5px] rounded-[10px] bg-[var(--surface-3)] p-[5px]'
|
||||
)}
|
||||
>
|
||||
<Tooltip.Root>
|
||||
@@ -90,17 +90,17 @@ export const ActionBar = memo(
|
||||
collaborativeToggleBlockEnabled(blockId)
|
||||
}
|
||||
}}
|
||||
className='h-[30px] w-[30px] rounded-[8px] bg-[var(--surface-9)] p-0 text-[#868686] hover:bg-[var(--brand-secondary)] hover:text-[var(--bg)] dark:text-[#868686] dark:hover:bg-[var(--brand-secondary)] dark:hover:text-[var(--bg)]'
|
||||
className='h-[23px] w-[23px] rounded-[8px] bg-[var(--surface-9)] p-0 text-[#868686] hover:bg-[var(--brand-secondary)] hover:text-[var(--bg)] dark:text-[#868686] dark:hover:bg-[var(--brand-secondary)] dark:hover:text-[var(--bg)]'
|
||||
disabled={disabled}
|
||||
>
|
||||
{isEnabled ? (
|
||||
<Circle className='h-[14px] w-[14px]' />
|
||||
<Circle className='h-[11px] w-[11px]' />
|
||||
) : (
|
||||
<CircleOff className='h-[14px] w-[14px]' />
|
||||
<CircleOff className='h-[11px] w-[11px]' />
|
||||
)}
|
||||
</Button>
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Content side='right'>
|
||||
<Tooltip.Content side='top'>
|
||||
{getTooltipMessage(isEnabled ? 'Disable Block' : 'Enable Block')}
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Root>
|
||||
@@ -116,13 +116,13 @@ export const ActionBar = memo(
|
||||
collaborativeDuplicateBlock(blockId)
|
||||
}
|
||||
}}
|
||||
className='h-[30px] w-[30px] rounded-[8px] bg-[var(--surface-9)] p-0 text-[#868686] hover:bg-[var(--brand-secondary)] hover:text-[var(--bg)] dark:text-[#868686] dark:hover:bg-[var(--brand-secondary)] dark:hover:text-[var(--bg)]'
|
||||
className='h-[23px] w-[23px] rounded-[8px] bg-[var(--surface-9)] p-0 text-[#868686] hover:bg-[var(--brand-secondary)] hover:text-[var(--bg)] dark:text-[#868686] dark:hover:bg-[var(--brand-secondary)] dark:hover:text-[var(--bg)]'
|
||||
disabled={disabled}
|
||||
>
|
||||
<Duplicate className='h-[14px] w-[14px]' />
|
||||
<Duplicate className='h-[11px] w-[11px]' />
|
||||
</Button>
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Content side='right'>{getTooltipMessage('Duplicate Block')}</Tooltip.Content>
|
||||
<Tooltip.Content side='top'>{getTooltipMessage('Duplicate Block')}</Tooltip.Content>
|
||||
</Tooltip.Root>
|
||||
)}
|
||||
|
||||
@@ -139,15 +139,13 @@ export const ActionBar = memo(
|
||||
)
|
||||
}
|
||||
}}
|
||||
className='h-[30px] w-[30px] rounded-[8px] bg-[var(--surface-9)] p-0 text-[#868686] hover:bg-[var(--brand-secondary)] hover:text-[var(--bg)] dark:text-[#868686] dark:hover:bg-[var(--brand-secondary)] dark:hover:text-[var(--bg)]'
|
||||
className='h-[23px] w-[23px] rounded-[8px] bg-[var(--surface-9)] p-0 text-[#868686] hover:bg-[var(--brand-secondary)] hover:text-[var(--bg)] dark:text-[#868686] dark:hover:bg-[var(--brand-secondary)] dark:hover:text-[var(--bg)]'
|
||||
disabled={disabled || !userPermissions.canEdit}
|
||||
>
|
||||
<LogOut className='h-[14px] w-[14px]' />
|
||||
<LogOut className='h-[11px] w-[11px]' />
|
||||
</Button>
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Content side='right'>
|
||||
{getTooltipMessage('Remove From Subflow')}
|
||||
</Tooltip.Content>
|
||||
<Tooltip.Content side='top'>{getTooltipMessage('Remove from Subflow')}</Tooltip.Content>
|
||||
</Tooltip.Root>
|
||||
)}
|
||||
|
||||
@@ -161,17 +159,17 @@ export const ActionBar = memo(
|
||||
collaborativeToggleBlockHandles(blockId)
|
||||
}
|
||||
}}
|
||||
className='h-[30px] w-[30px] rounded-[8px] bg-[var(--surface-9)] p-0 text-[#868686] hover:bg-[var(--brand-secondary)] hover:text-[var(--bg)] dark:text-[#868686] dark:hover:bg-[var(--brand-secondary)] dark:hover:text-[var(--bg)]'
|
||||
className='h-[23px] w-[23px] rounded-[8px] bg-[var(--surface-9)] p-0 text-[#868686] hover:bg-[var(--brand-secondary)] hover:text-[var(--bg)] dark:text-[#868686] dark:hover:bg-[var(--brand-secondary)] dark:hover:text-[var(--bg)]'
|
||||
disabled={disabled}
|
||||
>
|
||||
{horizontalHandles ? (
|
||||
<ArrowLeftRight className='h-[14px] w-[14px]' />
|
||||
<ArrowLeftRight className='h-[11px] w-[11px]' />
|
||||
) : (
|
||||
<ArrowUpDown className='h-[14px] w-[14px]' />
|
||||
<ArrowUpDown className='h-[11px] w-[11px]' />
|
||||
)}
|
||||
</Button>
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Content side='right'>
|
||||
<Tooltip.Content side='top'>
|
||||
{getTooltipMessage(horizontalHandles ? 'Vertical Ports' : 'Horizontal Ports')}
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Root>
|
||||
@@ -186,13 +184,13 @@ export const ActionBar = memo(
|
||||
collaborativeRemoveBlock(blockId)
|
||||
}
|
||||
}}
|
||||
className='h-[30px] w-[30px] rounded-[8px] bg-[var(--surface-9)] p-0 text-[#868686] hover:bg-[var(--brand-secondary)] hover:text-[var(--bg)] dark:text-[#868686] dark:hover:bg-[var(--brand-secondary)] dark:hover:text-[var(--bg)] '
|
||||
className='h-[23px] w-[23px] rounded-[8px] bg-[var(--surface-9)] p-0 text-[#868686] hover:bg-[var(--brand-secondary)] hover:text-[var(--bg)] dark:text-[#868686] dark:hover:bg-[var(--brand-secondary)] dark:hover:text-[var(--bg)] '
|
||||
disabled={disabled}
|
||||
>
|
||||
<Trash2 className='h-[14px] w-[14px]' />
|
||||
<Trash2 className='h-[11px] w-[11px]' />
|
||||
</Button>
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Content side='right'>{getTooltipMessage('Delete Block')}</Tooltip.Content>
|
||||
<Tooltip.Content side='top'>{getTooltipMessage('Delete Block')}</Tooltip.Content>
|
||||
</Tooltip.Root>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,84 +1,23 @@
|
||||
import { RepeatIcon, SplitIcon } from 'lucide-react'
|
||||
import {
|
||||
type ConnectedBlock,
|
||||
useBlockConnections,
|
||||
} from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel-new/components/editor/hooks/use-block-connections'
|
||||
import { getBlock } from '@/blocks'
|
||||
import { useBlockConnections } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel-new/components/editor/hooks/use-block-connections'
|
||||
|
||||
interface ConnectionsProps {
|
||||
blockId: string
|
||||
horizontalHandles: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the icon component for a given connection block
|
||||
* @param connection - The connected block to get the icon for
|
||||
* @returns The icon component or null if not found
|
||||
* Displays incoming connections at the bottom left of the workflow block
|
||||
*/
|
||||
function getConnectionIcon(connection: ConnectedBlock) {
|
||||
const blockConfig = getBlock(connection.type)
|
||||
|
||||
if (blockConfig?.icon) {
|
||||
return blockConfig.icon
|
||||
}
|
||||
|
||||
if (connection.type === 'loop') {
|
||||
return RepeatIcon
|
||||
}
|
||||
|
||||
if (connection.type === 'parallel') {
|
||||
return SplitIcon
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays incoming connections as compact floating text above the workflow block
|
||||
*/
|
||||
export function Connections({ blockId, horizontalHandles }: ConnectionsProps) {
|
||||
export function Connections({ blockId }: ConnectionsProps) {
|
||||
const { incomingConnections, hasIncomingConnections } = useBlockConnections(blockId)
|
||||
|
||||
if (!hasIncomingConnections) return null
|
||||
|
||||
const connectionCount = incomingConnections.length
|
||||
const maxVisibleIcons = 4
|
||||
const visibleConnections = incomingConnections.slice(0, maxVisibleIcons)
|
||||
const remainingCount = connectionCount - maxVisibleIcons
|
||||
|
||||
const connectionText = `${connectionCount} ${connectionCount === 1 ? 'connection' : 'connections'}`
|
||||
|
||||
const connectionIcons = (
|
||||
<>
|
||||
{visibleConnections.map((connection: ConnectedBlock) => {
|
||||
const Icon = getConnectionIcon(connection)
|
||||
if (!Icon) return null
|
||||
return (
|
||||
<Icon key={connection.id} className='h-[14px] w-[14px] text-[var(--text-tertiary)]' />
|
||||
)
|
||||
})}
|
||||
{remainingCount > 0 && (
|
||||
<span className='text-[14px] text-[var(--text-tertiary)]'>+{remainingCount}</span>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
|
||||
if (!horizontalHandles) {
|
||||
return (
|
||||
<div className='-translate-x-full -translate-y-1/2 pointer-events-none absolute top-1/2 left-0 flex flex-col items-end gap-[8px] pr-[8px] opacity-0 transition-opacity group-hover:opacity-100'>
|
||||
<span className='text-[14px] text-[var(--text-tertiary)] leading-[14px]'>
|
||||
{connectionText}
|
||||
</span>
|
||||
<div className='flex items-center justify-end gap-[4px]'>{connectionIcons}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='pointer-events-none absolute bottom-full left-0 ml-[8px] flex items-center gap-[8px] pb-[8px] opacity-0 transition-opacity group-hover:opacity-100'>
|
||||
<span className='text-[14px] text-[var(--text-tertiary)]'>{connectionText}</span>
|
||||
<div className='h-[14px] w-[1px] bg-[var(--text-tertiary)]' />
|
||||
<div className='flex items-center gap-[4px]'>{connectionIcons}</div>
|
||||
<div className='pointer-events-none absolute top-full left-0 ml-[8px] flex items-center gap-[8px] pt-[8px] opacity-0 transition-opacity group-hover:opacity-100'>
|
||||
<span className='text-[12px] text-[var(--text-tertiary)]'>{connectionText}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -723,9 +723,7 @@ export const WorkflowBlock = memo(function WorkflowBlock({
|
||||
|
||||
<ActionBar blockId={id} blockType={type} disabled={!userPermissions.canEdit} />
|
||||
|
||||
{shouldShowDefaultHandles && (
|
||||
<Connections blockId={id} horizontalHandles={horizontalHandles} />
|
||||
)}
|
||||
{shouldShowDefaultHandles && <Connections blockId={id} />}
|
||||
|
||||
{shouldShowDefaultHandles && (
|
||||
<Handle
|
||||
|
||||
@@ -81,9 +81,7 @@ function Container({
|
||||
'bg-[#1F1F1F] font-medium font-mono text-sm transition-colors',
|
||||
'dark:border-[var(--border-strong)]',
|
||||
// Overflow handling for long content
|
||||
'overflow-x-auto',
|
||||
// Vertical resize handle
|
||||
'resize-y overflow-y-auto',
|
||||
'overflow-x-auto overflow-y-auto',
|
||||
// Streaming state
|
||||
isStreaming && 'streaming-effect',
|
||||
className
|
||||
|
||||
Reference in New Issue
Block a user