Skip to content

Commit 700eb2d

Browse files
authored
Add the new workflow not executed node type (twentyhq#10030)
- Added the new workflow `not executed` node type - Fixed minor style issues - Created one big catalog for all node variants ![image](https://github.com/user-attachments/assets/5e510d49-c6a2-42a9-9641-057cff481dd9)
1 parent 5528577 commit 700eb2d

File tree

5 files changed

+89
-173
lines changed

5 files changed

+89
-173
lines changed

packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramBaseStepNode.tsx

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -50,18 +50,16 @@ const StyledStepNodeType = styled.div<{
5050
margin-left: ${({ theme }) => theme.spacing(2)};
5151
padding: ${({ theme }) => theme.spacing(1)} ${({ theme }) => theme.spacing(2)};
5252
53-
.selectable.selected &,
54-
.selectable:focus &,
55-
.selectable:focus-visible & {
53+
.selectable:is(.selected, :focus, :focus-visible) & {
5654
${({ nodeVariant, theme }) => {
5755
switch (nodeVariant) {
5856
case 'empty':
59-
case 'default': {
57+
case 'default':
58+
case 'not-executed':
6059
return css`
6160
background-color: ${theme.color.blue};
6261
color: ${theme.font.color.inverted};
6362
`;
64-
}
6563
}
6664
}}
6765
}
@@ -70,7 +68,7 @@ const StyledStepNodeType = styled.div<{
7068
const StyledStepNodeInnerContainer = styled.div<{
7169
variant: WorkflowDiagramNodeVariant;
7270
}>`
73-
background-color: ${({ theme }) => theme.background.secondary};
71+
background: ${({ theme }) => theme.background.secondary};
7472
border-color: ${({ theme }) => theme.border.color.medium};
7573
7674
border-radius: ${({ theme }) => theme.border.radius.md};
@@ -84,26 +82,41 @@ const StyledStepNodeInnerContainer = styled.div<{
8482
8583
position: relative;
8684
87-
.selectable.selected &,
88-
.selectable:focus &,
89-
.selectable:focus-visible & {
85+
transition: background ${({ theme }) => theme.animation.duration.fast} ease;
86+
87+
.workflow-node-container:hover & {
88+
${({ theme }) => {
89+
return css`
90+
background: linear-gradient(
91+
0deg,
92+
${theme.background.transparent.lighter} 0%,
93+
${theme.background.transparent.lighter} 100%
94+
),
95+
${theme.background.secondary};
96+
`;
97+
}}
98+
}
99+
100+
.selectable:is(.selected, :focus, :focus-visible)
101+
:is(.workflow-node-container, .workflow-node-container:hover)
102+
& {
90103
${({ theme, variant }) => {
91104
switch (variant) {
92105
case 'success': {
93106
return css`
94-
background-color: ${theme.adaptiveColors.turquoise1};
107+
background: ${theme.adaptiveColors.turquoise1};
95108
border-color: ${theme.adaptiveColors.turquoise4};
96109
`;
97110
}
98111
case 'failure': {
99112
return css`
100-
background-color: ${theme.background.danger};
113+
background: ${theme.background.danger};
101114
border-color: ${theme.color.red};
102115
`;
103116
}
104117
default: {
105118
return css`
106-
background-color: ${theme.accent.quaternary};
119+
background: ${theme.adaptiveColors.blue1};
107120
border-color: ${theme.color.blue};
108121
`;
109122
}
@@ -120,11 +133,20 @@ const StyledStepNodeLabel = styled.div<{
120133
font-size: 13px;
121134
font-weight: ${({ theme }) => theme.font.weight.medium};
122135
column-gap: ${({ theme }) => theme.spacing(2)};
123-
color: ${({ variant, theme }) =>
124-
variant === 'empty'
125-
? theme.font.color.extraLight
126-
: theme.font.color.primary};
136+
color: ${({ variant, theme }) => {
137+
switch (variant) {
138+
case 'empty':
139+
case 'not-executed':
140+
return theme.font.color.light;
141+
default:
142+
return theme.font.color.primary;
143+
}
144+
}};
127145
max-width: 200px;
146+
147+
.selectable:is(.selected, :focus, :focus-visible) & {
148+
color: ${({ theme }) => theme.font.color.primary};
149+
}
128150
`;
129151

130152
export const StyledHandle = styled(Handle)`
@@ -168,7 +190,7 @@ export const WorkflowDiagramBaseStepNode = ({
168190
RightFloatingElement?: React.ReactNode;
169191
}) => {
170192
return (
171-
<StyledStepNodeContainer>
193+
<StyledStepNodeContainer className="workflow-node-container">
172194
{nodeType !== 'trigger' ? (
173195
<StyledTargetHandle type="target" position={Position.Top} />
174196
) : null}
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,33 @@
11
import { Meta, StoryObj } from '@storybook/react';
22

33
import { WorkflowDiagramStepNodeData } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
4+
import { WorkflowDiagramNodeVariant } from '@/workflow/workflow-diagram/types/WorkflowDiagramNodeVariant';
45
import { fn } from '@storybook/test';
56
import '@xyflow/react/dist/style.css';
7+
import { ComponentProps } from 'react';
68
import { CatalogDecorator, CatalogStory } from 'twenty-ui';
79
import { ReactflowDecorator } from '~/testing/decorators/ReactflowDecorator';
810
import { graphqlMocks } from '~/testing/graphqlMocks';
911
import { WorkflowDiagramStepNodeEditableContent } from '../WorkflowDiagramStepNodeEditableContent';
1012

11-
const meta: Meta<typeof WorkflowDiagramStepNodeEditableContent> = {
13+
type ComponentState = 'default' | 'hover' | 'selected';
14+
15+
type WrapperProps = ComponentProps<
16+
typeof WorkflowDiagramStepNodeEditableContent
17+
> & { state: ComponentState };
18+
19+
const Wrapper = (_props: WrapperProps) => {
20+
return <div></div>;
21+
};
22+
23+
const meta: Meta<WrapperProps> = {
1224
title: 'Modules/Workflow/WorkflowDiagramStepNodeEditableContent',
1325
component: WorkflowDiagramStepNodeEditableContent,
1426
};
1527

1628
export default meta;
1729

18-
type Story = StoryObj<typeof WorkflowDiagramStepNodeEditableContent>;
30+
type Story = StoryObj<typeof Wrapper>;
1931

2032
const ALL_STEPS = [
2133
{
@@ -47,17 +59,13 @@ const ALL_STEPS = [
4759
{ nodeType: 'action', actionType: 'CODE', name: 'Code' },
4860
] satisfies WorkflowDiagramStepNodeData[];
4961

50-
export const All: CatalogStory<
51-
Story,
52-
typeof WorkflowDiagramStepNodeEditableContent
53-
> = {
62+
export const Catalog: CatalogStory<Story, typeof Wrapper> = {
5463
args: {
5564
onDelete: fn(),
56-
variant: 'default',
57-
selected: false,
5865
},
5966
parameters: {
6067
msw: graphqlMocks,
68+
pseudo: { hover: ['.hover'] },
6169
catalog: {
6270
options: {
6371
elementContainer: {
@@ -71,159 +79,36 @@ export const All: CatalogStory<
7179
values: ALL_STEPS,
7280
props: (data: WorkflowDiagramStepNodeData) => ({ data }),
7381
},
74-
],
75-
},
76-
},
77-
decorators: [CatalogDecorator, ReactflowDecorator],
78-
};
79-
80-
export const AllSelected: CatalogStory<
81-
Story,
82-
typeof WorkflowDiagramStepNodeEditableContent
83-
> = {
84-
args: {
85-
onDelete: fn(),
86-
variant: 'default',
87-
selected: true,
88-
},
89-
parameters: {
90-
msw: graphqlMocks,
91-
catalog: {
92-
options: {
93-
elementContainer: {
94-
width: 250,
95-
style: { position: 'relative' },
96-
className: 'selectable selected',
97-
},
98-
},
99-
dimensions: [
10082
{
101-
name: 'step type',
102-
values: ALL_STEPS,
103-
props: (data: WorkflowDiagramStepNodeData) => ({ data }),
83+
name: 'variant',
84+
values: [
85+
'empty',
86+
'default',
87+
'success',
88+
'failure',
89+
'not-executed',
90+
] satisfies WorkflowDiagramNodeVariant[],
91+
props: (variant: WorkflowDiagramNodeVariant) => ({ variant }),
10492
},
105-
],
106-
},
107-
},
108-
decorators: [CatalogDecorator, ReactflowDecorator],
109-
};
110-
111-
export const AllSuccess: CatalogStory<
112-
Story,
113-
typeof WorkflowDiagramStepNodeEditableContent
114-
> = {
115-
args: {
116-
onDelete: fn(),
117-
variant: 'success',
118-
},
119-
parameters: {
120-
msw: graphqlMocks,
121-
catalog: {
122-
options: {
123-
elementContainer: {
124-
width: 250,
125-
style: { position: 'relative' },
126-
},
127-
},
128-
dimensions: [
12993
{
130-
name: 'step type',
131-
values: ALL_STEPS,
132-
props: (data: WorkflowDiagramStepNodeData) => ({ data }),
94+
name: 'state',
95+
values: ['default', 'hover', 'selected'] satisfies ComponentState[],
96+
props: (state: ComponentState) => ({ state }),
13397
},
13498
],
13599
},
136100
},
137-
decorators: [CatalogDecorator, ReactflowDecorator],
138-
};
139-
140-
export const AllSuccessSelected: CatalogStory<
141-
Story,
142-
typeof WorkflowDiagramStepNodeEditableContent
143-
> = {
144-
args: {
145-
onDelete: fn(),
146-
variant: 'success',
147-
selected: true,
148-
},
149-
parameters: {
150-
msw: graphqlMocks,
151-
catalog: {
152-
options: {
153-
elementContainer: {
154-
width: 250,
155-
style: { position: 'relative' },
156-
className: 'selectable selected',
157-
},
158-
},
159-
dimensions: [
160-
{
161-
name: 'step type',
162-
values: ALL_STEPS,
163-
props: (data: WorkflowDiagramStepNodeData) => ({ data }),
164-
},
165-
],
166-
},
167-
},
168-
decorators: [CatalogDecorator, ReactflowDecorator],
169-
};
170-
171-
export const AllFailure: CatalogStory<
172-
Story,
173-
typeof WorkflowDiagramStepNodeEditableContent
174-
> = {
175-
args: {
176-
onDelete: fn(),
177-
variant: 'failure',
178-
},
179-
parameters: {
180-
msw: graphqlMocks,
181-
catalog: {
182-
options: {
183-
elementContainer: {
184-
width: 250,
185-
style: { position: 'relative' },
186-
},
187-
},
188-
dimensions: [
189-
{
190-
name: 'step type',
191-
values: ALL_STEPS,
192-
props: (data: WorkflowDiagramStepNodeData) => ({ data }),
193-
},
194-
],
195-
},
196-
},
197-
decorators: [CatalogDecorator, ReactflowDecorator],
198-
};
199-
200-
export const AllFailureSelected: CatalogStory<
201-
Story,
202-
typeof WorkflowDiagramStepNodeEditableContent
203-
> = {
204-
args: {
205-
onDelete: fn(),
206-
variant: 'failure',
207-
selected: true,
208-
},
209-
parameters: {
210-
msw: graphqlMocks,
211-
catalog: {
212-
options: {
213-
elementContainer: {
214-
width: 250,
215-
style: { position: 'relative' },
216-
className: 'selectable selected',
217-
},
218-
},
219-
dimensions: [
220-
{
221-
name: 'step type',
222-
values: ALL_STEPS,
223-
props: (data: WorkflowDiagramStepNodeData) => ({ data }),
224-
},
225-
],
101+
decorators: [
102+
(Story, { args }) => {
103+
return (
104+
<div
105+
className={`selectable ${args.state === 'selected' ? 'selected' : args.state === 'hover' ? 'workflow-node-container hover' : ''}`}
106+
>
107+
<Story />
108+
</div>
109+
);
226110
},
227-
},
228-
decorators: [CatalogDecorator, ReactflowDecorator],
111+
CatalogDecorator,
112+
ReactflowDecorator,
113+
],
229114
};

packages/twenty-front/src/modules/workflow/workflow-diagram/types/WorkflowDiagramNodeVariant.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ export type WorkflowDiagramNodeVariant =
22
| 'default'
33
| 'success'
44
| 'failure'
5-
| 'empty';
5+
| 'empty'
6+
| 'not-executed';

packages/twenty-ui/src/theme/constants/AdaptiveColorsDark.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,8 @@ export const ADAPTIVE_COLORS_DARK = {
55
turquoise2: THEME_COMMON.color.turquoise70,
66
turquoise3: THEME_COMMON.color.turquoise60,
77
turquoise4: THEME_COMMON.color.turquoise50,
8+
blue1: THEME_COMMON.color.blue80,
9+
blue2: THEME_COMMON.color.blue70,
10+
blue3: THEME_COMMON.color.blue60,
11+
blue4: THEME_COMMON.color.blue50,
812
};

packages/twenty-ui/src/theme/constants/AdaptiveColorsLight.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,8 @@ export const ADAPTIVE_COLORS_LIGHT = {
55
turquoise2: THEME_COMMON.color.turquoise20,
66
turquoise3: THEME_COMMON.color.turquoise30,
77
turquoise4: THEME_COMMON.color.turquoise40,
8+
blue1: THEME_COMMON.color.blue10,
9+
blue2: THEME_COMMON.color.blue20,
10+
blue3: THEME_COMMON.color.blue30,
11+
blue4: THEME_COMMON.color.blue40,
812
};

0 commit comments

Comments
 (0)