useFocusTrap
Traps keyboard focus within a container element using sentinel elements. Automatically detects focusable elements inside the container and cycles Tab navigation between them. The hook configures sentinel divs imperatively (setting tabIndex, data-focus-trapper, and focus event listeners). The sentinels never keep the focus, they just forward it to the first/last focusable element.
By default auto-focuses the container when activated.
Used internally by the Popover component.
Import
import { useFocusTrap } from '@andrejground/lab';
Usage
import React from 'react';
import { useFocusTrap } from '@andrejground/lab';
export default function App() {
const [isActive, setIsActive] = React.useState(false);
const { trapContainerRef, startTrapRef, endTrapRef } =
useFocusTrap({ isActive });
return (
<div>
<button onClick={() => setIsActive(true)}>Open dialog</button>
{isActive && (
<div ref={trapContainerRef}>
<div ref={startTrapRef} />
<input placeholder="First field" />
<input placeholder="Middle field" />
<button onClick={() => setIsActive(false)}>Close</button>
<div ref={endTrapRef} />
</div>
)}
</div>
);
}
API
const { trapContainerRef, startTrapRef, endTrapRef } =
useFocusTrap({ isActive, shouldAutoFocus });
| Parameter | Type | Default | Description |
|---|---|---|---|
isActive | boolean | - | Whether the focus trap is active |
shouldAutoFocus | boolean | true | Auto-focus the container on activation |
Returns
| Property | Type | Description |
|---|---|---|
trapContainerRef | RefObject<HTMLDivElement> | Ref for the trap container |
startTrapRef | RefObject<HTMLDivElement> | Ref for the first sentinel element |
endTrapRef | RefObject<HTMLDivElement> | Ref for the last sentinel element |