Skip to content
Utilities & Providers

FocusTrap

client17 kB

Keeps the keyboard inside a subtree, and hands it back when it closes.

@stellaria/nebula-webFocusTrapProps

Preview

FocusTrap renders no DOM of its own. It wraps a subtree and, while active, the Tab key cannot leave it.

Why an overlay needs it

A dialog that does not trap focus is a dialog only for the mouse. Tab past the last button and you land on the page behind it — still there, still scrollable, and now unreachable by eye. The APG requires the trap for modal dialogs, and the difference is not cosmetic: without it a keyboard user has no way to tell where they are.

The three switches

  • active turns the containment on and off. It is a prop, not a mount, so the same subtree can trap or release without losing its state.
  • restoreFocus returns focus to whatever held it when the trap unmounts. Skipping it is the most common bug in a home-made modal: you close it and focus falls back to <body>.
  • autoFocus moves focus to the first tabbable element on mount.

You rarely mount it yourself

Modal, Drawer, Popover and Dialog already trap. Use it directly when you build a surface that behaves like a dialog and is not one of them.

Props

4
PropTypeDefault

active

Whether the trap holds focus inside the subtree. Turning it off releases focus without unmounting anything, which is how a trap is suspended — a nested overlay taking over, a step that hands control back to the page — while its content stays on screen.

booleantrue

autoFocus

Moves focus to the first tabbable node when the trap mounts. Leave it off when something inside already claims focus — a field with its own `autoFocus`, or a dialog that focuses its heading.

booleanfalse

children

required

The trapped subtree. The trap renders no element of its own, so the children have to supply the node: focus is contained by what they render, not by a wrapper this component adds.

ReactNode

restoreFocus

Returns focus, on unmount, to whatever had it when the trap mounted. Overlays that open from a trigger want this on; without it, focus falls back to the document and the next Tab starts over from the top of the page.

booleanfalse