feat: add feature to customize onClick behaviour for phone, email and links data type (#16265)
Fixes Issue: #15797 This PR adds a configurable click behavior setting for Phone, Email, and Links field types, allowing users to customize what happens when clicking on these fields. A new option (**Click Behaviour**) to configure the default behaviour for onClick of data is added in the settings page (Settings → Data Model → Object → Field Edit) for Phone, Email and Links data types. Users can now choose between two actions: - **Copy to clipboard**: Copies the value to clipboard with a success toast message - **Open as link**: Opens the value as a link (tel:, mailto:, or http/https) The default behaviour is persisted for all these three types(phone- Copy to clipboard, email & links: open link) to maintain backward compatibility. **Screenshots :** <img width="2084" height="1736" alt="image" src="https://github.com/user-attachments/assets/eb5d129c-e3e0-4334-b426-eb38d8a4840c" /> <img width="1474" height="1428" alt="image" src="https://github.com/user-attachments/assets/487f4e44-6151-4254-bc5c-5398be5fc087" /> <img width="1594" height="1398" alt="image" src="https://github.com/user-attachments/assets/abdbc213-7223-4d57-809e-4d55c90cda80" /> --------- Co-authored-by: Etienne <45695613+etiennejouan@users.noreply.github.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useMemo } from 'react';
|
||||
import React, { useMemo } from 'react';
|
||||
|
||||
import { type FieldEmailsValue } from '@/object-record/record-field/ui/types/FieldMetadata';
|
||||
import { ExpandableList } from '@/ui/layout/expandable-list/components/ExpandableList';
|
||||
@@ -10,6 +10,7 @@ import { THEME_COMMON } from 'twenty-ui/theme';
|
||||
type EmailsDisplayProps = {
|
||||
value?: FieldEmailsValue;
|
||||
isFocused?: boolean;
|
||||
onEmailClick?: (email: string, event: React.MouseEvent<HTMLElement>) => void;
|
||||
};
|
||||
|
||||
const themeSpacing = THEME_COMMON.spacingMultiplicator;
|
||||
@@ -27,7 +28,11 @@ const StyledContainer = styled.div`
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
export const EmailsDisplay = ({ value, isFocused }: EmailsDisplayProps) => {
|
||||
export const EmailsDisplay = ({
|
||||
value,
|
||||
isFocused,
|
||||
onEmailClick,
|
||||
}: EmailsDisplayProps) => {
|
||||
const emails = useMemo(
|
||||
() =>
|
||||
[
|
||||
@@ -40,13 +45,23 @@ export const EmailsDisplay = ({ value, isFocused }: EmailsDisplayProps) => {
|
||||
return isFocused ? (
|
||||
<ExpandableList isChipCountDisplayed>
|
||||
{emails.map((email, index) => (
|
||||
<RoundedLink key={index} label={email} href={`mailto:${email}`} />
|
||||
<RoundedLink
|
||||
key={index}
|
||||
label={email}
|
||||
href={`mailto:${email}`}
|
||||
onClick={(event) => onEmailClick?.(email, event)}
|
||||
/>
|
||||
))}
|
||||
</ExpandableList>
|
||||
) : (
|
||||
<StyledContainer>
|
||||
{emails.map((email, index) => (
|
||||
<RoundedLink key={index} label={email} href={`mailto:${email}`} />
|
||||
<RoundedLink
|
||||
key={index}
|
||||
label={email}
|
||||
href={`mailto:${email}`}
|
||||
onClick={(event) => onEmailClick?.(email, event)}
|
||||
/>
|
||||
))}
|
||||
</StyledContainer>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useMemo } from 'react';
|
||||
import React, { useMemo } from 'react';
|
||||
|
||||
import { getFieldLinkDefinedLinks } from '@/object-record/record-field/ui/meta-types/input/utils/getFieldLinkDefinedLinks';
|
||||
import { type FieldLinksValue } from '@/object-record/record-field/ui/types/FieldMetadata';
|
||||
@@ -13,9 +13,10 @@ import { checkUrlType } from '~/utils/checkUrlType';
|
||||
|
||||
type LinksDisplayProps = {
|
||||
value?: FieldLinksValue;
|
||||
onLinkClick?: (url: string, event: React.MouseEvent<HTMLElement>) => void;
|
||||
};
|
||||
|
||||
export const LinksDisplay = ({ value }: LinksDisplayProps) => {
|
||||
export const LinksDisplay = ({ value, onLinkClick }: LinksDisplayProps) => {
|
||||
const links = useMemo(() => {
|
||||
if (!isDefined(value)) {
|
||||
return [];
|
||||
@@ -43,9 +44,20 @@ export const LinksDisplay = ({ value }: LinksDisplayProps) => {
|
||||
<ExpandableList>
|
||||
{links.map(({ url, label, type }, index) =>
|
||||
type === LinkType.LinkedIn || type === LinkType.Twitter ? (
|
||||
<SocialLink key={index} href={url} type={type} label={label} />
|
||||
<SocialLink
|
||||
key={index}
|
||||
href={url}
|
||||
type={type}
|
||||
label={label}
|
||||
onClick={(event) => onLinkClick?.(url, event)}
|
||||
/>
|
||||
) : (
|
||||
<RoundedLink key={index} href={url} label={label} />
|
||||
<RoundedLink
|
||||
key={index}
|
||||
href={url}
|
||||
label={label}
|
||||
onClick={(event) => onLinkClick?.(url, event)}
|
||||
/>
|
||||
),
|
||||
)}
|
||||
</ExpandableList>
|
||||
|
||||
@@ -75,13 +75,6 @@ export const PhonesDisplay = ({
|
||||
}
|
||||
};
|
||||
|
||||
const handleClick = (
|
||||
number: string,
|
||||
event: React.MouseEvent<HTMLElement>,
|
||||
) => {
|
||||
onPhoneNumberClick?.(number, event);
|
||||
};
|
||||
|
||||
return isFocused ? (
|
||||
<ExpandableList isChipCountDisplayed>
|
||||
{phones.map(({ number, callingCode }, index) => {
|
||||
@@ -95,7 +88,9 @@ export const PhonesDisplay = ({
|
||||
label={
|
||||
parsedPhone ? parsedPhone.formatInternational() : invalidPhone
|
||||
}
|
||||
onClick={(event) => handleClick(callingCode + number, event)}
|
||||
onClick={(event) =>
|
||||
onPhoneNumberClick?.(callingCode + number, event)
|
||||
}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
@@ -113,7 +108,9 @@ export const PhonesDisplay = ({
|
||||
label={
|
||||
parsedPhone ? parsedPhone.formatInternational() : invalidPhone
|
||||
}
|
||||
onClick={(event) => handleClick(callingCode + number, event)}
|
||||
onClick={(event) =>
|
||||
onPhoneNumberClick?.(callingCode + number, event)
|
||||
}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
||||
Reference in New Issue
Block a user