-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix focus styles showing up when using the mouse #2347
Merged
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
RobinMalfait
force-pushed
the
fix/issue-1694
branch
2 times, most recently
from
March 8, 2023 17:29
2ae3901
to
7486268
Compare
RobinMalfait
force-pushed
the
fix/issue-1694
branch
from
March 9, 2023 13:07
7486268
to
85d7e86
Compare
RobinMalfait
changed the title
Fix triggering focus styles when using the mouse
Improve focus styles showing up when using the mouse
Mar 9, 2023
RobinMalfait
changed the title
Improve focus styles showing up when using the mouse
Fix focus styles showing up when using the mouse
Mar 9, 2023
RobinMalfait
force-pushed
the
fix/issue-1694
branch
from
March 9, 2023 17:27
85d7e86
to
c412409
Compare
RobinMalfait
force-pushed
the
fix/issue-1694
branch
from
March 10, 2023 12:34
c412409
to
0206884
Compare
The focus was always set, but the ring wasn't showing up. This was also focusing a ring when the browser decided not the add one. Let's make the browser decide when to show this or not.
RobinMalfait
force-pushed
the
fix/issue-1694
branch
from
March 10, 2023 12:47
0206884
to
555c062
Compare
1 task
hello! has this update been released yet? not seeing the new variants on |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR fixes the annoying issue that focus styles show up even if you used the mouse.
Right now the issue exists whenever we call
element.focus()
that theelement
will show the focus related styles. Unfortunately this is something the browser does (even if you did this call in aclick
handler). There is also no API yet to control this behaviour. There is an experimental API that can be found here: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus#browser_compatibilitySo what are the solutions here?
For starters, you could immediately blur the active element when something receives focus. This would hide the focus ring (because the element won't have focus anymore) but it will degrade the usability of your application. Imagine you are filling out a big form, you tab to an input and fill it in, you tab to the next input and fill it in, and so on. You are now 50 fields further and you use a
Listbox
component. You select a value, theListbox
closes and focus is restored to theListbox.Button
. Now you want to continue but uh oh it won't work because you just blurred thatListbox.Button
and thebody
now has the focus.Some people mentioned that you could just blur the input when you are using the mouse, but then you would have to re-focus a nearby input field to continue. While this might be okay, it's not something we want as a default implementation we want the components to feel right and usable.
At the end of the day, we want the element to be focused, we just don't want to show the focus styles when you used the mouse. One day we have more control over when to show the focus ring and when not to, but for now this is not possible.
One solution is that we could expose a
focus
value in the render prop. We already exposeactive
andselected
in components like theListbox
so that you can style your elements based on these values. While this is doable, the issue is that some buttons are not controlled by Headless UI at all. For example when you are using theDialog
component, we will restore focus to the element that opened theDialog
component. This is not an element controlled by Headless UI so you won't be able to style the element based on exposedfocus
props.There are other solutions where we directly mutate the element we are restoring the focus to and "delete" the focus related styles. This is not an ideal solution because we don't always control the element.
Another potential solution is by introducing a phantom or proxy button that doesn't have any styles attached to it but can hold the focus, if you then perform any action, it will forward that to the element that should have required focus. This could work, but will have accessibility related issues.
The current behaviour where the focus is restored is also consistent with most other common libraries out there like React Aria, Radix UI and Reakit.
Custom selector
The solution we came up with for this problem is by exposing a new
ui-focus-visible
variant in the@headlessui/tailwindcss
package. This way we can give you control over when and how this should behave. If you always want the focus styles, then you can keep using thefocus
related styles. If you don't then you could switch to this new variant. In the future, this can hopefully all be handled by the browser but unfortunately for now this isn't the case.The variant can be used like this:
The implementation of that variant looks like this:
Where the
prefix
is defined as"ui"
by default. More info on this prefix and the@headlessui/tailwindcss
package can be found here: https://github.com/tailwindlabs/headlessui/tree/main/packages/%40headlessui-tailwindcssThis way the focus styles will only be applied if you used a keyboard, not when using another input method like a mouse or pointer.
As long as you use Headless UI, then you should be able to use the variant wherever you want and the focus styles should show up when using the keyboard, and won't when using the mouse.
This also means that when you open a
Dialog
, and click outside that the button won't have a focus ring attached, but it will still have the focus. If you now press space or enter then theDialog
will show again.You can play with an example of this here: https://headlessui-react-git-fix-issue-1694-tailwindlabs.vercel.app/combinations/tabs-in-dialog
If you want to play with this yourself, then you have to install the
insiders
versions of the Headless UI library for React or Vue, and also the Tailwind CSS plugin:npm install @headlessui/react@insiders
npm install @headlessui/vue@insiders
npm install @headlessui/tailwindcss@insiders
Fixes: #1694