Skip to content

Custom getKeysForDrag bug - Drag and drop selected items seperatly with GridListΒ #8162

Open
@JonRC

Description

@JonRC

Provide a general summary of the issue here

The documentation says that getKeysForDrag returns the selected items.
I want to overwrite this function to drag and drop selected items separately.
Even though I overwrite it, drag and drop don't work as expected.

GridList.bug.mp4

Overwriting getKeysForDrag, full example in "Steps to reproduce"

  dragAndDropHooks.useDraggableCollectionState =
    function useDraggableCollectionStateOverride(
      props: DraggableCollectionStateOpts
    ) {
      const draggableHook = useDraggableCollectionState({
        ...props,
        ...options,
      } as DraggableCollectionStateOptions);
      draggableHook.getKeysForDrag = function (key: string) {
        return new Set([key]); //Just the clicked item be a key for drag
      };
      return draggableHook;
    };

πŸ€” Expected Behavior?

Items of a GridList to be reordered (drag and drop) separately

😯 Current Behavior

All the selected keys are dragged

πŸ’ Possible Solution

I'm not sure, I didn't realize looking at the source code where onReorder evaluates the event.keys

πŸ”¦ Context

No response

πŸ–₯️ Steps to Reproduce

Repository

You can just clone and run this repository:
https://github.com/JonRC/react-aria-grid-list-bug

Code

Here is the code used in the repository below if you want reproduce by your own

/* eslint-disable @typescript-eslint/no-empty-object-type */
import {
  DraggableCollectionStateOptions,
  useDraggableCollectionState,
  useListData,
} from "react-stately";
import {
  GridList,
  GridListItem,
  useDragAndDrop,
  Checkbox as AriaCheckbox,
  CheckboxProps,
  DragAndDropOptions,
} from "react-aria-components";
import { useMemo } from "react";

interface DraggableCollectionStateOpts
  extends Omit<DraggableCollectionStateOptions, "getItems"> {}

function App() {
  const list = useListData({
    initialItems: [
      { id: 1, name: "Adobe Photoshop" },
      { id: 2, name: "Adobe XD" },
      { id: 3, name: "Adobe Dreamweaver" },
      { id: 4, name: "Adobe InDesign" },
      { id: 5, name: "Adobe Connect" },
    ],
  });

  const options = useMemo<DragAndDropOptions>(
    () => ({
      getItems: (keys) =>
        [...keys].map((key) => ({
          "text/plain": list.getItem(key)?.name ?? "",
        })),
      onReorder(e) {
        if (e.target.dropPosition === "before") {
          list.moveBefore(e.target.key, e.keys);
        } else if (e.target.dropPosition === "after") {
          list.moveAfter(e.target.key, e.keys);
        }
      },
    }),
    [list]
  );

  const { dragAndDropHooks } = useDragAndDrop(options);

  dragAndDropHooks.useDraggableCollectionState =
    function useDraggableCollectionStateOverride(
      props: DraggableCollectionStateOpts
    ) {
      const draggableHook = useDraggableCollectionState({
        ...props,
        ...options,
      } as DraggableCollectionStateOptions);
      draggableHook.getKeysForDrag = function (key: string) {
        return new Set([key]); //Just the clicked item be a key for drag
      };
      return draggableHook;
    };

  return (
    <GridList
      aria-label="Reorderable list"
      selectionMode="multiple"
      items={list.items}
      dragAndDropHooks={dragAndDropHooks}
      style={{ marginLeft: "100px" }}
    >
      {(item) => (
        <GridListItem style={{ display: "flex" }}>
          {() => (
            <>
              <Checkbox slot="selection" />
              {item.name}
            </>
          )}
        </GridListItem>
      )}
    </GridList>
  );
}

export function Checkbox(props: CheckboxProps) {
  return (
    <AriaCheckbox {...props} style={{ display: "flex" }}>
      {({ isSelected, isIndeterminate }) => (
        <>
          <div>{isIndeterminate ? "[ ]" : isSelected ? "[x]" : "[ ]"}</div>
          {props.children}
        </>
      )}
    </AriaCheckbox>
  );
}

export default App;

Version

"react-aria-components": "^1.8.0"

What browsers are you seeing the problem on?

Chrome

If other, please specify.

No response

What operating system are you using?

Linux, Ubuntu

🧒 Your Company/Team

No response

πŸ•· Tracking Issue

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesthelp wantedExtra attention is needed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions