feat: remove a link from a Links field (#5313)

Closes #5117

TO FIX in another PR: right now, the "Vertical Dots" LightIconButton
inside the Dropdown menu sometimes needs to be clicked twice to open the
nested dropdown, not sure why 🤔 Maybe an `event.preventDefault()` is
needed somewhere?

<img width="369" alt="image"
src="https://github.com/twentyhq/twenty/assets/3098428/dd0c771a-c18d-4eb2-8ed6-b107f56711e9">

---------

Co-authored-by: Jérémy Magrin <jeremy.magrin@gmail.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Thaïs
2024-05-22 09:39:21 +02:00
committed by GitHub
parent beaaf33544
commit 48003887ce
11 changed files with 160 additions and 64 deletions

View File

@ -1,4 +1,4 @@
import { MouseEvent } from 'react';
import { FunctionComponent, MouseEvent, ReactElement } from 'react';
import styled from '@emotion/styled';
import { IconComponent } from 'twenty-ui';
@ -14,7 +14,9 @@ export type LightIconButtonGroupProps = Pick<
'className' | 'size'
> & {
iconButtons: {
Wrapper?: FunctionComponent<{ iconButton: ReactElement }>;
Icon: IconComponent;
accent?: LightIconButtonProps['accent'];
onClick?: (event: MouseEvent<any>) => void;
disabled?: boolean;
}[];
@ -26,16 +28,26 @@ export const LightIconButtonGroup = ({
className,
}: LightIconButtonGroupProps) => (
<StyledLightIconButtonGroupContainer className={className}>
{iconButtons.map(({ Icon, onClick }, index) => {
return (
{iconButtons.map(({ Wrapper, Icon, accent, onClick }, index) => {
const iconButton = (
<LightIconButton
key={`light-icon-button-${index}`}
Icon={Icon}
accent={accent}
disabled={!onClick}
onClick={onClick}
size={size}
/>
);
return Wrapper ? (
<Wrapper
key={`light-icon-button-wrapper-${index}`}
iconButton={iconButton}
/>
) : (
iconButton
);
})}
</StyledLightIconButtonGroupContainer>
);

View File

@ -460,7 +460,7 @@ export const InternalDatePicker = ({
/>
</div>
{clearable && (
<StyledButtonContainer onClick={handleClear} isMenuOpen={false}>
<StyledButtonContainer onClick={handleClear}>
<StyledButton LeftIcon={IconCalendarX} text="Clear" />
</StyledButtonContainer>
)}

View File

@ -36,6 +36,7 @@ type DropdownProps = {
dropdownPlacement?: Placement;
dropdownMenuWidth?: `${string}px` | `${number}%` | 'auto' | number;
dropdownOffset?: { x?: number; y?: number };
dropdownStrategy?: 'fixed' | 'absolute';
disableBlur?: boolean;
onClickOutside?: () => void;
onClose?: () => void;
@ -51,6 +52,7 @@ export const Dropdown = ({
dropdownId,
dropdownHotkeyScope,
dropdownPlacement = 'bottom-end',
dropdownStrategy = 'absolute',
dropdownOffset = { x: 0, y: 0 },
disableBlur = false,
onClickOutside,
@ -75,6 +77,7 @@ export const Dropdown = ({
placement: dropdownPlacement,
middleware: [flip(), ...offsetMiddlewares],
whileElementsMounted: autoUpdate,
strategy: dropdownStrategy,
});
const handleHotkeyTriggered = () => {

View File

@ -25,8 +25,8 @@ const StyledDropdownMenu = styled.div<{
flex-direction: column;
z-index: 1;
width: ${({ width }) =>
width ? `${typeof width === 'number' ? `${width}px` : width}` : '160px'};
width: ${({ width = 160 }) =>
typeof width === 'number' ? `${width}px` : width};
`;
export const DropdownMenu = StyledDropdownMenu;

View File

@ -52,7 +52,7 @@ export const useDropdown = (dropdownId?: string) => {
return {
scopeId,
isDropdownOpen: isDropdownOpen,
isDropdownOpen,
closeDropdown,
toggleDropdown,
openDropdown,

View File

@ -1,6 +1,7 @@
import { MouseEvent, ReactNode } from 'react';
import { FunctionComponent, MouseEvent, ReactElement, ReactNode } from 'react';
import { IconComponent } from 'twenty-ui';
import { LightIconButtonProps } from '@/ui/input/button/components/LightIconButton';
import { LightIconButtonGroup } from '@/ui/input/button/components/LightIconButtonGroup';
import { MenuItemLeftContent } from '../internals/components/MenuItemLeftContent';
@ -11,7 +12,9 @@ import {
import { MenuItemAccent } from '../types/MenuItemAccent';
export type MenuItemIconButton = {
Wrapper?: FunctionComponent<{ iconButton: ReactElement }>;
Icon: IconComponent;
accent?: LightIconButtonProps['accent'];
onClick?: (event: MouseEvent<any>) => void;
};
@ -24,7 +27,7 @@ export type MenuItemProps = {
isTooltipOpen?: boolean;
className?: string;
testId?: string;
onClick?: (event: MouseEvent<HTMLLIElement>) => void;
onClick?: (event: MouseEvent<HTMLDivElement>) => void;
};
export const MenuItem = ({
@ -32,7 +35,6 @@ export const MenuItem = ({
accent = 'default',
text,
iconButtons,
isTooltipOpen,
isIconDisplayedOnHoverOnly = true,
className,
testId,
@ -40,7 +42,7 @@ export const MenuItem = ({
}: MenuItemProps) => {
const showIconButtons = Array.isArray(iconButtons) && iconButtons.length > 0;
const handleMenuItemClick = (event: MouseEvent<HTMLLIElement>) => {
const handleMenuItemClick = (event: MouseEvent<HTMLDivElement>) => {
if (!onClick) return;
event.preventDefault();
event.stopPropagation();
@ -54,7 +56,6 @@ export const MenuItem = ({
onClick={handleMenuItemClick}
className={className}
accent={accent}
isMenuOpen={!!isTooltipOpen}
isIconDisplayedOnHoverOnly={isIconDisplayedOnHoverOnly}
>
<StyledMenuItemLeftContent>

View File

@ -23,7 +23,6 @@ export const MenuItemDraggable = ({
LeftIcon,
accent = 'default',
iconButtons,
isTooltipOpen,
onClick,
text,
isDragDisabled = false,
@ -37,7 +36,6 @@ export const MenuItemDraggable = ({
onClick={onClick}
accent={accent}
className={className}
isMenuOpen={!!isTooltipOpen}
isIconDisplayedOnHoverOnly={isIconDisplayedOnHoverOnly}
>
<MenuItemLeftContent

View File

@ -10,7 +10,7 @@ export type MenuItemBaseProps = {
isKeySelected?: boolean;
};
export const StyledMenuItemBase = styled.li<MenuItemBaseProps>`
export const StyledMenuItemBase = styled.div<MenuItemBaseProps>`
--horizontal-padding: ${({ theme }) => theme.spacing(1)};
--vertical-padding: ${({ theme }) => theme.spacing(2)};
@ -101,23 +101,26 @@ export const StyledMenuItemRightContent = styled.div`
`;
export const StyledHoverableMenuItemBase = styled(StyledMenuItemBase)<{
isMenuOpen: boolean;
isIconDisplayedOnHoverOnly?: boolean;
}>`
${({ isIconDisplayedOnHoverOnly, theme }) =>
isIconDisplayedOnHoverOnly &&
css`
& .hoverable-buttons {
opacity: 0;
position: fixed;
right: ${theme.spacing(2)};
}
&:hover {
& .hoverable-buttons {
opacity: 1;
position: static;
}
}
`};
& .hoverable-buttons {
pointer-events: none;
position: fixed;
right: ${({ theme }) => theme.spacing(2)};
opacity: ${({ isIconDisplayedOnHoverOnly }) =>
isIconDisplayedOnHoverOnly ? 0 : 1};
transition: opacity ${({ theme }) => theme.animation.duration.instant}s ease;
}
&:hover {
& .hoverable-buttons {
opacity: 1;
pointer-events: auto;
position: static;
}
}
`;