Focus Trap React component
Keeps keyboard focus inside a dialog, drawer or menu while it's open: Tab and Shift+Tab loop through its controls, focus starts where you choose and returns to where it was, Escape calls you back, and an optional ring glides to whatever has focus.
About the Focus Trap component
Focus Trap keeps keyboard focus inside a part of the page, such as a dialog, a drawer or a full-screen menu, so Tab and Shift+Tab cycle through its controls instead of wandering into the page behind it. If something outside grabs focus, for example a click on the page behind, focus is pulled back inside. It is the piece you need when you build your own modal layer.
Wrap the content in FocusTrap, or call the useFocusTrap hook with a ref for the same behavior without the wrapper. active turns it on and off, initialFocus picks the element to focus first with a CSS selector, onEscape runs when Escape is pressed, and returnFocus sends focus back to where it was when the trap turns off. FocusTrap also draws an optional ring that glides to whichever control has keyboard focus, colored with indicatorColor.
When to use it
Use Focus Trap inside anything modal that you build yourself: dialogs, drawers, full-screen menus, command palettes, onboarding overlays. Keyboard and screen reader users otherwise tab into the page hidden behind.
Always give people a way out (Escape and a close button) and let focus return to the control that opened the layer.
Installation
Add the Focus Trap component to your project with the shadcn CLI. It lands in components/focus-trap.tsx as plain React + Tailwind CSS source you own and can edit.
npx shadcn@latest add @reactframe/focus-trapOr copy the source by hand and install its dependencies:
npm install motion clsx tailwind-mergeProps
<FocusTrap /> accepts 4 props, all optional.
| Prop | Type | Default |
|---|---|---|
| children | React.ReactNode | — |
| showIndicator A ring that glides to whichever element has keyboard focus inside the trap. | boolean | true |
| indicatorColor | string | "#F5F4F1" |
| className | string | — |
- childrenReact.ReactNode
- showIndicator
A ring that glides to whichever element has keyboard focus inside the trap.
booleanDefault: true - indicatorColorstringDefault: "#F5F4F1"
- classNamestring
npm dependencies
Installed for you by the shadcn CLI.
Focus Trap FAQ
- What gets focused first?
- The element matching initialFocus, otherwise the first focusable element inside, otherwise the container itself.
- Where does focus go when it closes?
- Back to whatever had focus when the trap turned on, usually the button that opened it. Set returnFocus={false} to handle that yourself.
- What is the moving ring?
- An optional indicator that glides to the keyboard-focused control, making focus easy to follow. It only shows for keyboard focus and can be turned off with showIndicator={false}.
- Can I use it without the wrapper element?
- Yes. Call useFocusTrap(ref, { active, onEscape, initialFocus, returnFocus }) on your own container. It traps focus the same way but does not draw the moving ring.