Skip to content

About

@phcdevworks/spectre-tokens is the design-token foundation of the Spectre system. It provides the shared visual values and semantic contracts used across Spectre packages and PHCDevworks applications.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

2 stars

Watchers

1 watching

Forks

Latest commit

 

History

582 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@phcdevworks/spectre-tokens

@phcdevworks/spectre-tokens is the design-token foundation of the Spectre system. It provides the shared visual values and semantic contracts used across Spectre packages and PHCDevworks applications.

Maintained by PHCDevworks. It defines the visual language, semantic roles, and token contracts that downstream consumers can rely on without filling gaps with raw palette values or local token inventions. Downstream UI packages define structure; adapter packages translate Spectre contracts for specific frameworks and runtimes.

Repository Snapshot

Field Value
Project team project-design
Repository role Spectre L1 design-token contract
Package/artifact @phcdevworks/spectre-tokens
Current version/status 4.15.0

Standard Workflow

  1. Read AGENTS.md, then the agent-specific guide for the task.
  2. Check TODO.md and ROADMAP.md for current scope.
  3. Make the smallest repo-local change that satisfies the task.
  4. Run npm run check when validation is required or practical.
  5. Update docs and CHANGELOG.md only when behavior, public contracts, or release-relevant metadata changed.

Documentation Map

Guide Path
Agent rules AGENTS.md
Claude Code CLAUDE.md
Codex CODEX.md
Copilot COPILOT.md
Jules JULES.md
Grok GROK.md
Roadmap ROADMAP.md
Todo TODO.md
Token reference TOKEN_REFERENCE.md
Downstream parity DOWNSTREAM_PARITY.md
Changelog CHANGELOG.md
Security SECURITY.md

npm version CI License Node

@phcdevworks/spectre-tokens is the design-token package of the Spectre system. It provides a complete, UI-ready token surface for downstream Spectre packages and compatible applications.

Maintained by PHCDevworks, it defines the visual language, semantic roles, and token contracts that downstream consumers can rely on without filling gaps with raw palette values or local token inventions. Downstream UI packages define structure; adapter packages translate Spectre contracts for specific frameworks and runtimes.

Contributing | Code of Conduct | Changelog | Token Contract | Roadmap | Security Policy

Source Of Truth

tokens/ is the source of truth. contract.manifest.json is the machine-readable contract authority. Everything else is derived from them or validated against them.

Layer Path Rule
Source token data tokens/*.json All token value changes start here — never anywhere else
Contract authority contract.manifest.json Governs public namespaces and required output surfaces
Public entry points src/index.ts · src/types.ts · src/css.ts Contract-authority files — changes require changelog classification
Generated TypeScript src/generated/tokens.ts Never edit directly — regenerated by npm run build
Generated dist dist/ Never edit directly — regenerated by npm run build

After any source change: run npm run build to regenerate outputs, then npm run check to validate the full contract.

What This Package Owns

  • Visual language expressed as token data in tokens/
  • Semantic roles and token contracts consumed downstream
  • Generated token outputs for JavaScript, TypeScript, CSS variables, and DTCG
  • Theme and mode definitions used by downstream consumers

This package is the correct place to define token meaning.

What This Package Does Not Own

  • Component structure or composition. That belongs in downstream UI packages such as @phcdevworks/spectre-ui.
  • Framework-specific delivery. Adapter packages translate Spectre contracts for specific frameworks and runtimes.
  • Local redefinition of token meaning. Downstream consumers should consume these contracts rather than recreate them independently.
  • Example app architecture. The example/ directory documents token usage; it is not the contract source and should not become a downstream UI layer.

When To Use This Package

  • You are building a Spectre ecosystem package and need the visual language contract.
  • You need design token values in JavaScript, TypeScript, CSS variables, or DTCG format.
  • You want a single source of truth for semantic roles: surface, text, component, buttons, forms, modes.
  • You are consuming tokens as named values, not inventing new token meaning.

When Not To Use This Package

  • You need UI components or component structure — use @phcdevworks/spectre-ui.
  • You need framework-specific component delivery — use the appropriate adapter package.
  • You want to define your own token meaning or override Spectre semantics locally — this package is the authority; downstream consumers should consume, not redefine.

Installation

npm install @phcdevworks/spectre-tokens

Quick Start

CSS import

Import the generated CSS variables:

@import '@phcdevworks/spectre-tokens/index.css';

Token usage

Load the token object in JavaScript or TypeScript:

import tokens from '@phcdevworks/spectre-tokens'

const card = {
  background: tokens.surface.page,
  color: tokens.text.onPage.default,
  maxWidth: tokens.layout.container.maxWidthProse,
  padding: tokens.space['16'],
  borderRadius: tokens.radii.md
}

Semantic Tokens Vs Raw Palette Tokens

Semantic tokens express UI meaning. Raw palette tokens expose the fixed color ramp. Always prefer semantic tokens for UI surfaces, text, buttons, forms, and mode-aware styling.

Semantic namespaces (prefer for all UI work)

Namespace What it expresses
surface Background roles: page, card, input, overlay, subtle, hero (gradient, hero sections only), hover, selected, active, divider
text Foreground roles: default, muted, subtle, meta, on-surface, on-page
component Role-specific tokens for navigation, overlays, feedback, data display, loading, forms, cards, badges, and content patterns
buttons Button state tokens: default, hover, active, disabled, CTA
forms Form state tokens: default, focused, error, disabled
link Inline link color roles: default, hover, active, visited
modes Mode-aware overrides under modes.default, modes.dark, and modes.highContrast (plus a CSS-only light and system mode)
import tokens from '@phcdevworks/spectre-tokens'

// Semantic — always prefer this for UI
const card = {
  background: tokens.surface.card,
  color: tokens.text.onSurface.default
}

// Mode-aware semantic
const dark = {
  background: tokens.modes.dark.surface.page,
  color: tokens.modes.dark.text.onPage.default
}

Raw palette (use sparingly)

The colors namespace exposes the raw palette ramp. Use it only when fixed color access is intentional — data visualization, compatibility layers, or tooling that inspects palette data directly.

// Raw palette — only when fixed color access is deliberate
const chart = {
  series1: tokens.colors.brand[500],
  series2: tokens.colors.neutral[300]
}

Do not use colors as a substitute for semantic tokens in normal UI surfaces.

Consumer Usage

JavaScript and TypeScript tokens

Use the runtime token object when a consumer needs token values directly in code.

import tokens from '@phcdevworks/spectre-tokens'

const card = {
  background: tokens.surface.card,
  color: tokens.text.onSurface.default,
  borderColor: tokens.component.iconBox.border,
  maxWidth: tokens.layout.container.maxWidthProse,
  padding: tokens.space['16']
}

Use named exports when you need generated helpers:

import tokens, { generateCssVariables } from '@phcdevworks/spectre-tokens'

const css = generateCssVariables(tokens)

Generated CSS variables

Import index.css when a downstream package or app wants the generated Spectre CSS variable contract.

@import '@phcdevworks/spectre-tokens/index.css';

.card {
  background: var(--sp-surface-card);
  color: var(--sp-text-on-surface-default);
  max-width: var(--sp-layout-container-max-width-prose);
}

.app-shell {
  width: var(--sp-layout-sidebar-width);
}

h1 {
  font-family: var(--sp-heading-h1-family);
  font-size: var(--sp-heading-h1-size);
  line-height: var(--sp-heading-h1-line-height);
  font-weight: var(--sp-heading-h1-weight);
  letter-spacing: var(--sp-heading-h1-letter-spacing);
}

body {
  font-family: var(--sp-body-family);
  font-size: var(--sp-body-size);
  line-height: var(--sp-body-line-height);
  font-weight: var(--sp-body-weight);
  letter-spacing: var(--sp-body-letter-spacing);
}

.hero-title {
  font-size: var(--sp-display-1-size);
  line-height: var(--sp-display-1-line-height);
  font-weight: var(--sp-display-1-weight);
}

.intro {
  font-size: var(--sp-lead-size);
  line-height: var(--sp-lead-line-height);
}

input {
  background: var(--sp-form-default-bg);
  color: var(--sp-form-default-text);
}

The CSS entry point is intended for consumers that want the token contract as variables rather than reading values in JavaScript.

typography.heading.{h1..h6}, typography.body, typography.display.{1..6}, and typography.lead are semantic role tokens — each a complete { fontFamily, fontSize, lineHeight, fontWeight, letterSpacing } object referencing typography.scale.* and typography.families.* — so downstream consumers get a text-role contract instead of hand-picking a raw typography.scale step per heading level. Each role emits --sp-<role>-{family,size,line-height,weight,letter-spacing} (for example --sp-heading-h1-size, --sp-display-1-size, --sp-lead-size).

--sp-form-default-{bg,text,placeholder} are redeclared in the [data-spectre-theme="dark"] block from modes.dark.forms.default.*, so they follow the active mode. Other forms.* variables, including --sp-form-default-border, keep their :root value in every mode, except that high-contrast mode overrides forms.valid.* and forms.invalid.*.

Color modes apply wherever the attribute is set, not only on the root. data-spectre-theme="dark", "high-contrast", or "light" on any element switches every mode variable for that element and its descendants, so a section can differ from the page (light restores default values inside a dark ancestor). data-spectre-theme="system" follows the visitor's OS setting through prefers-color-scheme, with no script. A page with no attribute is light.

modes.highContrast is a third mode alongside default and dark. It is light-based, and every text pair in it meets WCAG AAA (7:1). Borders and dividers are darkened too. Set data-spectre-theme="high-contrast" on the root, or on a section, to apply it. Buttons and the valid/invalid form states don't change between light and dark, but high-contrast mode overrides them (modes.highContrast.buttons and .forms.{valid,invalid}), so those also meet 7:1.

Links change in every mode. modes.dark.link lightens default, hover, active, visited, and the underline colours so they meet 4.5:1 on dark pages and cards, and modes.highContrast.link raises them to 7:1. link.onInverse and link.onInverseHover are for surface.inverse, so they keep the same value in every mode.

control.{sm,md,lg} gives the shared height, inline padding, and icon size for buttons, inputs, and selects (--sp-control-md-height, --sp-control-md-padding-inline, --sp-control-md-icon-size), and control.compact.* is the denser set. Any element with data-spectre-density="compact" swaps the default sizes for the compact ones inside it. Every height except lg is below accessibility.minTouchTarget (44px), so on touch layouts give smaller controls a 44px hit area (for example with padding or a pseudo-element) rather than shrinking it to the visible height.

elevation.{flat,raised,overlay,modal} pairs a shadow with its surface and z-index, so consumers pick one level instead of combining raw steps. The --sp-elevation-* variables are var() references to the shadow, surface, and z-index variables, so the surface follows the active color mode.

component.chart is the data-visualization palette: eight categorical series colors that differ in lightness as well as hue and meet 3:1 against chart.bg, seven-step sequential and diverging ramps, and grid, axis, and label roles. component.selection, component.caret, component.scrollbar, component.skeleton, and component.prose.kbd cover text selection, caret, scrollbar, skeleton-loading, and keycap colors. All of them are set for every mode.

Type scales

There are three ways to set text size, from most to least opinionated:

  1. Text roles (--sp-heading-h1-*, --sp-display-1-*, --sp-body-*, --sp-lead-*): size, line height, weight, and letter-spacing for a specific job. Use these first. Large headings and display text resize with the viewport (see Responsive text roles).

  2. Size presets font.{xs…9xl} (--sp-font-lg-size, --sp-font-lg-line-height, --sp-font-lg-weight, --sp-font-lg-letter-spacing): a size together with the line height and weight that suit it. The sizes match Tailwind's scale:

    Step xs sm md lg xl 2xl 3xl 4xl 5xl 6xl 7xl 8xl 9xl
    px 12 14 16 18 20 24 30 36 48 60 72 96 128

    md is Tailwind's base.

  3. Plain sizes fontSize.{12…128} (--sp-font-size-18): one size with no line height or weight attached. Pair them with the scales below.

.price {
  font-size: var(--sp-font-size-18);
  line-height: var(--sp-leading-snug);
  font-weight: var(--sp-font-weight-semibold);
  letter-spacing: var(--sp-tracking-tight);
}

a {
  text-decoration-color: var(--sp-link-underline);
  text-decoration-thickness: var(--sp-text-decoration-thickness-thin);
  text-underline-offset: var(--sp-text-decoration-offset-md);
}
Scale Steps CSS variable
fontWeight normal 400, medium 500, semibold 600, bold 700, extrabold 800, black 900 --sp-font-weight-*
leading (line height, unitless) none 1, tight 1.25, snug 1.375, normal 1.5, relaxed 1.625, loose 2 --sp-leading-*
tracking (letter-spacing) tightest −0.075em through widest 0.1em --sp-tracking-*
textDecoration thickness.{thin,base,thick} (1/2/3px), offset.{sm,md,lg} (0.125/0.2/0.3em) --sp-text-decoration-*

Responsive text roles

Headings h1–h5 and display 1–3 are mobile first. The role's own value is the phone size, and typography.responsive.md.* holds the size from the md breakpoint (768px) up. In CSS, @media (min-width: 768px) re-points --sp-heading-*-size/-line-height and --sp-display-*-size/-line-height at --sp-typography-responsive-md-*, so consumers keep using one variable and need no breakpoint of their own.

Role Below 768px 768px and up
display.1 36px 72px
display.2 36px 60px
display.3 36px 48px
display.4–6 36 / 30 / 24px same
heading.h1 36px 60px
heading.h2 30px 48px
heading.h3 24px 36px
heading.h4 20px 30px
heading.h5 20px 24px
heading.h6 20px same

Weights and families do not change. Each size keeps the line height of its scale step.

Action colour

action is the theme's own action colour: the one a site uses for its main buttons, stat units, and quote rules. It defaults to brand.

Token CSS variable Default (light)
action.bg, bgHover, bgActive --sp-action-bg, -bg-hover, -bg-active brand 700, 800, 900
action.text --sp-action-text white
action.focusRing --sp-action-focus-ring brand 500 at 40%
action.onPage, onSurface --sp-action-on-page, -on-surface brand 700
action.rail --sp-action-rail brand 700

A theme sets the colour with an attribute on the root element, not by declaring --sp-*:

<html data-spectre-action="emerald">

The value is brand, accent, info, or any colors.palette family except yellow and integration-icy-blue, which miss a contrast minimum. Hover and active shades come from the same family. In dark mode the text and rail roles move to step 400, and high-contrast mode uses 800/900/900 fills and 900 text. check:contrast checks every selectable family against every pair.

The attribute works on <html> only. The role variables are resolved on the root, so putting it on a nested element has no effect. Colour modes still apply anywhere, and they pick up the root's family.

Accent rails

A rail is the coloured edge on a card, badge, quote, and similar components. Each component that has one carries the same contract under component.<name>.accent: one colour per tone (neutral, brand, info, success, warning, danger, cta, accent) plus a single thickness (0.25rem). The components are card, badge, testimonial, pricingCard, nav, footer, modal, toast, tooltip, dropdown, listGroup, and quote. footer.light has its own tone colours and uses footer's thickness. Every rail colour is mode-aware.

.card--brand {
  border-inline-start: var(--sp-component-card-accent-thickness) solid
    var(--sp-component-card-accent-brand);
}

.toast--danger {
  border-inline-start: var(--sp-toast-accent-thickness) solid
    var(--sp-toast-accent-danger);
}

card and input keep a legacy component- segment in their variable names. Every other component uses its own name, such as --sp-badge-accent-* or --sp-quote-accent-*. Which edge the rail sits on, and how it's drawn, is up to the downstream component.

Accent and inverse roles

colors.accent is the second brand colour. It has its own semantic roles, so consumers never reach for the raw palette:

  • text.onPage.accent and text.onSurface.accent (--sp-text-on-page-accent) are accent text that passes contrast on the page or a card.
  • text.onInverse.{default,muted,brand,accent} is text on dark (inverse) backgrounds, such as a dark hero or footer.
  • buttons.accent and buttons.accentOutline are filled and outlined accent buttons. Button variables join camelCase names without hyphens, for example --sp-button-accentoutline-bghover.
  • component.stepper.tone.{brand,accent}.{active,done} colours a stepper in either brand colour.
  • component.quote covers a quote's text, attribution name and role, an accent-coloured quotation mark, a plain border, and an accent rail (--sp-quote-*).

Footer

component.footer is its own contract, separate from navigation: bg, text, heading, muted, link, linkHover, border, divider, chipBg, and an accent rail (--sp-footer-*). It is dark by default. component.footer.light (--sp-footer-light-*) has the same roles for a light footer.

Extended palette

colors.palette holds the full extended colour ramps (red through stone, slate, zinc, the mauve/olive/mist/taupe neutrals, and the named brand and integration colours), emitted as --sp-color-palette-<name>-<step>. Like colors, it is raw palette: use it for data visualisation or a brand colour that has no semantic role, not for normal UI.

HTML element coverage

Spectre aims to style every standard HTML element from tokens alone. element-coverage.json maps all 115 elements in the HTML Living Standard's element index, and 14 styleable pseudo-elements, to the token paths that style them. Elements with no visual styling of their own (<div>, <meta>, <template>, …) are marked as such, with a reason. The check:elements step of npm run check fails if an element is unmapped or mapped to a path that doesn't exist. TOKEN_REFERENCE.md has the generated table.

Element roles include:

Element Variables
<del>, <ins>, <mark>, <kbd>, <code>, <pre>, <blockquote>, <hr> --sp-prose-*
<dt>, <dd> --sp-prose-dt-text, --sp-prose-dd-text
<figcaption>, <caption>, <tfoot> --sp-prose-figcaption-text, --sp-table-caption-text, --sp-table-footer-*
<meter> --sp-meter-track, --sp-meter-fill-{optimum,suboptimum,critical}
<option>, <optgroup> --sp-select-option-*, --sp-select-optgroup-label-text
::marker --sp-prose-marker, --sp-prose-marker-accent
::selection, ::spelling-error, ::grammar-error --sp-selection-*, --sp-proofing-{spelling,grammar}
Code highlighting --sp-code-syntax-{keyword,string,comment,function,…}
Article spacing --sp-layout-prose-flow-{paragraph,heading,list,…}

Token model

The generated token object includes these namespaces:

  • colors
  • space
  • layout
  • radii
  • typography
  • font
  • shadows
  • breakpoints
  • zIndex
  • transitions
  • animations
  • opacity
  • aspectRatios
  • icons
  • border
  • accessibility
  • buttons
  • forms
  • link
  • surface
  • text
  • component
  • modes
  • tracking
  • leading
  • textDecoration
  • fontWeight
  • fontSize
  • control
  • elevation
  • action

The exported runtime token object is a flattened string-based tree generated from tokens/. Source-only wrapper fields such as value and metadata are internal generation details and are not part of the public package contract.

See TOKEN_REFERENCE.md for the exhaustive, generated list of every token path, resolved value, and usage note.

Downstream packages building recipes on the CSS output should use DOWNSTREAM_PARITY.md, which groups every published --sp-* variable into the family a recipe or stylesheet consumes. Run npm run audit:parity (optionally -- <sibling-repo>) for a checklist of the families a checked-out downstream repo has not consumed yet, and npm run audit:downstream for a read-only report of raw --sp-* redeclarations, hardcoded visual values, and workaround comments across the downstream repos.

The layout namespace includes section, stack, and container spacing tokens, plus fixed layout width tokens for common consumer shells: layout.container.maxWidth, layout.container.maxWidthProse, layout.container.maxWidthWide, and layout.sidebar.width.

Layout spacing sits on one 8px grid; check:structure fails on any off-grid step. Section padding, section gap, stack gap, and container inline padding run sm | md | lg | xl | 2xl | 3xl | 4xl. sm–lg are fixed. xl–4xl are responsive: the base value applies on narrow viewports and layout.responsive.lg.* takes over at the lg breakpoint. In CSS, the @media (min-width: 1024px) block re-points --sp-layout-*-{xl..4xl} at --sp-layout-responsive-lg-*, so consumers keep using one variable name. layout.hero.paddingTop and layout.hero.paddingBottom (sm | md | lg) reference section padding steps, and their CSS variables are var() references that follow the responsive override.

Public Contract Guarantees

contract.manifest.json is the machine-readable contract authority for this package.

It defines:

  • public namespaces
  • required output surfaces for JavaScript, CSS, and DTCG
  • protected semantic groups

Every contract-facing surface in this repository must match that manifest. Validation fails fast on token overwrite across files, undocumented namespaces, output drift, and README mismatch with the contract authority.

Themes and modes

The package includes mode-aware semantic tokens under modes, with default and dark mode definitions in the generated output.

Use semantic mode-aware values when the consumer needs light/dark or mode-specific behavior without branching on raw palette values.

import tokens from '@phcdevworks/spectre-tokens'

const darkPage = tokens.modes.dark.surface.page
const darkText = tokens.modes.dark.text.onPage.default
const darkInputBg = tokens.modes.dark.forms.default.bg

Top-level forms.default.{bg,text,placeholder} hold the default (light) values; read modes.dark.forms.default.* for their dark equivalents.

Guidance:

  • Prefer semantic tokens for theme-aware UI.
  • Prefer modes when a consumer explicitly needs mode-specific values.
  • Do not invent local light/dark token contracts when this package already provides the semantic path.

Protected Token Families

The following semantic groups are locked. Their values must not change without explicit approval from Bradley Potts. This applies to all contributors and all AI agents — apparent visual improvements still require human sign-off.

Protected group Backed by Guarded by
success colors.success palette check:locked + check:contrast
warning colors.warning palette check:locked + check:contrast
danger semantic roles colors.error palette check:locked + check:contrast
CTA / primary action / brand-action colors.brand + buttons.cta check:locked + check:contrast

check:locked fails immediately if any protected value changes from the recorded baseline. An intentional change requires updating the baseline as part of an approved, classified release.

Downstream Boundaries

Downstream packages should never redefine locally:

  • the meaning of surface, text, component, buttons, forms, or modes
  • protected semantic groups such as success, warning, danger, or CTA / brand-action semantics
  • public namespace shape that this package already exports

Downstream packages may:

  • compose UI structure on top of this contract
  • map these tokens into framework-specific delivery
  • use raw palette values when the usage is intentionally non-semantic

Upgrade Expectations For Consumers

Consumers should treat this package as a SemVer-governed contract.

Practical guidance:

  • additive token paths are intended to be safe for existing consumers
  • semantic shifts may keep the same path but still affect visual meaning
  • renames and removals are breaking
  • generated JS, TS, CSS, and DTCG outputs are expected to stay aligned

If a downstream package depends on specific token paths or semantic meaning:

  • read CHANGELOG.md for contract change classification
  • read TOKEN_CONTRACT.md for contract rules
  • prefer documented public namespaces over undocumented internal assumptions

Change classification

Every contract-affecting change is classified in CHANGELOG.md [Unreleased] with a Contract change type: line before release.

Classification When to use Examples
additive New tokens, new paths, new CSS variables — existing consumers unaffected Adding a namespace, adding a token inside an existing family
semantic change Path stays the same but meaning, intent, or visual output shifts Adjusting the role of an existing surface or text token
breaking Existing consumers may need code changes Renaming a token path, removing a namespace, changing mode names

Renames and removals are always breaking regardless of perceived scope.

Package Exports / API Surface

Root package

@phcdevworks/spectre-tokens exports:

  • default / tokens
  • generateCssVariables
  • TypeScript types including SpectreTokens, SpectreModeTokens, and SpectreModeName

Example:

import tokens, { generateCssVariables } from '@phcdevworks/spectre-tokens'

const css = generateCssVariables(tokens, {
  selector: ':root',
  prefix: 'sp'
})

CSS entry point

  • @phcdevworks/spectre-tokens/index.css

Relationship To The Rest Of Spectre

Spectre keeps responsibilities separate:

  • @phcdevworks/spectre-tokens defines visual language, semantic roles, and token contracts
  • @phcdevworks/spectre-ui turns those contracts into reusable CSS, utility tooling, and shared styling behavior
  • Adapter packages translate Spectre contracts for framework-specific delivery

That separation keeps token meaning centralized while letting the package system expand by responsibility.

Consumer Checklist

For downstream packages and compatible apps:

  • import tokens from the package root when you need runtime values
  • import index.css when you need generated CSS variables
  • prefer semantic namespaces for UI behavior
  • use raw palette values only when fixed palette access is intentional
  • treat tokens/ as source of truth and generated outputs as derived
  • do not redefine Spectre semantic contracts locally

Development

Install dependencies, then run the package verification flow:

npm install
npm run check

This project expects Node.js ^22.12.0 || >=24.0.0 and npm 12.0.1.

Common commands

Command What it does
npm run build Regenerate all outputs — run after any token source change
npm run check Full validation gate — every step must pass before commit
npm run lint Run ESLint against all source files
npm run format Apply Prettier formatting to all files
npm run generate Regenerate src/generated/tokens.ts from token sources only
npm run check:manifest Validate public namespaces against contract.manifest.json
npm run check:docs Validate README and TOKEN_CONTRACT headings against manifest
npm run check:locked Confirm protected color families are unchanged
npm run check:contrast Confirm all paired tokens meet WCAG AA
npm run check:dist Confirm dist/ artifacts are in sync with source

Key source areas

  • tokens/ — source token data (source of truth)
  • src/ — package entry points, CSS generation, and public types
  • src/generated/ — auto-generated output (do not edit directly)
  • scripts/ — build and validation scripts
  • example/ — usage examples and smoke consumer

The files in example/ are illustrative token demos only. They help explain the token contract, but they are not the package contract itself and should not be treated as downstream UI primitives.

Troubleshooting

Failure Cause Fix
check:regression fails A token value changed vs the recorded baseline Revert the unintended change, or update the baseline if the change was intentional
check:locked fails A protected color family was modified Revert unless Bradley Potts has explicitly approved the change
check:contrast fails A token pair is below WCAG AA, AAA in high-contrast mode, or its minContrast Adjust the token value or the metadata.pair reference in the source JSON
check:dist fails Generated dist is out of sync Run npm run build then re-run npm run check
check:manifest fails A namespace exists in outputs but is not declared in contract.manifest.json Add the namespace to the manifest or remove it from the source
check:docs fails README or TOKEN_CONTRACT.md has drifted from the manifest Update the doc to match the current contract
check:classification fails A contract-authority file changed without a classification entry Add Contract change type: additive, semantic change, or breaking to CHANGELOG.md [Unreleased]

AI And Automation Boundaries

Claude Code (claude-sonnet-4-6) is the primary development agent for this repository. Codex handles releases and production stabilization, including cutting tagged releases and GitHub Releases. Jules handles small automated fixes and generated-output sync. GitHub Copilot provides development support.

All AI agents with repository access (Claude Code, Codex, Copilot, Jules) have commit, push, and tag authority in this repository. Publishing to npm remains Bradley Potts's sole authority. See AGENTS.md for the full commit-policy and release-authority grant.

Protected from automated change: locked color families (success, warning, danger, CTA/brand-action), contract.manifest.json, and src/generated/tokens.ts. See AGENTS.md for full agent governance and boundary rules.

Contributing

PHCDevworks maintains this package as part of the Spectre system.

When contributing:

  • treat tokens/ as the source of truth
  • keep generated outputs derived from source data
  • avoid breaking token contracts without an intentional major-version change
  • run npm run build to regenerate outputs when sources change
  • run npm run check as the full validation gate before opening a pull request
  • do not modify locked semantic color families without explicit approval
  • keep README.md, generated outputs, and contract.manifest.json aligned

See CONTRIBUTING.md for the full workflow.

License

MIT © PHCDevworks. See LICENSE.

About

@phcdevworks/spectre-tokens is the design-token foundation of the Spectre system. It provides the shared visual values and semantic contracts used across Spectre packages and PHCDevworks applications.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

2 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages