focus-trap-lite
Version:
Lightweight (≤2kB) focus trapping utility for implementing accessible keyboard navigation constraints in modal dialogs, sidebars, and other contained UI components.
154 lines (109 loc) • 6.61 kB
Markdown
# focus-trap-lite
[](https://www.npmjs.com/package/focus-trap-lite)
[](https://opensource.org/licenses/MIT)
[](https://www.w3.org/WAI/standards-guidelines/aria/)
Lightweight (≤2kB) focus trapping utility for implementing accessible keyboard navigation constraints in modal dialogs, sidebars, and other contained UI components.
## Features
- ✅ Full WAI-ARIA compliance for accessibility
- ✅ Tiny footprint (ES6 module)
- ✅ Zero dependencies
- ✅ Flexible focus control
- ✅ Automatic cleanup
- ✅ TypeScript support
## Installation
```bash
npm install focus-trap-lite
```
## Usage
### Basic Implementation
```javascript
import { initFocusTrap } from 'focus-trap-lite'
// Initialize trap on modal open
function openModal() {
const trap = initFocusTrap(modalElement)
// Add your modal opening logic
// Clean up manually if needed
// trap.destroy()
}
// Trap automatically cleans up when:
// - User closes modal (Escape key)
// - Focus escapes trap boundaries (if logic allows)
// - Component unmounts
```
### Advanced Configuration
```javascript
// Container element with custom selector and options
initFocusTrap(document.querySelector('#modal-container'), '.custom-focusable', {
focus: true, // Auto-focus on initialization
firstFocusableElement: '#first-input', // Specific start element
})
// Nested Modals support
// The library maintains a stack of active traps.
// When a new trap is initialized, it takes precedence.
// When destroyed (e.g. via Escape), focus control returns to the previous trap.
```
## API
### initFocusTrap(element?, selector?, options?)
| Parameter | Type | Description |
| ----------------------------- | --------------------- | ------------------------------------------------------------------------------------------------------- |
| element | `Element` | _(Optional)_ DOM element to scope the focus trap. When omitted, uses document.body |
| selector | `string` | _(Optional)_ CSS selector for focusable elements within container. Default: standard focusable elements |
| options | `Object` | _(Optional)_ Configuration object |
| options.focus | `boolean` | Auto-focus the first element on initialization. Default: `false` |
| options.firstFocusableElement | `HTMLElement\|string` | Element to focus initially. Can be a selector string or DOM element. |
**Returns:**
```javascript
{
destroy: () => void, // Manually destroy the trap
container: HTMLElement // The container element
}
```
**Behavior:**
- Creates keyboard navigation constraints (Tab / Shift+Tab)
- Handles boundary focus wrapping
- **Nested Traps:** Supports multiple stacked traps (LIFO)
- **Auto Cleanup:**
- On `Escape` key press
- When calling `destroy()`
- When calling function returns (if implicit, though manual destroy is recommended for SPAs)
- **Smart Filtering:** Ignores hidden, invisible, or `tabindex="-1"` elements
## Changelog
### v0.1.0
- **Breaking Change:** `initFocusTrap` now returns an object `{ destroy, container }` instead of `void`.
- **New Feature:** Added `options` parameter.
- `options.focus`: Auto-focus support.
- `options.firstFocusableElement`: Custom initial focus target.
- **New Feature:** Nested focus traps support (Stack-based).
- **New Feature:** `Escape` key support for closing the trap.
- **Improvement:** Better filtering of non-focusable elements (hidden, zero-size, `tabindex="-1"`).
- **Improvement:** Optimized internal logic and variable naming.
## Browser Support
Modern browsers with ES6 support:
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/main/src/chrome/chrome_48x48.png" alt="Chrome" width="24" />](http://godban.github.io/browsers-support-badges/)<br/>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/main/src/firefox/firefox_48x48.png" alt="Firefox" width="24" />](http://godban.github.io/browsers-support-badges/)<br/>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/main/src/safari/safari_48x48.png" alt="Safari" width="24" />](http://godban.github.io/browsers-support-badges/)<br/>Safari |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 88+ | 78+ | 14.1+ |
For legacy browser support, add Array.prototype.at() polyfill.
## Contributing
1. Fork the repository
2. Clone your fork
```bash
git clone https://github.com/your-username/focus-trap-lite.git
```
3. Install dependencies
```bash
npm install
```
4. Create feature branch
```bash
git checkout -b feature/your-feature
```
5. Commit changes
6. Push to branch
7. Create Pull Request
## License
MIT © [Pipecraft](https://www.pipecraft.net)
---
📝 Report issues on [GitHub](https://github.com/utags/focus-trap-lite/issues)
## >\_
[](https://www.pipecraft.net)
[](https://github.com/utags)