ClickHouse / ClickHouse/click-ui
IconButton hard-codes aria-label to the icon name and ignores a consumer-provided aria-label
- Dominant language
- TypeScript
- Stars
- 135
- Forks
- 33
- Avg merge
- 2d 13h
- Merged PRs (30d)
- 19
Description
## Summary
`IconButton` sets `aria-label` to the **raw icon token name** (e.g. `sparkle`, `trash`, `cross`) and there is no way to override it. Because `aria-label={iconName}` is placed **after** the `{...props}` spread, a consumer-supplied `aria-label` is silently clobbered. This means every `IconButton` exposes a non-human-meaningful accessible name to screen-reader users, with no escape hatch.
## Current behavior
`src/components/IconButton/IconButton.tsx` (on `main`):
```tsx
export const IconButton = forwardRef(
({ type = 'primary', icon, size, disabled, className, ...props }, ref) => {
const iconName = icon ? icon.toString() : 'unknown icon';
return (
);
}
);
```
Two distinct problems:
1. **Poor default accessible name.** With no label provided, the accessible name falls back to the icon token (`"sparkle"`, `"trash"`, …), which is meaningless to assistive-tech users describing the *action*. Unlike `Button`, `IconButton` has no `label`/`ariaLabel` prop.
2. **The default can't be overridden.** `IconButtonProps extends HTMLAttributes`, so the type advertises `aria-label` as a valid prop, but the implementation ignores it at runtime (it's spread first, then overwritten). The only override that currently survives is `aria-labelledby` (spread via `...props`, and per the accessible-name spec it outranks `aria-label`) — which requires a referenced DOM node and is non-obvious.
This is a type/runtime contract mismatch, not just a styling default — which is why I'd classify it as a bug rather than an enhancement.
## Expected behavior
A consumer-provided accessible name should win, and there should be an explicit, discoverable way to set one.
## Suggested fix (small, backward-compatible)
Respect a consumer-provided `aria-label`, falling back to the icon name only when none is given:
```tsx
```
and/or add an explicit `label` prop mirroring `Button`:
```tsx
export interface IconButtonProps extends HTMLAttributes {
// ...
/** Accessible name for the button. Falls back to the icon name if omitted. */
label?: string;
}
```
## Impact
Affects every `IconButton` instance. In the control-plane `apps/web` app alone there are ~124 instances, each currently announcing an icon token as its accessible name.
## Environment
- Observed on `@clickhouse/click-ui` `v0.2.1-rc.8` (styled-components implementation) and confirmed still present on `main` (CSS-modules implementation).
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with src/components/IconButton/IconButton.tsx and inspect how props and aria-label are applied to the button. Verify the chosen behavior for a consumer-provided accessible name and the fallback icon name, then add coverage for both cases and confirm existing IconButton behavior remains intact.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- accessibility, frontend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100