From a9b7d75d87584f5717f4f0b89a9b1fe98c102d01 Mon Sep 17 00:00:00 2001 From: Waleed Date: Mon, 2 Feb 2026 12:22:08 -0800 Subject: [PATCH] feat(editor): added docs link to editor (#3116) --- .../panel/components/editor/editor.tsx | 133 ++++++------------ 1 file changed, 42 insertions(+), 91 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/editor.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/editor.tsx index 3d47e1fa4..07c8a9ce7 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/editor.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/editor.tsx @@ -50,6 +50,12 @@ import { useSubBlockStore } from '@/stores/workflows/subblock/store' /** Stable empty object to avoid creating new references */ const EMPTY_SUBBLOCK_VALUES = {} as Record +/** Shared style for dashed divider lines */ +const DASHED_DIVIDER_STYLE = { + backgroundImage: + 'repeating-linear-gradient(to right, var(--border) 0px, var(--border) 6px, transparent 6px, transparent 12px)', +} as const + /** * Icon component for rendering block icons. * @@ -89,31 +95,23 @@ export function Editor() { const blockConfig = currentBlock ? getBlock(currentBlock.type) : null const title = currentBlock?.name || 'Editor' - // Check if selected block is a subflow (loop or parallel) const isSubflow = currentBlock && (currentBlock.type === 'loop' || currentBlock.type === 'parallel') - // Get subflow display properties from configs const subflowConfig = isSubflow ? (currentBlock.type === 'loop' ? LoopTool : ParallelTool) : null - // Check if selected block is a workflow block const isWorkflowBlock = currentBlock && (currentBlock.type === 'workflow' || currentBlock.type === 'workflow_input') - // Get workspace ID from params const params = useParams() const workspaceId = params.workspaceId as string - // Refs for resize functionality const subBlocksRef = useRef(null) - // Get user permissions const userPermissions = useUserPermissionsContext() - // Get active workflow ID const activeWorkflowId = useWorkflowRegistry((state) => state.activeWorkflowId) - // Get block properties (advanced/trigger modes) const { advancedMode, triggerMode } = useEditorBlockProperties( currentBlockId, currentWorkflow.isSnapshotView @@ -145,10 +143,9 @@ export function Editor() { [subBlocksForCanonical] ) const canonicalModeOverrides = currentBlock?.data?.canonicalModes - const advancedValuesPresent = hasAdvancedValues( - subBlocksForCanonical, - blockSubBlockValues, - canonicalIndex + const advancedValuesPresent = useMemo( + () => hasAdvancedValues(subBlocksForCanonical, blockSubBlockValues, canonicalIndex), + [subBlocksForCanonical, blockSubBlockValues, canonicalIndex] ) const displayAdvancedOptions = userPermissions.canEdit ? advancedMode @@ -156,11 +153,9 @@ export function Editor() { const hasAdvancedOnlyFields = useMemo(() => { for (const subBlock of subBlocksForCanonical) { - // Must be standalone advanced (mode: 'advanced' without canonicalParamId) if (subBlock.mode !== 'advanced') continue if (canonicalIndex.canonicalIdBySubBlockId[subBlock.id]) continue - // Check condition - skip if condition not met for current values if ( subBlock.condition && !evaluateSubBlockCondition(subBlock.condition, blockSubBlockValues) @@ -173,7 +168,6 @@ export function Editor() { return false }, [subBlocksForCanonical, canonicalIndex.canonicalIdBySubBlockId, blockSubBlockValues]) - // Get subblock layout using custom hook const { subBlocks, stateToUse: subBlockState } = useEditorSubblockLayout( blockConfig || ({} as any), currentBlockId || '', @@ -206,31 +200,34 @@ export function Editor() { return { regularSubBlocks: regular, advancedOnlySubBlocks: advancedOnly } }, [subBlocks, canonicalIndex.canonicalIdBySubBlockId]) - // Get block connections const { incomingConnections, hasIncomingConnections } = useBlockConnections(currentBlockId || '') - // Connections resize hook const { handleMouseDown: handleConnectionsResizeMouseDown, isResizing } = useConnectionsResize({ subBlocksRef, }) - // Collaborative actions const { collaborativeSetBlockCanonicalMode, collaborativeUpdateBlockName, collaborativeToggleBlockAdvancedMode, } = useCollaborativeWorkflow() - // Advanced mode toggle handler const handleToggleAdvancedMode = useCallback(() => { if (!currentBlockId || !userPermissions.canEdit) return collaborativeToggleBlockAdvancedMode(currentBlockId) }, [currentBlockId, userPermissions.canEdit, collaborativeToggleBlockAdvancedMode]) - // Rename state const [isRenaming, setIsRenaming] = useState(false) const [editedName, setEditedName] = useState('') - const nameInputRef = useRef(null) + + /** + * Ref callback that auto-selects the input text when mounted. + */ + const nameInputRefCallback = useCallback((element: HTMLInputElement | null) => { + if (element) { + element.select() + } + }, []) /** * Handles starting the rename process. @@ -251,7 +248,6 @@ export function Editor() { if (trimmedName && trimmedName !== currentBlock?.name) { const result = collaborativeUpdateBlockName(currentBlockId, trimmedName) if (!result.success) { - // Keep rename mode open on error so user can correct the name return } } @@ -266,14 +262,6 @@ export function Editor() { setEditedName('') }, []) - // Focus input when entering rename mode - useEffect(() => { - if (isRenaming && nameInputRef.current) { - nameInputRef.current.select() - } - }, [isRenaming]) - - // Trigger rename mode when signaled from context menu useEffect(() => { if (shouldFocusRename && currentBlock) { handleStartRename() @@ -284,17 +272,13 @@ export function Editor() { /** * Handles opening documentation link in a new secure tab. */ - const handleOpenDocs = () => { + const handleOpenDocs = useCallback(() => { const docsLink = isSubflow ? subflowConfig?.docsLink : blockConfig?.docsLink - if (docsLink) { - window.open(docsLink, '_blank', 'noopener,noreferrer') - } - } + window.open(docsLink || 'https://docs.sim.ai/quick-reference', '_blank', 'noopener,noreferrer') + }, [isSubflow, subflowConfig?.docsLink, blockConfig?.docsLink]) - // Get child workflow ID for workflow blocks const childWorkflowId = isWorkflowBlock ? blockSubBlockValues?.workflowId : null - // Fetch child workflow state for preview (only for workflow blocks with a selected workflow) const { data: childWorkflowState, isLoading: isLoadingChildWorkflow } = useWorkflowState(childWorkflowId) @@ -307,7 +291,6 @@ export function Editor() { } }, [childWorkflowId, workspaceId]) - // Determine if connections are at minimum height (collapsed state) const isConnectionsAtMinHeight = connectionsHeight <= 35 return ( @@ -328,7 +311,7 @@ export function Editor() { )} {isRenaming ? ( setEditedName(e.target.value)} @@ -399,23 +382,21 @@ export function Editor() { )} */} - {currentBlock && (isSubflow ? subflowConfig?.docsLink : blockConfig?.docsLink) && ( - - - - - -

Open docs

-
-
- )} + + + + + +

Open docs

+
+
@@ -495,13 +476,7 @@ export function Editor() {
-
+
)} @@ -566,13 +541,7 @@ export function Editor() { /> {showDivider && (
-
+
)}
@@ -581,13 +550,7 @@ export function Editor() { {hasAdvancedOnlyFields && userPermissions.canEdit && (
-
+
-
+
)} @@ -630,13 +587,7 @@ export function Editor() { /> {index < advancedOnlySubBlocks.length - 1 && (
-
+
)}