Semantic-UI icon indicating copy to clipboard operation
Semantic-UI copied to clipboard

Modal component should disable keyboard navigation for hidden components

Open cowwoc opened this issue 10 years ago • 7 comments

Testcase: http://jsfiddle.net/pMDsH/102/

Repro steps:

Chrome Version 33.0.1750.154 m

  1. Open http://jsfiddle.net/pMDsH/102/embedded/result/
  2. Open Developer Console
  3. Click on checkbox. Note the DOM path being logged.
  4. Click on "Add company" to trigger the modal component
  5. Click in "name". Note the DOM path being logged.
  6. Hit SHIFT-TAB. Notice that the keyboard focus is on the checkbox.
  7. Hit SPACEBAR. Notice that the checkbox gets selected/unselected in the background.

Expected behavior: When a Modal component is active, keyboard navigation should get disabled for all other components. Users should only be able to interact with modal components.

Semantic-UI already handles this for mouse clicks, but it should do the same for keyboard navigation.

cowwoc avatar Mar 21 '14 04:03 cowwoc

Modal clears active element focus and restores it on hide. I'd recommend using tabindex to prioritize any fields in modal. Besides this I can't see any way to handle this programmatically.

Closing until anyone has an idea for a better fix.

jlukic avatar Apr 22 '14 03:04 jlukic

Posted http://stackoverflow.com/q/23212851/14731. Hopefully someone has an idea.

cowwoc avatar Apr 22 '14 07:04 cowwoc

It can be done by capturing the focusin event of the document element and redirecting outside focus changes to the modal DIV element.

function startFocusJail (focusRootElement) {
   $(document).off("focusin.focusJail");
   $(document).on("focusin.focusJail", function(event) {
      if (event.target !== focusRootElement && !$.contains(focusRootElement, event.target)) {
         focusRootElement.focus();
      }
   });
}

function stopFocusJail() {
   $(document).off("focusin.focusJail");
}

startFocusJail() is called when the modal is shown and stopFocusJail() is called when the modal is hidden. The function argument focusRootElement is the modal DIV element with tabindex="-1", so that the DIV can receive the focus. A better solution would be to move the focus to the first focusable element within the DIV.

The Bootstrap modal component (_enforceFocus()) also uses this approach. Works even with IE11.

chdh avatar Oct 18 '17 22:10 chdh

There has been no activity in this thread for 90 days. While we care about every issue and we’d love to see this fixed, the core team’s time is limited so we have to focus our attention on the issues that are most pressing. Therefore, we will likely not be able to get to this one.

However, PRs for this issue will of course be accepted and welcome!

If there is no more activity in the next 90 days, this issue will be closed automatically for housekeeping. To prevent this, simply leave a reply here. Thanks!

stale[bot] avatar Jun 05 '18 17:06 stale[bot]

Can i have any example for this? I am facing this same problem so i am trying to workout this solution but its showing error in console like Maximum call stack size exceeded.

$('#id_div').modal({
        closable: false,
        allowMultiple: true,
        context: $('#id_context'),
        onShow: function () {
           startFocusJail($('#id_div'));
        },
        onHide: function () {
           stopFocusJail();
        }
}).modal('show');

SangeethaSanthoshKumar avatar Jul 10 '19 10:07 SangeethaSanthoshKumar

@SangeethaSanthoshKumar You have to pass a HTMLElement to startFocusJail(), not a jQuery object.

 startFocusJail($('#id_div')[0]);

chdh avatar Jul 10 '19 13:07 chdh

We prepared a fix for upcoming Fomantic-UI 2.9.0 by https://github.com/fomantic/Fomantic-UI/pull/2036 We used a different approach, because the focusin solution above would always refocus the main element and did not care about tabbing order

lubber-de avatar Aug 06 '21 17:08 lubber-de