@manakind/manuia-tokens
v0.21.0
Published
Manuia's design tokens. Values live as DTCG-format JSON under `src/`, organized into three explicit layers, and are compiled to CSS and JS by Style Dictionary on every build.
Readme
@manakind/manuia-tokens
Manuia's design tokens. Values live as DTCG-format JSON under src/,
organized into three explicit layers, and are compiled to CSS and JS by
Style Dictionary on every build.
Layers
| Layer | Path | Rule |
|---|---|---|
| Primitives | src/primitives/ | Raw values only. Hue-named color families (olive, sage, teal, amber, red, neutral), numeric spacing/size scales, etc. No UI meaning. |
| Semantic | src/semantic/ | Role tokens that alias primitives (semantic.color.action.primary → {primitives.color.olive.500}). Never contains literal values. |
| Component | src/component/ | Per-component anatomy that aliases semantic. May alias primitives directly only when no semantic role exists yet (e.g. button padding). Never contains literal values. |
The check:tokens script enforces the alias rule:
bun run check:tokensBuild outputs
bun run --filter @manakind/manuia-tokens build writes to build/:
css/primitives.css—--primitives-*css/semantic.css—--semantic-*css/components.css—--component-*css/theme.css—--ds-*(the contract; see below)js/tokens.ts— flat object for runtime access (e.g. React Native)
The build outputs are committed so CI can detect drift.
The --ds-* contract
build/css/theme.css is the product-agnostic API the shared
@manakind/ui-core components consume. It is generated from
packages/ds-config/contract/components.json by resolving the contract's
{component.…} references against this product's component/ files.
Every product publishes a theme.css with the same variable names but
different values, so a Manuia button and a ShipTight button look different
without sharing a single line of styling code.
Recipe for a Manuia consumer
import '@manakind/manuia-tokens/css/primitives';
import '@manakind/manuia-tokens/css/semantic';
import '@manakind/manuia-tokens/css/components';
import '@manakind/manuia-tokens/css/theme';
// Dark theme. Emitted under `:root.dark, :root[data-theme='dark']`, so these
// are inert until you set the class or attribute — import them even if dark
// ships later, or switching it on silently does nothing. All three are needed:
// `manuia-ui` reads --semantic-* and --component-* directly, not only --ds-*.
import '@manakind/manuia-tokens/css/semantic-dark';
import '@manakind/manuia-tokens/css/components-dark';
import '@manakind/manuia-tokens/css/theme-dark';Loading theme.css is what makes @manakind/ui-core (or @manakind/manuia-ui's
re-exported components) render in Manuia's visual style. Loading the lower
layers is only necessary if product code consumes tokens directly.
JS entry points
Two non-CSS subpaths, for the surfaces that cannot use custom properties.
| Entry | Contents |
|---|---|
| @manakind/manuia-tokens/js | Flat object of every token, keyed by its flattened name ('primitives-color-olive-500'). For code that needs a value at runtime |
| @manakind/manuia-tokens/native | The typed React Native theme — the --ds-* contract as a nested JS object (theme.button.primary.bgHover) |
import { themes } from '@manakind/manuia-tokens/native';
// themes.light / themes.dark — there is no default export./native has exactly one legitimate importer: <ManuiaThemeProvider> in
@manakind/manuia-ui-native. Native base components read the theme through
useTheme(), never by importing a product's tokens — a direct import binds the
shared library to one product, which is the thing the contract exists to
prevent. See
Architecture conventions.
