Material-components-web: Showing a dialog with no buttons prints an error in console (You can't have a focus-trap without at least one focusable element)

Created on 7 Jun 2017  Â·  24Comments  Â·  Source: material-components/material-components-web

What MDC-Web Version are you using?

0.12.1, served from jsdelivr

What browser(s) is this bug affecting?

Chromium 58.0.3029.81

  • Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36

Firefox Nightly 55.0a1

  • Mozilla/5.0 (X11; Linux x86_64; rv:55.0) Gecko/20100101 Firefox/55.0

What OS are you using?

Arch Linux x86_64 (last updated May 3rd)

What are the steps to reproduce the bug?

https://codepen.io/anon/pen/PjqLWJ

Opening the page will cause the error in console. The dialog opens fine, otherwise.

What is the expected behavior?

Showing a dialog with no buttons shouldn't print an error in console.

What is the actual behavior?

Showing a dialog with no buttons prints an error in console.

Any other information you believe would be useful?

762 seems to have a similar error, though with a different cause.

The error trace from the site I initially experienced the issue with:

material-components-web.js:9692 Uncaught Error: You can't have a focus-trap without at least one focusable element
    at firstFocusNode (material-components-web.js:9692)
    at addListeners (material-components-web.js:9636)
    at Object.activate (material-components-web.js:9581)
    at Object.trapFocusOnSurface (material-components-web.js:1867)
    at MDCDialogFoundation.handleTransitionEnd_ (material-components-web.js:3971)
    at HTMLDivElement.MDCDialogFoundation._this.transitionEndHandler_ (material-components-web.js:3885)

Most helpful comment

@Garbee see what MD recommend in the Simple Dialog section.
"Simple dialogs do not have explicit buttons that accept or cancel an operation."
https://material.io/guidelines/components/dialogs.html#dialogs-simple-menus

All 24 comments

I can confirm this issue. I hope it gets resolved soon.

Why are you trying to use a dialog that has no internal trigger to be closed? That's bad for accessibility and usability. IMO this error is highly informative and is developer error, not an error in the focus trap.

I got this while testing with an empty dialog before adding a close button, and I would hardly call an unintelligible error about focus traps "highly informative".

So let's tweak the "Expected Behavior" bit. Instead what we should strive to do is catch the depended upon libraries error and throw one with a better message. Or throw our own error before the focus trap is even called if no focusable node is found. That way the message is more easily understood by developers when they see it in the console and there is a clear action to resolve it.

@Garbee see what MD recommend in the Simple Dialog section.
"Simple dialogs do not have explicit buttons that accept or cancel an operation."
https://material.io/guidelines/components/dialogs.html#dialogs-simple-menus

@faheem-akhtar Yes, however they do have internally focusable triggers that once being acted upon would close the dialog. Further solidifying this is a developer error in making an inaccessible system and not a problem with the focus trap system.

Dismissing dialogs
Dialogs may be dismissed by: If the user’s ability to dismiss a dialog is disabled, the user must choose a dialog action to proceed.

Dialogs may be dismissed by:
Tapping outside of the dialog
Tapping the “Cancel” button
Tapping the system back button (Android only)

could you please just remove

if (!node) {
throw new Error('You can\'t have a focus-trap without at least one focusable element');
}

as next function has name "tryFocus" and accepts nulls

Edit: Uh, so I got confused on what repository this issue was on. So forget about the intro bit here. Jump to the actual important bits please.

MDL is no longer being maintained. Material Components for Web has succeeded it. The MDLv2 that was in the works became the base of the new component library.

However, on this issue in particular, The error is necessary to help developers build more accessible applications. You must have some action within the context of the dialog that triggers it to close by the spec. This would either be a cancel action button or the button to let the user accept whatever the dialog's purpose is. If you are not providing something to that effect, you aren't providing a proper MD dialog (or dialog of any kind really.)

Instead of just saying you believe the console error is inappropriate therefore it should be removed, provide a use-case that displays how a dialog can align to MD specs (and good usability guidelines) while not having any internal actions that trigger the dialog to close in some way. The codepen provided in the initial report is not an acceptable use-case. It's just a dialog with a title. When in a real app would you use that?

eg dialog with QR code with link, that can be closed on esc or on click

with link

This would be a focusable action if done correctly

closed on esc or on click

Escape is fine as an additional close method but not as a primary one.

On click of what exactly?

Could you provide a coodepen example of the markup being used in this scenario?

ignore link, can I just to display QR code in nice dialog box. any key stroke\click should close the dialog

can I just to display QR code in nice dialog box

Not if you want the best user experience. You need to provide (as MD specs state) an action item that will close the dialog from within the dialog itself. If you just pop up a dialog without any indication on how to close it, then how do you expect users to know what to do to close it? "They'll just know" isn't a good accessible answer. What is so terrible about having the actions section with a single action that is a button to "Close" or "Continue"? Give users a better experience, not one that will leave them wondering how to move forward in your application.

@Garbee is correct; dialogs are designed to always contain at least one focusable element / call to action. This is intended behavior.

In your QR code example, if any keystroke/click should close the dialog, does that mean that the QR code itself can be interacted with to close the dialog? If so, giving that a tabindex to make it focusable would give it proper keyboard accessibility and would also avoid this error. However, having a dedicated Close button would probably be much more clear.

Why are you trying to use a dialog that has no internal trigger to be closed? That's bad for accessibility and usability. IMO this error is highly informative and is developer error, not an error in the focus trap.

What if I want to show a progress dialog or waiting dialog. We don't need button's there.

What if I want to show a progress dialog or waiting dialog. We don't need button's there.

Then you should probably assess an alternate UX path that is more accessible. For example, you could disable the submission triggers and update the one the user clicked to show the work is happening and once complete update with success wording before going back to the original state or redirecting/refreshing.

It should be noted, that this is a thrown error so developers understand early in the development processing there is an issue they should look into fixing. However, if you absolutely do not care for the user experience/accessibility of the app, you are free to catch the error and ignore it. Nothing here is stopping a driven developer from hindering the user experience. It's just attempting to prevent it early by making the problem known.

The Material Design specification, to my knowledge, has nothing to support any dialogs existing without something to focus on. So in the context of MD, the code as implemented is correct and attempts to enforce proper design rules. However, the HTML Living Spec has been updated to allow for non-focusable dialogs it seems. This appears in the dialog focusing steps section where they now return with inert content immediately.

I still strongly urge developers not make dialogs that don't have something focusable. In the case of a "progress or waiting dialog" even a "cancel" button to send a new request to stop processing in case a user realizes a mistake is way better than "You're stuck here with no way out." To have a dialog without something contained within it to close it and get back to the page/app at any point is a user experience flaw.

This is a non-sense opinionated approach, I want to A/B test users clicking on the background to escape non-actionable dialogs as I believe if a dialog is purely informative and it doesn't have actions, and the no 1 preferred way to close dialogs is clicking on the scrim/background, then I should be able to test that hypothesis without opinionated constraints and let the market define if it really is necessary or not and not a bunch of developers and UX designers with preconceptions and local biases, etc.

non-sense opinionated approach

Welcome to Material Design. It's all opinionated.

Shame, I was hoping there would be a dialog about the matter.

The Material Design team writes the spec as their opinion on how design should be based on their research and knowledge. There is also now a feedback cycle built with the Material Components implementations for developer feedback on the feasibility of implementing those things across platforms.

The components are written to adhere to those opinions as best as they can. There isn't a real dialog to be had outside of having a discussion with the design team should it be felt they are wrong. Which, the current team of MDC or MD Design people could chime in and hear things out.

No one is forcing people to use Material Design. If you don't agree with the opinions of the components, there are alternatives out there. Dialog is actually a native element in browsers with a really good polyfill. It is trivial to take advantage of it and rid yourself of any MD guidance in the matter UX wise. But, the library has to consider accessibility and usability as core principals. Not providing a focusable element in a dialog goes against every accessibility guideline for them.

Thanks for the answer @Garbee. I'm glad there's a feedback development process built-in, I implemented it under the premise that the scrim is the focusable element since it is what users will click on to dismiss the modal (desktop/tablet versions). I might come back in the future if I'm able to run A/B tests at a scale evaluating user behavior and usage friction with the two options. Cheers

Backdrops by definition have no focus. That's why they can't really be thought of that way. They're an escape hatch, not to be be relied upon as the primary close system. While the native HTML dialog does allow this situation to occur, it isn't one good for great UX since users inherently have no clear and precise way to close it. They're left guessing how to close it, if they even do.

While in any given subset of uses data can be built up to show it's known. On the whole when you consider a global audience of varying backgrounds, it's just vague. If your application is primarily targeting technically inclined users, sure it can skirt by. But that isn't what Material Design is engineered for. It considers any user can come by an application and they should be able to intuitively know how to work the UX.

So you are saying that the constraints of the opinionated framework, which are based on a status quo, trump data analytics, therefore and by definition crippling any UX evolution. That is the same framework that led companies like Nokia, Palm, etc to the ground. Societies adapt to technology, that is very clear, and the whole interpretation, semantics, and definitions of the background in this conversation can be rewritten based on how people evolve using these UIs, thinking otherwise only hinders progress. And by the way, similar things thought people when Apple and other companies started adapting gestures on their UIs, which have become absolutely mainstream among users of any background and age groups. Data is always right, thinking otherwise is arrogant and unwise.

Please keep in mind our code of conduct when discussing, especially around using welcoming language and being respectful of differing viewpoints.

One thing to keep in mind is that our UX designers spend a lot of time and use data from user-driven studies when creating the Material spec guidelines. This repository is simply the web team's implementation of all of that hard work and data. Discussion of broader topics like this are great to start here, but ultimately we as a team defer to the designers and the user studies conducted to make decisions.

The Material team is working on new ways for third-party developers and designers to provide feedback on the Material Design spec directly. I'd encourage you to share the findings from your dialog study when that happens!

@asyncLiz I understand the code of conduct, I was just quoting Eric Ries Author of the Lean Startup: "Use human centered design principles, not your arrogance of thinking you know what works for your audience without testing.", but I understand some citations can be a little edgy, I'll keep that in check in the future.

I appreciate your interest in my findings, and I'll definitely be happy to share some insights in the future. Thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

m-alzam picture m-alzam  Â·  3Comments

traviskaufman picture traviskaufman  Â·  4Comments

abhiomkar picture abhiomkar  Â·  3Comments

broros picture broros  Â·  3Comments

traviskaufman picture traviskaufman  Â·  3Comments