Skip to content

Semantic content tokens: icon/text interactive ladders disagree, and text.accent is off-scale #5330

Description

@eddiman

Three inconsistencies in the semantic text.* / icon.* groups, found while applying the new tokens to Chip in Figma. They are the same class of defect — the step assignment for content tokens is not uniform across tones — so they are worth deciding together.

Values below were read from the live Tokens Studio project (semantic set) on 2026-08-12, after the #5283 additions and the #5284 release.

Tone text.{tone} text.interactive d/h/p icon.{tone} icon.interactive d/h/p
accent 12 10 / 11 / 12 10 11 / 12 / 13
info 10 10 / 11 / 12 10 11 / 12 / 13
success 10 10 / 11 / 12 10 11 / 12 / 13
danger 10 10 / 11 / 12 10 10 / 11 / 12
warning 10 10 / 11 / 12 10 10 / 11 / 12
link info 8 / 9 / 10 info 8 / 9 / 10

1. icon.interactive and text.interactive disagree for accent, info and success

Three families (danger, warning, link) put icons on the same steps as their label. Two put icons one step further down the ladder. Accent was already like this; info and success inherited it when they were added in #5283.

Consequence in a real component: in a success Chip the icon renders one step darker than the label at every state (light mode icon.interactive.success.default #205c1f vs text.interactive.success.default #206d1f), while in a danger Chip the two are byte-identical. Same component, same anatomy, different relationship depending on tone.

This was flagged in review on #5284 as "cheap to align now, breaking later". That PR merged on 11 Aug, so the two new families are now public API and aligning them is a visual change rather than a pre-release fix. Worth doing anyway while adoption is a day old.

Decision needed: is 11/12/13 or 10/11/12 canonical for interactive icons? Then align the other families to it.

If the intent behind 11/12/13 is that thin icon strokes need more weight than text, that rationale applies to danger and warning too and they should move up. If there is no such intent, accent/info/success should come down to match text.

2. text.accent sits at step 12 while every other static tone text is at 10

text.accent = {accent.12}. text.danger, text.info, text.success, text.warning are all {tone.10}. All five static icon.{tone} are {tone.10}, so accent is also the only tone where static text and static icon differ from each other.

It also collides exactly with text.interactive.accent.pressed, which is likewise {accent.12} — a static accent label is indistinguishable from a permanently-pressed interactive one.

A plausible rationale is the APCA split in our decisions (LC90 for body text, LC60 for interactive): accent at step 10 may not clear LC90 as body text and was bumped, while interactive text only targets LC60 so 10 is fine there. That is inference, not recorded anywhere.

Decision needed: measure accent.10 against background.surface in both modes. If it clears LC90, bring text.accent down to 10 for consistency with the other four tones. If it does not, keep 12 and document the exception — and check whether the other tones' step 10 actually clears LC90, since if they do not the problem is the reverse.

3. Confirm that state-static neutral interactive text is deliberate

On #5283 the scoping comment excluded text/icon.interactive.neutral as duplicating the primary tokens, and @pomfrida asked whether that means neutral interactive text is intentionally state-static at neutral 12 while accent shifts 10→11→12. That question was not answered before the issue moved on to verification.

The duplication argument only holds if the answer is yes — a neutral ladder that shifted would not duplicate text.primary. Please confirm either way so #5245 can record it as a design choice rather than a gap.

Why now

The Chip migration recipe (#5245) is being written against these tokens. Whatever is decided here should land before that recipe codifies the current inconsistencies as per-tone rules that component authors have to memorise.

Related: #5283, #5284, #5245, #5225.

Metadata

Metadata

Assignees

Labels

Type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions