Fixed context menu on index page (#9316)

Fixes https://github.com/twentyhq/twenty/issues/8970

The context menu wasn't working because of wrong architecture with the
Dropdown component, as it's a unique behavior (no clickable component
and portal) it also required refactoring a bit the Dropdown component.

- Context menu now uses a portal
- Fixed dropdown offset without clickable component (now using a
fallback anchor component)
- Fixed React array key props
This commit is contained in:
Lucas Bordeau
2025-01-03 11:11:33 +01:00
committed by GitHub
parent 0674388426
commit 8333892647
4 changed files with 63 additions and 56 deletions

View File

@ -10,8 +10,12 @@ type ArrayDisplayProps = {
export const ArrayDisplay = ({ value }: ArrayDisplayProps) => {
return (
<ExpandableList>
{value?.map((item) => (
<Chip variant={ChipVariant.Highlighted} label={item} />
{value?.map((item, index) => (
<Chip
key={`${item}-${index}`}
variant={ChipVariant.Highlighted}
label={item}
/>
))}
</ExpandableList>
);

View File

@ -19,10 +19,17 @@ import { DropdownUnmountEffect } from '@/ui/layout/dropdown/components/DropdownU
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponeInstanceContext';
import { dropdownMaxHeightComponentStateV2 } from '@/ui/layout/dropdown/states/dropdownMaxHeightComponentStateV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import styled from '@emotion/styled';
import { flushSync } from 'react-dom';
import { isDefined } from 'twenty-ui';
import { DropdownOnToggleEffect } from './DropdownOnToggleEffect';
const StyledDropdownFallbackAnchor = styled.div`
left: 0;
position: absolute;
top: 0;
`;
type DropdownProps = {
className?: string;
clickableComponent?: ReactNode;
@ -53,7 +60,7 @@ export const Dropdown = ({
dropdownHotkeyScope,
dropdownPlacement = 'bottom-end',
dropdownStrategy = 'absolute',
dropdownOffset = { x: 0, y: 0 },
dropdownOffset,
onClickOutside,
onClose,
onOpen,
@ -61,24 +68,27 @@ export const Dropdown = ({
}: DropdownProps) => {
const { isDropdownOpen, toggleDropdown } = useDropdown(dropdownId);
const offsetMiddlewares = [];
const setDropdownMaxHeight = useSetRecoilComponentStateV2(
dropdownMaxHeightComponentStateV2,
dropdownId,
);
if (isDefined(dropdownOffset.x)) {
offsetMiddlewares.push(offset({ crossAxis: dropdownOffset.x }));
}
const isUsingOffset =
isDefined(dropdownOffset?.x) || isDefined(dropdownOffset?.y);
if (isDefined(dropdownOffset.y)) {
offsetMiddlewares.push(offset({ mainAxis: dropdownOffset.y }));
}
const offsetMiddleware = isUsingOffset
? [
offset({
crossAxis: dropdownOffset?.x ?? 0,
mainAxis: dropdownOffset?.y ?? 0,
}),
]
: [];
const { refs, floatingStyles, placement } = useFloating({
placement: dropdownPlacement,
middleware: [
...offsetMiddleware,
flip(),
size({
padding: 32,
@ -89,7 +99,6 @@ export const Dropdown = ({
},
boundary: document.querySelector('#root') ?? undefined,
}),
...offsetMiddlewares,
],
whileElementsMounted: autoUpdate,
strategy: dropdownStrategy,
@ -109,13 +118,15 @@ export const Dropdown = ({
>
<DropdownScope dropdownScopeId={getScopeIdFromComponentId(dropdownId)}>
<>
{clickableComponent && (
{isDefined(clickableComponent) ? (
<div
ref={refs.setReference}
onClick={handleClickableComponentClick}
>
{clickableComponent}
</div>
) : (
<StyledDropdownFallbackAnchor ref={refs.setReference} />
)}
{isDropdownOpen && (
<DropdownContent
@ -124,7 +135,7 @@ export const Dropdown = ({
dropdownMenuWidth={dropdownMenuWidth}
dropdownComponents={dropdownComponents}
dropdownId={dropdownId}
dropdownPlacement={placement ?? 'bottom-end'}
dropdownPlacement={placement}
floatingUiRefs={refs}
hotkeyScope={dropdownHotkeyScope}
hotkey={hotkey}