theKashey / react-focus-lock

It is a trap! A lock for a Focus. 🔓

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Not working with portals

nanot1m opened this issue · comments

How to reproduce?
Just render portal inside FocusTrap (example)

Why it's matter?
Dropdown menus usually render in portals. And it would be impossible to put focus on them to handle keydowns for example.

I don't know if it is possible to solve this issue

This is a hard problem and it is impossible to solve it using the current logic, cos current logic is about making some boundaries you could not escape, but you do.

How this can be made:

  1. I have a plan to work with more than one FocusLock on "one level". Currently, you can "nest" them, but what about one level, and next you can tab from the first lock, to the second? That's is a requirement for my another project. WIP.
  2. React handles evens, occurred in portaled code, as they occur in normal code. It is possible to detect focus "outside" of a lock, which occurs "inside".
  3. And after that detection - create a virtual lock around the portal.

Sounds doable, should be doable. But devil, usually, is hidden in realization details.

So - portals are working now - https://codesandbox.io/s/w2l1q3m5w7
But only if you were able to "tab" inside. The example above have to disable focusGuards to let tab from content to portal. So "portals" are "supported" by just understanding that you are inside a portal and thus allowing to leave a trap. It does not help you to get into trap.

If you want to manage portaled content as a part of Lock - you have to use scattered trap. Just place another FocusLock inside a portal and assign the same focus group.

<FocusLock group="focus1">
      <h2>Start editing to see some magic happen {"\u2728"}</h2>
      <button>I'm jailed</button>
      <button>And I'm too...</button>
      {createPortal(
        <div>portal
        <FocusLock group="focus1">
          <button>I'm in portal 1</button>
          <button>I'm in portal 2</button>
          <button>I'm in portal 3</button>
        </FocusLock>
        </div>,
        document.getElementById("portal-root")
      )}
    </FocusLock>