Skip to content
TkDodo's blog

Tooltip Components Should Not Exist

Nov 17, 2025 — ReactJs, Design System, API Design
Tooltip Components Should Not Exist
Photo by Daniel Herron

I have to admit: bad tooltips in web apps are one of my pet peeves. And to be fair, it’s quite easy to get tooltips wrong. There are lots of concerns that need to be thought of:

Over the years, I’ve seen many design systems try to implement a <Tooltip> component for consumers to use, and imo the one thing they have in common is that they will not be used as intended. From an API design perspective, that likely means that the <Tooltip> component is an abstraction that is too low level, which leads me to today’s hot take 🌶:

Tooltip Components Should Not Exist

I’m not saying tooltips themselves should not exist. They are a valuable tool when applied “correctly” - whatever that means for your use-cases. Sure, you might get there with education, but let’s be honest: Very few people read docs and AI only reproduces what it already sees, so chances are it will amplify the anti-patterns we have in our codebase.

So let’s dig into the potential problems you can get when using tooltips the wrong way before I’m trying to outline what an alternative world could look like.

Keyboard Interactivity

This one should be obvious: We ought to build web-apps for everyone, which means we have to be aware that not all users will be using a mouse. Nevertheless, I’ve often come across implementations that only show tooltips on hover in situations when the element that triggers the tooltip is not interactive.

We don’t have to look any further than Material UI (opens in a new window), one of the most popular component libraries. Their basic tooltip example (opens in a new window) from the docs looks like this:

MUI-basic-tooltip
<Tooltip title="Delete">
<IconButton>
<DeleteIcon />
</IconButton>
</Tooltip>

That’s easy and works, but what happens if we only add a <Tooltip> around an Icon, or around another non-interactive element like a Badge:

MUI-non-interactive-tooltip
<Tooltip title="Home">
<IconHome />
</Tooltip>
<Tooltip title="Unread Mails">
<Badge badgeContent={4} color="primary">
<IconMail color="action" />
</Badge>
</Tooltip>

That’s right - the tooltip will still show up on hover, but not on focus because tabbing will skip right over it. The element isn’t keyboard-interactive, so it never receives focus, meaning the tooltip will never appear when navigating with the keyboard alone.

There’s also no way to make this type-safe, as we can’t control the type of children that get passed to the <Tooltip> component. React Aria’s approach (opens in a new window) is a bit better, as it won’t show the tooltip at all for non-interactive elements, making it easier to spot for developers who are primarily using their mouse. The fix is then to wrap the custom trigger (opens in a new window) with the <Focusable> component. This is miles better than other approaches, but still suffers from other problems, specifically:

Least Surprise For All Users

If a <Tooltip> can be added to any element, someone will try. I’ve seen tooltips in the weirdest of places, like on a certain text in the middle of a sentence - without any indication that there is additional information behind that.

But I’ve also seen the opposite. It’s super annoying to me to see a button that only consists of an icon that I don’t understand, but I’m not getting any information about what’s going to happen when I click that button.

You’re basically guaranteed to get those inconsistencies in your app as soon as you have a critical mass of developers and designers working on it.

So, if a standalone <Tooltip> component isn’t ideal, what other approaches can a design system use to expose tooltip behavior? My take is:

Provide only higher level pattern components
that enforce consistent and accessible tooltip usage

Some things that I’ve seen work really well in the past are:

I’m sure there are other things I might be missing, but if that’s the case, adding another pattern component is better than giving everyone access to the low-level <Tooltip> component. Don’t get me wrong, flexibility is great for a lot of cases, like e.g. layouting, but providing consistent UX and being inclusive are way more important for tooltips, which is why being restrictive is better.

Restriction also breeds creativity, so if we can’t just stick information behind a tooltip just because we don’t have enough space on our screen, maybe that helps us re-think some ideas from the ground up.

So if you’re building a design system for your organization, try to resist the urge to add a <Tooltip> Component to your public interface.


That’s it for today. Feel free to reach out to me on bluesky (opens in a new window) if you have any questions, or just leave a comment below. ⬇️

Like the monospace font in the code blocks?

Check out monolisa.dev

Bytes - the JavaScript Newsletter that doesn't suck