From c543a930cdd2dd21dff35ea23c9ca3507c52b37c Mon Sep 17 00:00:00 2001 From: Baptiste Devessier Date: Tue, 14 Jan 2025 22:38:44 +0100 Subject: [PATCH] Improve workflow arrows' design (#9619) Old design: ![CleanShot_2024-11-12_at_17 37 33](https://github.com/user-attachments/assets/1fcaba6d-f23c-4679-b038-d051abeb0bbd) New design: ![CleanShot 2025-01-14 at 18 22 10@2x](https://github.com/user-attachments/assets/a683163d-2e3c-42ed-8abd-1f1fd31bf7db) --- .../WorkflowDiagramBaseStepNode.tsx | 9 ++++--- .../components/WorkflowDiagramCanvasBase.tsx | 12 +++++++++ .../WorkflowDiagramCreateStepNode.tsx | 8 ++++-- .../WorkflowDiagramCustomMarkers.tsx | 25 +++++++++++++++++++ .../constants/EdgeRoundedArrowMarkerId.ts | 1 + ...kflowVisualizerEdgeDefaultConfiguration.ts | 12 +++++++++ .../utils/addCreateStepNodes.ts | 7 ++---- .../utils/generateWorkflowDiagram.ts | 11 ++------ 8 files changed, 66 insertions(+), 19 deletions(-) create mode 100644 packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCustomMarkers.tsx create mode 100644 packages/twenty-front/src/modules/workflow/workflow-diagram/constants/EdgeRoundedArrowMarkerId.ts create mode 100644 packages/twenty-front/src/modules/workflow/workflow-diagram/constants/WorkflowVisualizerEdgeDefaultConfiguration.ts diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramBaseStepNode.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramBaseStepNode.tsx index 2b4658712..852aef9a2 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramBaseStepNode.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramBaseStepNode.tsx @@ -48,7 +48,7 @@ const StyledStepNodeInnerContainer = styled.div<{ variant?: Variant }>` position: relative; box-shadow: ${({ variant, theme }) => - variant === 'placeholder' ? 'none' : theme.boxShadow.superHeavy}; + variant === 'placeholder' ? 'none' : theme.boxShadow.strong}; .selectable.selected &, .selectable:focus &, @@ -63,7 +63,7 @@ const StyledStepNodeLabel = styled.div<{ variant?: Variant }>` display: flex; font-size: ${({ theme }) => theme.font.size.lg}; font-weight: ${({ theme }) => theme.font.weight.medium}; - column-gap: ${({ theme }) => theme.spacing(3)}; + column-gap: ${({ theme }) => theme.spacing(2)}; color: ${({ variant, theme }) => variant === 'placeholder' ? theme.font.color.extraLight @@ -72,7 +72,10 @@ const StyledStepNodeLabel = styled.div<{ variant?: Variant }>` `; const StyledSourceHandle = styled(Handle)` - background-color: ${({ theme }) => theme.color.gray50}; + background-color: ${({ theme }) => theme.grayScale.gray25}; + border: none; + width: 4px; + height: 4px; `; export const StyledTargetHandle = styled(Handle)` diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasBase.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasBase.tsx index aa42468c7..e48d5b300 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasBase.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasBase.tsx @@ -1,6 +1,7 @@ import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu'; import { useListenRightDrawerClose } from '@/ui/layout/right-drawer/hooks/useListenRightDrawerClose'; import { WorkflowVersionStatus } from '@/workflow/types/Workflow'; +import { WorkflowDiagramCustomMarkers } from '@/workflow/workflow-diagram/components/WorkflowDiagramCustomMarkers'; import { WorkflowVersionStatusTag } from '@/workflow/workflow-diagram/components/WorkflowVersionStatusTag'; import { useRightDrawerState } from '@/workflow/workflow-diagram/hooks/useRightDrawerState'; import { workflowDiagramState } from '@/workflow/workflow-diagram/states/workflowDiagramState'; @@ -46,6 +47,14 @@ const StyledResetReactflowStyles = styled.div` white-space: nowrap; } + .react-flow__handle { + min-height: 0; + min-width: 0; + } + .react-flow__handle.connectionindicator { + cursor: pointer; + } + --xy-node-border-radius: none; --xy-node-border: none; --xy-node-background-color: none; @@ -182,6 +191,8 @@ export const WorkflowDiagramCanvasBase = ({ return ( + + { if (isDefined(node)) { @@ -214,6 +225,7 @@ export const WorkflowDiagramCanvasBase = ({ edgesFocusable={false} nodesDraggable={false} onPaneClick={closeCommandMenu} + nodesConnectable={false} paneClickDistance={10} // Fix small unwanted user dragging does not select node > diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCreateStepNode.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCreateStepNode.tsx index 98b93c689..d9e7b0a4d 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCreateStepNode.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCreateStepNode.tsx @@ -2,16 +2,20 @@ import styled from '@emotion/styled'; import { Handle, Position } from '@xyflow/react'; import { IconButton, IconPlus } from 'twenty-ui'; +const StyledContainer = styled.div` + padding-top: ${({ theme }) => theme.spacing(1)}; +`; + export const StyledTargetHandle = styled(Handle)` visibility: hidden; `; export const WorkflowDiagramCreateStepNode = () => { return ( - <> + - + ); }; diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCustomMarkers.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCustomMarkers.tsx new file mode 100644 index 000000000..127b25c2c --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCustomMarkers.tsx @@ -0,0 +1,25 @@ +import { EDGE_ROUNDED_ARROW_MARKER_ID } from '@/workflow/workflow-diagram/constants/EdgeRoundedArrowMarkerId'; +import { useTheme } from '@emotion/react'; + +export const WorkflowDiagramCustomMarkers = () => { + const theme = useTheme(); + + return ( + + + + + + + + ); +}; diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/constants/EdgeRoundedArrowMarkerId.ts b/packages/twenty-front/src/modules/workflow/workflow-diagram/constants/EdgeRoundedArrowMarkerId.ts new file mode 100644 index 000000000..9f2a061ee --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/constants/EdgeRoundedArrowMarkerId.ts @@ -0,0 +1 @@ +export const EDGE_ROUNDED_ARROW_MARKER_ID = 'arrow-rounded'; diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/constants/WorkflowVisualizerEdgeDefaultConfiguration.ts b/packages/twenty-front/src/modules/workflow/workflow-diagram/constants/WorkflowVisualizerEdgeDefaultConfiguration.ts new file mode 100644 index 000000000..6ab64cc44 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/constants/WorkflowVisualizerEdgeDefaultConfiguration.ts @@ -0,0 +1,12 @@ +import { EDGE_ROUNDED_ARROW_MARKER_ID } from '@/workflow/workflow-diagram/constants/EdgeRoundedArrowMarkerId'; +import { WorkflowDiagramEdge } from '@/workflow/workflow-diagram/types/WorkflowDiagram'; +import { THEME_COMMON } from 'twenty-ui'; + +export const WORKFLOW_VISUALIZER_EDGE_DEFAULT_CONFIGURATION = { + markerEnd: EDGE_ROUNDED_ARROW_MARKER_ID, + style: { + stroke: THEME_COMMON.grayScale.gray25, + }, + deletable: false, + selectable: false, +} satisfies Partial; diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/utils/addCreateStepNodes.ts b/packages/twenty-front/src/modules/workflow/workflow-diagram/utils/addCreateStepNodes.ts index ca9d11505..c2de38c52 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/utils/addCreateStepNodes.ts +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/utils/addCreateStepNodes.ts @@ -1,9 +1,9 @@ +import { WORKFLOW_VISUALIZER_EDGE_DEFAULT_CONFIGURATION } from '@/workflow/workflow-diagram/constants/WorkflowVisualizerEdgeDefaultConfiguration'; import { WorkflowDiagram, WorkflowDiagramEdge, WorkflowDiagramNode, } from '@/workflow/workflow-diagram/types/WorkflowDiagram'; -import { MarkerType } from '@xyflow/react'; import { v4 } from 'uuid'; export const addCreateStepNodes = ({ nodes, edges }: WorkflowDiagram) => { @@ -30,13 +30,10 @@ export const addCreateStepNodes = ({ nodes, edges }: WorkflowDiagram) => { updatedNodes.push(newCreateStepNode); updatedEdges.push({ + ...WORKFLOW_VISUALIZER_EDGE_DEFAULT_CONFIGURATION, id: v4(), source: node.id, target: newCreateStepNode.id, - markerEnd: { - type: MarkerType.ArrowClosed, - }, - deletable: false, }); } diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/utils/generateWorkflowDiagram.ts b/packages/twenty-front/src/modules/workflow/workflow-diagram/utils/generateWorkflowDiagram.ts index 3c84483d5..a760a019c 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/utils/generateWorkflowDiagram.ts +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/utils/generateWorkflowDiagram.ts @@ -1,6 +1,7 @@ import { WorkflowStep, WorkflowTrigger } from '@/workflow/types/Workflow'; import { assertUnreachable } from '@/workflow/utils/assertUnreachable'; import { splitWorkflowTriggerEventName } from '@/workflow/utils/splitWorkflowTriggerEventName'; +import { WORKFLOW_VISUALIZER_EDGE_DEFAULT_CONFIGURATION } from '@/workflow/workflow-diagram/constants/WorkflowVisualizerEdgeDefaultConfiguration'; import { WorkflowDiagram, WorkflowDiagramEdge, @@ -8,7 +9,6 @@ import { } from '@/workflow/workflow-diagram/types/WorkflowDiagram'; import { TRIGGER_STEP_ID } from '@/workflow/workflow-trigger/constants/TriggerStepId'; -import { MarkerType } from '@xyflow/react'; import { capitalize } from 'twenty-shared'; import { isDefined } from 'twenty-ui'; import { v4 } from 'uuid'; @@ -23,7 +23,6 @@ export const generateWorkflowDiagram = ({ const nodes: Array = []; const edges: Array = []; - // Helper function to generate nodes and edges recursively const processNode = ( step: WorkflowStep, parentNodeId: string, @@ -45,22 +44,16 @@ export const generateWorkflowDiagram = ({ }, }); - // Create an edge from the parent node to this node edges.push({ + ...WORKFLOW_VISUALIZER_EDGE_DEFAULT_CONFIGURATION, id: v4(), source: parentNodeId, target: nodeId, - markerEnd: { - type: MarkerType.ArrowClosed, - }, - deletable: false, - selectable: false, }); return nodeId; }; - // Start with the trigger node const triggerNodeId = TRIGGER_STEP_ID; if (isDefined(trigger)) {