@cssints/mise-en-mode

The look layer of Mise en Mode for cssints: a look is a theme set on a data-mode scope, and looks from three sources are resolved by the Mode Contract. It is one call member of cssints/plugin scope() (positional arguments $tokens and $overrides, returning themes), so a look is checked against your token set, and check.contrast sees it. No runtime.

import { createTokens } from "cssints" with { type: "cssints" };
import { look } from "@cssints/mise-en-mode" with { type: "cssints" };

const t = createTokens({
  color: { $type: "color", bg: { $value: "#ffffff" }, fg: { $value: "#111111" } },
});

// look(tokens, expression, source, overrides, { scope? })
look(t, "dark", "app", { color: { bg: "#0b0b0f", fg: "#f3f4f6" } });
look(t, "dark", "viewer", { color: { bg: "#101018" } });
look(t, "hero", "author", { color: { bg: "#123456" } }, { scope: "article.post" });
@layer app, author, viewer;
@layer app {
  :where([data-mode="dark"], [data-mode~="dark/color"]) {
    --color-bg: #0b0b0f;
    --color-fg: #f3f4f6;
  }
}
@layer viewer {
  :where([data-mode="dark"], [data-mode~="dark/color"]) {
    --color-bg: #101018;
  }
}
@layer author {
  @scope (article.post) {
    :where([data-mode="hero"], [data-mode~="hero/color"]) {
      --color-bg: #123456;
    }
  }
}

The contract, as the package does it

A look prints no class: call it at a module's top level, like createGlobalTheme. Its types are inferred from the scope() definition in src/index.ts: there is no types file.

Changed from cssints/mise-en-mode, which this package replaces: look(expression, source, declarations, { scope }) took raw custom-property declarations ("--color-bg": "#000") that nothing checked; it is now look(tokens, expression, source, overrides, { scope }) with the token set first and the overrides by token path, so the declarations are checked, the aliases are re-derived and contrast sees them. Aspects are the groups of the tokens, no longer a table of --color- and --typography- prefixes, and a look emits themes, no longer globals.

cd packages/mise-en-mode && bun run test   # fixtures through the engine (output, errors, contrast), and the type test via bun run typecheck

Credits

Mise en Mode is an open style standard on AT Protocol (https://standard.mode.place), and the Mode Contract is its rules: data-mode scopes, the layers app < author < viewer, aspects. This package is an implementation of the contract on scope(); no code of the standard's site is copied.