Skip to content

Color

Components read color roles, not colors: primary, surface-container, on-surface and the rest. A scheme assigns every role a color for light and dark, either the baseline scheme or one generated from your seed color.

Build a scheme

Pick a seed color and a scheme variant. Material Color Utilities 0.4.0 derives tonal palettes from it and maps every role, for the contrast level and color spec you choose. The swatches and the CSS below update together; the CSS is what createTheme returns for those options, scoped to a selector. Use on this site applies the theme to every page, components included.

The theme builder runs with JavaScript. The same output comes from createTheme (below) or the m3e-theme CLI in the theming guide.

Dynamic color

  • Variants: tonalSpot (default), expressive, vibrant, neutral, monochrome, fidelity, content, rainbow and fruitSalad. Each is a DynamicScheme of Material Color Utilities that moves the roles' hue and chroma differently from the seed; expressive is deliberately detached from it.
  • Contrast: from −1 to 1, where 0 is standard; the presets are standard (0), medium (0.5) and high (1). Color spec 2025 treats negative contrast as standard.
  • Color spec: 2025 is the default (DECISIONS D3) and adds the -dim roles; 2021 stays selectable. Material Color Utilities itself still defaults to 2021, so createTheme always passes the version explicitly.
  • Dark mode: mode: 'system' writes both schemes and follows prefers-color-scheme; data-theme="light" or "dark" on an ancestor forces one.
import { createTheme } from '@kyralabs/m3exp-web/theme';

const { cssText } = createTheme({ seed: '#6750a4', variant: 'expressive', contrast: 'medium' });
document.head.append(Object.assign(document.createElement('style'), { textContent: cssText }));

Roles of the baseline scheme

Without a seed theme the components use the baseline scheme in @kyralabs/m3e-tokens/theme.css: Compose's expressive light scheme (its on-*-container roles are tone 30, not 10) and the dark scheme. Each role is a custom property, --m3e-sys-color-<role>. The swatches show the current theme of this site; the values are the baseline's.

Primary

Role Now Baseline light Baseline dark
--m3e-sys-color-inverse-primary #d0bcff #6750a4
--m3e-sys-color-on-primary #ffffff #381e72
--m3e-sys-color-on-primary-container #4f378b #eaddff
--m3e-sys-color-on-primary-fixed #21005d #21005d
--m3e-sys-color-on-primary-fixed-variant #4f378b #4f378b
--m3e-sys-color-primary #6750a4 #d0bcff
--m3e-sys-color-primary-container #eaddff #4f378b
--m3e-sys-color-primary-fixed #eaddff #eaddff
--m3e-sys-color-primary-fixed-dim #d0bcff #d0bcff

Secondary

Role Now Baseline light Baseline dark
--m3e-sys-color-on-secondary #ffffff #332d41
--m3e-sys-color-on-secondary-container #4a4458 #e8def8
--m3e-sys-color-on-secondary-fixed #1d192b #1d192b
--m3e-sys-color-on-secondary-fixed-variant #4a4458 #4a4458
--m3e-sys-color-secondary #625b71 #ccc2dc
--m3e-sys-color-secondary-container #e8def8 #4a4458
--m3e-sys-color-secondary-fixed #e8def8 #e8def8
--m3e-sys-color-secondary-fixed-dim #ccc2dc #ccc2dc

Tertiary

Role Now Baseline light Baseline dark
--m3e-sys-color-on-tertiary #ffffff #492532
--m3e-sys-color-on-tertiary-container #633b48 #ffd8e4
--m3e-sys-color-on-tertiary-fixed #31111d #31111d
--m3e-sys-color-on-tertiary-fixed-variant #633b48 #633b48
--m3e-sys-color-tertiary #7d5260 #efb8c8
--m3e-sys-color-tertiary-container #ffd8e4 #633b48
--m3e-sys-color-tertiary-fixed #ffd8e4 #ffd8e4
--m3e-sys-color-tertiary-fixed-dim #efb8c8 #efb8c8

Error

Role Now Baseline light Baseline dark
--m3e-sys-color-error #b3261e #f2b8b5
--m3e-sys-color-error-container #f9dedc #8c1d18
--m3e-sys-color-on-error #ffffff #601410
--m3e-sys-color-on-error-container #8c1d18 #f9dedc

Surface and background

Role Now Baseline light Baseline dark
--m3e-sys-color-background #fef7ff #141218
--m3e-sys-color-inverse-on-surface #f5eff7 #322f35
--m3e-sys-color-inverse-surface #322f35 #e6e0e9
--m3e-sys-color-on-background #1d1b20 #e6e0e9
--m3e-sys-color-on-surface #1d1b20 #e6e0e9
--m3e-sys-color-on-surface-variant #49454f #cac4d0
--m3e-sys-color-surface #fef7ff #141218
--m3e-sys-color-surface-bright #fef7ff #3b383e
--m3e-sys-color-surface-container #f3edf7 #211f26
--m3e-sys-color-surface-container-high #ece6f0 #2b2930
--m3e-sys-color-surface-container-highest #e6e0e9 #36343b
--m3e-sys-color-surface-container-low #f7f2fa #1d1b20
--m3e-sys-color-surface-container-lowest #ffffff #0f0d13
--m3e-sys-color-surface-dim #ded8e1 #141218
--m3e-sys-color-surface-tint #6750a4 #d0bcff
--m3e-sys-color-surface-variant #e7e0ec #49454f

Other

Role Now Baseline light Baseline dark
--m3e-sys-color-outline #79747e #938f99
--m3e-sys-color-outline-variant #cac4d0 #49454f
--m3e-sys-color-scrim #000000 #000000
--m3e-sys-color-shadow #000000 #000000

Sources

  • Roles, variants, contrast and spec versions: @material/material-color-utilities 0.4.0 (dynamiccolor/, scheme/; FOUNDATIONS_SPEC §1).
  • Baseline scheme: Compose ColorLightTokens, ColorDarkTokens, PaletteTokens and expressiveLightColorScheme() (ColorScheme.kt L1172–1179) at the pinned commit, generated by m3e-codegen.