diff --git a/packages/twenty-front/src/modules/ui/field/display/components/LinkDisplay.tsx b/packages/twenty-front/src/modules/ui/field/display/components/LinkDisplay.tsx index 0712d07dd7..6abb642f18 100644 --- a/packages/twenty-front/src/modules/ui/field/display/components/LinkDisplay.tsx +++ b/packages/twenty-front/src/modules/ui/field/display/components/LinkDisplay.tsx @@ -24,7 +24,7 @@ export const LinkDisplay = ({ value }: LinkDisplayProps) => { const type = checkUrlType(absoluteUrl); if (isSocialLinkType(type)) { - return ; + return ; } return ; diff --git a/packages/twenty-front/src/modules/ui/field/display/components/LinksDisplay.tsx b/packages/twenty-front/src/modules/ui/field/display/components/LinksDisplay.tsx index 33a7d47d8e..e94658526c 100644 --- a/packages/twenty-front/src/modules/ui/field/display/components/LinksDisplay.tsx +++ b/packages/twenty-front/src/modules/ui/field/display/components/LinksDisplay.tsx @@ -35,7 +35,8 @@ export const LinksDisplay = ({ value, onLinkClick }: LinksDisplayProps) => { } return { url: absoluteUrl, - label: label || hostname, + label, + displayLabel: label || hostname, type: checkUrlType(absoluteUrl), }; }); @@ -43,7 +44,7 @@ export const LinksDisplay = ({ value, onLinkClick }: LinksDisplayProps) => { return ( - {links.map(({ url, label, type }, index) => + {links.map(({ url, label, displayLabel, type }, index) => isSocialLinkType(type) ? ( { onLinkClick?.(url, event)} /> ), diff --git a/packages/twenty-front/src/modules/ui/field/display/components/URLDisplay.tsx b/packages/twenty-front/src/modules/ui/field/display/components/URLDisplay.tsx index b33f56ea8a..52b67c0175 100644 --- a/packages/twenty-front/src/modules/ui/field/display/components/URLDisplay.tsx +++ b/packages/twenty-front/src/modules/ui/field/display/components/URLDisplay.tsx @@ -28,7 +28,7 @@ export const URLDisplay = ({ value }: URLDisplayProps) => { href={absoluteUrl} onClick={handleClick} type={type} - label={displayedValue} + label={null} /> ); diff --git a/packages/twenty-front/src/modules/ui/field/display/components/__stories__/LinksDisplay.stories.tsx b/packages/twenty-front/src/modules/ui/field/display/components/__stories__/LinksDisplay.stories.tsx index 0009f1c150..62ced2e32d 100644 --- a/packages/twenty-front/src/modules/ui/field/display/components/__stories__/LinksDisplay.stories.tsx +++ b/packages/twenty-front/src/modules/ui/field/display/components/__stories__/LinksDisplay.stories.tsx @@ -125,12 +125,12 @@ export const SocialMediaLinks: Story = { args: { value: { primaryLinkUrl: 'https://www.linkedin.com/company/twenty', - primaryLinkLabel: 'Twenty on LinkedIn', + primaryLinkLabel: '', secondaryLinks: [ - { url: 'https://twitter.com/twentycrm', label: 'Twenty on Twitter' }, + { url: 'https://twitter.com/twentycrm', label: null }, { url: 'https://www.instagram.com/twenty_hq', - label: 'Twenty on Instagram', + label: null, }, ], }, @@ -170,10 +170,10 @@ export const InstagramLinks: Story = { args: { value: { primaryLinkUrl: 'https://www.instagram.com/twenty_hq', - primaryLinkLabel: 'Twenty on Instagram', + primaryLinkLabel: '', secondaryLinks: [ - { url: 'https://instagram.com/p/ABC123', label: 'A post' }, - { url: 'https://instagram.com/reel/XYZ789', label: 'A reel' }, + { url: 'https://instagram.com/p/ABC123', label: null }, + { url: 'https://instagram.com/reel/XYZ789', label: null }, ], }, }, @@ -197,6 +197,43 @@ export const InstagramLinks: Story = { }, }; +export const SocialLinksWithCustomLabels: Story = { + args: { + value: { + primaryLinkUrl: 'https://www.linkedin.com/company/twenty', + primaryLinkLabel: 'Twenty on LinkedIn', + secondaryLinks: [ + { + url: 'https://www.instagram.com/twenty_hq', + label: 'Twenty on Instagram', + }, + ], + }, + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + await waitFor(() => { + const links = canvas.queryAllByRole('link'); + expect(links).toHaveLength(2); + }); + + const linkedinLink = await canvas.findByText('Twenty on LinkedIn'); + expect(linkedinLink).toBeVisible(); + expect(linkedinLink).toHaveAttribute( + 'href', + 'https://www.linkedin.com/company/twenty', + ); + + const instagramLink = await canvas.findByText('Twenty on Instagram'); + expect(instagramLink).toBeVisible(); + expect(instagramLink).toHaveAttribute( + 'href', + 'https://www.instagram.com/twenty_hq', + ); + }, +}; + export const AutomaticLabelFromURL: Story = { args: { value: { diff --git a/packages/twenty-ui/src/navigation/SocialLink/SocialLink.tsx b/packages/twenty-ui/src/navigation/SocialLink/SocialLink.tsx index 7ed28907c4..d1135c4c72 100644 --- a/packages/twenty-ui/src/navigation/SocialLink/SocialLink.tsx +++ b/packages/twenty-ui/src/navigation/SocialLink/SocialLink.tsx @@ -1,19 +1,22 @@ import * as React from 'react'; +import { isNonEmptyString } from '@sniptt/guards'; + import { type LinkType } from '@ui/navigation/SocialLink/LinkType'; import { RoundedLink } from '@ui/navigation/RoundedLink/RoundedLink'; import { getDisplayValueByUrlType } from '@ui/utilities'; type SocialLinkProps = { - label: string; + label?: string | null; href: string; type: LinkType; onClick?: (event: React.MouseEvent) => void; }; export const SocialLink = ({ label, href, onClick, type }: SocialLinkProps) => { - const displayValue = - getDisplayValueByUrlType({ type: type, href: href }) ?? label; + const displayValue = isNonEmptyString(label) + ? label + : (getDisplayValueByUrlType({ type: type, href: href }) ?? href); return ; }; diff --git a/packages/twenty-ui/src/navigation/SocialLink/__stories__/SocialLink.stories.tsx b/packages/twenty-ui/src/navigation/SocialLink/__stories__/SocialLink.stories.tsx index 9d9c256a31..dce54772e5 100644 --- a/packages/twenty-ui/src/navigation/SocialLink/__stories__/SocialLink.stories.tsx +++ b/packages/twenty-ui/src/navigation/SocialLink/__stories__/SocialLink.stories.tsx @@ -11,7 +11,6 @@ const meta: Meta = { decorators: [ComponentWithRouterDecorator], args: { href: 'https://twenty.com', - label: 'Social Link', }, }; @@ -22,7 +21,6 @@ const clickJestFn = fn(); export const LinkedIn: Story = { args: { href: 'https://www.linkedin.com/in/johndoe', - label: 'LinkedIn', onClick: clickJestFn, type: LinkType.LinkedIn, }, @@ -31,7 +29,6 @@ export const LinkedIn: Story = { export const Twitter: Story = { args: { href: 'https://twitter.com/johndoe', - label: 'Twitter', onClick: clickJestFn, type: LinkType.Twitter, }, @@ -49,7 +46,6 @@ export const Twitter: Story = { export const X: Story = { args: { href: 'https://x.com/johndoe', - label: 'X', onClick: clickJestFn, type: LinkType.Twitter, }, @@ -58,7 +54,6 @@ export const X: Story = { export const Facebook: Story = { args: { href: 'https://www.facebook.com/johndoe', - label: 'Facebook', onClick: clickJestFn, type: LinkType.Facebook, }, @@ -67,7 +62,6 @@ export const Facebook: Story = { export const Instagram: Story = { args: { href: 'https://www.instagram.com/johndoe', - label: 'Instagram', onClick: clickJestFn, type: LinkType.Instagram, }, @@ -76,7 +70,6 @@ export const Instagram: Story = { export const TikTok: Story = { args: { href: 'https://www.tiktok.com/@johndoe', - label: 'TikTok', onClick: clickJestFn, type: LinkType.TikTok, }, @@ -85,8 +78,23 @@ export const TikTok: Story = { export const Bluesky: Story = { args: { href: 'https://bsky.app/profile/johndoe.bsky.social', - label: 'Bluesky', onClick: clickJestFn, type: LinkType.Bluesky, }, }; + +export const WithCustomLabel: Story = { + args: { + href: 'https://www.instagram.com/cristiano', + label: 'Cristiano Ronaldo Official', + onClick: clickJestFn, + type: LinkType.Instagram, + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + await expect( + canvas.getByText('Cristiano Ronaldo Official'), + ).toBeInTheDocument(); + }, +};