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
deleted file mode 100644
index a1cb0f14d..000000000
--- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramBaseStepNode.tsx
+++ /dev/null
@@ -1,219 +0,0 @@
-import { NODE_BORDER_WIDTH } from '@/workflow/workflow-diagram/constants/NodeBorderWidth';
-import { NODE_HANDLE_HEIGHT_PX } from '@/workflow/workflow-diagram/constants/NodeHandleHeightPx';
-import { NODE_HANDLE_WIDTH_PX } from '@/workflow/workflow-diagram/constants/NodeHandleWidthPx';
-import { NODE_ICON_LEFT_MARGIN } from '@/workflow/workflow-diagram/constants/NodeIconLeftMargin';
-import { NODE_ICON_WIDTH } from '@/workflow/workflow-diagram/constants/NodeIconWidth';
-import { WorkflowDiagramStepNodeData } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
-import { WorkflowDiagramNodeVariant } from '@/workflow/workflow-diagram/types/WorkflowDiagramNodeVariant';
-import { css } from '@emotion/react';
-import styled from '@emotion/styled';
-import { Handle, Position } from '@xyflow/react';
-import React from 'react';
-import { capitalize, isDefined } from 'twenty-shared';
-import { Label, OverflowingTextWithTooltip } from 'twenty-ui';
-
-const StyledStepNodeContainer = styled.div`
- display: flex;
- flex-direction: column;
-
- padding-block: ${({ theme }) => theme.spacing(3)};
-`;
-
-const StyledStepNodeType = styled.div<{
- nodeVariant: WorkflowDiagramNodeVariant;
-}>`
- ${({ nodeVariant, theme }) => {
- switch (nodeVariant) {
- case 'success': {
- return css`
- background-color: ${theme.tag.background.turquoise};
- color: ${theme.tag.text.turquoise};
- `;
- }
- case 'failure': {
- return css`
- background-color: ${theme.tag.background.red};
- color: ${theme.color.red};
- `;
- }
- default: {
- return css`
- background-color: ${theme.background.tertiary};
- `;
- }
- }
- }}
-
- align-self: flex-start;
- border-radius: ${({ theme }) =>
- `${theme.border.radius.sm} ${theme.border.radius.sm} 0 0`};
- margin-left: ${({ theme }) => theme.spacing(2)};
- padding: ${({ theme }) => theme.spacing(1)} ${({ theme }) => theme.spacing(2)};
-
- .selectable:is(.selected, :focus, :focus-visible) & {
- ${({ nodeVariant, theme }) => {
- switch (nodeVariant) {
- case 'empty':
- case 'default':
- case 'not-executed':
- return css`
- background-color: ${theme.color.blue};
- color: ${theme.font.color.inverted};
- `;
- }
- }}
- }
-`.withComponent(Label);
-
-const StyledStepNodeInnerContainer = styled.div<{
- variant: WorkflowDiagramNodeVariant;
-}>`
- background: ${({ theme }) => theme.background.secondary};
- border-color: ${({ theme }) => theme.border.color.medium};
-
- border-radius: ${({ theme }) => theme.border.radius.md};
- border-style: solid;
- border-width: ${NODE_BORDER_WIDTH}px;
- box-shadow: ${({ variant, theme }) =>
- variant === 'empty' ? 'none' : theme.boxShadow.strong};
- display: flex;
- gap: ${({ theme }) => theme.spacing(2)};
- padding: ${({ theme }) => theme.spacing(2)};
-
- position: relative;
-
- transition: background ${({ theme }) => theme.animation.duration.fast} ease;
-
- .workflow-node-container:hover & {
- ${({ theme }) => {
- return css`
- background: linear-gradient(
- 0deg,
- ${theme.background.transparent.lighter} 0%,
- ${theme.background.transparent.lighter} 100%
- ),
- ${theme.background.secondary};
- `;
- }}
- }
-
- .selectable:is(.selected, :focus, :focus-visible)
- :is(.workflow-node-container, .workflow-node-container:hover)
- & {
- ${({ theme, variant }) => {
- switch (variant) {
- case 'success': {
- return css`
- background: ${theme.adaptiveColors.turquoise1};
- border-color: ${theme.adaptiveColors.turquoise4};
- `;
- }
- case 'failure': {
- return css`
- background: ${theme.background.danger};
- border-color: ${theme.color.red};
- `;
- }
- default: {
- return css`
- background: ${theme.adaptiveColors.blue1};
- border-color: ${theme.color.blue};
- `;
- }
- }
- }}
- }
-`;
-
-const StyledStepNodeLabel = styled.div<{
- variant: WorkflowDiagramNodeVariant;
-}>`
- align-items: center;
- display: flex;
- font-size: 13px;
- font-weight: ${({ theme }) => theme.font.weight.medium};
- column-gap: ${({ theme }) => theme.spacing(2)};
- color: ${({ variant, theme }) => {
- switch (variant) {
- case 'empty':
- case 'not-executed':
- return theme.font.color.light;
- default:
- return theme.font.color.primary;
- }
- }};
- max-width: 200px;
-
- .selectable:is(.selected, :focus, :focus-visible) & {
- color: ${({ theme }) => theme.font.color.primary};
- }
-`;
-
-export const StyledHandle = styled(Handle)`
- background-color: ${({ theme }) => theme.grayScale.gray25};
- border: none;
- width: ${NODE_HANDLE_WIDTH_PX}px;
- height: ${NODE_HANDLE_HEIGHT_PX}px;
-`;
-
-const StyledSourceHandle = styled(StyledHandle)`
- background-color: ${({ theme }) => theme.border.color.strong};
- left: ${NODE_ICON_WIDTH + NODE_ICON_LEFT_MARGIN + NODE_BORDER_WIDTH}px;
-`;
-
-const StyledTargetHandle = styled(StyledSourceHandle)`
- left: ${NODE_ICON_WIDTH + NODE_ICON_LEFT_MARGIN + NODE_BORDER_WIDTH}px;
- visibility: hidden;
-`;
-
-const StyledRightFloatingElementContainer = styled.div`
- display: flex;
- align-items: center;
- position: absolute;
- right: ${({ theme }) => theme.spacing(-4)};
- bottom: 0;
- top: 0;
- transform: translateX(100%);
-`;
-
-export const WorkflowDiagramBaseStepNode = ({
- nodeType,
- name,
- variant,
- Icon,
- RightFloatingElement,
-}: {
- nodeType: WorkflowDiagramStepNodeData['nodeType'];
- name: string;
- variant: WorkflowDiagramNodeVariant;
- Icon?: React.ReactNode;
- RightFloatingElement?: React.ReactNode;
-}) => {
- return (
-
- {nodeType !== 'trigger' ? (
-
- ) : null}
-
-
- {capitalize(nodeType)}
-
-
-
-
- {Icon}
-
-
-
-
- {isDefined(RightFloatingElement) ? (
-
- {RightFloatingElement}
-
- ) : null}
-
-
-
-
- );
-};
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 170d1dfd4..c060ff842 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
@@ -1,4 +1,4 @@
-import { StyledHandle } from '@/workflow/workflow-diagram/components/WorkflowDiagramBaseStepNode';
+import { StyledHandle } from '@/workflow/workflow-diagram/components/WorkflowDiagramStepNodeBase';
import { NODE_BORDER_WIDTH } from '@/workflow/workflow-diagram/constants/NodeBorderWidth';
import { NODE_ICON_LEFT_MARGIN } from '@/workflow/workflow-diagram/constants/NodeIconLeftMargin';
import { NODE_ICON_WIDTH } from '@/workflow/workflow-diagram/constants/NodeIconWidth';
diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramEmptyTrigger.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramEmptyTrigger.tsx
index 60a6bb96c..dd1528b8f 100644
--- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramEmptyTrigger.tsx
+++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramEmptyTrigger.tsx
@@ -1,4 +1,4 @@
-import { WorkflowDiagramBaseStepNode } from '@/workflow/workflow-diagram/components/WorkflowDiagramBaseStepNode';
+import { WorkflowDiagramStepNodeBase } from '@/workflow/workflow-diagram/components/WorkflowDiagramStepNodeBase';
import styled from '@emotion/styled';
const StyledStepNodeLabelIconContainer = styled.div`
@@ -12,7 +12,7 @@ const StyledStepNodeLabelIconContainer = styled.div`
export const WorkflowDiagramEmptyTrigger = () => {
return (
- theme.background.transparent.light};
- border-radius: ${({ theme }) => theme.spacing(1)};
+const StyledStepNodeContainer = styled.div`
display: flex;
- justify-content: center;
- padding: ${({ theme }) => theme.spacing(1)};
+ flex-direction: column;
+
+ padding-block: ${({ theme }) => theme.spacing(3)};
+`;
+
+const StyledStepNodeType = styled.div<{
+ nodeVariant: WorkflowDiagramNodeVariant;
+}>`
+ ${({ nodeVariant, theme }) => {
+ switch (nodeVariant) {
+ case 'success': {
+ return css`
+ background-color: ${theme.tag.background.turquoise};
+ color: ${theme.tag.text.turquoise};
+ `;
+ }
+ case 'failure': {
+ return css`
+ background-color: ${theme.tag.background.red};
+ color: ${theme.color.red};
+ `;
+ }
+ default: {
+ return css`
+ background-color: ${theme.background.tertiary};
+ `;
+ }
+ }
+ }}
+
+ align-self: flex-start;
+ border-radius: ${({ theme }) =>
+ `${theme.border.radius.sm} ${theme.border.radius.sm} 0 0`};
+ margin-left: ${({ theme }) => theme.spacing(2)};
+ padding: ${({ theme }) => theme.spacing(1)} ${({ theme }) => theme.spacing(2)};
+
+ .selectable:is(.selected, :focus, :focus-visible) & {
+ ${({ nodeVariant, theme }) => {
+ switch (nodeVariant) {
+ case 'empty':
+ case 'default':
+ case 'not-executed':
+ return css`
+ background-color: ${theme.color.blue};
+ color: ${theme.font.color.inverted};
+ `;
+ }
+ }}
+ }
+`.withComponent(Label);
+
+const StyledStepNodeInnerContainer = styled.div<{
+ variant: WorkflowDiagramNodeVariant;
+}>`
+ background: ${({ theme }) => theme.background.secondary};
+ border-color: ${({ theme }) => theme.border.color.medium};
+
+ border-radius: ${({ theme }) => theme.border.radius.md};
+ border-style: solid;
+ border-width: ${NODE_BORDER_WIDTH}px;
+ box-shadow: ${({ variant, theme }) =>
+ variant === 'empty' ? 'none' : theme.boxShadow.strong};
+ display: flex;
+ gap: ${({ theme }) => theme.spacing(2)};
+ padding: ${({ theme }) => theme.spacing(2)};
+
+ position: relative;
+
+ transition: background ${({ theme }) => theme.animation.duration.fast} ease;
+
+ .workflow-node-container:hover & {
+ ${({ theme }) => {
+ return css`
+ background: linear-gradient(
+ 0deg,
+ ${theme.background.transparent.lighter} 0%,
+ ${theme.background.transparent.lighter} 100%
+ ),
+ ${theme.background.secondary};
+ `;
+ }}
+ }
+
+ .selectable:is(.selected, :focus, :focus-visible)
+ :is(.workflow-node-container, .workflow-node-container:hover)
+ & {
+ ${({ theme, variant }) => {
+ switch (variant) {
+ case 'success': {
+ return css`
+ background: ${theme.adaptiveColors.turquoise1};
+ border-color: ${theme.adaptiveColors.turquoise4};
+ `;
+ }
+ case 'failure': {
+ return css`
+ background: ${theme.background.danger};
+ border-color: ${theme.color.red};
+ `;
+ }
+ default: {
+ return css`
+ background: ${theme.adaptiveColors.blue1};
+ border-color: ${theme.color.blue};
+ `;
+ }
+ }
+ }}
+ }
+`;
+
+const StyledStepNodeLabel = styled.div<{
+ variant: WorkflowDiagramNodeVariant;
+}>`
+ align-items: center;
+ display: flex;
+ font-size: 13px;
+ font-weight: ${({ theme }) => theme.font.weight.medium};
+ column-gap: ${({ theme }) => theme.spacing(2)};
+ color: ${({ variant, theme }) => {
+ switch (variant) {
+ case 'empty':
+ case 'not-executed':
+ return theme.font.color.light;
+ default:
+ return theme.font.color.primary;
+ }
+ }};
+ max-width: 200px;
+
+ .selectable:is(.selected, :focus, :focus-visible) & {
+ color: ${({ theme }) => theme.font.color.primary};
+ }
+`;
+
+export const StyledHandle = styled(Handle)`
+ background-color: ${({ theme }) => theme.grayScale.gray25};
+ border: none;
+ width: ${NODE_HANDLE_WIDTH_PX}px;
+ height: ${NODE_HANDLE_HEIGHT_PX}px;
+`;
+
+const StyledSourceHandle = styled(StyledHandle)`
+ background-color: ${({ theme }) => theme.border.color.strong};
+ left: ${NODE_ICON_WIDTH + NODE_ICON_LEFT_MARGIN + NODE_BORDER_WIDTH}px;
+`;
+
+const StyledTargetHandle = styled(StyledSourceHandle)`
+ left: ${NODE_ICON_WIDTH + NODE_ICON_LEFT_MARGIN + NODE_BORDER_WIDTH}px;
+ visibility: hidden;
+`;
+
+const StyledRightFloatingElementContainer = styled.div`
+ display: flex;
+ align-items: center;
+ position: absolute;
+ right: ${({ theme }) => theme.spacing(-4)};
+ bottom: 0;
+ top: 0;
+ transform: translateX(100%);
`;
export const WorkflowDiagramStepNodeBase = ({
- data,
+ nodeType,
+ name,
variant,
+ Icon,
RightFloatingElement,
}: {
- data: WorkflowDiagramStepNodeData;
+ nodeType: WorkflowDiagramStepNodeData['nodeType'];
+ name: string;
variant: WorkflowDiagramNodeVariant;
+ Icon?: React.ReactNode;
RightFloatingElement?: React.ReactNode;
}) => {
- const theme = useTheme();
- const { getIcon } = useIcons();
- const Icon = getIcon(getWorkflowNodeIconKey(data));
-
- const renderStepIcon = () => {
- switch (data.nodeType) {
- case 'trigger': {
- switch (data.triggerType) {
- case 'DATABASE_EVENT': {
- return (
-
-
-
- );
- }
- case 'MANUAL': {
- return (
-
-
-
- );
- }
- }
-
- return assertUnreachable(data.triggerType);
- }
- case 'action': {
- switch (data.actionType) {
- case 'CODE': {
- return (
-
-
-
- );
- }
- case 'SEND_EMAIL': {
- return (
-
-
-
- );
- }
- default: {
- return (
-
-
-
- );
- }
- }
- }
- }
- };
-
return (
-
+
+ {nodeType !== 'trigger' ? (
+
+ ) : null}
+
+
+ {capitalize(nodeType)}
+
+
+
+
+ {Icon}
+
+
+
+
+ {isDefined(RightFloatingElement) ? (
+
+ {RightFloatingElement}
+
+ ) : null}
+
+
+
+
);
};
diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramStepNodeEditableContent.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramStepNodeEditableContent.tsx
index 3c98a60a1..ff03ef61d 100644
--- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramStepNodeEditableContent.tsx
+++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramStepNodeEditableContent.tsx
@@ -1,4 +1,5 @@
import { WorkflowDiagramStepNodeBase } from '@/workflow/workflow-diagram/components/WorkflowDiagramStepNodeBase';
+import { WorkflowDiagramStepNodeIcon } from '@/workflow/workflow-diagram/components/WorkflowDiagramStepNodeIcon';
import { WorkflowDiagramStepNodeData } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
import { WorkflowDiagramNodeVariant } from '@/workflow/workflow-diagram/types/WorkflowDiagramNodeVariant';
import { FloatingIconButton, IconTrash } from 'twenty-ui';
@@ -16,8 +17,10 @@ export const WorkflowDiagramStepNodeEditableContent = ({
}) => {
return (
}
RightFloatingElement={
selected ? (
theme.background.transparent.light};
+ border-radius: ${({ theme }) => theme.spacing(1)};
+ display: flex;
+ justify-content: center;
+ padding: ${({ theme }) => theme.spacing(1)};
+`;
+
+export const WorkflowDiagramStepNodeIcon = ({
+ data,
+}: {
+ data: WorkflowDiagramStepNodeData;
+}) => {
+ const theme = useTheme();
+ const { getIcon } = useIcons();
+ const Icon = getIcon(getWorkflowNodeIconKey(data));
+
+ switch (data.nodeType) {
+ case 'trigger': {
+ switch (data.triggerType) {
+ case 'DATABASE_EVENT': {
+ return (
+
+
+
+ );
+ }
+ case 'MANUAL': {
+ return (
+
+
+
+ );
+ }
+ }
+
+ return assertUnreachable(data.triggerType);
+ }
+ case 'action': {
+ switch (data.actionType) {
+ case 'CODE': {
+ return (
+
+
+
+ );
+ }
+ case 'SEND_EMAIL': {
+ return (
+
+
+
+ );
+ }
+ default: {
+ return (
+
+
+
+ );
+ }
+ }
+ }
+ }
+};
diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramStepNodeReadonly.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramStepNodeReadonly.tsx
index 0b9b493bc..48bd8a9c1 100644
--- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramStepNodeReadonly.tsx
+++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramStepNodeReadonly.tsx
@@ -1,4 +1,5 @@
import { WorkflowDiagramStepNodeBase } from '@/workflow/workflow-diagram/components/WorkflowDiagramStepNodeBase';
+import { WorkflowDiagramStepNodeIcon } from '@/workflow/workflow-diagram/components/WorkflowDiagramStepNodeIcon';
import { WorkflowDiagramStepNodeData } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
export const WorkflowDiagramStepNodeReadonly = ({
@@ -6,5 +7,12 @@ export const WorkflowDiagramStepNodeReadonly = ({
}: {
data: WorkflowDiagramStepNodeData;
}) => {
- return ;
+ return (
+ }
+ />
+ );
};