Button: Limit link underline to the label - #8408
Conversation
🦋 Changeset detectedLatest commit: 246380d The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
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 |
|
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The updated hover underline selectors don’t account for [aria-disabled='true'], and the new E2E test uses order-dependent .nth(1) locators that are likely to be brittle.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review tier: Lite
Findings: 1
New issues introduced by this change (2)
| Severity | Finding |
|---|---|
packages/react/src/Button/ButtonBase.module.css — The link-variant hover underline is suppressed for :disabled and [data-inactive], but not for… |
|
e2e/components/Button.test.ts — The test selects the target button via .nth(1), which is order-dependent and can become brittle… |
What changed in this PR
Updates the link variant underline styling for Button/LinkButton so the underline is applied only to the text label (not visuals/gaps) and adds intended underline spacing, with an accompanying E2E assertion for both “always show underlines” preference states.
Changes:
- Apply
text-decorationto the.Labelelement (instead of the button root) for link-variant underlines. - Add
text-underline-offsetto improve spacing between label text and underline. - Add a Playwright test verifying underline behavior with
data-a11y-link-underlineson/off (including hover behavior).
| File | Description |
|---|---|
| packages/react/src/Button/ButtonBase.module.css | Moves link-variant underline styling to .Label and adjusts underline offset/hover behavior. |
| e2e/components/Button.test.ts | Adds an E2E test that checks underline is applied only to the label for both underline-preference states. |
| .changeset/button-label-underline.md | Adds a patch changeset describing the link-variant underline behavior change. |
Suppressed comments (3)
packages/react/src/Button/ButtonBase.module.css:641
- This hover underline override also doesn't exclude
[aria-disabled='true'], so an aria-disabled LinkButton can still gain an underline on hover. Suggest matching the same disabled/inactive exclusions used for the base link-variant hover styling.
&:where(:hover:not(:disabled, [data-inactive])) .Label {
text-decoration: underline;
}
packages/react/src/Button/ButtonBase.module.css:631
- In the a11y underline-preference override, the hover selector removes the underline for all hovered link-variant buttons, including ones that are
[aria-disabled='true']or[data-inactive]. If a LinkButton is aria-disabled/inactive, it shouldn't change decoration on hover; consider matching the same disabled/inactive exclusions used elsewhere in the link-variant rules.
&:where(:hover) .Label {
text-decoration: none;
}
e2e/components/Button.test.ts:132
- Same as above: selecting with
.nth(1)is order-dependent. Filtering for a button that contains a visual makes the intent clearer and reduces brittleness.
const preferenceOffButton = page.locator('[data-a11y-link-underlines="false"]').getByRole('button').nth(1)
const preferenceOffLabel = preferenceOffButton.locator('[data-component="text"]')
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.


Fixes #8408
Link-style buttons with an icon currently draw the underline beneath the icon and the space before the label. The design calls for the underline to appear only beneath the label, with more space between the text and the line. This change fixes the underline area and spacing without changing when the underline appears.
Before and after
Screenshots shown at 4x size.
Changelog
New
N/A
Changed
ButtonandLinkButtonwithvariant="link"underline only their label text and use the intended spacing.Removed
N/A
Rollout strategy
Testing & Reviewing
Open the Button playground with the link variant and
EyeIcon. Check that the line begins beneath the label instead of the icon or gap, and that its spacing matches the after screenshot. An automated browser test covers both states of the "always show link underlines" setting, including hover.Merge checklist