dnd-kit
dnd-kit copied to clipboard
Proposal: add a SensorOptions property to facilitate disabling drag on interactive elements
Problem
Sometimes it is useful to make an entire element draggable, except interactive child elements.
Current Solution: As discussed in https://github.com/clauderic/dnd-kit/issues/477, a current solution to this issue is a custom sensor extending PointerSensor
and overriding its activators. This has some downsides: (1) it's a little hard to discover as a library user, (2) if the PointerSensor
's activators are updated in future releases, custom classes that override its activators won't benefit from those updates; (3) while not too hard, creating a custom sensor for this seems like a lot of code.
Other Libraries: For comparison, some other drag libraries include this behavior by default. For example, react-beautiful-dnd
automatically prevents drag on interactive child elements: Interactive child elements within a <Draggable />
Proposal:
Add some sort of sensor option to determine whether an element is draggable or not, something like
interface PointerSensorOptions {
/**
* Invoked with the target of `pointerdown` event. If returns `false`, drag
* events will not be emitted.
*/
isDraggableElement?: (element: HTMLElement) => boolean;
/** ...existing options */
}
Omitted isDraggableElement
in the sensor options would be equivalent to passing () => true
(all elements draggable).
Additionally, dnd-kit could then export a helper like isNotInteractiveElement
, or leave that to userland. (Writing a isNotInteractiveElement
predicate is much simpler than writing your own sensor, so leaving that for userland seems OK.)
Questions
- @clauderic Would you be open to this additional option, or something similar? I'd be happy to make a PR for it.
- If yes, would
PointerSensor
actually be the right place, or would this be suitable for all sensors? - This seems like an
activationConstraint
... Is it? On the other hand, those seem to be mutually exclusive, and providingisDraggableElement
should not preclude using other constraints.
For anyone interested, here is a CustomPointSensor
that provides this option: https://github.com/ChristopherChudzicki/math3d-next/blob/a224ca3865aa079aef34d349edfcf23d0fdf1cb9/client/src/util/components/dnd/PointerSensor.ts#L11
(I'm not sure if the activators
array is actually the best place to put this kind of logic, but it works for a proof of concept.)
And a CustomKeyboardSensor
dealing with a similar issue, namely that pressing the spacebar or enter keys on an input inside a draggable initiates drags:
https://github.com/ChristopherChudzicki/math3d-next/blob/f59bea5d1605a8276ac6a67c0e31c626fb7dda9c/client/src/util/components/dnd/KeyboardSensor.ts#L16
I tried that approach but didn't work for me. Then I opened an issue here: https://stackoverflow.com/questions/74963931. Anyways, if you have any idea on make that work, just let me know. Thanks!