hooks
hooks copied to clipboard
fallbackFocus option
You can see the code that reproduces the issue. Tested in both Chrome and FF on MacOS.
https://gist.github.com/brandonkal/088da2bf362cf23df58cb9e1f9c263ab
Focus remains on the button that triggered the drawer. Tab will move to the wrong input. Clicking into one of the fields in the drawer and then tabbing will cause the focus trap to take effect. However, having useFocusTrap select the first focusable element or passing it in manually '#first' does not appear to do anything.
The issue occurs due to the visibility CSS prop. It looks like the hook is firing before the animated.div has a chance to update the style prop.
https://gist.github.com/brandonkal/088da2bf362cf23df58cb9e1f9c263ab#file-drawer-tsx-L114-L117
Perhaps adding a short setTimout inside the hook would help with these edge cases?
On another note, I would like a fallbackFocus prop.
Hey @brandonkal Thanks for letting me know. When using the Hook, you should be sure that the focus trap can actually get focus.
A quick look at your code, and I think a solution for your specific usecase might be to delay setting the ref on the animated.div until the element is visible.
Consider rendering null when the isOpen is false (and the animation is not running).
Regarding the fallbackFocus, the hook takes options, that currently support a focusSelector value. This is a querySelector string that's used to set the initial focus. Is this what you are looking for?
I'll look into updating the Readme, to include more/better examples.
Thanks. Changing to use opacity over visibility worked to make the initial focus work.
I am building reusable UI components. The behavior I want here is that when a Drawer or Modal component becomes visible the focus attaches to the component's first focus-able child. If it has no focus-able children, then the Drawer or Modal itself should receive focus (which could be achieved by querying for fallbackFocus: '[tabindex="-1"]' which would be set on my Dialog and Drawer components by default.
The important thing here is that when a Modal appears, the focus does not remain on some now hidden element.
Here is an example of fallbackFocus: https://github.com/davidtheclark/focus-trap#usage
That makes sense. I hadn't seen the focus-trap library before. I think I'll look into using that instead, and in the process also supporting the options it contains.
FWIW, I prefer your useFocusTrap over focus-trap because it is half the bundle size.
If you do want to go the focus-trap route, here is an implementation
I have this same issue with Framer Motion, even when I ‘apply’ the hook inside a modal only when it’s showing (with <AnimatePresence />).
There are no visibility animations going on—it goes from not existing to existing, and back, in the DOM.
Any pointers on what’s going on here much appreciated!