Repository navigation
Theming: High-Contrast Token Source Consolidation #4265
Description
Summary
Extract the PlatformColor-remapping logic shared by the three high-contrast alias
token files into a single internal utility, and eliminate the byte-for-byte duplicate
that win32-theme carries of the theme-tokens Win32 variant.
The Windows/UWP name transform (SystemColor*Color) and the Win32 name transform
(raw system color name) are intentional platform differences that must be preserved
exactly. This task shares the mechanism without silently unifying the behavior.
Goal
Reduce the processAliasTokens body to one definition, called from both platform
variants in theme-tokens, and replace win32-theme's local copy with an import
from @fluentui-react-native/theme-tokens, which win32-theme already depends on.
Stage
Stage 1 - Beta foundations.
Why it matters
- Observed.
packages/theming/theme-tokens/src/highContrast/tokens-alias.win32.ts
andpackages/theming/win32-theme/src/highContrast/tokens-alias.tsare
byte-for-byte identical: same JSON import, sameprocessAliasTokensbody, same
hcAliasTokensexport. Adiffof the two files produces no output. - Observed. A bug fix or behavior change in the Win32
PlatformColorremapping
path must be applied in two places by hand. The duplication has already allowed the
two Win32 files to exist without any comment explaining why a copy lives in
win32-themeinstead of importing fromtheme-tokens. - Observed. No unit test exists for
processAliasTokensin either package.
The only high-contrast coverage is thewin32-themesnapshot suite, which
exercisescreateOfficeColorAliasTokensfor theHighContrastcase and captures
round-trip output, but does not assert either name-transform rule directly. - Inferred. Consolidating before
Package Consolidation is executed avoids migrating
duplicated code into the design package and having to reconcile the copies there.
Observed current state
The three implementations
All three files import
@fluentui-react-native/design-tokens-win32/hc/tokens-aliases.json and export
hcAliasTokens. They differ only in how they rewrite the string-encoded
PlatformColor(name) entries found in the JSON.
- Observed.
packages/theming/theme-tokens/src/highContrast/tokens-alias.ts
is the default (Windows/UWP) variant. For each entry whose string value contains
"PlatformColor", it constructs the name as
'SystemColor' + entry.substring(14, entry.length - 1) + 'Color'. A JSON entry
reading"PlatformColor(ButtonFace)"becomes
PlatformColor('SystemColorButtonFaceColor'). - Observed.
packages/theming/theme-tokens/src/highContrast/tokens-alias.win32.ts
is the Win32 platform override. It extracts the raw name without prefix or suffix:
entry.substring(14, entry.length - 1). The same JSON entry becomes
PlatformColor('ButtonFace'). - Observed.
packages/theming/win32-theme/src/highContrast/tokens-alias.ts
is an independent copy oftokens-alias.win32.ts, behaving identically to it.
Intentional name-transform difference
- Observed. The Windows/UWP
PlatformColorAPI (react-native-windows) expects
CSS4 system-color names of the formSystemColorButtonFaceColor. The Win32
PlatformColorAPI (@office-iss/react-native-win32) expects raw Win32 system
color names of the formButtonFace. The two formats are not interchangeable;
passing the wrong format to either API produces incorrect or missing colors at
runtime. - Inferred. This difference is a load-bearing platform contract. Any shared
utility must accept the name transform as a parameter rather than encoding one
behavior.
Consumers and package boundary
- Observed.
packages/theming/theme-tokens/src/getTokens.ts
imports{ hcAliasTokens }from./highContrast/tokens-aliasand returns it for
mode === 'highContrast'. The React Native bundler resolves the.win32.ts
override on Win32 and falls back to.tson other platforms. - Observed.
packages/theming/win32-theme/src/getOfficeTokens.ts
imports{ hcAliasTokens }from./highContrast/tokens-alias(the local
duplicate) and returns it forofficeTheme === 'HighContrast'. - Observed.
win32-themealready declares
@fluentui-react-native/theme-tokensas a directdependencyin its
package.json,
so no new package-level dependency is required to remove the local copy.
Test coverage
- Observed.
packages/theming/theme-tokenshas no__tests__directory and no
unit tests for the high-contrast alias processing. - Observed.
packages/theming/win32-theme/src/__tests__/win32-theme.test.ts
coverscreateOfficeColorAliasTokensandcreateOfficeShadowAliasTokensfor
each of the five office themes, includingHighContrast, through Jest snapshots.
The snapshots provide round-trip coverage but do not assert either name-transform
rule directly.
Scope
- Extract the
processAliasTokenslogic into a single internal utility inside
packages/theming/theme-tokens/src/highContrast/that accepts the alias token
object and a name-transform function, and returns the remapped result. - Update
tokens-alias.ts(Windows/UWP) andtokens-alias.win32.ts(Win32) to
call the shared utility with their respective transforms. The visible behavior of
each must be identical to the current implementation. - Export
hcAliasTokensfrompackages/theming/theme-tokens/src/index.tsso
win32-themecan import it by package name without reaching into internal paths. - Update
win32-theme/src/getOfficeTokens.tsto importhcAliasTokensfrom
@fluentui-react-native/theme-tokensand delete
win32-theme/src/highContrast/tokens-alias.ts. - Add unit tests in
packages/theming/theme-tokensthat assert the two
name-transform rules independently. - Add changesets for each changed package.
Out of scope
- Changing the
PlatformColorname values, the JSON source file
(design-tokens-win32/hc/tokens-aliases.json), or the two-level loop structure
that iterates over the alias object. - Modifying the Windows/UWP transform rule (
SystemColor*Color) or the Win32
transform rule (raw name). Both must remain as documented above; see the
intentional difference section. - Moving the high-contrast alias logic into
@fluentui-react-native/design; that
boundary question belongs to Package Consolidation. - Broadening unit test coverage in
theme-tokensbeyond theprocessAliasTokens
utility itself. - Any changes to iOS or Android high-contrast handling.
- Changing the in-place mutation pattern; the function currently mutates the JSON
object passed to it, which is load-time-only and safe today. Altering that
behavior is a separate decision.
Deliverables
- A shared internal utility function in
packages/theming/theme-tokens/src/highContrast/that processes alias token
JSON with a caller-supplied name-transform function. - Updated
tokens-alias.tsandtokens-alias.win32.tsusing that utility,
verified to produce identical output to the current implementations. hcAliasTokensadded topackages/theming/theme-tokens/src/index.tsexports.win32-theme/src/getOfficeTokens.tsimportinghcAliasTokensfrom
@fluentui-react-native/theme-tokens, withwin32-theme/src/highContrast/
removed.- Unit tests in
packages/theming/theme-tokensasserting theSystemColor*Color
transform and the raw Win32 name transform. - Changesets for
@fluentui-react-native/theme-tokensand
@fluentui-react-native/win32-theme.
Acceptance criteria
- Only one definition of the alias-processing logic exists in the repository;
the two platform-variant files intheme-tokenscall it with different
name-transform functions. -
win32-theme/src/highContrast/does not contain atokens-alias.tsfile. -
win32-theme/src/getOfficeTokens.tsimportshcAliasTokensfrom
@fluentui-react-native/theme-tokens, not from a local relative path. - A unit test asserts that the Windows/UWP transform converts
"PlatformColor(ButtonFace)"toPlatformColor('SystemColorButtonFaceColor'),
and a separate unit test asserts that the Win32 transform converts the same
input toPlatformColor('ButtonFace'). - The existing
win32-themeJest snapshots for theHighContrasttheme pass
without modifying the snapshot files. -
yarn build,yarn lage test, andyarn lage lintpass at the repository
root, and changesets are present.
Dependencies and ordering
- No prerequisite tasks; this cleanup can proceed at any stage independently of the
staged roadmap. - Interacts with Package Consolidation: if
theme-tokensis shimmed before this task lands, the shared utility and the new
hcAliasTokensexport must be placed in the design destination submodule rather
than intheme-tokensdirectly. Landing this task first avoids migrating
duplicated code. - Interacts with System Appearance Handling:
hcAliasTokensis currently consumed bygetAliasTokens, which that task may
replace or restructure. No sequencing constraint exists; this task changes only
the source location of the alias data, not how it is selected.
Risks and open decisions
- Open decision. Whether
hcAliasTokensis added to the existing
theme-tokensroot index or exposed through a separate subpath export. Adding it
to the root barrel makes a Win32-specific value reachable on all platforms; a
subpath entry avoids that but introduces a new export pattern. Inferred: given
thatgetAliasTokensandgetShadowTokensare already in the root index and are
similarly platform-conditional in their useful values, addinghcAliasTokens
there follows the existing precedent. - Risk. Adding
hcAliasTokenstotheme-tokens/index.tschanges the public
export surface of the package. Observed: no consumer inpackages/orapps/
re-exports* from '@fluentui-react-native/theme-tokens'; the package is consumed
by named import throughout, so the surface change has no fan-out risk. - Risk. The current
processAliasTokensfunction mutates the imported JSON
object in place. This is safe today because the module-levelhcAliasTokensis
the sole reference. The shared utility must carry a comment documenting this
mutation so it is not accidentally removed in a refactor that calls the function
more than once.
Evidence and references
packages/theming/theme-tokens/src/highContrast/tokens-alias.ts: Windows/UWP variant;SystemColor*Colortransform.packages/theming/theme-tokens/src/highContrast/tokens-alias.win32.ts: Win32 variant; raw name.packages/theming/win32-theme/src/highContrast/tokens-alias.ts: byte-for-byte duplicate oftokens-alias.win32.ts.packages/theming/theme-tokens/src/getTokens.ts: platform-resolved consumer intheme-tokens.packages/theming/win32-theme/src/getOfficeTokens.ts: consumer inwin32-theme; currently imports from local copy.packages/theming/win32-theme/package.json: confirms existing@fluentui-react-native/theme-tokensdependency.packages/theming/win32-theme/src/__tests__/win32-theme.test.ts: snapshot tests covering theHighContrastpath.packages/theming/theme-tokens/src/index.ts: current exports;hcAliasTokensis not yet public.- Package Consolidation: the task that will shim
theme-tokens; landing this task first avoids migrating duplicated code. - System Appearance Handling: may restructure
getAliasTokens; no ordering dependency.
Activity
[-]High-Contrast Token Source Consolidation[/-][+]Theming: High-Contrast Token Source Consolidation[/+]