Surface Contexts Proposal

A proposal for contextual surface tokens, token renames, and removing the on-color token.

Before & After

Current tokens use flat names that don't adapt to nesting depth. The proposed system resolves tokens contextually.

Current (flat tokens)
Page · bg-surface-inset
Card · bg-surface-default

Primary text on card

Nested card · bg-surface-default (same!)

No visual distinction from parent

Proposed (surface contexts)
Page · level 0 · surface.inset
Card · level 100 · surface.defaultPrimary text on card
Nested card · level 200 · shadow separatesSame surface color, shadow provides depth

Interactive Explorer

Toggle between context levels to see how the full palette resolves. Then see levels compose in the nesting demo.

Context level:
Surface
surface.inset
surface.default
surface.hover
surface.emphasized
Text & Icon
Aa
text.primary
Aa
text.secondary
icon.primary
icon.secondary
Interactive
surface.interactive.primary
surface.interactive.secondary
stroke.default
stroke.strong
Sample textMuted text
Nested context cascade
Level 0 · Page
Level 100 · Card
Inset area
Level 200 · Popover
Inset area
Level 300 · NestedStill readable, still distinct

Token Migration

Proposed renames and removals. Names use DTCG dot notation.

CurrentProposedNote
app.color.foreground.primaryapp.color.text.primaryClarifies usage for text only
app.color.foreground.secondaryapp.color.text.secondary
app.color.foreground.inverseapp.color.text.inverse
app.color.foreground.on-colorremovedReplaced by surface context — primary button establishes context where text.primary resolves to correct contrast value
app.color.interactive.primaryapp.color.surface.interactive.primaryMakes it clear this is a surface color, responds to context
app.color.interactive.primary-hoverapp.color.surface.interactive.primary-hover
app.color.interactive.secondaryapp.color.surface.interactive.secondarySecondary interactive surface adapts per context level
app.color.interactive.secondary-hoverapp.color.surface.interactive.secondary-hover
app.color.surface.defaultapp.color.surface.defaultName unchanged but value is now context-dependent
app.color.surface.insetapp.color.surface.insetName unchanged but value is now context-dependent
(new)app.color.surface.hoverExplicit hover surface — no more guessing offset tokens
(new)app.color.surface.emphasizedReplaces elevated/offset tokens with a single emphasized stop
Demos