Skip to content

Trap focus

The TrapFocus component prevents the user's focus from escaping its children components.

TrapFocus is a utility component that is useful when implementing an overlay such as a modal dialog, which should block all interactions outside of it while open.

TrapFocus

import TrapFocus from '@mui/base/TrapFocus';

Basic trap focus

The following demo shows a Button that opens a Box component nested inside of a TrapFocus. As long as the Box is open, the user's keyboard cannot interact with the rest of the app:

<button type="button" onClick={() => setOpen(true)}>
  Open
</button>
{open && (
  <TrapFocus open>
    <Box tabIndex={-1} sx={{ mt: 1, p: 1 }}>
      <label>
        First name: <input type="text" />
      </label>
      <br />
      <button type="button" onClick={() => setOpen(false)}>
        Close
      </button>
    </Box>
  </TrapFocus>
)}

Disable enforced focus

By default, clicks outside of the TrapFocus component are blocked.

You can disable this behavior with the disableEnforceFocus prop:

<button type="button" onClick={() => setOpen(true)}>
  Open
</button>
{open && (
  <TrapFocus disableEnforceFocus open>
    <Box tabIndex={-1} sx={{ mt: 1, p: 1 }}>
      <label>
        First name: <input type="text" />
      </label>
      <br />
      <button type="button" onClick={() => setOpen(false)}>
        Close
      </button>
    </Box>
  </TrapFocus>
)}

Lazy activation

By default, the TrapFocus component automatically moves the focus to the first of its children when the open prop is present.

You can disable this behavior and make it lazy with the disableAutoFocus prop. When auto focus is disabled—as in the demo below—the component only traps the focus once the user moves it there:

<button type="button" onClick={() => setOpen(true)}>
  Open
</button>
{open && (
  <TrapFocus open disableAutoFocus>
    <Box tabIndex={-1} sx={{ mt: 1, p: 1 }}>
      <label>
        First name: <input type="text" />
      </label>
      <br />
      <button type="button" onClick={() => setOpen(false)}>
        Close
      </button>
    </Box>
  </TrapFocus>
)}

Escape the focus loop

The following demo uses the Portal component to render a subset of the TrapFocus children into a new "subtree" outside of the current DOM hierarchy. This way, they are no longer part of the focus loop.

Component size