Primitive tokens

Loom Base's primitive palette and scales (311 values in packages/base/tokens/primitive.tokens.json): the only place a hex or pixel value is written.

Token · stable · v1.0.0 · owner: Site system lead · contract 18 of 20 points (open: usage, no owned-class occurrences in built pages or metadata-token references in built CSS; application declarations and executed coverage are separate; figma)

Reference

Source reference; not an executed check.

primitives
311

Do and don't

2 positive / 2 negative authored documentation examples (2 each required); 1 reference (1 required); 0 failed. References and failures do not count; this is not behavior acceptance.

Do: The heading consumes a semantic type role

Authored by tokens.ts

Rendered consumer example; not an executed correctness check. heading Isolated document follows the browser's colour and contrast preferences. The outer theme toolbar does not control this document.

Open example: Primitive tokens · Do: The heading consumes a semantic type role Use the full-page example to follow page links.

The actual native heading reaches source values through its existing semantic typography. The separate primitive specimen remains a count-only inventory, not a rendered list of every value.

Do: Change source values at their authority

Authored by tokens.ts

Rule illustration; not an executed check. tokens-primitive / tokens.primitive-only-in-base

A primitive-value proposal targets packages/base/tokens/primitive.tokens.json.
Dependent semantic roles and component outputs must be regenerated and checked before use; the count specimen supplies no consumer acceptance.
This positive rule illustration names the existing authority and downstream obligation without inventing a token, editing the source or claiming a check passed.

Don't: A component alias skips its semantic role

Authored by tokens.ts

Rule illustration; not an executed check. tokens-component / tokens.component-from-semantic

Proposed misuse, not applied: assign --button-background-ink directly from color.palette.dye-indigo.800 in packages/base/tokens/primitive.tokens.json.
The actual button binding in apps/showcase/site/brand/component-bindings.json assigns that alias from --ink. This illustration is a source-mapping proposal, not exported CSS syntax.
The existing component alias must keep its semantic dependency. A direct primitive assignment would violate the linked component-from-semantic rule; the illustration claims neither a new real binding nor an executed rejection.

Don't: A local raw value forks the primitive source

Authored by tokens.ts

Rule illustration; not an executed check. tokens-primitive / tokens.primitive-only-in-base

.local-heading { color: #1e2a78; }
The element copies the source colour instead of depending on its semantic role.
Copying the current primitive bytes into an element would silently fork its authority and future updates.

Rules

RuleWhyCheck
Hex and pixel values exist only in Base primitives.One source of truth for values (D-SITE-014).Automated: tests/unit/site-component-bindings.test.ts; tests/unit/site-identity.test.ts

API

No props.

Contract details

The full contract: identity, anatomy, variants, states, tokens, layout, motion, accessibility, content, tests

Identity

AspectValue
Idtokens-primitive
LayerTokens
Categorytokens
OwnerSite system lead
Statusstable
Version1.0.0
Sourceapps/showcase/site/system/tokens/tokens.ts (private repository; the contract and the render function are this one module)
VersionDateChange
1.0.02026-10-26Primitive tokens as one module: its markup moved out of the page builder (scripts/site) into the system.

Use when

  • Referenced by semantic tokens only. Why: Elements never read a primitive directly; meaning lives one level up.

Do not use when

  • In element CSS. Why: A primitive in element CSS skips the meaning layer.

Anatomy

PartWhat it is
sourcepackages/base/tokens/primitive.tokens.json (MIT, Loom Base)

Made of: nothing (a base element).

Used in: tokens-semantic.

Variants

VariantWhenWhy
light and darkEvery page, following the reader's setting.The same roles resolve to light or dark values, so no element chooses its own.

States

StateRendered or not applicable
defaultThe specimen.
hoverNot applicable: A foundation is not interactive.
focus-visibleNot applicable: Not focusable.
activeNot applicable: Not interactive.
disabledNot applicable: Nothing to disable.
loadingNot applicable: Values are built into the stylesheet.
emptyNot applicable: The build fails if a value is missing.
errorNot applicable: Unresolved values fail the brand gate, not the reader.
currentNot applicable: No current item.
visitedNot applicable: Not a link.
expandedNot applicable: Does not open.

Tokens

PartToken
color.palette.dye-indigo.800#1e2a78
color.palette.greige.900#17140f
color.palette.greige.25#f3eee3

Layout

AspectValue
breakpointsRequired review at 390, 768, 1024 and 1440 px; execution is not implied by this declaration; columns stack under 768 px; the wrap keeps a 16 px gutter on phones.
wrappingText wraps; nothing scrolls sideways.
textExpansionJapanese runs 20 to 40% longer; headings break between phrases (jaBreaks) and blocks grow downwards.

Spacing and rhythm

AspectValue
internalNot applicable: a foundation has no box of its own.
externalNot applicable.
rhythmApplies to every element that reads it.

Motion

AspectValue
NoneA foundation does not move.

Runtime and reuse

  1. Render-only element; mount any registered child enhancements separately. Preserve required Site CSS, fonts, responsive and locale rules from nativeElement.

Accessibility passport

AspectValue
roleNot rendered on the site; its specimen in the Library is a list
nameThe foundation's name
keyboardNot interactive.
focusNot focusable.
screenReaderThe specimen is a plain list of names and values.
contrastEvery text and ground pair in the palette is checked (check-brand).
targetNot a target.

Content

SlotLengthVoice
specimen: primitive count (read-only)One primitives/count row derived from primitive.tokens.json; individual names and values are source and contract references, not rows in this specimen.Describe the count as source inventory, not semantic-use or consumer verification.

Good: “Read the primitive count in the specimen; inspect packages/base/tokens/primitive.tokens.json and the contract's token references for individual names and values.”

Bad: “Treat the count-only specimen as a complete rendered list of primitive names and values.” · “Set an element's text to a primitive directly instead of using a semantic role.”

Japanese: The specimen's fixed primitives label and numeric count have no localized text input. Translate documentation explanations; preserve source paths and contract token identifiers unchanged.

Icons and illustrations

None: this element uses no icon or illustration of its own.

Decisions and exceptions

Usage

0 owned-class occurrences in built pages plus metadata-token references in built CSS (measured by npm run site:system).

Application and coverage

Indirect token chain (declared): Base primitives feed semantic.tokens.json and mode overlays. brand.ts maps --ink to color.text.default; brand-tokens.ts resolves its source chain in colourSources. component-bindings.json binds --button-background-ink to --ink, read by native button CSS. Elements consume semantic/component roles; the count-only specimen and zero direct primitive CSS occurrences do not establish unused primitives or complete chain coverage.

Current check result: not assessed by this report. Declarations and source-file presence do not establish executed enforcement or accepted coverage.

Source authority and implementation (paths in the private checkout):

  • packages/base/tokens/primitive.tokens.json
  • packages/base/tokens/semantic.tokens.json
  • apps/showcase/site/brand/brand.ts
  • scripts/site/brand-tokens.ts
  • apps/showcase/site/brand/component-bindings.json
  • apps/showcase/site/system/styles/core/button.css
  • scripts/site/system/component-bindings.ts
  • scripts/site/check-brand.ts

Declared rules and checks (not execution results):

  • tokens.primitive-only-in-base: Hex and pixel values exist only in Base primitives. Automated check declared: tests/unit/site-component-bindings.test.ts; tests/unit/site-identity.test.ts

Coverage still needed (not assessed here):

  • Retain current token freshness, selector/state binding and CSS-bypass results, including tests/unit/site-component-bindings.test.ts and tests/unit/site-identity.test.ts; trace exact source-to-semantic-to-component-to-CSS paths/modes using existing compiler provenance.
  • Inventory count is not consumption proof: unused individual primitives and complete all-token/mode coverage need explicit disposition and attributable consumer results.

Tests

AspectValue
unittests/unit/site-system.test.ts: renders every do and don't example through the registry and checks the classes it owns
visualNot yet: there are no screenshot baselines; the Library page is checked for sideways scroll at 1440 px by tests/site/system.spec.ts
a11ytests/site/system.spec.ts: axe (0 serious or critical) on the element's Library page in light and dark
parityscripts/site/system/check.ts: Library examples are rendered by the same render function the site imports

Figma

not-yet: The Loom Site Figma library is the last stage of the plan; this element is not mapped yet.

Open in Storybook

Start with a conversation about your system.

We read your system, show you what we found, and agree with your team what to fix first.