From 736c79afde07d9e860e66750316e3a5c8bf7724f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tha=C3=AFs?= Date: Fri, 24 May 2024 17:59:08 +0200 Subject: [PATCH] fix: Links field fixes (#5565) Related issue: #3607 --- .../record-field/components/FieldInput.tsx | 2 +- .../input/components/LinksFieldInput.tsx | 47 ++++++----------- .../input/components/LinksFieldMenuItem.tsx | 51 +++++++++++-------- .../components/MultiSelectFieldInput.tsx | 2 - .../field/display/components/LinkDisplay.tsx | 27 +++------- .../link/components/RoundedLink.tsx | 8 ++- .../navigation/link/components/SocialLink.tsx | 15 +----- .../menu-item/components/MenuItem.tsx | 22 +++++--- .../src/display/chip/components/Chip.tsx | 16 +++--- 9 files changed, 84 insertions(+), 106 deletions(-) diff --git a/packages/twenty-front/src/modules/object-record/record-field/components/FieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/components/FieldInput.tsx index 58320f47b..42ae3153d 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/components/FieldInput.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/components/FieldInput.tsx @@ -136,7 +136,7 @@ export const FieldInput = ({ onShiftTab={onShiftTab} /> ) : isFieldLinks(fieldDefinition) ? ( - + ) : isFieldCurrency(fieldDefinition) ? ( void; - onSubmit?: FieldInputEvent; }; -export const LinksFieldInput = ({ - onCancel, - onSubmit, -}: LinksFieldInputProps) => { +export const LinksFieldInput = ({ onCancel }: LinksFieldInputProps) => { const { persistLinksField, hotkeyScope, fieldValue } = useLinksField(); const containerRef = useRef(null); @@ -99,7 +94,6 @@ export const LinksFieldInput = ({ ) { setIsInputDisplayed(false); setInputValue(''); - onCancel?.(); return; } @@ -109,14 +103,11 @@ export const LinksFieldInput = ({ : toSpliced(links, linkToEditIndex, 1, linkValue); const [nextPrimaryLink, ...nextSecondaryLinks] = nextLinks; - onSubmit?.(() => - persistLinksField({ - primaryLinkUrl: nextPrimaryLink.url ?? '', - primaryLinkLabel: nextPrimaryLink.label ?? '', - secondaryLinks: nextSecondaryLinks, - }), - ); - + persistLinksField({ + primaryLinkUrl: nextPrimaryLink.url ?? '', + primaryLinkLabel: nextPrimaryLink.label ?? '', + secondaryLinks: nextSecondaryLinks, + }); setIsInputDisplayed(false); setInputValue(''); }; @@ -125,26 +116,18 @@ export const LinksFieldInput = ({ const nextLinks = moveArrayItem(links, { fromIndex: index, toIndex: 0 }); const [nextPrimaryLink, ...nextSecondaryLinks] = nextLinks; - onSubmit?.(() => - persistLinksField({ - primaryLinkUrl: nextPrimaryLink.url ?? '', - primaryLinkLabel: nextPrimaryLink.label ?? '', - secondaryLinks: nextSecondaryLinks, - }), - ); + persistLinksField({ + primaryLinkUrl: nextPrimaryLink.url ?? '', + primaryLinkLabel: nextPrimaryLink.label ?? '', + secondaryLinks: nextSecondaryLinks, + }); }; const handleDeleteLink = (index: number) => { - onSubmit?.(() => - persistLinksField({ - ...fieldValue, - secondaryLinks: toSpliced( - fieldValue.secondaryLinks ?? [], - index - 1, - 1, - ), - }), - ); + persistLinksField({ + ...fieldValue, + secondaryLinks: toSpliced(fieldValue.secondaryLinks ?? [], index - 1, 1), + }); }; return ( diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/LinksFieldMenuItem.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/LinksFieldMenuItem.tsx index 8bdca7785..39be33237 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/LinksFieldMenuItem.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/LinksFieldMenuItem.tsx @@ -1,4 +1,4 @@ -import { useEffect } from 'react'; +import { useEffect, useState } from 'react'; import styled from '@emotion/styled'; import { IconBookmark, @@ -40,8 +40,12 @@ export const LinksFieldMenuItem = ({ onDelete, url, }: LinksFieldMenuItemProps) => { + const [isHovered, setIsHovered] = useState(false); const { isDropdownOpen, closeDropdown } = useDropdown(dropdownId); + const handleMouseEnter = () => setIsHovered(true); + const handleMouseLeave = () => setIsHovered(false); + // Make sure dropdown closes on unmount. useEffect(() => { if (isDropdownOpen) { @@ -51,13 +55,14 @@ export const LinksFieldMenuItem = ({ return ( } isIconDisplayedOnHoverOnly={!isPrimary && !isDropdownOpen} iconButtons={[ { - Wrapper: isPrimary - ? undefined - : ({ iconButton }) => ( + Wrapper: isHovered + ? ({ iconButton }) => ( - + {!isPrimary && ( + + )} - + {!isPrimary && ( + + )} } /> - ), - Icon: isPrimary - ? (StyledIconBookmark as IconComponent) - : IconDotsVertical, + ) + : undefined, + Icon: + isPrimary && !isHovered + ? (StyledIconBookmark as IconComponent) + : IconDotsVertical, accent: 'tertiary', - onClick: isPrimary ? undefined : () => {}, + onClick: isHovered ? () => {} : undefined, }, ]} /> diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/MultiSelectFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/MultiSelectFieldInput.tsx index 38c3cca0c..2f24422ee 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/MultiSelectFieldInput.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/MultiSelectFieldInput.tsx @@ -2,7 +2,6 @@ import { useRef, useState } from 'react'; import styled from '@emotion/styled'; import { useMultiSelectField } from '@/object-record/record-field/meta-types/hooks/useMultiSelectField'; -import { FieldInputEvent } from '@/object-record/record-field/types/FieldInputEvent'; import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput'; @@ -18,7 +17,6 @@ const StyledRelationPickerContainer = styled.div` `; export type MultiSelectFieldInputProps = { - onSubmit?: FieldInputEvent; onCancel?: () => void; }; 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 0131cb054..2fe16defa 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 @@ -1,5 +1,4 @@ import { MouseEvent } from 'react'; -import styled from '@emotion/styled'; import { FieldLinkValue } from '@/object-record/record-field/types/FieldMetadata'; import { RoundedLink } from '@/ui/navigation/link/components/RoundedLink'; @@ -11,15 +10,6 @@ import { checkUrlType } from '~/utils/checkUrlType'; import { getAbsoluteUrl } from '~/utils/url/getAbsoluteUrl'; import { getUrlHostName } from '~/utils/url/getUrlHostName'; -import { EllipsisDisplay } from './EllipsisDisplay'; - -const StyledRawLink = styled(RoundedLink)` - a { - font-size: ${({ theme }) => theme.font.size.md}; - white-space: nowrap; - } -`; - type LinkDisplayProps = { value?: FieldLinkValue; }; @@ -35,18 +25,15 @@ export const LinkDisplay = ({ value }: LinkDisplayProps) => { if (type === LinkType.LinkedIn || type === LinkType.Twitter) { return ( - - - {displayedValue} - - + + {displayedValue} + ); } + return ( - - - {displayedValue} - - + + {displayedValue} + ); }; diff --git a/packages/twenty-front/src/modules/ui/navigation/link/components/RoundedLink.tsx b/packages/twenty-front/src/modules/ui/navigation/link/components/RoundedLink.tsx index e54f9ebdb..d5d39cd9f 100644 --- a/packages/twenty-front/src/modules/ui/navigation/link/components/RoundedLink.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/link/components/RoundedLink.tsx @@ -11,14 +11,18 @@ type RoundedLinkProps = { }; const StyledLink = styled(ReactLink)` + font-size: ${({ theme }) => theme.font.size.md}; max-width: 100%; + height: ${({ theme }) => theme.spacing(5)}; `; const StyledChip = styled(Chip)` border-color: ${({ theme }) => theme.border.color.strong}; box-sizing: border-box; - padding: ${({ theme }) => theme.spacing(2)}; + padding: ${({ theme }) => theme.spacing(0, 2)}; max-width: 100%; + height: ${({ theme }) => theme.spacing(5)}; + min-width: 40px; `; export const RoundedLink = ({ @@ -39,7 +43,7 @@ export const RoundedLink = ({ ); diff --git a/packages/twenty-front/src/modules/ui/navigation/link/components/SocialLink.tsx b/packages/twenty-front/src/modules/ui/navigation/link/components/SocialLink.tsx index fa859e72a..bb23e32ba 100644 --- a/packages/twenty-front/src/modules/ui/navigation/link/components/SocialLink.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/link/components/SocialLink.tsx @@ -1,5 +1,4 @@ import * as React from 'react'; -import styled from '@emotion/styled'; import { getDisplayValueByUrlType } from '~/utils/getDisplayValueByUrlType'; @@ -18,16 +17,6 @@ type SocialLinkProps = { onClick?: (event: React.MouseEvent) => void; }; -const StyledRawLink = styled(RoundedLink)` - overflow: hidden; - - a { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } -`; - export const SocialLink = ({ children, href, @@ -38,8 +27,8 @@ export const SocialLink = ({ getDisplayValueByUrlType({ type: type, href: href }) ?? children; return ( - + {displayValue} - + ); }; diff --git a/packages/twenty-front/src/modules/ui/navigation/menu-item/components/MenuItem.tsx b/packages/twenty-front/src/modules/ui/navigation/menu-item/components/MenuItem.tsx index 36449c7c5..4e40759f9 100644 --- a/packages/twenty-front/src/modules/ui/navigation/menu-item/components/MenuItem.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/menu-item/components/MenuItem.tsx @@ -19,26 +19,30 @@ export type MenuItemIconButton = { }; export type MenuItemProps = { - LeftIcon?: IconComponent | null; accent?: MenuItemAccent; - text: ReactNode; + className?: string; iconButtons?: MenuItemIconButton[]; isIconDisplayedOnHoverOnly?: boolean; isTooltipOpen?: boolean; - className?: string; - testId?: string; + LeftIcon?: IconComponent | null; onClick?: (event: MouseEvent) => void; + onMouseEnter?: (event: MouseEvent) => void; + onMouseLeave?: (event: MouseEvent) => void; + testId?: string; + text: ReactNode; }; export const MenuItem = ({ - LeftIcon, accent = 'default', - text, + className, iconButtons, isIconDisplayedOnHoverOnly = true, - className, - testId, + LeftIcon, onClick, + onMouseEnter, + onMouseLeave, + testId, + text, }: MenuItemProps) => { const showIconButtons = Array.isArray(iconButtons) && iconButtons.length > 0; @@ -57,6 +61,8 @@ export const MenuItem = ({ className={className} accent={accent} isIconDisplayedOnHoverOnly={isIconDisplayedOnHoverOnly} + onMouseEnter={onMouseEnter} + onMouseLeave={onMouseLeave} > diff --git a/packages/twenty-ui/src/display/chip/components/Chip.tsx b/packages/twenty-ui/src/display/chip/components/Chip.tsx index e44740377..18369254b 100644 --- a/packages/twenty-ui/src/display/chip/components/Chip.tsx +++ b/packages/twenty-ui/src/display/chip/components/Chip.tsx @@ -87,13 +87,6 @@ const StyledContainer = styled('div', { } }} - // Size style overrides - ${({ theme, size }) => - size === ChipSize.Large && - css` - height: ${theme.spacing(4)}; - `} - // Variant style overrides ${({ disabled, theme, variant }) => { if (variant === ChipVariant.Regular) { @@ -153,6 +146,13 @@ const StyledLabel = styled.span` white-space: nowrap; `; +const StyledOverflowingTextWithTooltip = styled(OverflowingTextWithTooltip)<{ + size?: ChipSize; +}>` + height: ${({ theme, size }) => + size === ChipSize.Large ? theme.spacing(4) : 'auto'}; +`; + export const Chip = ({ size = ChipSize.Small, label, @@ -183,7 +183,7 @@ export const Chip = ({ > {leftComponent} - + {rightComponent}