Minor fixes on context menu (#9340)

- Fixed click outside for kanban not working (changed strategy)
- Tried a different approach for setting the context menu position
- Fixes https://github.com/twentyhq/twenty/issues/9336
This commit is contained in:
Lucas Bordeau
2025-01-03 17:46:42 +01:00
committed by GitHub
parent e87b2c9e33
commit ae4615d140
4 changed files with 64 additions and 12 deletions

View File

@ -4,7 +4,9 @@ import { useContext, useRef } from 'react';
import { useRecoilCallback } from 'recoil'; import { useRecoilCallback } from 'recoil';
import { Key } from 'ts-key-enum'; import { Key } from 'ts-key-enum';
import { useActionMenu } from '@/action-menu/hooks/useActionMenu';
import { ActionBarHotkeyScope } from '@/action-menu/types/ActionBarHotKeyScope'; import { ActionBarHotkeyScope } from '@/action-menu/types/ActionBarHotKeyScope';
import { getActionMenuIdFromRecordIndexId } from '@/action-menu/utils/getActionMenuIdFromRecordIndexId';
import { RecordBoardHeader } from '@/object-record/record-board/components/RecordBoardHeader'; import { RecordBoardHeader } from '@/object-record/record-board/components/RecordBoardHeader';
import { RecordBoardStickyHeaderEffect } from '@/object-record/record-board/components/RecordBoardStickyHeaderEffect'; import { RecordBoardStickyHeaderEffect } from '@/object-record/record-board/components/RecordBoardStickyHeaderEffect';
import { RECORD_BOARD_CLICK_OUTSIDE_LISTENER_ID } from '@/object-record/record-board/constants/RecordBoardClickOutsideListenerId'; import { RECORD_BOARD_CLICK_OUTSIDE_LISTENER_ID } from '@/object-record/record-board/constants/RecordBoardClickOutsideListenerId';
@ -22,6 +24,7 @@ import { recordStoreFamilyState } from '@/object-record/record-store/states/reco
import { TableHotkeyScope } from '@/object-record/record-table/types/TableHotkeyScope'; import { TableHotkeyScope } from '@/object-record/record-table/types/TableHotkeyScope';
import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect'; import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { useClickOutsideListener } from '@/ui/utilities/pointer-event/hooks/useClickOutsideListener';
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
import { getScopeIdFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdFromComponentId'; import { getScopeIdFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdFromComponentId';
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper'; import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
@ -65,6 +68,23 @@ export const RecordBoard = () => {
useContext(RecordBoardContext); useContext(RecordBoardContext);
const boardRef = useRef<HTMLDivElement>(null); const boardRef = useRef<HTMLDivElement>(null);
const { toggleClickOutsideListener } = useClickOutsideListener(
RECORD_BOARD_CLICK_OUTSIDE_LISTENER_ID,
);
const actionMenuId = getActionMenuIdFromRecordIndexId(recordBoardId);
const { closeActionMenuDropdown } = useActionMenu(actionMenuId);
const handleDragSelectionStart = () => {
closeActionMenuDropdown();
toggleClickOutsideListener(false);
};
const handleDragSelectionEnd = () => {
toggleClickOutsideListener(true);
};
const visibleRecordGroupIds = useRecoilComponentFamilyValueV2( const visibleRecordGroupIds = useRecoilComponentFamilyValueV2(
visibleRecordGroupIdsComponentFamilySelector, visibleRecordGroupIdsComponentFamilySelector,
ViewType.Kanban, ViewType.Kanban,
@ -89,10 +109,13 @@ export const RecordBoard = () => {
'command-menu', 'command-menu',
'modal-backdrop', 'modal-backdrop',
'page-action-container', 'page-action-container',
'record-board-card',
], ],
listenerId: RECORD_BOARD_CLICK_OUTSIDE_LISTENER_ID, listenerId: RECORD_BOARD_CLICK_OUTSIDE_LISTENER_ID,
refs: [boardRef], refs: [],
callback: resetRecordSelection, callback: () => {
resetRecordSelection();
},
}); });
const selectAll = useRecoilCallback( const selectAll = useRecoilCallback(
@ -219,8 +242,9 @@ export const RecordBoard = () => {
<RecordBoardScrollRestoreEffect /> <RecordBoardScrollRestoreEffect />
<DragSelect <DragSelect
dragSelectable={boardRef} dragSelectable={boardRef}
onDragSelectionStart={resetRecordSelection} onDragSelectionEnd={handleDragSelectionEnd}
onDragSelectionChange={setRecordAsSelected} onDragSelectionChange={setRecordAsSelected}
onDragSelectionStart={handleDragSelectionStart}
/> />
</StyledBoardContentContainer> </StyledBoardContentContainer>
</StyledContainerContainer> </StyledContainerContainer>

View File

@ -66,5 +66,23 @@ export const useRecordBoardSelection = (recordBoardId: string) => {
[isRecordBoardCardSelectedFamilyState], [isRecordBoardCardSelectedFamilyState],
); );
return { resetRecordSelection, setRecordAsSelected }; const checkIfLastUnselectAndCloseDropdown = useRecoilCallback(
({ snapshot, set }) =>
() => {
const recordIds = getSnapshotValue(
snapshot,
recordBoardSelectedRecordIdsSelector,
);
if (recordIds.length === 0) {
set(isActionMenuDropdownOpenState, false);
}
},
[recordBoardSelectedRecordIdsSelector, isActionMenuDropdownOpenState],
);
return {
resetRecordSelection,
setRecordAsSelected,
checkIfLastUnselectAndCloseDropdown,
};
}; };

View File

@ -3,6 +3,7 @@ import { recordIndexActionMenuDropdownPositionComponentState } from '@/action-me
import { getActionMenuDropdownIdFromActionMenuId } from '@/action-menu/utils/getActionMenuDropdownIdFromActionMenuId'; import { getActionMenuDropdownIdFromActionMenuId } from '@/action-menu/utils/getActionMenuDropdownIdFromActionMenuId';
import { getActionMenuIdFromRecordIndexId } from '@/action-menu/utils/getActionMenuIdFromRecordIndexId'; import { getActionMenuIdFromRecordIndexId } from '@/action-menu/utils/getActionMenuIdFromRecordIndexId';
import { RecordBoardContext } from '@/object-record/record-board/contexts/RecordBoardContext'; import { RecordBoardContext } from '@/object-record/record-board/contexts/RecordBoardContext';
import { useRecordBoardSelection } from '@/object-record/record-board/hooks/useRecordBoardSelection';
import { RecordBoardCardContext } from '@/object-record/record-board/record-board-card/contexts/RecordBoardCardContext'; import { RecordBoardCardContext } from '@/object-record/record-board/record-board-card/contexts/RecordBoardCardContext';
import { RecordBoardScopeInternalContext } from '@/object-record/record-board/scopes/scope-internal-context/RecordBoardScopeInternalContext'; import { RecordBoardScopeInternalContext } from '@/object-record/record-board/scopes/scope-internal-context/RecordBoardScopeInternalContext';
import { isRecordBoardCardSelectedComponentFamilyState } from '@/object-record/record-board/states/isRecordBoardCardSelectedComponentFamilyState'; import { isRecordBoardCardSelectedComponentFamilyState } from '@/object-record/record-board/states/isRecordBoardCardSelectedComponentFamilyState';
@ -191,6 +192,9 @@ export const RecordBoardCard = ({
RecordBoardScopeInternalContext, RecordBoardScopeInternalContext,
); );
const { checkIfLastUnselectAndCloseDropdown } =
useRecordBoardSelection(recordBoardId);
const actionMenuId = getActionMenuIdFromRecordIndexId(recordBoardId); const actionMenuId = getActionMenuIdFromRecordIndexId(recordBoardId);
const actionMenuDropdownId = const actionMenuDropdownId =
@ -215,6 +219,13 @@ export const RecordBoardCard = ({
openActionMenuDropdown(); openActionMenuDropdown();
}; };
const handleCardClick = () => {
if (!isCreating) {
setIsCurrentCardSelected(!isCurrentCardSelected);
checkIfLastUnselectAndCloseDropdown();
}
};
const PreventSelectOnClickContainer = ({ const PreventSelectOnClickContainer = ({
children, children,
}: { }: {
@ -262,18 +273,17 @@ export const RecordBoardCard = ({
); );
return ( return (
<StyledBoardCardWrapper onContextMenu={handleActionMenuDropdown}> <StyledBoardCardWrapper
className="record-board-card"
onContextMenu={handleActionMenuDropdown}
>
{!isCreating && <RecordValueSetterEffect recordId={recordId} />} {!isCreating && <RecordValueSetterEffect recordId={recordId} />}
<InView> <InView>
<StyledBoardCard <StyledBoardCard
ref={cardRef} ref={cardRef}
selected={isCurrentCardSelected} selected={isCurrentCardSelected}
onMouseLeave={onMouseLeaveBoard} onMouseLeave={onMouseLeaveBoard}
onClick={() => { onClick={handleCardClick}
if (!isCreating) {
setIsCurrentCardSelected(!isCurrentCardSelected);
}
}}
> >
<StyledBoardCardHeader showCompactView={isCompactModeActive}> <StyledBoardCardHeader showCompactView={isCompactModeActive}>
{isCreating && position !== undefined ? ( {isCreating && position !== undefined ? (

View File

@ -50,8 +50,8 @@ export const useTriggerActionMenuDropdown = ({
event.preventDefault(); event.preventDefault();
set(recordIndexActionMenuDropdownPositionState, { set(recordIndexActionMenuDropdownPositionState, {
x: event.clientX, x: event.pageX,
y: event.clientY, y: event.pageY,
}); });
const isRowSelected = getSnapshotValue( const isRowSelected = getSnapshotValue(