feat(Avatar): make fallback initials typography theme-reachable via derived vars#4292
Open
Lee-Dongwook wants to merge 2 commits into
Open
feat(Avatar): make fallback initials typography theme-reachable via derived vars#4292Lee-Dongwook wants to merge 2 commits into
Lee-Dongwook wants to merge 2 commits into
Conversation
Lee-Dongwook
requested review from
cixzhang,
ejhammond and
imdreamrunner
as code owners
July 24, 2026 12:43
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
github-actions
Bot
requested review from
cvkxx,
ernestt,
kentonquatman and
rubyycheung
July 24, 2026 12:44
Lee-Dongwook
force-pushed
the
fix/avatar-fallback-font
branch
from
July 24, 2026 12:46
36ff917 to
10f5583
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issue
#4256
Summary
Avatar's fallback initials rendered at an inline
size × 0.4px value with ahardcoded weight and color. Because that font size resolves to a literal
pxvalue inline, no theme token could reach it — a consumer needing a different
fallback type scale (or weight/color/fill) had to abandon Avatar and hand-compose
their own.
This routes the fallback typography through the design system's existing
component-scoped derived-var mechanism (the same one Button uses for
--_button-radius), so a theme can re-scope the fallback per size tier.Default rendering is byte-for-byte unchanged.
Motivation
An adjacent internal library renders Avatar fallback initials at a per-size type
scale (smaller avatars → proportionally smaller initials, regular weight, a muted
secondary-text color on a wash fill). Matching that by theming Astryx's Avatar was
impossible today, specifically because of the inline dynamic font size. The only
workaround was forking the component — which defeats the point of a themeable
design system.
Approach
Introduce four Avatar-scoped internal vars on the fallback surface, each read with
a default that reproduces today's exact output:
--_avatar-fallback-font-sizefontSizesize × 0.4px(per-size)--_avatar-fallback-font-weightfontWeight--font-weight-medium--_avatar-fallback-colorcolor--color-text-secondary--_avatar-fallback-backgroundbackgroundColor--color-neutralRegistered in
derivedVarRegistryand documented inAvatar.doc.mjs(
theming.vars/theming.derived), matching the existing Button/Cardconvention. No new global tokens; nothing added to
tokens.stylex.ts.Consumers can now theme the fallback without forking:
Non-breaking
Every var defaults to the current value, so unthemed Avatars are unchanged. A new
Avatar.test.tsxcase asserts the initials still render atsize × 0.4(sm =9.6px) — via the seam — so a regression back to a bare literal fails loudly.
Scope / non-goals
The status-dot corner offsets use the same inline-dynamic pattern but are
out of scope — they're structural geometry, not a themeable design choice, and
weren't the reported gap.
Test plan
Avatar.test.tsx— 7/7 pass, incl. new seam assertiongenerateThemeRules.test.ts— new cases provecomponents.avataremits theinternal vars for
baseand a per-size (size:sm) keyderivedVarRegistry.test.ts— registry ↔ doc consistency (addedAvatar: 'avatar'mapping)typecheck+eslintcleanThemed Fallback Type Scalestory (default vs themed)ScreenShot