Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sortable in modal - keydown event propagation issue #1367

Open
wolkyura opened this issue Mar 20, 2024 · 0 comments
Open

Sortable in modal - keydown event propagation issue #1367

wolkyura opened this issue Mar 20, 2024 · 0 comments

Comments

@wolkyura
Copy link

When using useSortable in a modal, there is an issue with keyboard event propagation. Currently, keyboard events are not prevented from propagation, causing unintended behavior. The modal catches keydown event (Escape) before dnd-kit listeners do, and closes instead of canceling the drag and stopping the propagation.

Expected behavior:

I'd expect that when keyboard navigation is activated within the sortable items, keyboard events should be stopped from further propagation. This would ensure that the modal (or other components) does not receive and act upon keyboard events when it shouldn't.

Codesandbox example

https://codesandbox.io/p/sandbox/priceless-currying-8ytlml?file=%2Fsrc%2FSortable.js%3A48%2C1

Steps to reproduce

  • Open modal
  • Press Tab to focus on one of the items
  • Press Space or Enter to activate keyboard listeners
  • Press Escape

Notes

I tried to prevent event propagation before invoking useSortable listeners, but this breaks the cancel functionality. I discovered that these events are attached to the document, causing them to be fired at the very end, which looks like the main issue. To fix this, I created MyKeyboardSensor and overrode attach() and detach() methods to set events directly to the target, and added event.stopPropagation(), this fixed my issue. I'm curious is there any particular reason why events are set to the document and not to the target itself?

class MyKeyboardSensor extends KeyboardSensor {
  private attach() {
    this.handleStart();

    this.windowListeners.add('resize', this.handleCancel);
    this.windowListeners.add('visibilitychange', this.handleCancel);

    this.props.event.target.addEventListener('keydown', this.handleKeyDown);
  }

  private detach() {
    this.props.event.target.removeEventListener('keydown', this.handleKeyDown);
    this.windowListeners.removeAll();
  }

  private handleCancel(event: Event) {
    const { onCancel } = this.props;

    event.stopPropagation();
    event.preventDefault();
    this.detach();
    onCancel();
  }
}

Also, I think listeners lack blur event handling, I'd expect that drag is canceled when this event is fired on the target element. Let me know if I should create a separate issue for this.

By the way, thanks for creating such an awesome library!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant