ExternalLink: Align appearance with Link from @wordpress/ui#77790
Conversation
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
Updates ExternalLink styles to match the brand color, underline treatment, focus ring, and external-link icon spacing of Link from @wordpress/ui, so the two components look visually consistent when used side-by-side. Made-with: Cursor
25ed752 to
5f27ea3
Compare
|
Size Change: +664 B (+0.01%) Total Size: 7.82 MB 📦 View Changed
ℹ️ View Unchanged
|
|
Flaky tests detected in 5851296. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/25116695303
|
| display: inline-block; | ||
| margin-inline-start: var(--wpds-dimension-padding-xs); | ||
| font-weight: var(--wpds-typography-font-weight-regular); | ||
| text-decoration: none; |
There was a problem hiding this comment.
text-decoration: none; here is likely redundant, since the actual text decoration is applied to .components-external-link__contents , a sibling element (and not a parent)
| .components-external-link__contents { | ||
| text-decoration: underline; | ||
| text-underline-offset: 0.2em; | ||
| text-decoration-thickness: 0.5px; |
There was a problem hiding this comment.
Using sub-pixel values may create rendering glitches on low-density screens. A few ideas:
- apply
0.5pxinside a@media (min-resolution: 2dppx)query, and fallback to1px - test the
from fontvalue
In any case, we should update Link in @wordpress/ui, too
There was a problem hiding this comment.
TIL about from-font. In my testing this produces the same result as what we have currently (.5px), so we can likely use that :)
Co-authored-by: Marco Ciampini <marco.ciampo@gmail.com>
The parent `.components-external-link` already sets `text-decoration: none`, and the icon span never opts into an underline, so this declaration has no effect. Made-with: Cursor
Lets the browser use the underline thickness defined by the font's metrics instead of a fixed sub-pixel value, which avoids inconsistent rendering across device pixel ratios and adapts if the font changes. Made-with: Cursor
Made-with: Cursor
|
Good point — I guess so? cc @jameskoster |






What
Aligns the appearance of
ExternalLink(@wordpress/components) withLink(@wordpress/ui), so the two components look visually consistent when used side-by-side.Why
ExternalLinkandLinkwere drifting visually: different colors, underline thickness/offset, focus ring treatment, and external-link icon spacing. Now thatLinkfrom@wordpress/uiis the recommended primitive (andExternalLinkis on the path to being redirected to it — see #77012 review), it's worth bringing the legacy component up to visual parity in the meantime so the two don't look mismatched in the same UI.This addresses the appearance differences flagged in #77012 (comment).
How
Primarily updates
packages/components/src/external-link/style.scss— no JSX or API changes. Also makes one small tweak topackages/ui/src/link/style.module.cssto keep the two components in lockstep.--wpds-color-fg-interactive-brand(and…-activeon hover/active), matchingLink's defaulttone="brand".text-underline-offset: 0.2emandtext-decoration-thickness: from-font(kept on the__contentsspan so the icon stays clean).from-fonthonors the font's underline metrics rather than hard-coding a sub-pixel value, which renders inconsistently across device pixel ratios. Applied to bothExternalLinkandLinkso they stay aligned.outset-ring--focustreatment from@wordpress/ui— transparent0 solidoutline at rest (so theoutlinetransition animates in, and forced-colors mode doesn't render a permanent ring) plusoutline-offset: 1px, swapping tovar(--wpds-border-width-focus) solid var(--wpds-color-stroke-focus-brand)on:focus.margin-inline-start: var(--wpds-dimension-padding-xs)(wasmargin-left: 0.5ch) andfont-weight: var(--wpds-typography-font-weight-regular)(was400).text-decoration: nonefrom.components-external-link__icon— the parent anchor already setstext-decoration: none, and the icon span never opts into an underline, so the declaration had no effect.Out of scope / notes
tone,variant).ExternalLinkis slated to redirect toLink+openInNewTab; consumers needing tone variants should reach forLinkdirectly. Keeping the API minimal keeps the eventual migration mechanical.:focus(not:focus-visible) to matchLink's current behavior. The open question raised in #77744 — should links use:focus-visible? — is best resolved across both components in a follow-up.Linkuses a::afterpseudo-element to dodge text-selection / Twemoji issues;ExternalLinkalready mitigates Twemoji viawp-exclude-emoji. Reworking it to a pseudo-element would be a JSX-level change with potential consumer impact, so it's deferred.Testing instructions
Use of AI Tools
Created with Cursor & Claude Opus 4.7