Skip to content

IconButton should include Tooltip by default #2008

@iansan5653

Description

@iansan5653

Summary

There is no documented example of how to render an icon-only button with an accessible tooltip in a way that would meet all of the following standard requirements:

  • Render as an icon-only button with a single focus target
  • Read the label one time in a manner that ties it to the button, for screen reader users
  • Show the label on hover, for mouse users
  • Show the label on focus, for keyboard users

If this is a supported behavior, then some documentation is needed to show how to do it. If this is not supported, it would be very useful functionality to add to Primer.

The IconButton documentation provides an example of how to label the component in an accessible manner:

<IconButton aria-label="Search" icon={SearchIcon} />

And the Tooltip documentation has the same:

<Tooltip aria-label="Hello, Tooltip!">Text with a tooltip</Tooltip>

Both of these examples use aria-label however, which provides no obvious way to create an icon button that shows its accessible label on hover as a tooltip.

Use Cases

This is a very common requirement. See for example these instances on github.com:

Notifications bell:
Screenshot of the GitHub notifications bell button showing a tooltip that says 'you have unread notifications'

Markdown editor toolbar:
Screenshot of the GitHub markdown editor 'bold' button showing a tooltip

Code view:
Screenshot of the GitHub pull request code view, showing the 'Expand all' button with a tooltip

This is recommended as a best practice by Primer's own tooltip guide:

Do: Use a tooltip to give a text label to an icon button

Attempts

I've tried all of the following examples but I haven't been able to find a satisfying way to do this:

Label on tooltip: Tooltip does not appear on button focus and the button appears as unlabelled in the accessibility tree.

<Tooltip aria-label="Bold">
  <IconButton icon={BoldIcon} />
</Tooltip>

Label on button only: Tooltip does not work at all.

<Tooltip>
  <IconButton icon={BoldIcon} aria-label="Bold" />
</Tooltip>

Label on both: The label will be read twice to screen readers (something like "Tooltip: Bold, Button: Bold") which is unnecessarily redundant. Also the tooltip still doesn't appear on focus.

<Tooltip aria-label="Bold">
  <IconButton icon={BoldIcon} aria-label="Bold" />
</Tooltip>

Tooltip as button: Seems like a promising idea but Tooltip does not support the as prop.

<Tooltip aria-label="Bold" as={IconButton} icon={BoldIcon} />

Button as tooltip: Renders an unfocuseable span instead of a button.

<IconButton icon={BoldIcon} as={Tooltip} aria-label="Bold" />

Tooltip in button children: Does not work because the IconButton ignores children.

<IconButton icon={BoldIcon} aria-label="Bold">
  <Tooltip aria-label="Bold" role="presentation">Bold</Tooltip>
</IconButton>

Tooltip as button icon: This is horribly inelegant, but it does generate a good accessibility tree and still shows the tooltip on hover. It unfortunately still doesn't show the tooltip on focus, but it's the best I have for now.

<IconButton
  icon={() => <Tooltip aria-label="Bold" role="presentation"><BoldIcon /></Tooltip>}
  aria-label="Bold"
/>

Proposed Solution

My ideal solution would be to just show the IconButton's aria-label as a tooltip by default.

To configure this, I propose adding two new props to the IconButton component:

  • disableTooltip: Turn off the tooltip.
  • tooltipProps: Configure the tooltip by passing props to the underlying Tooltip component.

Then I could achieve my goal simply with:

<IconButton icon={BoldIcon} aria-label="Bold" />

Metadata

Metadata

Labels

accessibilitybugSomething isn't workingcomponent: ButtonIssues related to the Button componentcomponent: TooltipIssues related to the Tooltip componentenhancementNew feature or requestreactsize: rocksupportTasks where the team is supporting and helping other teams

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions