headlessui icon indicating copy to clipboard operation
headlessui copied to clipboard

Static Dialog Focus Trap Improvements

Open aaronmhargrove opened this issue 2 months ago • 0 comments

What package within Headless UI are you using?

@headlessui/react

What version of that package are you using?

v2.2.9

What browser are you using?

Chrome, safari, etc (not browser dependent)

Problematic Code

Minimal Reproduction Example Note: Only occurs on touch devices https://codesandbox.io/p/devbox/laughing-framework-8zvyvy

Describe your issue Hi! I was hoping to have some minor tweaks made to the FocusTrap component to better support static dialog use cases. In my case I'm using the static prop to allow conditional modality of a bottom sheet which is inspired from how vaul works. Though I think this would really apply to any static dialog usages since the consumer of the component is controlling the animate in / out behavior. In migrating to HeadlessUI from our previous impl (radix based), I've found a few small things I've had to patch

The two minor things I noticed are:

  1. When setting initial focus on touch devices (where initial focus isn't enabled), the useInitialFocus hook will force focus on the dialog container even if something within the dialog already has focus. It would be great if it checked if something already had focus like it does when its enabled and bailed early if that was the case. In our usage, its stealing focus from an element we want to remain focused on open.
  2. When animating out in static mode, the useRestoreFocus hook may choose an element that's within the dialog container that we want to "close". It looks like it just needs to be passed the container ref and do a container does not contain element check.

Happy to open a PR with the changes, just wanted to make sure those additional checks made sense to you guys. Thanks!

aaronmhargrove avatar Oct 06 '25 21:10 aaronmhargrove