How primitive and semantic tokens relate, how a semantic token's name reads, and how the color tokens use both.
Tokens are the named design decisions Pluma components are built from. They come in three layers. Primitives name raw values, semantic tokens name what a value is for, and the rare component token covers a single component. This page covers the layers and how a semantic token's name reads, using color as the example. Full token lists are available on Color tokens and All tokens.
Each layer builds on the one below it. Primitives hold the raw values, semantic tokens point at primitives or mix them, and component tokens build on semantic tokens. A component that reads a semantic token follows it when a theme gives that token a different value.
Primitive
Primitives are raw values named for their place on a scale, with no indication of where they're used. In color, the primitives are the palette.
Semantic
Semantic tokens are named for a purpose. Most point at a primitive, and a few, such as the overlays, mix primitives into a recipe. Each theme can give them different values. In color, the semantic layer is color.*.
Component
Component tokens are a last resort for a value specific to one component that no semantic token fits. They're rare, and when one is needed, it's built on semantic tokens rather than on primitives.
The chain below follows one semantic token, color.scope.critical.text, from the primitive each theme points it at to the component that paints from it.
Primitive
Semantic
Component
Semantic token names read from general to specific, with one part per dot. The first part is the category, the second is the group, and the rest say what the token is for. Groups divide a category by purpose, and color has six of them.
color.surface.*
The neutral planes the UI is built from, including base, content, block, floating, recessed, inverse, and the track channel. A surface is a background by definition.
8 tokens per theme
color.text.*
The neutral text roles, which are primary, secondary, disabled, inverse (on the inverse plane), and code.
5 tokens per theme
color.mark.*
The neutral icons, which are primary, secondary, and disabled.
3 tokens per theme
color.scope.*
A hue or a semantic name with everything that belongs to it, from text, border, and mark on the surface to the solid and subtle rungs. Also includes the control and focus scopes.
293 tokens per theme
color.overlay.*
The translucent layers, including a resting tint, hover, pressed, the backdrop behind floating content, and the inverse plane's own tint, hover, and pressed.
7 tokens per theme
color.ai.*
The AI gradient, made of two radial fill stops and the surface they mix toward, three conic ring stops, and the ring's fade and gap.
8 tokens per theme
Surfaces are backgrounds by definition, so a surface.<plane> name carries no slot and color.surface.content is the background color itself. The text and mark groups hold the neutral inks, with text.<role> for words and mark.<role> for glyphs.
Scope names follow the pattern scope.<name>[.solid|.subtle].<slot> and read as a sentence.
Read that way, color.scope.critical.subtle.bg is the critical scope's subtle background, and the text on it is color.scope.critical.subtle.text. In a theme that mixes the background, it's mixed from color.scope.critical.subtle.bgMix. With no rung, color.scope.critical.text is critical text directly on a surface.
In code, each token is available as an id (color-scope-critical-subtle-bg), a themeVars key, and a CSS custom property. Color tokens lists every color token by id and themeVars key.
Color puts the layers into practice, with a palette of primitives and a semantic layer that components paint from. The sections below start with the palette, then follow the semantic groups from surfaces to scopes, and end with how interaction states are built.
The palette is the set of color primitives. It has 17 hue families sharing one 13-step lightness scale, plus white and black. Gray adds half steps (75, 925, and 975) for the surface planes. Verdant is the brand green and is separate from success, which uses green.
A swatch shows its OKLCH and hex values on hover or focus and copies its CSS custom property on click.
Components paint from the semantic layer, so the palette is read directly only by the data visualization tokens, CodeBlock's forced code themes, and the literal white and black (palette.white and palette.black).
Each step marks an intended position in its ramp, so the same step reads at a similar strength across families.
Surfaces and boundaries
Foregrounds and icons
Strong foregrounds, fills, and dark surfaces
Surfaces are the neutral background planes used to build a screen, from the page itself to content floating above it. Anything with a hue is a scope, not a surface.
color.surface.baseThe page behind everything.
color.surface.contentThe main content area, and Modal and Drawer, which are content brought forward.
color.surface.blockA contained region inside the content area, such as a panel or card.
color.surface.recessedA sunken region inside the content area, such as a drop zone or a well that holds examples.
color.surface.floatingContent floating above the page, such as popovers, selects, dropdown menus, and tooltips.
color.surface.inverseA high-contrast plane of the opposite polarity, for tooltips and compact chrome.
color.surface.inverse-raisedA step off the inverse plane, such as the key cap inside a Tooltip.
color.surface.trackA neutral channel with no text of its own, used for skeletons, progress and slider tracks, and the off toggle track.
Text and mark tokens are the neutral inks used for words, icons, and dots. There's no role bolder than primary, so emphasis comes from font weight instead.
color.text.primaryBody text on any surface and on any subtle scope.
color.text.secondaryDe-emphasized text, such as helper text, placeholders, group headers, footers, and muted values.
color.text.disabledText that describes a disabled control.
color.text.codeInline code.
color.text.inverseText on the inverse plane.
color.mark.primaryA neutral icon at full strength.
color.mark.secondaryA de-emphasized neutral icon, such as a field affordance, a chevron, or a decorative glyph.
color.mark.disabledAn icon or dot that describes a disabled control.
Scopes are sets of colors that hold everything a component needs to paint in one hue or semantic name. Each scope has three rungs, and the explorer below shows them for every scope in the active theme.
On the surface
Colored text, border, and mark with no background of their own.
Solid
A saturated background with its text and mark.
Subtle
A tinted background with its text, border, and mark.
Subtle backgrounds are authored per theme and read through fillScope. For more information, see Fill in Interaction states.
Semantic names are scope names that describe a meaning rather than a hue. Components take the name, and the name picks the hue.
neutralgrayThe default, with no particular meaning.
solidsubtletextaccenttealThe brand color for indicators, such as a selected tab, a focused field, or a progress bar.
solidsubtletextactiontealInteractive controls and links, such as the primary Button.
solidsubtletextinformationblueHelpful context or a neutral notice.
solidsubtletextsuccessgreenA completed or healthy outcome.
solidsubtletextcautionyellowSomething that needs attention but is not an error.
solidsubtletextcriticalredAn error, a failure, or a blocking problem.
solidsubtletextdestructiveredControls whose action deletes or cannot be undone.
solidsubtletextfeaturevioletA highlighted feature, such as something new.
solidsubtletextNeutral edges are the three border weights used for neutral lines, each named for what it draws. Form controls take their face and edge from color.scope.control, and the focus ring uses color.scope.focus.border.
Quiet edge
color. scope. neutral. subtle. borderThe hairline that closes something with a face of its own, such as a panel, card, popover, menu, divider, field, or the table grid.
Structural stroke
color. scope. neutral. borderA line with nothing behind it, such as an outline Badge, a Coin ring, or a connector.
Control edge
color. scope. control. borderThe outline of a checkbox or radio, where the edge is the whole shape.
There's no hover or pressed version of each color token, and selected and disabled have no color of their own. Each state is built from the color an element already has, in one of three ways.
Transparent elements
A translucent layer is painted over whatever sits behind the element, such as a table row or menu item. The layer mixes the overlay color, near-black in light and near-white in dark, into transparent at an amount each theme sets.
Opaque colors
A solid fill shifts its own OKLCH lightness instead of mixing, and text and borders take a larger step on hover. Light themes step darker and dark themes step lighter.
Disabled controls
The whole control dims to a lower opacity and keeps its colors.
The overlay layer is built with color-mix(in oklab, <overlay color> <percentage>%, transparent).
A selected item is marked by weight, or by the pressed layer where it keeps a background. For more information, see Interaction states.
Spacing, typography, elevation, motion, and AI surfaces each have their own token page.