Theme Slots

This page lists every slot: each part of a screen a theme can recolor, and the mixin that sets it. A slot takes a framework token, not a raw color, so whatever you map still renders correctly on every device.

#

Semantic Channels

Start with the semantic channels: a few lines recolor the whole screen, because every component reads them. The set is fixed:

  • semantic-bg($semantic, $token): sets a background channel to a token.
  • semantic-text($semantic, $token): sets a text channel to a token, with everything text needs (color, dither pattern, clipping).
  • semantic-stroke($semantic, $token): sets the stroke channel to a token.
  • semantic-border($semantic, $token): sets a border channel to a token's fill.
  • semantic-icon($token): optional color for adaptive icons; omit it and icons follow text-primary.

Every semantic mixin takes $raw: true, which writes a plain color and skips device rendering; a theme never needs it. See Authoring Themes .

@include theme-slots.semantic-bg("canvas", "yellow");
@include theme-slots.semantic-bg("surface", "yellow");
@include theme-slots.semantic-text("text-primary", "black");
@include theme-slots.semantic-text("text-secondary", "yellow-30");
@include theme-slots.semantic-stroke("stroke-contrast", "yellow");
@include theme-slots.semantic-border("border-muted", "yellow-30");
#

Component Slots

Component slots recolor one surface, like the title bar, without moving a whole channel. Each slot is named after the part it colors and takes one kind of paint. These are the slots components read today:

  • Background slots: screen-backdrop, title-bar, item-meta, item-meta-emphasis-2, item-meta-emphasis-3, progress-track, progress-fill, progress-fill-emphasis-2, progress-fill-emphasis-3, progress-dot, progress-dot-current, table-meta, table-meta-device, chip
  • Text slots: label-gray, chip
  • Border slots: table-head-row, table-body-row, label-underline

chip is two slots for one surface: a solid box with readable text on it, for markers the framework has no component for. Its defaults point at the semantic channels (box from fill-strong, text from text-inverse), so it follows the theme on its own. Set both halves yourself when the box needs a specific pairing, the way White and Red gives it a white box with red text.

Using the wrong mixin on a slot fails silently. Give a background slot text-slot and it writes variables no component reads; nothing on the screen changes.

  • bg-slot($slot, $token): a slot's background paint.
  • text-slot($slot, $token): a slot's text paint, dither pattern and clipping included.
  • border-level-slot($slot, $level, $dir: h): sets a slot's border to one of the framework border levels.
  • border-token-slot($slot, $token, $dir: h): sets a slot's border to a token's fill instead of a level.

Slot values cascade down from the screen, so you can set them again on a component or a state wrapper. On an unthemed screen, inverse flips its subtree to the opposite scheme. On a themed screen the subtree keeps the theme's slots; the theme itself restates the slots that should flip, as in the example below.

@include theme-slots.bg-slot("title-bar", "yellow-40");
@include theme-slots.bg-slot("progress-fill", "yellow-55");
@include theme-slots.text-slot("label-gray", "yellow-30");
@include theme-slots.border-token-slot("label-underline", "yellow-30");

.screen--theme-example .inverse {
    @include theme-slots.bg-slot("progress-fill", "yellow-20");
}
#

Utility Remaps

Utility remaps recolor the raw palette utilities (bg--*, text--*, text-stroke--*), so markup that says bg--gray-50 follows the theme without edits.

  • utility-remap-grayscale($to-hue, $side): the bulk remap, moving the whole grayscale ladder to a hue; $side controls how.
  • utility-remap-border-grayscale($to-hue, $side): the same remap for border lines: their two inks recolor, their patterns keep their shape.
  • utility-bg($token, $remap-to) / utility-text($token, $remap-to) / utility-stroke($token, $remap-to): remap one utility token, for exceptions on top of a bulk remap.
  • utility-border-token($level, $dir, $token): remap one border level and direction to a token's paint.
  • utility-border-level($level, $dir, $from-level): swap one border level for another level's line art, colors and rendering included. The 2-bit borders need this mixin: their four tones are drawn into the line itself, where no token remap can reach them. Restating a level onto itself is not a no-op: it also pins the two ink colors the level's line draws with.

The $side values: 'dark' (default) presses the grays into the hue's dark steps 10 to 40, keeps black as ink, and sends white to the hue. 'bright' presses them into steps 45 to 75, sends black to the hue, and keeps white. 'linear' maps gray steps to hue steps 1:1.

Strokes are the one exception: whichever token maps to the hue itself keeps a visible stroke, taken from the nearest hue step (45 under bright, 40 under dark, 75 under linear), so outlines never dissolve into the canvas.

Black and Yellow remaps to the dark side, and White and Red remaps to the bright side with one exception, utility-bg("white", "red"), so white surfaces turn red while white text stays ink. Dark flips the grayscale token by token with the single-token remaps, and uses utility-border-level for the 2-bit borders and for the one level that maps to itself.

// White and Red: bright-side remap with one exception.
@include theme-slots.utility-remap-grayscale("red", $side: "bright");
@include theme-slots.utility-remap-border-grayscale("red", $side: "bright");
@include theme-slots.utility-bg("white", "red");
#

Border Levels and Lines

Border levels are the seven steps the framework draws borders in: 1 is black, 2 through 6 step through the grays (gray-15, gray-30, gray-40, gray-50, gray-65), 7 is white, each with an h and a v direction. border-level-slot sets a component's border to a level; utility-border-token recolors a level itself, and utility-remap-border-grayscale recolors the two line inks in bulk. See Border and Divider for how levels render.

Every border slot and remap changes two things at once: the CSS line, and what TRMNLPaint.border() and TRMNLPaint.divider() hand to JavaScript. Bind a slot to a level and JavaScript gets that level's pattern. Bind it to a token and JavaScript gets a flat line in the token's stroke color, because only levels have patterns.

#

The Chart Ramp

chart-series-ramp($tokens, $span: 6) sets the colors charts pick their series from: list the tokens in order, strongest contrast against the background first, and series 0 gets the first one. Each entry keeps the token's own rendering, so series dither or paint solid per device. JavaScript spreads series across the first $span entries of the list.

A short list is safe. The ramp always has 16 entries; the ones past your last token are cleared instead of keeping the framework's default grays, and $span never reaches past your last token.

Charts read the ramp through TRMNLPaint.series(); see Painting Charts and Chart .

@include theme-slots.chart-series-ramp((
    black, yellow-10, yellow-20, yellow-30, yellow-40, yellow-55, yellow-75, yellow
));