Make WordPress Core

Opened 5 weeks ago

Last modified 5 weeks ago

#65085 new enhancement

Expose admin design tokens (radius, spacing, grayscale, typography) as CSS custom properties via wp-base-styles

Reported by: jillq's profile jillq Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version: trunk
Component: Administration Keywords:
Focuses: ui, css Cc:

Description

Background

WordPress 7.0's admin visual reskin (#64308) introduced a comprehensive design token system in src/wp-admin/css/_tokens.scss, covering:

  • Border radius: $radius-xs (1px), $radius-s (2px), $radius-m (4px), $radius-l (8px), $radius-30 (12px), $radius-full (9999px)
  • Spacing: $grid-unit-05 through $grid-unit-60 (4px increments)
  • Grayscale: $gray-100 through $gray-900 (a unified neutral palette)
  • Typography: $font-size-xs through $font-size-xl, $font-weight-regular, $font-weight-medium
  • Elevation: $elevation-xs through $elevation-l

These tokens are used internally by core CSS during the Sass build, but the resulting values are not exposed as CSS custom properties at runtime. Plugin authors who want to align with Core's design system therefore have to hardcode the values (e.g. border-radius: 8px to match dashboard widgets).

The existing wp-base-styles stylesheet handle already exposes admin color scheme tokens this way (--wp-admin-theme-color, --wp-admin-theme-color--rgb, --wp-admin-theme-color-darker-10, --wp-admin-theme-color-darker-20, --wp-admin-border-width-focus). This proposal extends that pattern to the rest of the token system.

Problem

Plugins and themes that want to follow WP 7.0's modernized visual language currently have three suboptimal choices:

  1. Hardcode the values — brittle, silently drifts when Core updates the token values
  2. Conditionally override with version-gated CSS — what WooCommerce currently does; adds maintenance burden
  3. Don't align — fragments the admin visual experience, which is exactly what #64308 was trying to fix

Proposal

Extend wp-base-styles (or introduce a sibling handle) to emit CSS custom properties for the public subset of _tokens.scss:

:root {
    /* Border radius */
    --wp-admin-radius-xs: 1px;
    --wp-admin-radius-s: 2px;
    --wp-admin-radius-m: 4px;
    --wp-admin-radius-l: 8px;
    --wp-admin-radius-30: 12px;
    --wp-admin-radius-full: 9999px;

    /* Grid units */
    --wp-admin-grid-unit-05: 4px;
    --wp-admin-grid-unit-10: 8px;
    --wp-admin-grid-unit-15: 12px;
    --wp-admin-grid-unit-20: 16px;
    --wp-admin-grid-unit-30: 24px;
    --wp-admin-grid-unit-40: 32px;
    --wp-admin-grid-unit-50: 40px;
    --wp-admin-grid-unit-60: 48px;

    /* Grayscale */
    --wp-admin-gray-100: #f0f0f0;
    --wp-admin-gray-200: #e0e0e0;
    --wp-admin-gray-300: #dddddd;
    --wp-admin-gray-400: #cccccc;
    --wp-admin-gray-600: #949494;
    --wp-admin-gray-700: #757575;
    --wp-admin-gray-900: #1e1e1e;

    /* Typography */
    --wp-admin-font-size-xs: 11px;
    --wp-admin-font-size-s: 12px;
    --wp-admin-font-size-m: 13px;
    --wp-admin-font-size-l: 15px;
    --wp-admin-font-size-xl: 20px;
    --wp-admin-font-weight-regular: 400;
    --wp-admin-font-weight-medium: 500;
}

Naming follows the existing --wp-admin-[thing] convention already established for --wp-admin-theme-color, --wp-admin-border-width-focus, etc.

Benefits

  • Plugins align automatically — When Core updates a token value (as happened with the reskin itself), anything depending on these custom properties updates with it. No plugin PR required.
  • Consistent admin visual experience — Fragmented admin styling is a merchant pain point. This unlocks plugin-side alignment without duplicating Core values.
  • Extends an existing pattern — No new architecture; just the next step of the work #64308 already started with color tokens.
  • Low risk — CSS-only change, additive, no functional impact. Existing styles unchanged.

Implementation notes

The wp-base-styles handle is already loaded on admin pages (from #64308's sub-tickets). This change would extend that stylesheet's contents to include the additional custom properties listed above, likely sourced from the same _tokens.scss during the Sass build.

An optional follow-up could also migrate existing hardcoded token usage inside Core admin CSS to reference these custom properties, but that's not required for this ticket — exposing the values is sufficient to unlock plugin alignment.

Prior art

Alternatives considered

Core could instead publish admin tokens via an NPM package similar to @wordpress/base-styles. That approach works well for plugins with modern build pipelines, but doesn't help plugins without one, and can't respond to runtime preferences like the user's admin color scheme. A CSS custom property approach (like the existing --wp-admin-theme-color) complements the NPM package route rather than replacing it.

I've been doing plugin-side alignment work for WooCommerce (see woocommerce/woocommerce#64196 for a recent example) and ran into this friction directly. To be clear, I'm not waiting on this to ship the plugin-side work — WooCommerce is already adopting the existing --wp-admin-theme-color pattern with hardcoded fallbacks where Core tokens aren't exposed. This ticket is about making the next round of that work more systemic.

Change History (2)

#1 follow-up: @jameskoster
5 weeks ago

Closely related: Is there any way to extract and use the design tokens (https://github.com/WordPress/gutenberg/blob/trunk/packages/theme/src/prebuilt/css/design-tokens.css) from Gutenberg's Theme Package, rather than duplicating?

#2 in reply to: ↑ 1 @jillq
5 weeks ago

Replying to jameskoster:

Closely related: Is there any way to extract and use the design tokens (https://github.com/WordPress/gutenberg/blob/trunk/packages/theme/src/prebuilt/css/design-tokens.css) from Gutenberg's Theme Package, rather than duplicating?

Claude says yes because the tokens are twins with slight differences only in naming, not in visuals. Haha. I'm assuming -- as long as we are committed to keeping Gutenberg + wp-admin aligned (which I am also assuming we are?) then it works!

Note: See TracTickets for help on using tickets.