npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@bento/focus-lock

v0.0.2

Published

Focus lock primitive for managing focus within a scope

Readme

FocusLock

The @bento/focus-lock package provides focus management for containing and controlling keyboard focus within specific areas of your application. Built on top of React ARIA's FocusScope, it ensures focus remains trapped within designated boundaries, making it essential for modals, dialogs, drawers, select popovers, and other overlay components.

Installation

npm install --save @bento/focus-lock

Props

The following properties are available to be used on the FocusLock component:

| Prop | Type | Required | Description | |------|------|----------|------------| | contain | boolean | No | Whether to contain focus within the scope. When true, focus will cycle between focusable elements within the scope. | | restoreFocus | boolean | No | Whether to restore focus to the previously focused element when the focus scope unmounts. | | autoFocus | boolean | No | Whether to automatically focus the first focusable element when the focus scope mounts. | | children | ReactNode | No | The content to render inside the focus lock. Can be a single element or multiple elements. | | onFocusEnter | (e: FocusEvent<Element, Element>) => void | No | Callback fired when focus enters the scope | | onFocusLeave | (e: FocusEvent<Element, Element>) => void | No | Callback fired when focus leaves the scope | | className | string \| ((state: FocusLockState) => string) | No | Render prop for className | | style | ((state: FocusLockState) => CSSProperties) \| CSSProperties | No | Render prop for style | | slot | string | No | A named part of a component that can be customized. This is implemented by the consuming component. The exposed slot names of a component are available in the components documentation. | | slots | Record<string, object \| Function> | No | An object that contains the customizations for the slots. The main way you interact with the slot system as a consumer. |

For all other properties specified on the FocusLock component, they will be passed down to the underlying React ARIA FocusScope component.

Examples

The simplest use case is to wrap your modal or dialog content with FocusLock and enable focus containment.

Focus scopes can be nested, allowing you to have multiple layers of focus containment. When a nested scope is active, focus is trapped within the innermost scope.

The FocusLock component applies data attributes directly to its children without introducing a wrapper element. This example demonstrates multiple children (backdrop and content).

When used with a single child, the focus lock applies data attributes to that child element.

Focus lock is particularly useful for multi-step forms where you want to keep focus within the current step.

Customization

The FocusLock component is created using the @bento/slots package and allows assignment of the custom slot property for overrides. The component applies props to the underlying React ARIA FocusScope component and data attributes to its children.

Slots

The @bento/focus-lock component is registered as BentoFocusLock and can be customized using the slot system. See the @bento/slots package for more information on how to use the slot and slots properties.

Render prop function receives a state object with the following properties:

interface FocusLockState {
  hasFocus: boolean;      // Whether focus is currently within the scope
  isContained: boolean;   // Whether focus is contained (same as contain prop)
}

Data Attributes

The following data attributes are automatically applied to the children of the FocusLock component:

| Attribute | Description | Example Values | | ---------------------- | ------------------------------------------------ | --------------- | | data-focus-contained | Indicates whether focus is contained | "true" / "false"| | data-has-focus | Indicates whether the scope currently has focus | "true" / "false"|

These data attributes can be targeted using CSS selectors for styling. When using data attributes for styling, ensure you scope them properly with a className to avoid affecting unrelated elements:

.my-modal[data-focus-contained="true"] {
  outline: 2px solid blue;
}

.my-modal[data-has-focus="true"] {
  background-color: rgba(0, 0, 0, 0.05);
}

Apply the scoping className to your FocusLock children:

<FocusLock contain restoreFocus autoFocus>
  <div className="my-modal">
    Modal content
  </div>
</FocusLock>

Accessibility

Focus management is crucial for accessibility. The FocusLock component ensures that keyboard users can navigate within the focus scope using Tab and Shift+Tab, focus is trapped within the scope when contain is enabled, focus is automatically restored to the previously focused element when the scope is removed (when restoreFocus is enabled), and the first focusable element is automatically focused when the scope is mounted (when autoFocus is enabled).

When using focus lock, follow these accessibility guidelines:

  • Always provide a way to exit the focus scope (e.g., a close button or escape key handler)
  • Use restoreFocus to ensure users return to their previous location when the scope is closed
  • Use autoFocus to immediately draw attention to important content like modals
  • Consider using aria-modal on modal dialogs to provide additional context to screen readers
  • Ensure all focusable elements within the scope are keyboard accessible