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:
@ -4,8 +4,8 @@ import { Key } from 'ts-key-enum';
|
|||||||
import { IconPlus } from 'twenty-ui';
|
import { IconPlus } from 'twenty-ui';
|
||||||
|
|
||||||
import { useLinksField } from '@/object-record/record-field/meta-types/hooks/useLinksField';
|
import { useLinksField } from '@/object-record/record-field/meta-types/hooks/useLinksField';
|
||||||
|
import { LinksFieldMenuItem } from '@/object-record/record-field/meta-types/input/components/LinksFieldMenuItem';
|
||||||
import { FieldInputEvent } from '@/object-record/record-field/types/FieldInputEvent';
|
import { FieldInputEvent } from '@/object-record/record-field/types/FieldInputEvent';
|
||||||
import { LinkDisplay } from '@/ui/field/display/components/LinkDisplay';
|
|
||||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||||
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||||
import { DropdownMenuInput } from '@/ui/layout/dropdown/components/DropdownMenuInput';
|
import { DropdownMenuInput } from '@/ui/layout/dropdown/components/DropdownMenuInput';
|
||||||
@ -14,6 +14,7 @@ import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownM
|
|||||||
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
||||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||||
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
||||||
|
import { toSpliced } from '~/utils/array/toSpliced';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isDefined } from '~/utils/isDefined';
|
||||||
|
|
||||||
const StyledDropdownMenu = styled(DropdownMenu)`
|
const StyledDropdownMenu = styled(DropdownMenu)`
|
||||||
@ -35,7 +36,7 @@ export const LinksFieldInput = ({
|
|||||||
|
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const links = useMemo(
|
const links = useMemo<{ url: string; label: string }[]>(
|
||||||
() =>
|
() =>
|
||||||
[
|
[
|
||||||
fieldValue.primaryLinkUrl
|
fieldValue.primaryLinkUrl
|
||||||
@ -53,51 +54,47 @@ export const LinksFieldInput = ({
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const handleDropdownClose = () => {
|
||||||
|
onCancel?.();
|
||||||
|
};
|
||||||
|
|
||||||
useListenClickOutside({
|
useListenClickOutside({
|
||||||
refs: [containerRef],
|
refs: [containerRef],
|
||||||
callback: (event) => {
|
callback: handleDropdownClose,
|
||||||
event.stopImmediatePropagation();
|
|
||||||
|
|
||||||
const isTargetInput =
|
|
||||||
event.target instanceof HTMLInputElement &&
|
|
||||||
event.target.tagName === 'INPUT';
|
|
||||||
|
|
||||||
if (!isTargetInput) {
|
|
||||||
onCancel?.();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useScopedHotkeys(Key.Escape, handleDropdownClose, hotkeyScope);
|
||||||
|
|
||||||
const [isInputDisplayed, setIsInputDisplayed] = useState(false);
|
const [isInputDisplayed, setIsInputDisplayed] = useState(false);
|
||||||
const [inputValue, setInputValue] = useState('');
|
const [inputValue, setInputValue] = useState('');
|
||||||
|
|
||||||
useScopedHotkeys(Key.Escape, onCancel ?? (() => {}), hotkeyScope);
|
const handleAddLink = () => {
|
||||||
|
|
||||||
const handleSubmit = () => {
|
|
||||||
if (!inputValue) return;
|
if (!inputValue) return;
|
||||||
|
|
||||||
setIsInputDisplayed(false);
|
setIsInputDisplayed(false);
|
||||||
setInputValue('');
|
setInputValue('');
|
||||||
|
|
||||||
if (!links.length) {
|
const nextLinks = [...links, { label: '', url: inputValue }];
|
||||||
onSubmit?.(() =>
|
const [nextPrimaryLink, ...nextSecondaryLinks] = nextLinks;
|
||||||
persistLinksField({
|
|
||||||
primaryLinkUrl: inputValue,
|
|
||||||
primaryLinkLabel: '',
|
|
||||||
secondaryLinks: [],
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
onSubmit?.(() =>
|
||||||
|
persistLinksField({
|
||||||
|
primaryLinkUrl: nextPrimaryLink.url ?? '',
|
||||||
|
primaryLinkLabel: nextPrimaryLink.label ?? '',
|
||||||
|
secondaryLinks: nextSecondaryLinks,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeleteLink = (index: number) => {
|
||||||
onSubmit?.(() =>
|
onSubmit?.(() =>
|
||||||
persistLinksField({
|
persistLinksField({
|
||||||
...fieldValue,
|
...fieldValue,
|
||||||
secondaryLinks: [
|
secondaryLinks: toSpliced(
|
||||||
...(fieldValue.secondaryLinks ?? []),
|
fieldValue.secondaryLinks ?? [],
|
||||||
{ label: '', url: inputValue },
|
index - 1,
|
||||||
],
|
1,
|
||||||
|
),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -108,9 +105,13 @@ export const LinksFieldInput = ({
|
|||||||
<>
|
<>
|
||||||
<DropdownMenuItemsContainer>
|
<DropdownMenuItemsContainer>
|
||||||
{links.map(({ label, url }, index) => (
|
{links.map(({ label, url }, index) => (
|
||||||
<MenuItem
|
<LinksFieldMenuItem
|
||||||
key={index}
|
key={index}
|
||||||
text={<LinkDisplay value={{ label, url }} />}
|
dropdownId={`${hotkeyScope}-links-${index}`}
|
||||||
|
isPrimary={index === 0}
|
||||||
|
label={label}
|
||||||
|
onDelete={() => handleDeleteLink(index)}
|
||||||
|
url={url}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</DropdownMenuItemsContainer>
|
</DropdownMenuItemsContainer>
|
||||||
@ -124,9 +125,9 @@ export const LinksFieldInput = ({
|
|||||||
value={inputValue}
|
value={inputValue}
|
||||||
hotkeyScope={hotkeyScope}
|
hotkeyScope={hotkeyScope}
|
||||||
onChange={(event) => setInputValue(event.target.value)}
|
onChange={(event) => setInputValue(event.target.value)}
|
||||||
onEnter={handleSubmit}
|
onEnter={handleAddLink}
|
||||||
rightComponent={
|
rightComponent={
|
||||||
<LightIconButton Icon={IconPlus} onClick={handleSubmit} />
|
<LightIconButton Icon={IconPlus} onClick={handleAddLink} />
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@ -0,0 +1,77 @@
|
|||||||
|
import styled from '@emotion/styled';
|
||||||
|
import {
|
||||||
|
IconBookmark,
|
||||||
|
IconComponent,
|
||||||
|
IconDotsVertical,
|
||||||
|
IconTrash,
|
||||||
|
} from 'twenty-ui';
|
||||||
|
|
||||||
|
import { LinkDisplay } from '@/ui/field/display/components/LinkDisplay';
|
||||||
|
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||||
|
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||||
|
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||||
|
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
||||||
|
|
||||||
|
type LinksFieldMenuItemProps = {
|
||||||
|
dropdownId: string;
|
||||||
|
isPrimary?: boolean;
|
||||||
|
label: string;
|
||||||
|
onDelete: () => void;
|
||||||
|
url: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const StyledIconBookmark = styled(IconBookmark)`
|
||||||
|
color: ${({ theme }) => theme.font.color.light};
|
||||||
|
height: ${({ theme }) => theme.icon.size.sm}px;
|
||||||
|
width: ${({ theme }) => theme.icon.size.sm}px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const LinksFieldMenuItem = ({
|
||||||
|
dropdownId,
|
||||||
|
isPrimary,
|
||||||
|
label,
|
||||||
|
onDelete,
|
||||||
|
url,
|
||||||
|
}: LinksFieldMenuItemProps) => {
|
||||||
|
const { isDropdownOpen } = useDropdown(dropdownId);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MenuItem
|
||||||
|
text={<LinkDisplay value={{ label, url }} />}
|
||||||
|
isIconDisplayedOnHoverOnly={!isPrimary && !isDropdownOpen}
|
||||||
|
iconButtons={[
|
||||||
|
{
|
||||||
|
Wrapper: isPrimary
|
||||||
|
? undefined
|
||||||
|
: ({ iconButton }) => (
|
||||||
|
<Dropdown
|
||||||
|
dropdownId={dropdownId}
|
||||||
|
dropdownHotkeyScope={{
|
||||||
|
scope: dropdownId,
|
||||||
|
}}
|
||||||
|
dropdownPlacement="right-start"
|
||||||
|
dropdownStrategy="fixed"
|
||||||
|
disableBlur
|
||||||
|
clickableComponent={iconButton}
|
||||||
|
dropdownComponents={
|
||||||
|
<DropdownMenuItemsContainer>
|
||||||
|
<MenuItem
|
||||||
|
accent="danger"
|
||||||
|
LeftIcon={IconTrash}
|
||||||
|
text="Delete"
|
||||||
|
onClick={onDelete}
|
||||||
|
/>
|
||||||
|
</DropdownMenuItemsContainer>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
Icon: isPrimary
|
||||||
|
? (StyledIconBookmark as IconComponent)
|
||||||
|
: IconDotsVertical,
|
||||||
|
accent: 'tertiary',
|
||||||
|
onClick: isPrimary ? undefined : () => {},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -1,4 +1,4 @@
|
|||||||
import { MouseEvent } from 'react';
|
import { FunctionComponent, MouseEvent, ReactElement } from 'react';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { IconComponent } from 'twenty-ui';
|
import { IconComponent } from 'twenty-ui';
|
||||||
|
|
||||||
@ -14,7 +14,9 @@ export type LightIconButtonGroupProps = Pick<
|
|||||||
'className' | 'size'
|
'className' | 'size'
|
||||||
> & {
|
> & {
|
||||||
iconButtons: {
|
iconButtons: {
|
||||||
|
Wrapper?: FunctionComponent<{ iconButton: ReactElement }>;
|
||||||
Icon: IconComponent;
|
Icon: IconComponent;
|
||||||
|
accent?: LightIconButtonProps['accent'];
|
||||||
onClick?: (event: MouseEvent<any>) => void;
|
onClick?: (event: MouseEvent<any>) => void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
}[];
|
}[];
|
||||||
@ -26,16 +28,26 @@ export const LightIconButtonGroup = ({
|
|||||||
className,
|
className,
|
||||||
}: LightIconButtonGroupProps) => (
|
}: LightIconButtonGroupProps) => (
|
||||||
<StyledLightIconButtonGroupContainer className={className}>
|
<StyledLightIconButtonGroupContainer className={className}>
|
||||||
{iconButtons.map(({ Icon, onClick }, index) => {
|
{iconButtons.map(({ Wrapper, Icon, accent, onClick }, index) => {
|
||||||
return (
|
const iconButton = (
|
||||||
<LightIconButton
|
<LightIconButton
|
||||||
key={`light-icon-button-${index}`}
|
key={`light-icon-button-${index}`}
|
||||||
Icon={Icon}
|
Icon={Icon}
|
||||||
|
accent={accent}
|
||||||
disabled={!onClick}
|
disabled={!onClick}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
size={size}
|
size={size}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return Wrapper ? (
|
||||||
|
<Wrapper
|
||||||
|
key={`light-icon-button-wrapper-${index}`}
|
||||||
|
iconButton={iconButton}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
iconButton
|
||||||
|
);
|
||||||
})}
|
})}
|
||||||
</StyledLightIconButtonGroupContainer>
|
</StyledLightIconButtonGroupContainer>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -460,7 +460,7 @@ export const InternalDatePicker = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{clearable && (
|
{clearable && (
|
||||||
<StyledButtonContainer onClick={handleClear} isMenuOpen={false}>
|
<StyledButtonContainer onClick={handleClear}>
|
||||||
<StyledButton LeftIcon={IconCalendarX} text="Clear" />
|
<StyledButton LeftIcon={IconCalendarX} text="Clear" />
|
||||||
</StyledButtonContainer>
|
</StyledButtonContainer>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -36,6 +36,7 @@ type DropdownProps = {
|
|||||||
dropdownPlacement?: Placement;
|
dropdownPlacement?: Placement;
|
||||||
dropdownMenuWidth?: `${string}px` | `${number}%` | 'auto' | number;
|
dropdownMenuWidth?: `${string}px` | `${number}%` | 'auto' | number;
|
||||||
dropdownOffset?: { x?: number; y?: number };
|
dropdownOffset?: { x?: number; y?: number };
|
||||||
|
dropdownStrategy?: 'fixed' | 'absolute';
|
||||||
disableBlur?: boolean;
|
disableBlur?: boolean;
|
||||||
onClickOutside?: () => void;
|
onClickOutside?: () => void;
|
||||||
onClose?: () => void;
|
onClose?: () => void;
|
||||||
@ -51,6 +52,7 @@ export const Dropdown = ({
|
|||||||
dropdownId,
|
dropdownId,
|
||||||
dropdownHotkeyScope,
|
dropdownHotkeyScope,
|
||||||
dropdownPlacement = 'bottom-end',
|
dropdownPlacement = 'bottom-end',
|
||||||
|
dropdownStrategy = 'absolute',
|
||||||
dropdownOffset = { x: 0, y: 0 },
|
dropdownOffset = { x: 0, y: 0 },
|
||||||
disableBlur = false,
|
disableBlur = false,
|
||||||
onClickOutside,
|
onClickOutside,
|
||||||
@ -75,6 +77,7 @@ export const Dropdown = ({
|
|||||||
placement: dropdownPlacement,
|
placement: dropdownPlacement,
|
||||||
middleware: [flip(), ...offsetMiddlewares],
|
middleware: [flip(), ...offsetMiddlewares],
|
||||||
whileElementsMounted: autoUpdate,
|
whileElementsMounted: autoUpdate,
|
||||||
|
strategy: dropdownStrategy,
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleHotkeyTriggered = () => {
|
const handleHotkeyTriggered = () => {
|
||||||
|
|||||||
@ -25,8 +25,8 @@ const StyledDropdownMenu = styled.div<{
|
|||||||
|
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
width: ${({ width }) =>
|
width: ${({ width = 160 }) =>
|
||||||
width ? `${typeof width === 'number' ? `${width}px` : width}` : '160px'};
|
typeof width === 'number' ? `${width}px` : width};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const DropdownMenu = StyledDropdownMenu;
|
export const DropdownMenu = StyledDropdownMenu;
|
||||||
|
|||||||
@ -52,7 +52,7 @@ export const useDropdown = (dropdownId?: string) => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
scopeId,
|
scopeId,
|
||||||
isDropdownOpen: isDropdownOpen,
|
isDropdownOpen,
|
||||||
closeDropdown,
|
closeDropdown,
|
||||||
toggleDropdown,
|
toggleDropdown,
|
||||||
openDropdown,
|
openDropdown,
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { MouseEvent, ReactNode } from 'react';
|
import { FunctionComponent, MouseEvent, ReactElement, ReactNode } from 'react';
|
||||||
import { IconComponent } from 'twenty-ui';
|
import { IconComponent } from 'twenty-ui';
|
||||||
|
|
||||||
|
import { LightIconButtonProps } from '@/ui/input/button/components/LightIconButton';
|
||||||
import { LightIconButtonGroup } from '@/ui/input/button/components/LightIconButtonGroup';
|
import { LightIconButtonGroup } from '@/ui/input/button/components/LightIconButtonGroup';
|
||||||
|
|
||||||
import { MenuItemLeftContent } from '../internals/components/MenuItemLeftContent';
|
import { MenuItemLeftContent } from '../internals/components/MenuItemLeftContent';
|
||||||
@ -11,7 +12,9 @@ import {
|
|||||||
import { MenuItemAccent } from '../types/MenuItemAccent';
|
import { MenuItemAccent } from '../types/MenuItemAccent';
|
||||||
|
|
||||||
export type MenuItemIconButton = {
|
export type MenuItemIconButton = {
|
||||||
|
Wrapper?: FunctionComponent<{ iconButton: ReactElement }>;
|
||||||
Icon: IconComponent;
|
Icon: IconComponent;
|
||||||
|
accent?: LightIconButtonProps['accent'];
|
||||||
onClick?: (event: MouseEvent<any>) => void;
|
onClick?: (event: MouseEvent<any>) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -24,7 +27,7 @@ export type MenuItemProps = {
|
|||||||
isTooltipOpen?: boolean;
|
isTooltipOpen?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
testId?: string;
|
testId?: string;
|
||||||
onClick?: (event: MouseEvent<HTMLLIElement>) => void;
|
onClick?: (event: MouseEvent<HTMLDivElement>) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const MenuItem = ({
|
export const MenuItem = ({
|
||||||
@ -32,7 +35,6 @@ export const MenuItem = ({
|
|||||||
accent = 'default',
|
accent = 'default',
|
||||||
text,
|
text,
|
||||||
iconButtons,
|
iconButtons,
|
||||||
isTooltipOpen,
|
|
||||||
isIconDisplayedOnHoverOnly = true,
|
isIconDisplayedOnHoverOnly = true,
|
||||||
className,
|
className,
|
||||||
testId,
|
testId,
|
||||||
@ -40,7 +42,7 @@ export const MenuItem = ({
|
|||||||
}: MenuItemProps) => {
|
}: MenuItemProps) => {
|
||||||
const showIconButtons = Array.isArray(iconButtons) && iconButtons.length > 0;
|
const showIconButtons = Array.isArray(iconButtons) && iconButtons.length > 0;
|
||||||
|
|
||||||
const handleMenuItemClick = (event: MouseEvent<HTMLLIElement>) => {
|
const handleMenuItemClick = (event: MouseEvent<HTMLDivElement>) => {
|
||||||
if (!onClick) return;
|
if (!onClick) return;
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
@ -54,7 +56,6 @@ export const MenuItem = ({
|
|||||||
onClick={handleMenuItemClick}
|
onClick={handleMenuItemClick}
|
||||||
className={className}
|
className={className}
|
||||||
accent={accent}
|
accent={accent}
|
||||||
isMenuOpen={!!isTooltipOpen}
|
|
||||||
isIconDisplayedOnHoverOnly={isIconDisplayedOnHoverOnly}
|
isIconDisplayedOnHoverOnly={isIconDisplayedOnHoverOnly}
|
||||||
>
|
>
|
||||||
<StyledMenuItemLeftContent>
|
<StyledMenuItemLeftContent>
|
||||||
|
|||||||
@ -23,7 +23,6 @@ export const MenuItemDraggable = ({
|
|||||||
LeftIcon,
|
LeftIcon,
|
||||||
accent = 'default',
|
accent = 'default',
|
||||||
iconButtons,
|
iconButtons,
|
||||||
isTooltipOpen,
|
|
||||||
onClick,
|
onClick,
|
||||||
text,
|
text,
|
||||||
isDragDisabled = false,
|
isDragDisabled = false,
|
||||||
@ -37,7 +36,6 @@ export const MenuItemDraggable = ({
|
|||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
accent={accent}
|
accent={accent}
|
||||||
className={className}
|
className={className}
|
||||||
isMenuOpen={!!isTooltipOpen}
|
|
||||||
isIconDisplayedOnHoverOnly={isIconDisplayedOnHoverOnly}
|
isIconDisplayedOnHoverOnly={isIconDisplayedOnHoverOnly}
|
||||||
>
|
>
|
||||||
<MenuItemLeftContent
|
<MenuItemLeftContent
|
||||||
|
|||||||
@ -10,7 +10,7 @@ export type MenuItemBaseProps = {
|
|||||||
isKeySelected?: boolean;
|
isKeySelected?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const StyledMenuItemBase = styled.li<MenuItemBaseProps>`
|
export const StyledMenuItemBase = styled.div<MenuItemBaseProps>`
|
||||||
--horizontal-padding: ${({ theme }) => theme.spacing(1)};
|
--horizontal-padding: ${({ theme }) => theme.spacing(1)};
|
||||||
--vertical-padding: ${({ theme }) => theme.spacing(2)};
|
--vertical-padding: ${({ theme }) => theme.spacing(2)};
|
||||||
|
|
||||||
@ -101,23 +101,26 @@ export const StyledMenuItemRightContent = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export const StyledHoverableMenuItemBase = styled(StyledMenuItemBase)<{
|
export const StyledHoverableMenuItemBase = styled(StyledMenuItemBase)<{
|
||||||
isMenuOpen: boolean;
|
|
||||||
isIconDisplayedOnHoverOnly?: 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 {
|
& .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;
|
transition: opacity ${({ theme }) => theme.animation.duration.instant}s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
|
||||||
& .hoverable-buttons {
|
|
||||||
opacity: 1;
|
|
||||||
pointer-events: auto;
|
|
||||||
position: static;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
|
|||||||
@ -19,6 +19,7 @@ export {
|
|||||||
IconBell,
|
IconBell,
|
||||||
IconBolt,
|
IconBolt,
|
||||||
IconBook2,
|
IconBook2,
|
||||||
|
IconBookmark,
|
||||||
IconBox,
|
IconBox,
|
||||||
IconBrandGithub,
|
IconBrandGithub,
|
||||||
IconBrandGoogle,
|
IconBrandGoogle,
|
||||||
|
|||||||
Reference in New Issue
Block a user