useFocusRestore
Capture and restore focus around overlays, panels, command palettes, and triggerless temporary UI with nested stack safety.
useFocusRestore captures the currently focused element before temporary UI opens and returns focus to it when that UI closes. It is standalone (no provider) and stack-aware, so nested overlays restore in close order and an older layer never steals focus from a newer one. Use it when there is no single trigger button to focus back — command palettes, globally summoned panels, and toasts-turned-dialogs.
When to use it
- A panel or palette is opened from a keyboard shortcut rather than a specific button, so focus must return to wherever the user was.
- Several temporary surfaces can stack and each must restore focus to the layer beneath it.
- You need restore semantics but not Tab trapping — for trapping, use
useFocusTrap(which manages restoration internally).
Installation
dgadd is not public on npm yet. Until the first release, pack @diffgazer/add from the repository and install that tarball into this app, which is what puts dgadd on pnpm exec.
The hosted registry is not public yet because r.b4r7.dev does not resolve. Use this source checkout or a local registry preview until the endpoint returns 200.
Diffgazer packages are not yet published to npm. Until the first release, pack @diffgazer/ui and @diffgazer/keys from the repository and install those tarballs.
@diffgazer/keys requires no CSS or Tailwind setup.
Parameters
Returns
Call capture() as the overlay opens (storing the active element) and restore() as it closes. target exposes the last captured element.
Examples
Temporary panel focus restore
Triggerless palette with fallback
Notes
Hook boundary
useFocusRestore is the React hook. getRestorableFocusTarget and restoreFocus are plain DOM utilities for non-hook code.
Nested overlays
Focus restore entries are stack-aware, so nested overlays restore focus in close order and older layers do not steal focus from newer ones.
Edge cases
fallback. When nothing was focused at capture time, or the captured element is gone, focus moves to thefallbackelement. Supply one for triggerless UI so focus never lands on<body>.restoreOnUnmount. On by default — if the component unmounts aftercapture()without an explicitrestore(), cleanup restores focus. Set it tofalsewhen another hook (such asuseFocusTrap) owns the restoration timing.- Stack ordering. Only the top stack entry restores. Releasing a middle entry removes it without moving focus, so nested overlays unwind correctly.
- Hook vs utilities.
useFocusRestoreis the React hook;getRestorableFocusTargetandrestoreFocusare plain DOM utilities for non-hook code.
Related
useFocusTrap— trap Tab and restore focus on release.- Utilities —
getRestorableFocusTargetandrestoreFocusfor imperative code. - Focus and scroll guide — overlay focus patterns.
Source
Highlighted source loads after this disclosure opens. Browse the source repository.