Skip to content

Commit 0d5c7b9

Browse files
committed
improvement: subflow ui/ux
1 parent f86bdda commit 0d5c7b9

File tree

5 files changed

+22
-24
lines changed

5 files changed

+22
-24
lines changed

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/action-bar/action-bar.tsx renamed to apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/action-bar/action-bar.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ export const ActionBar = memo(
100100
const isStartBlock = blockType === 'starter' || blockType === 'start_trigger'
101101
const isResponseBlock = blockType === 'response'
102102
const isNoteBlock = blockType === 'note'
103+
const isSubflowBlock = blockType === 'loop' || blockType === 'parallel'
103104

104105
/**
105106
* Get appropriate tooltip message based on disabled state
@@ -125,7 +126,7 @@ export const ActionBar = memo(
125126
'dark:border-transparent dark:bg-[var(--surface-4)]'
126127
)}
127128
>
128-
{!isNoteBlock && (
129+
{!isNoteBlock && !isSubflowBlock && (
129130
<Tooltip.Root>
130131
<Tooltip.Trigger asChild>
131132
<Button
@@ -148,7 +149,7 @@ export const ActionBar = memo(
148149
</Tooltip.Root>
149150
)}
150151

151-
{!isStartBlock && !isResponseBlock && (
152+
{!isStartBlock && !isResponseBlock && !isSubflowBlock && (
152153
<Tooltip.Root>
153154
<Tooltip.Trigger asChild>
154155
<Button
@@ -169,7 +170,7 @@ export const ActionBar = memo(
169170
</Tooltip.Root>
170171
)}
171172

172-
{!isNoteBlock && (
173+
{!isNoteBlock && !isSubflowBlock && (
173174
<Tooltip.Root>
174175
<Tooltip.Trigger asChild>
175176
<Button

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/note-block/note-block.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ import type { NodeProps } from 'reactflow'
44
import remarkGfm from 'remark-gfm'
55
import { cn } from '@/lib/core/utils/cn'
66
import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider'
7+
import { ActionBar } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/action-bar/action-bar'
78
import { useBlockVisual } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks'
89
import {
910
BLOCK_DIMENSIONS,
1011
useBlockDimensions,
1112
} from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-block-dimensions'
1213
import { useSubBlockStore } from '@/stores/workflows/subblock/store'
13-
import { ActionBar } from '../workflow-block/components'
1414
import type { WorkflowBlockProps } from '../workflow-block/types'
1515

1616
interface NoteBlockNodeData extends WorkflowBlockProps {}

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/subflows/subflow-node.tsx

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { memo, useMemo, useRef } from 'react'
22
import { RepeatIcon, SplitIcon } from 'lucide-react'
33
import { Handle, type NodeProps, Position, useReactFlow } from 'reactflow'
4-
import { Button, Trash } from '@/components/emcn'
54
import { cn } from '@/lib/core/utils/cn'
65
import { HANDLE_POSITIONS } from '@/lib/workflows/blocks/block-dimensions'
76
import { type DiffStatus, hasDiffStatus } from '@/lib/workflows/diff/types'
7+
import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider'
8+
import { ActionBar } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/action-bar/action-bar'
89
import { useCurrentWorkflow } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks'
9-
import { useCollaborativeWorkflow } from '@/hooks/use-collaborative-workflow'
1010
import { usePanelEditorStore } from '@/stores/panel'
1111

1212
/**
@@ -18,11 +18,16 @@ import { usePanelEditorStore } from '@/stores/panel'
1818
const SubflowNodeStyles: React.FC = () => {
1919
return (
2020
<style jsx global>{`
21-
/* Z-index management for subflow nodes */
21+
/* Z-index management for subflow nodes - default behind blocks */
2222
.workflow-container .react-flow__node-subflowNode {
2323
z-index: -1 !important;
2424
}
2525
26+
/* Selected subflows appear above other subflows but below blocks (z-21) */
27+
.workflow-container .react-flow__node-subflowNode:has([data-subflow-selected='true']) {
28+
z-index: 10 !important;
29+
}
30+
2631
/* Drag-over states */
2732
.loop-node-drag-over,
2833
.parallel-node-drag-over {
@@ -63,8 +68,8 @@ export interface SubflowNodeData {
6368
*/
6469
export const SubflowNodeComponent = memo(({ data, id }: NodeProps<SubflowNodeData>) => {
6570
const { getNodes } = useReactFlow()
66-
const { collaborativeBatchRemoveBlocks } = useCollaborativeWorkflow()
6771
const blockRef = useRef<HTMLDivElement>(null)
72+
const userPermissions = useUserPermissionsContext()
6873

6974
const currentWorkflow = useCurrentWorkflow()
7075
const currentBlock = currentWorkflow.getBlockById(id)
@@ -80,6 +85,8 @@ export const SubflowNodeComponent = memo(({ data, id }: NodeProps<SubflowNodeDat
8085
const currentBlockId = usePanelEditorStore((state) => state.currentBlockId)
8186
const isFocused = currentBlockId === id
8287

88+
const isPreviewSelected = data?.isPreviewSelected || false
89+
8390
/**
8491
* Calculate the nesting level of this subflow node based on its parent hierarchy.
8592
* Used to apply appropriate styling for nested containers.
@@ -125,8 +132,6 @@ export const SubflowNodeComponent = memo(({ data, id }: NodeProps<SubflowNodeDat
125132
return { top: `${HANDLE_POSITIONS.DEFAULT_Y_OFFSET}px`, transform: 'translateY(-50%)' }
126133
}
127134

128-
const isPreviewSelected = data?.isPreviewSelected || false
129-
130135
/**
131136
* Determine the ring styling based on subflow state priority:
132137
* 1. Focused (selected in editor) or preview selected - blue ring
@@ -162,7 +167,12 @@ export const SubflowNodeComponent = memo(({ data, id }: NodeProps<SubflowNodeDat
162167
data-node-id={id}
163168
data-type='subflowNode'
164169
data-nesting-level={nestingLevel}
170+
data-subflow-selected={isFocused || isPreviewSelected}
165171
>
172+
{!isPreview && (
173+
<ActionBar blockId={id} blockType={data.kind} disabled={!userPermissions.canEdit} />
174+
)}
175+
166176
{/* Header Section */}
167177
<div
168178
className={cn(
@@ -180,18 +190,6 @@ export const SubflowNodeComponent = memo(({ data, id }: NodeProps<SubflowNodeDat
180190
{blockName}
181191
</span>
182192
</div>
183-
{!isPreview && (
184-
<Button
185-
variant='ghost'
186-
onClick={(e) => {
187-
e.stopPropagation()
188-
collaborativeBatchRemoveBlocks([id])
189-
}}
190-
className='h-[14px] w-[14px] p-0 opacity-0 transition-opacity duration-100 group-hover:opacity-100'
191-
>
192-
<Trash className='h-[14px] w-[14px]' />
193-
</Button>
194-
)}
195193
</div>
196194

197195
{!isPreview && (

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/index.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/workflow-block.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { getBaseUrl } from '@/lib/core/utils/urls'
99
import { createMcpToolId } from '@/lib/mcp/utils'
1010
import { getProviderIdFromServiceId } from '@/lib/oauth'
1111
import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider'
12-
import { ActionBar } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components'
12+
import { ActionBar } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/action-bar/action-bar'
1313
import {
1414
useBlockProperties,
1515
useChildWorkflow,

0 commit comments

Comments
 (0)