diff --git a/packages/twenty-front/src/modules/object-record/record-field/components/FormFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/components/FormFieldInput.tsx
index 5a99fd7d3..dd0d999da 100644
--- a/packages/twenty-front/src/modules/object-record/record-field/components/FormFieldInput.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-field/components/FormFieldInput.tsx
@@ -1,11 +1,16 @@
import { FormBooleanFieldInput } from '@/object-record/record-field/form-types/components/FormBooleanFieldInput';
+import { FormFullNameFieldInput } from '@/object-record/record-field/form-types/components/FormFullNameFieldInput';
import { FormNumberFieldInput } from '@/object-record/record-field/form-types/components/FormNumberFieldInput';
import { FormSelectFieldInput } from '@/object-record/record-field/form-types/components/FormSelectFieldInput';
import { FormTextFieldInput } from '@/object-record/record-field/form-types/components/FormTextFieldInput';
import { VariablePickerComponent } from '@/object-record/record-field/form-types/types/VariablePickerComponent';
import { FieldDefinition } from '@/object-record/record-field/types/FieldDefinition';
-import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
+import {
+ FieldFullNameValue,
+ FieldMetadata,
+} from '@/object-record/record-field/types/FieldMetadata';
import { isFieldBoolean } from '@/object-record/record-field/types/guards/isFieldBoolean';
+import { isFieldFullName } from '@/object-record/record-field/types/guards/isFieldFullName';
import { isFieldNumber } from '@/object-record/record-field/types/guards/isFieldNumber';
import { isFieldSelect } from '@/object-record/record-field/types/guards/isFieldSelect';
import { isFieldText } from '@/object-record/record-field/types/guards/isFieldText';
@@ -55,5 +60,12 @@ export const FormFieldInput = ({
field={field}
VariablePicker={VariablePicker}
/>
+ ) : isFieldFullName(field) ? (
+
) : null;
};
diff --git a/packages/twenty-front/src/modules/object-record/record-field/form-types/components/FormFullNameFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/FormFullNameFieldInput.tsx
new file mode 100644
index 000000000..e4cf57b42
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/FormFullNameFieldInput.tsx
@@ -0,0 +1,66 @@
+import { FormTextFieldInput } from '@/object-record/record-field/form-types/components/FormTextFieldInput';
+import { StyledFormCompositeFieldInputContainer } from '@/object-record/record-field/form-types/components/StyledFormCompositeFieldInputContainer';
+import { StyledFormFieldInputContainer } from '@/object-record/record-field/form-types/components/StyledFormFieldInputContainer';
+import { VariablePickerComponent } from '@/object-record/record-field/form-types/types/VariablePickerComponent';
+import { FIRST_NAME_PLACEHOLDER_WITH_SPECIAL_CHARACTER_TO_AVOID_PASSWORD_MANAGERS } from '@/object-record/record-field/meta-types/input/constants/FirstNamePlaceholder';
+import { LAST_NAME_PLACEHOLDER_WITH_SPECIAL_CHARACTER_TO_AVOID_PASSWORD_MANAGERS } from '@/object-record/record-field/meta-types/input/constants/LastNamePlaceholder';
+import { FieldFullNameValue } from '@/object-record/record-field/types/FieldMetadata';
+import { InputLabel } from '@/ui/input/components/InputLabel';
+
+type FormFullNameFieldInputProps = {
+ label?: string;
+ defaultValue: FieldFullNameValue | undefined;
+ onPersist: (value: FieldFullNameValue) => void;
+ VariablePicker?: VariablePickerComponent;
+ readonly?: boolean;
+};
+
+export const FormFullNameFieldInput = ({
+ label,
+ defaultValue,
+ onPersist,
+ readonly,
+ VariablePicker,
+}: FormFullNameFieldInputProps) => {
+ const handleFirstNameChange = (newText: string) => {
+ onPersist({
+ lastName: defaultValue?.lastName ?? '',
+ firstName: newText,
+ });
+ };
+
+ const handleLastNameChange = (newText: string) => {
+ onPersist({
+ firstName: defaultValue?.firstName ?? '',
+ lastName: newText,
+ });
+ };
+
+ return (
+
+ {label ? {label} : null}
+
+
+
+
+
+ );
+};
diff --git a/packages/twenty-front/src/modules/object-record/record-field/form-types/components/StyledFormCompositeFieldInputContainer.tsx b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/StyledFormCompositeFieldInputContainer.tsx
new file mode 100644
index 000000000..47a8bfe77
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/StyledFormCompositeFieldInputContainer.tsx
@@ -0,0 +1,11 @@
+import styled from '@emotion/styled';
+
+export const StyledFormCompositeFieldInputContainer = styled.div`
+ display: flex;
+ flex-direction: column;
+ background: ${({ theme }) => theme.background.secondary};
+ border: 1px solid ${({ theme }) => theme.border.color.medium};
+ border-radius: ${({ theme }) => theme.border.radius.sm};
+ gap: ${({ theme }) => theme.spacing(2)};
+ padding: ${({ theme }) => theme.spacing(2)};
+`;
diff --git a/packages/twenty-front/src/modules/object-record/record-field/form-types/components/StyledFormFieldInputContainer.tsx b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/StyledFormFieldInputContainer.tsx
index 5615ab80b..cc04e0f7a 100644
--- a/packages/twenty-front/src/modules/object-record/record-field/form-types/components/StyledFormFieldInputContainer.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/StyledFormFieldInputContainer.tsx
@@ -3,4 +3,5 @@ import styled from '@emotion/styled';
export const StyledFormFieldInputContainer = styled.div`
display: flex;
flex-direction: column;
+ width: 100%;
`;
diff --git a/packages/twenty-front/src/modules/object-record/record-field/form-types/components/__stories__/FormFullNameFieldInput.stories.tsx b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/__stories__/FormFullNameFieldInput.stories.tsx
new file mode 100644
index 000000000..62def51e5
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/__stories__/FormFullNameFieldInput.stories.tsx
@@ -0,0 +1,31 @@
+import { Meta, StoryObj } from '@storybook/react';
+import { within } from '@storybook/test';
+import { FormFullNameFieldInput } from '../FormFullNameFieldInput';
+
+const meta: Meta = {
+ title: 'UI/Data/Field/Form/Input/FormFullNameFieldInput',
+ component: FormFullNameFieldInput,
+ args: {},
+ argTypes: {},
+};
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {
+ args: {
+ label: 'Name',
+ defaultValue: {
+ firstName: 'John',
+ lastName: 'Doe',
+ },
+ },
+ play: async ({ canvasElement }) => {
+ const canvas = within(canvasElement);
+
+ await canvas.findByText('Name');
+ await canvas.findByText('First Name');
+ await canvas.findByText('Last Name');
+ },
+};
diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/FullNameFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/FullNameFieldInput.tsx
index bdba34f0c..49335d42b 100644
--- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/FullNameFieldInput.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/FullNameFieldInput.tsx
@@ -3,18 +3,14 @@ import { FieldDoubleText } from '@/object-record/record-field/types/FieldDoubleT
import { DoubleTextInput } from '@/ui/field/input/components/DoubleTextInput';
import { FieldInputOverlay } from '@/ui/field/input/components/FieldInputOverlay';
+import { FIRST_NAME_PLACEHOLDER_WITH_SPECIAL_CHARACTER_TO_AVOID_PASSWORD_MANAGERS } from '@/object-record/record-field/meta-types/input/constants/FirstNamePlaceholder';
+import { LAST_NAME_PLACEHOLDER_WITH_SPECIAL_CHARACTER_TO_AVOID_PASSWORD_MANAGERS } from '@/object-record/record-field/meta-types/input/constants/LastNamePlaceholder';
import { isDoubleTextFieldEmpty } from '@/object-record/record-field/meta-types/input/utils/isDoubleTextFieldEmpty';
import {
FieldInputClickOutsideEvent,
FieldInputEvent,
} from './DateTimeFieldInput';
-const FIRST_NAME_PLACEHOLDER_WITH_SPECIAL_CHARACTER_TO_AVOID_PASSWORD_MANAGERS =
- 'First name';
-
-const LAST_NAME_PLACEHOLDER_WITH_SPECIAL_CHARACTER_TO_AVOID_PASSWORD_MANAGERS =
- 'Last name';
-
type FullNameFieldInputProps = {
onClickOutside?: FieldInputClickOutsideEvent;
onEnter?: FieldInputEvent;
diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/constants/FirstNamePlaceholder.ts b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/constants/FirstNamePlaceholder.ts
new file mode 100644
index 000000000..7eac65e02
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/constants/FirstNamePlaceholder.ts
@@ -0,0 +1,2 @@
+export const FIRST_NAME_PLACEHOLDER_WITH_SPECIAL_CHARACTER_TO_AVOID_PASSWORD_MANAGERS =
+ 'First name';
diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/constants/LastNamePlaceholder.ts b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/constants/LastNamePlaceholder.ts
new file mode 100644
index 000000000..04f082144
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/constants/LastNamePlaceholder.ts
@@ -0,0 +1,2 @@
+export const LAST_NAME_PLACEHOLDER_WITH_SPECIAL_CHARACTER_TO_AVOID_PASSWORD_MANAGERS =
+ 'Last name';
diff --git a/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdown.tsx b/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdown.tsx
index 965a41f40..64eebb382 100644
--- a/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdown.tsx
+++ b/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdown.tsx
@@ -1,4 +1,5 @@
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
+import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { StyledDropdownButtonContainer } from '@/ui/layout/dropdown/components/StyledDropdownButtonContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { SearchVariablesDropdownFieldItems } from '@/workflow/search-variables/components/SearchVariablesDropdownFieldItems';
@@ -26,7 +27,7 @@ const StyledDropdownVariableButtonContainer = styled(
}
`;
-const StyledDropdownComponetsContainer = styled.div`
+const StyledDropdownComponentsContainer = styled(DropdownMenuItemsContainer)`
background-color: ${({ theme }) => theme.background.transparent.light};
`;
@@ -136,9 +137,9 @@ const SearchVariablesDropdown = ({
}
dropdownComponents={
-
+
{renderSearchVariablesDropdownComponents()}
-
+
}
dropdownPlacement="bottom-end"
dropdownOffset={{ x: 0, y: 4 }}
diff --git a/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdownFieldItems.tsx b/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdownFieldItems.tsx
index 8dcd83572..ac274e131 100644
--- a/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdownFieldItems.tsx
+++ b/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdownFieldItems.tsx
@@ -1,5 +1,4 @@
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader';
-import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
import {
BaseOutputSchema,
@@ -100,8 +99,14 @@ export const SearchVariablesDropdownFieldItems = ({
: options;
return (
-
-
+ <>
+
))}
-
+ >
);
};
diff --git a/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdownObjectItems.tsx b/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdownObjectItems.tsx
index 92aace99a..b48cf0bff 100644
--- a/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdownObjectItems.tsx
+++ b/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdownObjectItems.tsx
@@ -1,5 +1,4 @@
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader';
-import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
import {
OutputSchema,
@@ -112,7 +111,7 @@ export const SearchVariablesDropdownObjectItems = ({
: options;
return (
-
+ <>
@@ -154,6 +153,6 @@ export const SearchVariablesDropdownObjectItems = ({
LeftIcon={value.icon ? getIcon(value.icon) : undefined}
/>
))}
-
+ >
);
};
diff --git a/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdownWorkflowStepItems.tsx b/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdownWorkflowStepItems.tsx
index 4c0520752..b4a390c73 100644
--- a/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdownWorkflowStepItems.tsx
+++ b/packages/twenty-front/src/modules/workflow/search-variables/components/SearchVariablesDropdownWorkflowStepItems.tsx
@@ -1,5 +1,4 @@
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader';
-import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { StepOutputSchema } from '@/workflow/search-variables/types/StepOutputSchema';
@@ -36,7 +35,7 @@ export const SearchVariablesDropdownWorkflowStepItems = ({
);
return (
-
+ <>
@@ -74,6 +73,6 @@ export const SearchVariablesDropdownWorkflowStepItems = ({
hasSubMenu={false}
/>
)}
-
+ >
);
};
diff --git a/packages/twenty-front/src/modules/workflow/workflow-actions/components/WorkflowEditActionFormServerlessFunction.tsx b/packages/twenty-front/src/modules/workflow/workflow-actions/components/WorkflowEditActionFormServerlessFunction.tsx
index a5685313e..93527dd2a 100644
--- a/packages/twenty-front/src/modules/workflow/workflow-actions/components/WorkflowEditActionFormServerlessFunction.tsx
+++ b/packages/twenty-front/src/modules/workflow/workflow-actions/components/WorkflowEditActionFormServerlessFunction.tsx
@@ -1,4 +1,5 @@
import { FormTextFieldInput } from '@/object-record/record-field/form-types/components/FormTextFieldInput';
+import { StyledFormCompositeFieldInputContainer } from '@/object-record/record-field/form-types/components/StyledFormCompositeFieldInputContainer';
import { useGetAvailablePackages } from '@/settings/serverless-functions/hooks/useGetAvailablePackages';
import { useServerlessFunctionUpdateFormState } from '@/settings/serverless-functions/hooks/useServerlessFunctionUpdateFormState';
import { useUpdateOneServerlessFunction } from '@/settings/serverless-functions/hooks/useUpdateOneServerlessFunction';
@@ -44,17 +45,6 @@ const StyledLabel = styled.div`
margin-bottom: ${({ theme }) => theme.spacing(2)};
`;
-const StyledInputContainer = styled.div`
- background: ${({ theme }) => theme.background.secondary};
- border: 1px solid ${({ theme }) => theme.border.color.medium};
- border-radius: ${({ theme }) => theme.border.radius.md};
- display: flex;
- flex-direction: column;
- gap: ${({ theme }) => theme.spacing(2)};
- padding: ${({ theme }) => theme.spacing(2)};
- position: relative;
-`;
-
type WorkflowEditActionFormServerlessFunctionProps = {
action: WorkflowCodeAction;
actionOptions:
@@ -223,9 +213,9 @@ export const WorkflowEditActionFormServerlessFunction = ({
return (
{inputKey}
-
+
{renderFields(inputValue, currentPath, false)}
-
+
);
} else {