Skip to content
This repository has been archived by the owner on Mar 8, 2023. It is now read-only.

[Modal] focus gets trapped on close #558

Closed
frodesigns opened this issue Dec 10, 2020 · 28 comments
Closed

[Modal] focus gets trapped on close #558

frodesigns opened this issue Dec 10, 2020 · 28 comments
Assignees
Milestone

Comments

@frodesigns
Copy link

When dealing with form inputs within a bx-modal and clicking our Submit button (<bx-btn data-modal-close> triggers the beforeclose event), validations are run, preventDefault is called for errors, and focus becomes trapped on the Submit button and the modal close X button, and we are unable to click into inputs to re-focus. This has been observed with both the bx-input and bx-date-picker.

I've narrowed it down that I don't think any of our project's code, such as the validation, is causing this. It must be something in the bx-modal code related to the beforeclose or close events.

@frodesigns frodesigns added the bug Something isn't working label Dec 10, 2020
@asudoh
Copy link
Collaborator

asudoh commented Dec 12, 2020

Hi @frodesigns thank you for reporting! Tried to create a content like below, but couldn't reproduce the problem. Would you try forking https://codesandbox.io/s/github/carbon-design-system/carbon-web-components/tree/master/examples/codesandbox/basic, put your content and see if the problem reproduces? If so, could you please share the fork? Some movie shots of the user interaction you described will also be a help. Thanks!

<bx-modal id="modal">
  <bx-modal-header>
    <bx-modal-close-button></bx-modal-close-button>
    <bx-modal-label>Label (Optional)</bx-modal-label>
    <bx-modal-heading>Modal Title</bx-modal-heading>
  </bx-modal-header>
  <bx-modal-body>
    <form>
      <bx-form-item>
        <bx-date-picker>
          <bx-date-picker-input kind="single" label-text="Date picker">
          </bx-date-picker-input>
        </bx-date-picker>
      </bx-form-item>
      <bx-form-item>
        <bx-input id="input" label-text="input"></bx-input>
      </bx-form-item>
    </form>
  </bx-modal-body>
  <bx-modal-footer>
    <bx-btn kind="secondary" data-modal-close>Cancel</bx-btn>
    <bx-btn kind="primary">Save</bx-btn>
  </bx-modal-footer>
</bx-modal>
<script type="module" src="src/index.js"></script>
<script type="text/javascript">
  document.addEventListener('click', event => {
    if (event.target.id === 'launcher') {
      document.getElementById('modal').open = true;
    }
  });
  document.addEventListener('bx-modal-beingclosed', event => {
    const input = document.getElementById('input');
    if (!input.value) {
      event.preventDefault();
    }
  });
</script>

@frodesigns
Copy link
Author

I also can't reproduce this way, may have to look at another approach.

@asudoh
Copy link
Collaborator

asudoh commented Dec 15, 2020

I see, another way for further investigation is opening node_modules/carbon-web-components/es/components/modal/modal.js, find the corresponding code to _handleBlur() method, and put below code right before the 1st if() block:

console.log('this:', this);
console.log('target:', target);
console.log('oldContains:', oldContains);
console.log('relatedTarget:', relatedTarget);
console.log('currentContains:', currentContains);

The focus wrapping (trapping) runs when oldContains equals to true and currentContains equals to false. Do you get such condition even though it shouldn't happen?

@RobertaJHahn
Copy link

Bug reviewed in the Dec 15, 2020 meeting. Waiting to hear from the adopter with additional info.

@RobertaJHahn
Copy link

No additional info received. Closing.

@frodesigns
Copy link
Author

frodesigns commented Aug 3, 2021

The focus wrapping (trapping) runs when oldContains equals to true and currentContains equals to false. Do you get such condition even though it shouldn't happen?

@asudoh Sorry for the long delay between comments, but to follow up on this yes oldContains == true and currentContains == false in this scenario.

Steps:

  1. Click Submit/Apply/Ok
  2. beingclosed event is captured, default is prevented
  3. Click on any carbon input inside the modal body
  4. Breakpoint hits on this line: https://github.com/carbon-design-system/carbon-web-components/blob/v1.10.0/src/components/modal/modal.ts#L117
  5. Focus goes to the X in the modal instead of the input
  6. Unable to click/focus the input
  7. Clicking inside the modal body not on the inputs releases focus, and then I can click an input

Maybe it has something to do with having created a custom component to wrap the Carbon modal components, and passing the content down an extra layer of slots?

@RobertaJHahn
Copy link

Fireline will try to replicate the issue. Review when done.

@emyarod
Copy link
Member

emyarod commented Aug 17, 2021

@frodesigns I created a Code Sandbox based on the example code above https://zrumj.sse.codesandbox.io/ but I haven't been able to replicate the focus trapping issue. Would you be able to modify the sandbox into a reduced test case for easier testing and debugging?

@frodesigns
Copy link
Author

Actually, I think I am able to replicate it in the storybook instance:

  1. Go to: https://web-components.carbondesignsystem.com/?path=/story/components-modal--default
  2. Modal X is focused initially
  3. Click in the white area anywhere below "Modal text description" and above the buttons
  4. Focus flickers back to the X
  5. This is the same behavior we have been seeing with our inputs within the modal body

I am also noticing in your sandbox (https://zrumj.sse.codesandbox.io/), that the modal appears briefly before fading away. This is another bug we have been dealing with.

@emyarod
Copy link
Member

emyarod commented Aug 17, 2021

does updating the package version resolve the first issue for you? it looks like the storybook is using package version 1.13.3, and I can only replicate the behavior in the sandbox by downgrading to 1.13.3

for the the second issue, is this happening when you dismiss the modal? would you be able to provide a recording of the behavior for example? I think if this is a separate issue we may need to capture it in a new ticket

@frodesigns
Copy link
Author

frodesigns commented Aug 17, 2021

Yes, the issue still occurs in 1.16.0. There must be a flaw in the logic for focus trapping, possibly related to how we have a custom component for our modal that wraps the carbon modal components, and passes the body content down an extra layer of slots.

For the other issue, it is on load (or anytime we revisit the page with the modal). Modal starts visible and fades out even though it should be closed/hidden initially. Particularly noticeable in Firefox

@emyarod
Copy link
Member

emyarod commented Aug 17, 2021

oh I see, from what I can tell after some more testing, the focus trap issue was not appearing when clicking on the form margin below the inputs, but it would appear when clicking underneath the input and the margin. will need to look more into this

image

I haven't been able to replicate the second issue on my end but ultimately I think it can be contained in a separate ticket

@frodesigns
Copy link
Author

I haven't been able to replicate the second issue on my end but ultimately I think it can be contained in a separate ticket

Interesting. For me, it happens every time I load your sandbox: https://codesandbox.io/s/zrumj

@emyarod
Copy link
Member

emyarod commented Aug 17, 2021

I'm not sure if I'm misunderstanding but this is what I see when I load the sandbox:

Screen.Recording.2021-08-17.at.12.32.59.mov

@frodesigns
Copy link
Author

screen-capture.mp4

@asudoh
Copy link
Collaborator

asudoh commented Aug 21, 2021

A couple suggestions:

  • Move "modal comes and goes away in short amount of time" issue to a new issue
  • The team work with @frodesigns to figure out the reduced case

@emyarod
Copy link
Member

emyarod commented Aug 23, 2021

opened #689 to potentially resolve the current issue in the meantime

@emyarod emyarod added this to the Sprint 21-17 milestone Aug 23, 2021
@emyarod emyarod self-assigned this Aug 23, 2021
@frodesigns
Copy link
Author

Tested version 1.16.1 containing fix #689, focus trapping issue is still present unfortunately.

@emyarod
Copy link
Member

emyarod commented Aug 24, 2021

can you provide the steps to replicate the issue? you can view the steps we took to test this in the recorded videos in #689

@frodesigns
Copy link
Author

frodesigns commented Aug 24, 2021

I am unable to replicate in the storybook, but here is a video from our application:

2021-08-24_09-36-50.mp4

Here are some more details from dev tools when I put a breakpoint and the focus trap evaluates to true:

Screenshot 2021-08-24 095233

@jeffchew jeffchew changed the title [Bug] Modal component - focus gets trapped on close [Modal] focus gets trapped on close Aug 24, 2021
@emyarod
Copy link
Member

emyarod commented Aug 24, 2021

would you be able to create a reduced test case in code sandbox? That would really help with testing and debugging especially when the issue can't be replicated in storybook. You can follow the instructions outlined earlier #558 (comment)

@frodesigns
Copy link
Author

frodesigns commented Aug 24, 2021

I tried to create a test case before in the sandbox, but I was having too much trouble trying to re-create our component structure. We have a custom component we created as a wrapper for the modal, with a slot that passes content to the modal body.

Here is a quick example:

<catalyst-modal>
  <bx-date-picker></bx-date-picker>
  <!-- other inputs here -->
</catalyst-modal>

Here is a gist containing the content of the <catalyst-modal> wrapper component:
https://gist.github.com/frodesigns/4c3a61f496fe99987052e95b2ebaad99

I am fairly certain this has to do with having an extra level of slot nesting that the focus trapping code is having trouble handling. The focus trap needs to handle any amount of shadowRoot nesting.

@emyarod
Copy link
Member

emyarod commented Aug 24, 2021

thank you for the additional context about how you're using the modal, I was trying to figure that out

I am fairly certain this has to do with having an extra level of slot nesting that the focus trapping code is having trouble handling. The focus trap needs to handle any amount of shadowRoot nesting.

I think you might be right with this hunch, I can take a deeper look once I'm able to create a reproducible test case

@emyarod
Copy link
Member

emyarod commented Sep 1, 2021

after a bit of testing I was finally able to identify an issue or at least something similar. it seems that in your use case when currentContains is calculated, relatedTarget is never seen as a descendent of this (this evaluates to bx-modal) because the relatedTarget is actually found within catalyst-modal instead.

to get around this, I think we would have to traverse up the DOM to determine if any of the relatedTarget's parents contains bx-modal. I am not sure if that would be in scope for our library but I would like to learn more about the use case to see how we should proceed with supporting it

Is there any particular reason for wrapping the Carbon modal as you showed in your earlier gist?

@frodesigns
Copy link
Author

Yes, the main reason is to standardize our usage of the carbon modal for all implementations. It also avoids having to import each individual sub-component of the modal for every instance.

@emyarod
Copy link
Member

emyarod commented Sep 1, 2021

given that the issue is not reproducible in the storybook, it seems that the Carbon modal's focus wrap behavior is working as expected when self-contained. The modal's focus wrap behavior currently doesn't support custom wrappers or containers so it won't extend beyond the Carbon modal itself. I'm not sure if there are plans to extend the focus wrap behavior in the Carbon modal beyond its current scope

in the meantime I think the workaround would be to use the Carbon modal as-is (without a wrapper) or to implement a separate modal with custom focus wrap behavior

@frodesigns
Copy link
Author

Disappointing to hear, but I guess we will have to live with it or find some other workaround. Thank you for all of your time spent on this.

@RobertaJHahn
Copy link

Closing based on the comments above.

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

No branches or pull requests

4 participants