diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellButton.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellButton.tsx
deleted file mode 100644
index 8cceeaab74..0000000000
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellButton.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-import styled from '@emotion/styled';
-import { AnimatedContainer } from 'twenty-ui/utilities';
-import { FloatingIconButton } from 'twenty-ui/input';
-import { type IconComponent } from 'twenty-ui/display';
-import { MOBILE_VIEWPORT } from 'twenty-ui/theme';
-
-const StyledButtonContainer = styled.div`
- margin: ${({ theme }) => theme.spacing(1)};
- @media (max-width: ${MOBILE_VIEWPORT}px) {
- position: relative;
- right: 7px;
- }
-`;
-
-type RecordTableCellButtonProps = {
- onClick?: () => void;
- Icon: IconComponent;
-};
-
-export const RecordTableCellButton = ({
- onClick,
- Icon,
-}: RecordTableCellButtonProps) => (
-
-
-
-
-
-);
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellButtons.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellButtons.tsx
new file mode 100644
index 0000000000..2d1b5cc09b
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellButtons.tsx
@@ -0,0 +1,34 @@
+import styled from '@emotion/styled';
+import { type IconComponent } from 'twenty-ui/display';
+import { LightIconButtonGroup } from 'twenty-ui/input';
+import { MOBILE_VIEWPORT } from 'twenty-ui/theme';
+import { AnimatedContainer } from 'twenty-ui/utilities';
+
+const StyledButtonContainer = styled.div`
+ margin: ${({ theme }) => theme.spacing(1)};
+ @media (max-width: ${MOBILE_VIEWPORT}px) {
+ position: relative;
+ right: 7px;
+ }
+ border-radius: ${({ theme }) => theme.border.radius.sm};
+ border: 1px solid ${({ theme }) => theme.border.color.strong};
+`;
+
+type RecordTableCellButtonsProps = {
+ onClick?: () => void;
+ Icon: IconComponent;
+}[];
+
+export const RecordTableCellButtons = ({
+ buttons,
+}: {
+ buttons: RecordTableCellButtonsProps;
+}) => {
+ return (
+
+
+
+
+
+ );
+};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellEditButton.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellEditButton.tsx
index a996c1a009..fc362d1c7b 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellEditButton.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellEditButton.tsx
@@ -1,7 +1,9 @@
import { useGetButtonIcon } from '@/object-record/record-field/ui/hooks/useGetButtonIcon';
import { useIsFieldInputOnly } from '@/object-record/record-field/ui/hooks/useIsFieldInputOnly';
+
import { RecordTableCellContext } from '@/object-record/record-table/contexts/RecordTableCellContext';
-import { RecordTableCellButton } from '@/object-record/record-table/record-table-cell/components/RecordTableCellButton';
+import { RecordTableCellButtons } from '@/object-record/record-table/record-table-cell/components/RecordTableCellButtons';
+import { useGetSecondaryRecordTableCellButton } from '@/object-record/record-table/record-table-cell/hooks/useGetSecondaryRecordTableCellButton';
import { useOpenRecordTableCellFromCell } from '@/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellFromCell';
import { useContext } from 'react';
import { isDefined } from 'twenty-shared/utils';
@@ -9,20 +11,20 @@ import { IconArrowUpRight, IconPencil } from 'twenty-ui/display';
export const RecordTableCellEditButton = () => {
const { cellPosition } = useContext(RecordTableCellContext);
-
const { openTableCell } = useOpenRecordTableCellFromCell();
-
const isFieldInputOnly = useIsFieldInputOnly();
const isFirstColumn = cellPosition.column === 0;
const customButtonIcon = useGetButtonIcon();
- const buttonIcon = isFirstColumn
+ const secondaryButton = useGetSecondaryRecordTableCellButton();
+
+ const mainButtonIcon = isFirstColumn
? IconArrowUpRight
: isDefined(customButtonIcon)
? customButtonIcon
: IconPencil;
- const handleButtonClick = () => {
+ const handleMainButtonClick = () => {
if (!isFieldInputOnly && isFirstColumn) {
openTableCell(undefined, false, true);
} else {
@@ -31,6 +33,14 @@ export const RecordTableCellEditButton = () => {
};
return (
-
+
);
};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useGetSecondaryRecordTableCellButton.ts b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useGetSecondaryRecordTableCellButton.ts
new file mode 100644
index 0000000000..3cfa98a335
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useGetSecondaryRecordTableCellButton.ts
@@ -0,0 +1,88 @@
+import { FieldContext } from '@/object-record/record-field/ui/contexts/FieldContext';
+import {
+ type FieldEmailsValue,
+ type FieldLinksValue,
+ type FieldPhonesValue,
+} from '@/object-record/record-field/ui/types/FieldMetadata';
+import { isFieldEmails } from '@/object-record/record-field/ui/types/guards/isFieldEmails';
+import { isFieldLinks } from '@/object-record/record-field/ui/types/guards/isFieldLinks';
+import { isFieldPhones } from '@/object-record/record-field/ui/types/guards/isFieldPhones';
+import { useRecordFieldValue } from '@/object-record/record-store/hooks/useRecordFieldValue';
+import { t } from '@lingui/core/macro';
+import { useContext } from 'react';
+import { FieldMetadataSettingsOnClickAction } from 'twenty-shared/types';
+import { getAbsoluteUrl, isDefined } from 'twenty-shared/utils';
+import { IconArrowUpRight, IconCopy } from 'twenty-ui/display';
+import { useCopyToClipboard } from '~/hooks/useCopyToClipboard';
+
+export const useGetSecondaryRecordTableCellButton = () => {
+ const { fieldDefinition, recordId } = useContext(FieldContext);
+ const { copyToClipboard } = useCopyToClipboard();
+
+ const fieldValue = useRecordFieldValue<
+ FieldPhonesValue | FieldEmailsValue | FieldLinksValue | undefined
+ >(recordId, fieldDefinition.metadata.fieldName, fieldDefinition);
+
+ if (
+ (!isFieldPhones(fieldDefinition) &&
+ !isFieldLinks(fieldDefinition) &&
+ !isFieldEmails(fieldDefinition)) ||
+ !isDefined(fieldValue)
+ ) {
+ return [];
+ }
+
+ const secondaryActionOnClick =
+ fieldDefinition.metadata.settings?.clickAction ===
+ FieldMetadataSettingsOnClickAction.OPEN_LINK
+ ? FieldMetadataSettingsOnClickAction.COPY
+ : FieldMetadataSettingsOnClickAction.OPEN_LINK;
+
+ let openLinkOnClick: () => void = () => {};
+ let copyOnClick: () => void = () => {};
+
+ if (isFieldPhones(fieldDefinition)) {
+ const { primaryPhoneCallingCode = '', primaryPhoneNumber = '' } =
+ fieldValue as FieldPhonesValue;
+ const phoneNumber = `${primaryPhoneCallingCode}${primaryPhoneNumber}`;
+ openLinkOnClick = () => {
+ window.open(`tel:${phoneNumber}`, '_blank');
+ };
+ copyOnClick = () => {
+ copyToClipboard(phoneNumber, t`Phone number copied to clipboard`);
+ };
+ }
+
+ if (isFieldEmails(fieldDefinition)) {
+ const email = (fieldValue as FieldEmailsValue).primaryEmail ?? '';
+ openLinkOnClick = () => {
+ window.open(`mailto:${email}`, '_blank');
+ };
+ copyOnClick = () => {
+ copyToClipboard(email, t`Email copied to clipboard`);
+ };
+ }
+
+ if (isFieldLinks(fieldDefinition)) {
+ const url = (fieldValue as FieldLinksValue).primaryLinkUrl ?? '';
+ openLinkOnClick = () => {
+ window.open(getAbsoluteUrl(url), '_blank');
+ };
+ copyOnClick = () => {
+ copyToClipboard(url, t`Link copied to clipboard`);
+ };
+ }
+
+ return [
+ {
+ onClick:
+ secondaryActionOnClick === FieldMetadataSettingsOnClickAction.OPEN_LINK
+ ? openLinkOnClick
+ : copyOnClick,
+ Icon:
+ secondaryActionOnClick === FieldMetadataSettingsOnClickAction.OPEN_LINK
+ ? IconArrowUpRight
+ : IconCopy,
+ },
+ ];
+};
diff --git a/packages/twenty-front/src/modules/settings/data-model/fields/preview/components/__stories__/SettingsDataModelFieldPreviewWidget.stories.tsx b/packages/twenty-front/src/modules/settings/data-model/fields/preview/components/__stories__/SettingsDataModelFieldPreviewWidget.stories.tsx
index 16400bb1a8..a363fe51b1 100644
--- a/packages/twenty-front/src/modules/settings/data-model/fields/preview/components/__stories__/SettingsDataModelFieldPreviewWidget.stories.tsx
+++ b/packages/twenty-front/src/modules/settings/data-model/fields/preview/components/__stories__/SettingsDataModelFieldPreviewWidget.stories.tsx
@@ -30,6 +30,7 @@ const meta: Meta = {
MemoryRouterDecorator,
ComponentDecorator,
ObjectMetadataItemsDecorator,
+ I18nFrontDecorator,
SnackBarDecorator,
],
args: {