-
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
[Bug]: Dialog: There are no focusable elements inside the <FocusTrap /> #407
Comments
I believe it is purposeful, as there are specific cases that the modal needs to be displayed without a button or input. If you need to display this modal and do not want the button/input appear, you can use it like this: <button className="h-0 w-0 overflow-hidden"/> But I strongly recommend to add at least one "close" button in case of usability or smaller screens, where the space of the overlay is not large enough to be clickable / touchable. |
You got a point, but I think there are many valid usecases where there are no focusable elements and you don't want any, e. g.
Even then, there is no big red caveat that this error will happen if you somewhat forget to render anything in the Dialog. So I propose two ways out:
If it was the second, then I think many users (including me) which are building internal set of components on top of headless ui will just insert the hidden focusable element to prevent Dialogs from crashing. |
@Krystofee I 100% agree with your proposal, but I would add another change:
|
@trm217 this is doable by managing the state of the modal by yourself and handling Dialog onClose prop according to the loading state. I think that's not the problem of this issue and should be resolved in the discussions. |
@Krystofee I'm aware of that, yet I believe that this would be a fitting change in regards to your above-mentioned proposed changes. Therefore if your proposed changes would be implemented, my proposal would make sense to implement as well since it goes hand in hand with others. |
I've got a In my case, there are focusable components in the dialog - but as it's not rendered, those are not actually focusable. Does the UPDATE: I could get around the issue by setting the |
I think components that are not rendered are generally not focusable. That's not a feature of headless ui but general feature of browser. And yeah, I was reading the source code and also noticed the hack with the I'm really interested in hearing a feedback from @RobinMalfait on this topic. |
Hey! This isn't a bug, for accessibility reasons all modal dialogs must contain a focusable element. Worth reading: https://www.w3.org/TR/wai-aria-practices-1.1/#dialog_modal
If you are showing a loading state or similar, it seems like it would be acceptable to add I don't think we have any plans to change the current behavior as a major goal of this project is to help people build accessible interfaces, but I'll leave this open unless @RobinMalfait has anything he would like to add. |
Thinking about it (every since), also reading up on this (thanks, @adamwathan), the TL;DR I'll leave a simplified example below, just in case somebody tries to abuse the
The Again, thinking this through, the Thanks for the help! |
@adamwathan what you are saying is that "There should be at least one focusable element in the modal." and I agree with that. What I don't agree with, is the way it's enforced. You cannot throw an error because of accessibility reasons. By doing that, you are putting accessibility before reliability, which means that you will have fully accessible software which will crash all the time or not even boot. I believe software must be fully reliable before one start dealing with accessibility. I don't understand the reasons behind this decision, and it's also because I haven't seen any UI framework enforcing accessibility via throwing errors. And going even further, if I notice that some of the hundreds of dependencies in our project throws an exception, I just go to the project github and report a bug, because most of the time it's a bug. And even if it was intentional, it's not documented and users will have to read through the code and will eventually create a Bug report like this one. |
This is also an issue with hmr (react) which I believe is a bug. When I have a dialog, whenever I have a dialog open and change something so it has to reload (e.g. text in the dialog content) I always get There are no focusable elements inside the It seems to be related to initialFocus e.g. if I have <Dialog>
<input />
</Dialog> Then on the hmr reload it will fail, but if I have <Dialog initialFocus={inputRef}>
<input ref={inputRef} />
</Dialog> Then it will work as expected |
I'm running into this error when using the Dialog. It's occurring while using the component in Storybook. I'm not sure if it's related to the above HMR issue, I can create a new issue if need be. I'm using the React Dialog component. The error occurs while trying to control the component using Storybooks controls, where I can click a button to toggle a Controlling the Dialog from within the story (having a button setState to show/hide it) also throws. If I manually pass the ref, it works as expected. It works as expected in my Redwood app, without the need to explicitly define the initial ref. Edit: After putting more time towards the bug, and not what I was trying to accomplish at the time, I'm able to use the Dialog within a Story and control it with Storybook's controls by creating an intermediary component that handles the Dialog's state; no explicit passing of a |
Any news related to this issue? 🤔 |
Having an error thrown is terrible, as it blocks the rendering in the app I'm working on. |
@adamwathan - You're right here, however I'm fine personally with I'd be happy to take a stab at a PR if I can find the time. |
The What you describe with the Here is an example: https://stackblitz.com/edit/react-gvucjx?file=src/App.js |
Thanks for that example! Edit: We're using Vue 3, FYI |
@pieterbeulque I do the same thing. I've got a
|
This issue is getting muddled. There's a discussion around a feature request (i.e. allow modals that have no focusable elements) and a bug (i.e. as @hailwood pointed out this error is thrown in scenarios where you DO have a focusable element). Most folks probably agree that the bug needs fixing sooner rather than later, and that the feature request requires more discussion (or not - it seems the maintainers don't agree that this feature is required), so this should be split into two issues |
I would definitely appreciate if we think about the high level design concept of throwing errors in favor of accessibility (which is why I opened this issue) and not deal with other peoples specific issues with it, because the fundamental issue gets only more distorted. I don't mean to bother you, but these concrete problems and hacks with |
I would also welcome a decision on what the core purpose of the library is. For me as a developer it would be important to know what the core target of HeadlessUI is. For me at least this would be important to know. Does it offer utility with a11y in mind or offer utility and enforce a11y? |
Fair point, Krystofee, sorry if I contributed to sidetracking this issue. |
I'd like to add another use case where forcing the existence of a focusable element on initial render is troublesome. I have a Dialog wrapped by a Transition with very complex animations set dynamically for root and children. Also animations may or may not run depending on context. This is leading to many errors due to the fact that Dialog may try to focus before it should (i.e.: animations are not done and not all elements are mounted yet). This is very painfully when developing the animations, since elements may get removed due to HMR Like others have said, I think a warning should be enough. Even when React detects something dodgy, it warns the developer rather than throw, panic and make everything failed. Not having a focusable element is bad for accessibility. In fact, I do know my Dialog is accessible because eventually (a matter of milliseconds) there will be a focusable element. But the Dialog component cannot know that, and a escape hatch would be nice to have |
Cam we at least consider downgrading this to a warning until the issues with it being thrown when there are focusable elemets is fixed. It is the wrost of all worlds throwing an exception when the check is known to be flaky. |
I agree that the error can be warning instead of throw. I have a similar case when using headlessui with next.js in a medium sized application, where I use dynamic import for non "important" components during the page initialization period. In my point of view, it is more "accessible" not to have accessibility than to have an application broken by not having minimum component requirements. |
I totally agree with you. I think this issue is open for way too long. It would be really nice if @RobinMalfait left here his opinion on that so we can somehow resolve this issue. |
Leaving my usecase here. I am using this to display a slide shopping cart content. However, I have 2 different versions of content for mobile and desktop. I am currently showing/hiding one of the dialogs based on tailwind's breakpoints. Conditional rendering is a bit problematic since I'm using nextjs and want to avoid hydration issues. The |
Hey guys, I've created a pull request which resolves this issue as discussed above. Feedback is appreciated 🙂 |
As a first step, we will now log a warning instead of throwing an actual error. A bit more info can be found in the PR here: #775 This should be fixed, and is available in the next release. You can try it using:
|
What package within Headless UI are you using?
@headlessui/react
What version of that package are you using?
1.0.0
What browser are you using?
Chrome
Reproduction repository
https://codesandbox.io/s/gallant-butterfly-wnxjb
Description
When there is no focusable element inside modal, it fails with error
There are no focusable elements inside the <FocusTrap />
. I don't know if it's a feature or a bug, but there isn't said in the documentation that Dialog must include at least one focusable element and I totally see a use-case when there are modals without any focusable element. I think it at least should fail with warning instead of fatal error.Anyways I would like to thank you for the great job you all are doing with the tailwind ecosystem, we really appreciate your work!
The text was updated successfully, but these errors were encountered: