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.