If anyone could provide an example with how I can use a grab and grabbing cursor with a drag handle, that would be great. Right now, no matter what CSS I try to use, the cursor seems to always go to default when dragging is active.
Edit: Closing this, I ended up using a workaround where I just applied a class to the whole document body
for other people who bump in here: https://github.com/clauderic/react-sortable-hoc/issues/253
this issue (and all the links there) can provide you with tips on ways to do this.
FYI heres's how i did it:
onSortStart={() => (document.body.style.cursor = 'grabbing')}
onSortEnd={({ newIndex, oldIndex }: any) => {
document.body.style.cursor = 'default';
...
then on your drag handler make sure to put cursor: grab on it
Thank you for this @zackify 鈥擨 would never have figured this out :( This should be documented somewhere :/
Completely agree. I searched forever then figured this out 馃槀 I don鈥檛 like having to call document methods inside react. But oh well!
A somewhat improved version of @zackify 's method. I wanted the cursor to change immediately on click for user feedback. Still pretty hacky, and there's a cursor flash if you release the mouse button over the drag handle or happen to pass over any elements that change cursor while you're dragging:
const GroupDragHandle = SortableHandle((): React.ReactElement => {
return (
<DragHandleIcon
onMouseEnter={ (): void => { if (document.body.style.cursor !== 'grabbing') document.body.style.cursor = 'grab' } }
onMouseLeave={ (): void => { if (document.body.style.cursor === 'grab') document.body.style.cursor = '' } }
onMouseDown={ (): void => { document.body.style.cursor = 'grabbing' } }
/>
);
});
...then on the SortableList itself:
onSortEnd={ (): void => { document.body.style.cursor = ''; } }
Thanks @neckro it works the way I need it. Could you tell me please what the void operator does there?
It is possible to do this with only changing one component:
const SortableList = SortableContainer(({ items }: { items: typeof values }) => (
<div
className="sortable_list_container"
style={{ cursor: 'grab' }}
onMouseDown={() => document.querySelectorAll('.sortable_list_container').forEach((el) => ((el as HTMLElement).style.cursor = 'grabbing'))}
onMouseUp={() => document.querySelectorAll('.sortable_list_container').forEach((el) => ((el as HTMLElement).style.cursor = 'grab'))}
>
{items.map((item, index) => (
<SortableItem key={keys[index]} index={index} item={item} />
))}
</div>
));
Where className is used, instead of id, to support more than one "sortable list" per document.
Thanks @neckro it works the way I need it. Could you tell me please what the void operator does there?
Sorry for not checking my notifications. That's Typescript -- you can remove the : void and the : React.ReactElement type hints for plain JS.
FYI heres's how i did it:
onSortStart={() => (document.body.style.cursor = 'grabbing')} onSortEnd={({ newIndex, oldIndex }: any) => { document.body.style.cursor = 'default'; ...then on your drag handler make sure to put
cursor: grabon it
Just to add to @zackify 's approach, to make sure that the cursor will not change when you drag over, say a button (it may change to a pointer), you can do this:
onSortStart={() => (document.body.className = 'grabbing')}
onSortEnd={({ newIndex, oldIndex }: any) => {
document.body.className = '';
...
where grabbing is
grabbing {
cursor: grabbing;
}
grabbing * {
cursor: grabbing;
}
@arosisi Your solution works like a charm :+1: It should be in the doc. Team Work power, thx guys ;p
Most helpful comment
FYI heres's how i did it:
then on your drag handler make sure to put
cursor: grabon it