From 382746dd52afd261c6301b36accb97d5d361764f Mon Sep 17 00:00:00 2001 From: BOHEUS <56270748+BOHEUS@users.noreply.github.com> Date: Tue, 10 Feb 2026 11:35:37 +0000 Subject: [PATCH] Clarify forms usage (#17772) Fixes https://github.com/twentyhq/core-team-issues/issues/1704 --- .../components/WorkflowStepDetail.tsx | 1 + .../components/WorkflowMessage.tsx | 2 +- .../WorkflowEditActionFormBuilder.tsx | 21 ++- .../twenty-ui/src/display/callout/Callout.tsx | 143 ++++++++++++++++++ .../callout/__stories__/Callout.stories.tsx | 56 +++++++ .../display/icon/components/TablerIcons.ts | 1 + packages/twenty-ui/src/display/index.ts | 3 + 7 files changed, 225 insertions(+), 2 deletions(-) create mode 100644 packages/twenty-ui/src/display/callout/Callout.tsx create mode 100644 packages/twenty-ui/src/display/callout/__stories__/Callout.stories.tsx diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowStepDetail.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowStepDetail.tsx index 8aa3d524f9..3b2469d178 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowStepDetail.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowStepDetail.tsx @@ -187,6 +187,7 @@ export const WorkflowStepDetail = ({ case 'FORM': { return ( - + { @@ -136,6 +142,7 @@ export const WorkflowEditActionFormBuilder = ({ const [formData, setFormData] = useState(action.settings.input); + const [isCalloutVisible, setIsCalloutVisible] = useState(true); const [selectedField, setSelectedField] = useState(null); const [hoveredField, setHoveredField] = useState(null); @@ -213,6 +220,18 @@ export const WorkflowEditActionFormBuilder = ({ return ( <> + {triggerType && triggerType !== 'MANUAL' && isCalloutVisible && ( + setIsCalloutVisible(false)} + learnMoreUrl={ + 'https://docs.twenty.com/user-guide/workflows/capabilities/workflow-actions#form' + } + /> + )} {formData.length === 0 && ( ` + background-color: ${({ theme, variant }) => + variant === 'info' + ? theme.color.blue1 + : variant === 'warning' + ? theme.color.yellow1 + : variant === 'success' + ? theme.color.green1 + : variant === 'error' + ? theme.color.red1 + : theme.color.gray1}; + border: 1px solid + ${({ theme, variant }) => + variant === 'info' + ? theme.color.blue6 + : variant === 'warning' + ? theme.color.yellow6 + : variant === 'success' + ? theme.color.green6 + : variant === 'error' + ? theme.color.red6 + : theme.color.gray6}; + border-radius: ${({ theme }) => theme.border.radius.md}; + box-sizing: border-box; + display: flex; + gap: ${({ theme }) => theme.spacing(2)}; + padding: ${({ theme }) => theme.spacing(4)}; + position: relative; + margin-bottom: ${({ theme }) => theme.spacing(2)}; + margin-left: ${({ theme }) => theme.spacing(7)}; +`; + +const StyledIconContainer = styled.div<{ variant: CalloutVariant }>` + align-items: flex-start; + color: ${({ theme, variant }) => + variant === 'info' + ? theme.color.blue9 + : variant === 'warning' + ? theme.color.orange9 + : variant === 'success' + ? theme.color.green9 + : variant === 'error' + ? theme.color.red9 + : theme.color.gray9}; + display: flex; + flex-shrink: 0; + padding-top: ${({ theme }) => theme.spacing(0.5)}; +`; + +const StyledContent = styled.div` + display: flex; + flex-direction: column; + flex-grow: 1; + gap: ${({ theme }) => theme.spacing(2)}; + min-width: 0; +`; + +const StyledTitle = styled.div` + color: ${({ theme }) => theme.font.color.primary}; + font-family: ${({ theme }) => theme.font.family}; + font-size: ${({ theme }) => theme.font.size.md}; + font-weight: ${({ theme }) => theme.font.weight.medium}; + line-height: 1.5; +`; + +const StyledDescription = styled.div` + color: ${({ theme }) => theme.font.color.tertiary}; + font-family: ${({ theme }) => theme.font.family}; + font-size: ${({ theme }) => theme.font.size.sm}; + font-weight: ${({ theme }) => theme.font.weight.regular}; + line-height: 15px; +`; + +const StyledFooter = styled.div` + align-items: center; + display: flex; + justify-content: flex-end; + margin-top: ${({ theme }) => theme.spacing(1)}; +`; + +const StyledCloseButton = styled(IconButton)` + position: absolute; + right: ${({ theme }) => theme.spacing(3)}; + top: ${({ theme }) => theme.spacing(3)}; +`; + +export type CalloutProps = { + variant: CalloutVariant; + title: string; + description: string; + learnMoreText: string; + learnMoreUrl: string; + onClose: () => void; +}; + +export const Callout = ({ + variant, + title, + description, + learnMoreText, + learnMoreUrl, + onClose, +}: CalloutProps) => { + return ( + + + + + + + {title} + {description} + + { + window.open(learnMoreUrl, '_blank', 'noopener noreferrer'); + }} + /> + + + + + ); +}; diff --git a/packages/twenty-ui/src/display/callout/__stories__/Callout.stories.tsx b/packages/twenty-ui/src/display/callout/__stories__/Callout.stories.tsx new file mode 100644 index 0000000000..4161d82eb3 --- /dev/null +++ b/packages/twenty-ui/src/display/callout/__stories__/Callout.stories.tsx @@ -0,0 +1,56 @@ +import { type Meta, type StoryObj } from '@storybook/react-vite'; +import { + CatalogDecorator, + type CatalogStory, + ComponentDecorator, +} from '@ui/testing'; + +import { Callout } from '@ui/display'; +import { type CalloutVariant } from '@ui/display/callout/Callout'; + +const meta: Meta = { + title: 'UI/Display/Callout', + component: Callout, +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + variant: 'neutral', + title: 'An callout component', + description: 'Description of callout component', + learnMoreText: 'Learn more link', + }, + decorators: [ComponentDecorator], +}; + +export const Catalog: CatalogStory = { + args: { + title: 'An callout component', + description: 'Description of callout component', + learnMoreText: 'Learn more link', + }, + argTypes: { + variant: { control: false }, + }, + parameters: { + catalog: { + dimensions: [ + { + name: 'accents', + values: [ + 'warning', + 'neutral', + 'error', + 'info', + 'success', + ] satisfies CalloutVariant[], + props: (variant: CalloutVariant) => ({ variant }), + }, + ], + }, + }, + decorators: [CatalogDecorator], +}; diff --git a/packages/twenty-ui/src/display/icon/components/TablerIcons.ts b/packages/twenty-ui/src/display/icon/components/TablerIcons.ts index 20b71cc153..92236756a4 100644 --- a/packages/twenty-ui/src/display/icon/components/TablerIcons.ts +++ b/packages/twenty-ui/src/display/icon/components/TablerIcons.ts @@ -203,6 +203,7 @@ export { IconHeart, IconHeartOff, IconHeartRateMonitor, + IconHelp, IconHelpCircle, IconHierarchy, IconHierarchy2, diff --git a/packages/twenty-ui/src/display/index.ts b/packages/twenty-ui/src/display/index.ts index e12755ebac..4c44267ec7 100644 --- a/packages/twenty-ui/src/display/index.ts +++ b/packages/twenty-ui/src/display/index.ts @@ -19,6 +19,8 @@ export type { BannerVariant } from './banner/components/Banner'; export { Banner } from './banner/components/Banner'; export type { SidePanelInformationBannerProps } from './banner/components/SidePanelInformationBanner'; export { SidePanelInformationBanner } from './banner/components/SidePanelInformationBanner'; +export type { CalloutVariant, CalloutProps } from './callout/Callout'; +export { Callout } from './callout/Callout'; export type { AnimatedCheckmarkProps } from './checkmark/components/AnimatedCheckmark'; export { AnimatedCheckmark } from './checkmark/components/AnimatedCheckmark'; export type { CheckmarkProps } from './checkmark/components/Checkmark'; @@ -272,6 +274,7 @@ export { IconHeart, IconHeartOff, IconHeartRateMonitor, + IconHelp, IconHelpCircle, IconHierarchy, IconHierarchy2,