Skip to content

Theming Workstream #4276

Description

@JasonVMo

Summary

Make @fluentui-react-native/design the central location for theming and
styling utilities and defaults. The target is a single package that owns the
theme contract, Flex tokens, generated defaults, appearance resolution, and
optional runtime color derivation, while the remaining theming packages become
thin compatibility shims or platform themes built on that contract.

The workstream also makes that contract maintainable: mapping and upstream
drift checks, resolved-token snapshots, consolidated high-contrast sources,
current consumer documentation, Storybook appearance coverage, and a
tree-shakeable contrast audit.

Beta versus production

Inferred from the baseline and from the owner task list.

Definition
Beta One public theming contract in @fluentui-react-native/design that agentic components can rely on. Themes can be authored in Flex or Fluent terms, default values are generated rather than hand-maintained, appearance and high contrast are resolved through one structured API, and every legacy theming package is a shim or a platform theme built on that contract. API may still change with changesets and a documented migration note.
Production The contract is stable and bundle-conscious: optional capabilities (runtime color derivation, legacy Fluent token construction) live in submodules that are only bundled when imported, generated defaults are de-duplicated across appearances, the macOS look and feel matches an owner-approved specification, and all supported platforms are validated.

Staged roadmap

Stage Focus Tasks Gate
Stage 1 - Beta foundations Approve the public contract, implement Flex-first authoring, verify mapping consistency, and consolidate HC sources Package Consolidation, Dynamic Theme Building, Stage 1 of Mapping Drift Detection, High-Contrast Source Consolidation Owner approves the export boundary and the Flex-value context type
Stage 2 - Beta delivery Generate and snapshot defaults, resolve appearance, detect upstream drift, refresh docs, and exercise Storybook Default Values Codegen, System Appearance Handling, Theme Snapshot Parity, Stage 2 of Mapping Drift Detection, Theming Documentation Refresh, Storybook Appearance Integration Beta exit criteria below
Stage 3 - Production fidelity Add optional derivation and auditing, measured de-duplication, and platform look and feel Runtime Color Utilities, Contrast Auditing, Apple Theme, production portions of Default Values Codegen, Theming Documentation Refresh, and Storybook Appearance Integration Production exit criteria below

Tasks

Task Stage Summary
Package Consolidation Stage 1 Finish moving theming and styling utilities into @fluentui-react-native/design submodules and reduce theme-tokens, theming-utils, use-tokens, use-styling, themed-stylesheet, and utils/tokens to thin re-exports, continuing the pattern already used by theme-types and framework/theme.
Default Values Codegen Stages 2 and 3 Replace the hand-authored 473-line defaultTokens.ts with generated Flex defaults sourced from the Fluent design token packages, extending the existing platform de-duplication in scripts/src/codegen/json.ts to also de-duplicate across appearances so shared values are declared once.
Dynamic Theme Building Stage 1 Allow a theme to be defined directly in Flex tokens or in Fluent Theme terms, add the Flex-value context type, build the Fluent token set only for legacy hooks, and make useFlexTokens context-aware instead of returning a fixed default.
Runtime Color Utilities Stage 3 Port x3's OKLCH interaction algorithm -- a lightness and alpha shift with a low-lightness amplification curve, applied in a standard or inverse direction per token family -- into a tree-shakeable submodule, so themes that supply only rest values still render correct hover and pressed states. Verified test vectors are recorded in the task.
Apple Theme Stage 3 Build a Flex-contract Apple theme for the macOS look and feel from the linked Office macOS Figma specification, replacing reliance on the legacy apple-theme package for agentic components.
System Appearance Handling Stage 2 Replace the five divergent platformUtils implementations and the single highContrast boolean with a structured color-scheme model that separates the requested scheme from the resolved scheme and exposes it on ThemeState.
Theming Documentation Refresh Stages 2 and 3 Make @fluentui-react-native/design the documented theming entry point, add its package README, update the legacy theming package index, and refresh the theming guides after the public contract stabilizes.
Theme Snapshot Parity Stage 2 Snapshot the fully resolved Flex token set for every supported appearance and platform, with a reviewed update policy that makes codegen and mapping changes visible.
Mapping Drift Detection Stages 1 and 2 Enforce consistency among the internal mapping artifacts, pin the x3 source revision, and generate an offline-safe report when the upstream token and interaction sources drift.
Storybook Appearance Integration Stages 2 and 3 Add dynamic system appearance and a Flex-authored theme to Storybook, style its chrome from active tokens, and validate appearance switching on macOS and Windows.
High-Contrast Source Consolidation Stage 1 Share the high-contrast alias processing mechanism while preserving the intentional Windows SystemColor*Color and Win32 raw-name transforms.
Contrast Auditing Stage 3 Add a tree-shakeable contrast audit submodule with WCAG thresholds, compositing, token pairings, and explicit diagnostics for native colors that cannot be resolved in JavaScript.

Cross-task dependency ordering

  1. Stage 1 of Mapping Drift Detection can
    land immediately and must gate mapping-driven codegen.
  2. Package Consolidation fixes the submodule
    boundary that every later public capability publishes into.
  3. Dynamic Theme Building defines the
    Flex-value context and theme-definition model.
  4. High-Contrast Source Consolidation
    follows the package-boundary decision and feeds the structured appearance
    work without changing platform-specific color-name behavior.
  5. Default Values Codegen and
    System Appearance Handling can proceed in
    parallel after steps 1-3.
  6. Theme Snapshot Parity follows generated
    per-appearance defaults and the structured appearance model.
  7. Theming Documentation Refresh and
    Storybook Appearance Integration
    follow the stabilized authoring and appearance APIs.
  8. Runtime Color Utilities depends on the
    optional-submodule pattern and generated defaults.
    Contrast Auditing then reuses the stable color
    utilities to measure, rather than derive, theme values.
  9. Apple Theme depends on dynamic theme building,
    generated defaults, system appearance, and runtime color utilities; Storybook
    appearance integration provides its macOS validation surface.

Beta exit criteria

  • @fluentui-react-native/design is the only package that defines theme
    types, theme construction, appearance resolution, Flex tokens, and styling
    helpers; the remaining theming packages are shims or platform themes.
  • A theme can be authored directly in Flex tokens and consumed through
    context without constructing a Fluent Theme.
  • useFlexTokens resolves from context rather than returning a fixed
    default set.
  • Flex default values are generated by yarn prebuild codegen from the
    Fluent token packages, with no hand-maintained color literal tables.
  • Light, dark, and high-contrast appearances resolve through one structured
    API on all supported platforms, and ThemeState exposes the resolved
    scheme.
  • Internal mapping consistency is CI-enforced, and the pinned x3 revision
    has an offline-safe drift report and documented update workflow.
  • Every supported generated appearance has a reviewed resolved-Flex-token
    snapshot.
  • The duplicated high-contrast alias processing source is consolidated
    without changing Windows or Win32 platform color names.
  • The design package and theming guides document the approved Flex-first and
    Fluent-compatibility paths.
  • Storybook can follow dynamic system appearance and render a Flex-authored
    theme without hard-coded chrome colors.
  • yarn build, yarn lage test, and yarn lage lint pass at the
    repository root, and every changed package carries a changeset.

Production exit criteria

  • Runtime color derivation ships as an optional submodule that is absent
    from a bundle that does not import it, with the derivation verified
    against the x3 algorithms.
  • Generated defaults de-duplicate values shared across appearances and
    platforms, and the reduction is measured against a recorded baseline.
  • Legacy Fluent token construction runs only when a legacy hook is used.
  • An Apple/macOS theme built on the Flex contract is validated against an
    owner-approved specification.
  • The optional contrast submodule audits the approved token pairings,
    reports native colors as explicitly unresolvable, and is absent unless
    imported.
  • Deprecation and migration guidance is published for every shimmed package.

Cross-workstream infrastructure

The owner-approved bundle-size regression addition is tracked by
Add bundle-size and dependency regression gates.
The Theming workstream defines which capabilities must remain optional and
which de-duplication results it claims; the Infrastructure workstream owns the
repeatable consumer bundles, checked-in baselines, and CI enforcement.

Suggested additions

None. All theming Suggested Additions have been promoted to the Tasks table;
the two drift additions are combined in
Mapping Drift Detection.

Observed current baseline

Observed upstream baseline (x3-design/fluent-design)

The upstream baseline is pinned to
x3-design/fluent-design@d334acf5cbad813f2b7cd554da942b09a7ff8f10.

  • Observed. The Flex source lives in two packages inside the x3 monorepo:
    @x3-design/flex-tokens@0.9.0 at dev/web/flex-tokens (the data layer:
    tokens.json, mappings.json) and @x3-design/flex-themes@0.8.0 at
    dev/web/flex-themes (CSS themes, a createTheme factory, and OKLCH and
    contrast utilities). Both are MIT-licensed and describe themselves as alpha
    with instructions to pin exact versions.
  • Observed. The two file paths recorded in FURN's
    flex-token-map.yaml
    and flex.types.ts --
    dev/web/flex-themes/css/semantic.css and
    dev/web/flex-themes/css/interaction-fallback.css -- both exist at this commit.
  • Observed. Hover and pressed states are computed in OKLCH from four
    relative-color fragments, not authored per token; the precomputed
    interaction-fallback.css is an opt-in compatibility artifact. The full
    algorithm, constants, and verified test vectors are recorded in
    Runtime Color Utilities.
  • Observed. x3's interaction token set is exactly FURN's:
    mappings.interaction has 118 entries over 59 base tokens, and those 59 names
    match FURN's 59-member InteractiveColorOverrides one to one after
    kebab-case to camel-case conversion.
  • Observed. Values shared across themes are de-duplicated at the primitive
    layer upstream: mappings.json holds 640 primitives (574 distinct values),
    and its 264 generics reference either a single mode-invariant primitive
    (142 of them) or a primitive_light/primitive_dark pair (116), with 6
    layered entries.
  • Observed. A theme is constructed programmatically by
    createTheme({ brand, primitives, generics }), which returns both resolved
    modes plus a toCss serializer; per-mode overrides use a { light, dark }
    shape and a scalar applies to both modes.
  • Observed. Appearance upstream is a two-mode model only -- light-dark(),
    color-scheme, and [data-theme="light"|"dark"]. There is no high-contrast
    or forced-colors theme anywhere in dev/web/flex-themes.
  • Observed. x3's Flex layer is web and CSS only. It contains no React
    Native, macOS, Windows, or other native output.

Sources

Retrieved 2026-08-20.

Source Type Note
packages/agentic/design Local Design package source, codegen, mappings, and tests.
packages/theming Local Legacy theming packages and their shim status.
packages/framework Local theme, use-tokens, use-styling, themed-stylesheet.
scripts/src/codegen Local Shared codegen and de-duplication implementation.
AGENTS.md Local Repository build, validation, and authoring conventions.
microsoft/fluentui-react-native@e37b04b Remote PR #4140, added the design package with token codegen.
microsoft/fluentui-react-native@d2690c9 Remote PR #4143, consolidated theming logic into the design package.
microsoft/fluentui-react-native@03ba7ef Remote PR #4153, added the Flex token shape and mapping information.
microsoft/fluentui-react-native@80bf14d Remote PR #4155, consolidated appearance and high-contrast helpers.
microsoft/fluentui-react-native@1eef74e Remote PR #4156, temporary useFlexTokens implementation.
microsoft/fluentui-react-native@ea738f0 Remote PR #4186, made useThemeState work with existing FURN themes.
microsoft/fluentui-react-native@51fab45 Remote PR #4210, repathed packages/agentic-* to packages/agentic/*.
x3-design/fluent-design@d334acf Remote dev/web/flex-themes and dev/web/flex-tokens are the upstream sources used by this workstream.
Office macOS Figma file Remote Design source for the Apple theme.

Technical gaps

  • Observed. No high-contrast or forced-colors source exists in x3's Flex
    layer. FURN's high-contrast behavior therefore cannot be sourced upstream and
    must come from the platform and Fluent token packages; see
    System Appearance Handling.
  • Observed. x3's Flex layer produces web CSS only, so it supplies no macOS,
    Windows, or React Native values. The native mapping in
    flex-token-map.yaml
    remains FURN's own bridge.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions