diff --git a/packages/twenty-front/src/modules/ui/utilities/drag-and-drop/constants/DndKitSensors.ts b/packages/twenty-front/src/modules/ui/utilities/drag-and-drop/constants/DndKitSensors.ts index 9d7af274bb..1f228ac0ac 100644 --- a/packages/twenty-front/src/modules/ui/utilities/drag-and-drop/constants/DndKitSensors.ts +++ b/packages/twenty-front/src/modules/ui/utilities/drag-and-drop/constants/DndKitSensors.ts @@ -1,14 +1,11 @@ -import { PointerActivationConstraints } from '@dnd-kit/dom'; import { KeyboardSensor, PointerSensor } from '@dnd-kit/react'; +import { getDragActivationConstraints } from '@/ui/utilities/drag-and-drop/utils/getDragActivationConstraints'; import { shouldPreventDragActivation } from '@/ui/utilities/drag-and-drop/utils/shouldPreventDragActivation'; -// Pointer drags only start past 8px so clicks on draggable items still register. export const DND_KIT_SENSORS = [ PointerSensor.configure({ - activationConstraints: [ - new PointerActivationConstraints.Distance({ value: 8 }), - ], + activationConstraints: getDragActivationConstraints, preventActivation: shouldPreventDragActivation, }), KeyboardSensor, diff --git a/packages/twenty-front/src/modules/ui/utilities/drag-and-drop/utils/__tests__/getDragActivationConstraints.test.ts b/packages/twenty-front/src/modules/ui/utilities/drag-and-drop/utils/__tests__/getDragActivationConstraints.test.ts new file mode 100644 index 0000000000..c03cc8c2d7 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/drag-and-drop/utils/__tests__/getDragActivationConstraints.test.ts @@ -0,0 +1,29 @@ +import { PointerActivationConstraints } from '@dnd-kit/dom'; + +import { getDragActivationConstraints } from '@/ui/utilities/drag-and-drop/utils/getDragActivationConstraints'; + +const createPointerEvent = (pointerType: string) => + ({ pointerType }) as unknown as PointerEvent; + +describe('getDragActivationConstraints', () => { + it('should require a press and hold when the pointer is a touch', () => { + const [constraint, ...otherConstraints] = getDragActivationConstraints( + createPointerEvent('touch'), + ); + + expect(constraint).toBeInstanceOf(PointerActivationConstraints.Delay); + expect(otherConstraints).toHaveLength(0); + }); + + it.each(['mouse', 'pen'])( + 'should require a movement distance when the pointer is a %s', + (pointerType) => { + const [constraint, ...otherConstraints] = getDragActivationConstraints( + createPointerEvent(pointerType), + ); + + expect(constraint).toBeInstanceOf(PointerActivationConstraints.Distance); + expect(otherConstraints).toHaveLength(0); + }, + ); +}); diff --git a/packages/twenty-front/src/modules/ui/utilities/drag-and-drop/utils/getDragActivationConstraints.ts b/packages/twenty-front/src/modules/ui/utilities/drag-and-drop/utils/getDragActivationConstraints.ts new file mode 100644 index 0000000000..75ce7ead63 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/drag-and-drop/utils/getDragActivationConstraints.ts @@ -0,0 +1,24 @@ +import { PointerActivationConstraints } from '@dnd-kit/dom'; + +// Same values as dnd-kit's own touch default: a swipe has to scroll the board, +// so a drag only starts after a press and hold that stays put. +const TOUCH_ACTIVATION_DELAY_IN_MS = 250; +const TOUCH_ACTIVATION_TOLERANCE_IN_PX = 5; + +// dnd-kit also delays activation for mouse and pen, which we leave out: holding +// a card still would start a drag and swallow the click that opens the record. +const POINTER_ACTIVATION_DISTANCE_IN_PX = 8; + +export const getDragActivationConstraints = (event: PointerEvent) => + event.pointerType === 'touch' + ? [ + new PointerActivationConstraints.Delay({ + value: TOUCH_ACTIVATION_DELAY_IN_MS, + tolerance: TOUCH_ACTIVATION_TOLERANCE_IN_PX, + }), + ] + : [ + new PointerActivationConstraints.Distance({ + value: POINTER_ACTIVATION_DISTANCE_IN_PX, + }), + ];