react-modal icon indicating copy to clipboard operation
react-modal copied to clipboard

ReactModal focuses on last input/button when modal closes

Open trevlar opened this issue 6 years ago • 7 comments

Summary:

When the modal is closed it focuses on the last focused input field/button. This is unexpected and not clearly documented. I had a button that was only visible when focusing on a particular element using a CSS transform. Focusing on the input field caused it's container to scroll to the button which caused the CSS transform to hide the button on focus.

Steps to reproduce:

  1. Code for react modal component is used by a stateful component that will open model.
  2. In same stateful component have another component that uses a CSS transition on hover to show a button to open the modal.
  3. On hover to view the button click on the button and the modal will open.
  4. Closing the modal will cause the hidden button to always be displayed.
  5. Hovering over the component will cause the button to be hidden.

With example

  1. Go to https://codesandbox.io/s/74x8ynqr6q
  2. Hover over the box with the red border
  3. Click on the button to open react modal
  4. Close the modal

Results: The CSS transformation is no longer in its original state. The focus is now placed on the button which caused the container to scroll to the button. Hovering over it hides the button and reveals whatever is below. In my case there was nothing below the buttons.

Expected behavior:

Modal will close without restoring focus on last focused input field / button.

Link to example of issue:

https://codesandbox.io/s/74x8ynqr6q

Additional notes:

When I hover over the menu the visible icon scrolls out of view and a button to open a modal scrolls into view. When clicking on the button it brings up the react-modal. When the react modal is closed the icon is no longer visible though the button to open the modal is visible. The CSS transformation now shows nothing when hovering over the menu.

ReactModal is placing focus on the hidden button causing the view of the menu to focus on the wrong thing in it's initial state.

trevlar avatar Aug 16 '18 03:08 trevlar

This is related to https://github.com/reactjs/react-modal/issues/675

trevlar avatar Aug 16 '18 03:08 trevlar

I found a work around to this. In the function that gets called onClick I blur off of the input field/button before opening the modal and it appears to have solved the issue.

<button onClick={ (e) => {
      e.currentTarget.blur();
      props.openModal()
  }}> Open Modal </button>

trevlar avatar Aug 16 '18 04:08 trevlar

would the shouldReturnFocusAfterClose prop fix your problem?

http://reactcommunity.org/react-modal/#usage

mattlub avatar Aug 20 '18 09:08 mattlub

@mattlub yeah that would work great.

trevlar avatar Aug 21 '18 00:08 trevlar

@trevlar Thanks for reporting this issue and the example. I'll try to find sometime to debug this.

@mattlub Thanks for the help.

diasbruno avatar Sep 17 '18 15:09 diasbruno

react-modal relies on the last document.activeElement to know which element it should give back focus. Ideally, the expected behaviour should be "Open React Modal" button to be the last active element.

Firefox and Safari have the same behaviour - they don't set the button as the active element after click on it. Chrome will actually focus the button when clicked. IE and Edge - needs testing.

  openModal = () => {
    debugger;
    document.activeElement; // to make it easy to inspect.
    this.setState({ modalOpen: true });
  };

After changing the openModal method, you can step through to see which element has been the last element on the document.activeElement.

Using the keyboard to navigate will produce the expected behaviour on all browsers.

Safari: Version 11.1.2 (13605.3.8) Firefox: 61.0.2 (64-bit) Chrome: Version 68.0.3440.106 (Official Build) (64-bit)

diasbruno avatar Sep 17 '18 16:09 diasbruno

I have a similar problem or maybe not. I am not 100% sure why this happening. And I am not sure if this is the right place to post my problem. Let me know if I should open a new issue...

I use animate-scroll-to to scroll to a button further down in the page which opens the modal on click. When I use the animated scroll to get to the button, the page scrolls to the top when the modal is closed. This does not happen when I scroll manually to the button.

BUT, another piece in this puzzle is that the button is within a div which I scale on hover via

transition: all 0.25s;
transform: scale(1);

// removing the following resolves the problem
@media (hover: hover) {
    &:hover {
        transform: scale(1.02);
    }
}

If I remove this part of the code the page does also NOT scroll to top when the modal is closed.

I can solve this problem either with shouldReturnFocusAfterClose={false} or with shouldFocusAfterRender ={false} but both options are bad for accessibility.

Note: I tested this only in Chrome (96)

FelixButzbach avatar Dec 17 '21 18:12 FelixButzbach