Skip to content

fix(IconButton): respect consumer-supplied aria-label - #1140

Open
munzzyy wants to merge 3 commits into
ClickHouse:mainfrom
munzzyy:fix/iconbutton-aria-label-override
Open

fix(IconButton): respect consumer-supplied aria-label#1140
munzzyy wants to merge 3 commits into
ClickHouse:mainfrom
munzzyy:fix/iconbutton-aria-label-override

Conversation

@munzzyy

@munzzyy munzzyy commented Jul 5, 2026

Copy link
Copy Markdown

Why?

IconButton sets aria-label to the raw icon token ("trash", "sparkle", etc.) and there's no way to override it. The line is placed after {...props} in the render, so if you pass your own aria-label, it gets silently thrown away and screen readers just announce the icon's internal name instead of what the button actually does. Closes #1056.

How?

  • Changed aria-label={iconName} to aria-label={props['aria-label'] ?? iconName} so a consumer's label wins and the icon name is only the fallback
  • Added two tests: one confirming the icon-name fallback still works with no label, one confirming a supplied aria-label now actually sticks
  • Added a changeset (patch bump)

Tickets?

Contribution checklist?

  • You've done enough research before writing
  • You have reviewed the PR
  • The commit messages are detailed
  • The build command runs locally
  • Assets or static content are linked and stored in the project
  • For documentation, guides or references, you've tested the commands

Security checklist?

  • All user inputs are validated and sanitized
  • No usage of dangerouslySetInnerHTML
  • Sensitive data has been identified and is being protected properly
  • Build output contains no secrets or API keys

Preview?

N/A — one-line prop precedence fix, no visual change.

aria-label was set after the {...props} spread, so it always
overrode a consumer-supplied aria-label with the raw icon token
name (e.g. 'trash', 'sparkle'). Screen readers announced the
icon's internal name instead of the button's actual purpose.

Now a consumer aria-label wins, falling back to the icon name
only when none is given. Added tests covering both paths.
@changeset-bot

changeset-bot Bot commented Jul 5, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 791edba

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

This PR includes changesets to release 1 package
Name Type
@clickhouse/click-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

@CLAassistant

CLAassistant commented Jul 5, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.

Fix All in Cursor

Reviewed by Cursor Bugbot for commit b84db50. Configure here.

Comment thread src/components/IconButton/IconButton.tsx Outdated
Comment thread src/components/IconButton/IconButton.tsx Outdated
… fallback

The Icon rendered inside IconButton still exposed its own role="img"
aria-label, so assistive tech announced two names for one control. Mark
it aria-hidden, matching how Button and ButtonGroup already hide their
icons.

Also switch the aria-label fallback from ?? to ||, so an explicit empty
aria-label="" falls back to the icon name instead of leaving the button
nameless.
@munzzyy

munzzyy commented Jul 5, 2026

Copy link
Copy Markdown
Author

Pushed a follow-up commit for both review points.

  • The inner Icon is now aria-hidden, matching how Button/ButtonGroup already hide their icons. Before this, the icon's own role="img" aria-label was still exposed alongside the button's aria-label, so assistive tech announced two names for one control.
  • Switched the fallback from ?? to ||, so aria-label="" now falls back to the icon name instead of leaving the button nameless.

Added tests for both. yarn test on IconButton is 11/11 passing, and yarn typecheck / eslint are clean on the changed files.

@munzzyy

munzzyy commented Jul 27, 2026

Copy link
Copy Markdown
Author

Both of these are already handled in the current revision. The inner Icon is rendered with aria-hidden, so it isn't exposed to assistive tech and the button doesn't end up with two names (first finding). And the label is props['aria-label'] || iconName, not ?? — an empty string is falsy, so an empty consumer aria-label still falls back to the icon name (second finding). Looks like Bugbot reviewed an earlier commit before those two changes landed.

@XOP

XOP commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

Hey @munzzyy, thank you for taking this issue into work and appreciate the details on description!
lgtm, @ariser please check if any additional work needed.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes IconButton accessibility behavior by ensuring a consumer-supplied aria-label is not silently overridden, improving the accessible name exposed to assistive technologies.

Changes:

  • Update IconButton to prefer a passed aria-label and fall back to the icon token when absent (including empty string).
  • Mark the inner Icon as aria-hidden to keep the control’s accessible name focused on the button itself.
  • Add unit tests covering label precedence and fallback behavior; add a patch changeset.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
src/components/IconButton/IconButton.tsx Adjusts aria-label precedence and hides the inner icon from assistive tech.
src/components/IconButton/IconButton.test.tsx Adds tests for aria-label fallback/override and icon accessibility behavior.
.changeset/fix-iconbutton-aria-label-override.md Documents the patch-level change for release notes/versioning.

Comment thread src/components/IconButton/IconButton.tsx
@XOP
XOP self-requested a review July 29, 2026 10:50
@XOP XOP added a11y Accessibility improvements good first issue Good for newcomers labels Jul 29, 2026

@ariser ariser left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@munzzyy

munzzyy commented Jul 29, 2026

Copy link
Copy Markdown
Author

Thanks for the look. Nothing outstanding from my side, so I'll leave it with @ariser.

Comment thread src/components/IconButton/IconButton.tsx
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a11y Accessibility improvements good first issue Good for newcomers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

IconButton hard-codes aria-label to the icon name and ignores a consumer-provided aria-label

5 participants