Skip to content

Conversation

alizehkhan
Copy link

@alizehkhan alizehkhan commented Jun 13, 2025

Description

Accessibility improvement: Adds an optional isLabelledBy prop to the TooltipTrigger component, allowing the tooltip content to be announced by screen readers as a label (via aria-labelledby) instead of the default description (aria-describedby). This is useful when the tooltip should serve as the accessible name of the trigger element.

AriaLabel story was adjusted to use and explain the new prop.

Screen.Recording.2025-06-13.at.12.24.17.PM.mov

Copy link

changeset-bot bot commented Jun 13, 2025

🦋 Changeset detected

Latest commit: 1b3b526

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@radix-ui/react-tooltip Minor
radix-ui Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@alizehkhan
Copy link
Author

Hey would be really awesome to get a review on this small accessibility improvement as its the only thing preventing us from using this primitive 😁 It replaces the awkward workaround currently featured in storybook to use the tooltip as a label.

@stubar
Copy link

stubar commented Jun 27, 2025

Thanks for this PR, I'm looking forward to this, it will make our testing library tests easier!

@chaance
Copy link
Member

chaance commented Jul 3, 2025

Not entirely clear why this is needed. Can't you pass aria-labelledby and aria-describedby to the trigger directly? Doing so should override what we set internally.

@alizehkhan
Copy link
Author

alizehkhan commented Jul 3, 2025

@chaance Unfortunately, that results in buggy behaviour where the screen reader announces the label three times. Since this is a common use case for tooltips, it would make sense for Radix to support it directly in the API to avoid this bug or the need for fiddly workarounds.

Untitled.mov

@chaance
Copy link
Member

chaance commented Jul 3, 2025

Unfortunately, that results in buggy behaviour where the screen reader announces the label three times
In this example you are not overriding the aria-describedby prop. I guess what I'm suggesting is that users can do both on their own side to achieve the same result.

I do see the larger point, which is that perhaps associating the tooltip is more appropriate in some scenarios as the desired behavior. This is certainly common, but I'm not sure if it should be encouraged. Tooltips are already clunky from an accessibility/usability perspective, and they are least problematic when used to provide context rather than serve as a label.

There are cases IMO where API friction is a good thing. If your product needs demand it (I know developers don't always get the final say here), we don't stop you from implementing the behavior you want. We just don't want to make doing the usually bad thing too easy. It's a tightrope to be sure. You can pass null to effectively unset aria-describedby, and if you want a prop that simplifies this in your app you can always wrap Tooltip.Trigger in your own component library.

<Tooltip.Root>
  <Tooltip.Trigger aria-labelledby="foo" aria-describedby={null!}>
    <button />
  </Tooltip.Trigger>
  <Tooltip.Content id="foo" />
</Tooltip.Root>

I'll leave this open for now. I could be convinced that it's worthwhile, but I'm ambivalent. I'll seek some outside opinions and come back to it if I decide one way or another.

@alizehkhan
Copy link
Author

Unfortunately that only reduced the number of times the screenreader would repeat the label from 3 to 2 times.

Totally agree tooltips are clunky from an accessibility / usability perspective. That said, I do see a common use for it as a label for example

In the cases above, the semantically correct thing would be to use aria-labelledby.

@alizehkhan
Copy link
Author

alizehkhan commented Jul 7, 2025

When checking what's rendered via screen.debug() it shows "content" is rendered twice with the id attached to the outer element so it announces content twice.
Screenshot 2025-07-07 at 2 41 34 PM
Screenshot 2025-07-07 at 2 39 05 PM

@kaikubasta
Copy link

kaikubasta commented Jul 7, 2025

Hey, I'm affiliated with @alizehkhan and we're currently looking into implementing fully accessible tooltips. We did some research and identified two valid use cases:

Label tooltip Contextual tooltip
labelling, describing interaction providing more context
aria-labelledby aria-describedby
trigger does not contain visible text trigger contains visible text

While it's good to provide developers a stable basis for accessible components without the need for additional configuration, the devil is in the detail – especially in accessibility. We didn't find any established component library that reflects the necessary differences between these two use cases, although it's just about offering developers the option to change one attribute. I believe that making a considered decision with the help of good documentation should be simple enough and will eliminate a lot of confusion about the accessible name and description of an element.

@alizehkhan alizehkhan closed this Aug 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants