#Using matTooltip on a disabled button to show why it is disabled

31 messages · Page 1 of 1 (latest)

forest saddle
#

That seems like a straightforward use for a tooltip : if there is an error that prevents the form from being validated, the button is disabled, and that would be a good place to show the reason for the error (though not the only good place).
Apparently matTooltip works

  • on focusable elements like buttons
  • on non-focusable elements like plain span or div
  • but not on disabled buttons

Why ?

harsh relicBOT
#

Hi @forest saddle. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

forest saddle
#

will you

harsh relicBOT
#

Why matTooltip Doesn't Work on Disabled Buttons

This is a classic accessibility/browser behavior issue. Here's why:

The Root Cause

Native HTML <button disabled> elements have pointer-events: none applied by the browser (and reinforced by Angular Material's styles). This means:

  • Mouse hover events never reach the button
  • matTooltip relies on mouseenter/mouseleave events to show/hide
  • Since those events are blocked, the tooltip never triggers

Disabled buttons also cannot receive focus, so keyboard-triggered tooltips don't work either.

The Angular Material Solution: disabledInteractive

Angular Material provides the disabledInteractive input precisely for this scenario. It styles the button as disabled but keeps it interactive: [Interactive Disabled Buttons]

<button
  mat-flat-button
  [disabled]="isDisabled"
  [disabledInteractive]="true"
  [matTooltip]="disabledReason"
>
  Submit
</button>

When disabledInteractive is enabled: [Button API]

  • The button is styled as disabled
  • It is marked as aria-disabled="true" for assistive technology
  • It can still receive focus and pointer events — so matTooltip works
  • It is not natively disabled, so you must guard against unintended actions (e.g., form submissions) yourself

⚠️ Important caveat: Since the button is no longer natively disabled, it won't automatically prevent form submission. You need to handle that in your component logic.

Global Configuration

#

You can also configure this behavior globally via the MAT_BUTTON_CONFIG injection token so you don't have to add disabledInteractive to every button. [Interactive Disabled Buttons]

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@forest saddle Kapa.ai is still learning and improving, please let me know how I did by reacting below.

azure drift
#

Sidenote: In general, if you can avoid disabling a button, do it, accessibility wise it's possible to deal with but the answers are kind of all over the place of "interactable with aria-disabled vs. actually disabled and non-interactable"

forest saddle
#

I don't understand

#

you mean avoid both native-disabled and interactive-disabled ?

#

What should I do then, hide the button ?

#

make it clickable but displaying the error ?

azure drift
# forest saddle What should I do then, hide the button ?

No, keep it enabled.
If the user presses it too soon, show an error/mark the entire form as touched to trigger its inline validation and don't do anything.
https://adrianroselli.com/2024/02/dont-disable-form-controls.html

#

https://www.smashingmagazine.com/2021/08/frustrating-design-patterns-disabled-buttons/
This here (referenced by adrian's article) is also a decent reference on what can be done regarding submit buttons.
He also makes a caveat that for some scenarios a disabled button can be valid, but that refers to e.g. the button having been clicked, submission having been sent and now you're waiting for return, so the user pretty much can not do anything

Smashing Magazine

How can we make disabled buttons more inclusive? When do they work well, and when do they fail on us? And finally, when do we actually need them, and how can we avoid them? In this article, Vitaly Friedman will take a look to common usability issues with disabled buttons, how to fix these issues and when disabling buttons actually makes sense. W...

forest saddle
#

I personnaly find that harder to understand, and I have an experience of that just from today

azure drift
#

I'll ultimately be referring to the designers on that one every time rather than relying on my personal feelings there.

#

I think the order of preference for what to use according to him and Adrian:
Not disabled > Disabled via aria-disabled and styling, not via disabled attribute >>> disabled via disabled attribute

#

Mostly because the disabled attribute takes the button out of tab-order

forest saddle
#

Sure, I agree that a button that's disabled and doesn't tell you why is a wall, hence why I wanted the tooltip feature

azure drift
#

I swear to ....

forest saddle
#

heh, found it in the article

azure drift
#

Second attempt: Then you and him are somewhat in agreement, though it's not his first choice

#

Personally I'd rather a static error text near the submit button somewhere than a tooltip (I'd combine that with the button not being disabled), but if he can live with a tooltip then so can I

forest saddle
#

I'm also showing the error in red aside the button (I added that before the tooltip worked)

#

I was planning on mostly disabling it, but I could show it when people click on the disabled button

#

since it's technically interactive

azure drift
#

You see, you could let the user click on the enabled button and then show it 😄

#

But alternatively to that to suit more your initial idea, the next best thing I think would be have it be disabled based on form state and showing the tooltip on focus and hover

forest saddle
#

Setting aside aria considerations, I find that an enabled button with an enabled style conveys the information that all is good, and earlier today when I clicked one that did nothing, I think I was even more lost than if it had been disabled. Because seeing a disabled button, I know to parse the form again (even though, sure, it's faster if I already know what field to look), and when I see an enabled button I believe everything is fine.

#

so, for me : disabled with tooltip > disabled without error information > enabled without error information

azure drift
#

So it's never disabled/enabled without error information, it's more about when you show it