@phcdevworks/spectre-ui 1.6.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,18 +6,95 @@ reflects package releases published to npm.
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [1.8.0] - 2026-06-07
10
+
11
+ Release Title: Spinner Contract and Token Focus Alignment
12
+
13
+ Contract change type: additive
14
+
15
+ ### Added
16
+
17
+ - **Spinner Component**: Added standard brand and status variants (`primary`,
18
+ `secondary`, `success`, `warning`, `danger`, `info`, `neutral`, `accent`,
19
+ `cta`) and states (`disabled`, `loading` with `[aria-busy="true"]` support).
20
+ - Added `@phcdevworks/spectre-manifest` as a devDependency. `spectre.manifest.json`
21
+ at the repo root declares this package's ecosystem role, layer, exports, and
22
+ allowed dependency targets. `check:ecosystem` validates it in the check pipeline.
23
+ - **Token Alignment**: Updated `@phcdevworks/spectre-tokens` dependency to
24
+ `^2.8.0`.
25
+ - **Button Focus Ring Parity**: Consumed `buttons.danger.focusVisible` and
26
+ `buttons.success.focusVisible` tokens newly published in `2.8.0`. Danger and
27
+ success button variants now render a semantically correct focus ring (red and
28
+ green alpha respectively) on `:focus-visible`, matching the parity already
29
+ present for primary, secondary, ghost, and accent variants.
30
+
31
+ ## [1.7.0] - 2026-06-03
32
+
33
+ Release Title: Tag Variant Expansion and Token Alignment
34
+
35
+ ### Added
36
+
37
+ - **Tag Variants**: Expanded Tag recipe with `primary`, `secondary`, `success`,
38
+ `warning`, `danger`, `info`, `neutral`, `accent`, `cta`, and `ghost` variants
39
+ for full parity with Badge and Button components. CSS selectors backed by
40
+ token roles only.
41
+ - **Dark Mode Fixtures**: Added dark mode verification fixtures under `examples/`
42
+ for Alert, Avatar, and Tag recipes.
43
+
9
44
  ### Changed
10
45
 
11
- - Clarified Spectre layer documentation so the UI package remains Layer 2,
12
- `@phcdevworks/spectre-components` is the Layer 3 web-component package, and
13
- framework adapters such as `@phcdevworks/spectre-ui-astro` remain downstream
14
- delivery packages.
15
- - Added root Copilot support guidance to match the Spectre AI instruction
16
- structure used by `@phcdevworks/spectre-tokens`.
17
- - Corrected README automation wording so Jules' bounded maintenance commit
18
- authority matches `JULES.md`.
19
- - Removed a stale `.agents/jules.md` reference from shared agent guidance.
20
- - Updated shared agent guidance to reference the root Copilot support file.
46
+ - **Token Alignment**: Updated `@phcdevworks/spectre-tokens` dependency to
47
+ `^2.7.0`.
48
+ - **CI**: Promoted Node 24.x to the primary CI matrix target; Node 22.x
49
+ retained for one more cycle.
50
+ - **Documentation**: Added Recipe Composition section to `CONTRIBUTING.md`
51
+ covering how adapters compose multiple recipe helpers, contract guarantees
52
+ (pure function, deterministic output, no side effects), and non-guarantees
53
+ (CSS specificity interactions, class ordering).
54
+
55
+ ## [1.6.0] - 2026-05-22
56
+
57
+ Release Title: Contract Expansion and Governance Hardening
58
+
59
+ ### Added
60
+
61
+ - **Component Variants**: Added `cta` variant support for `Badge` and
62
+ `IconBox`, `fullWidth` structural support for `IconBox`, and structural
63
+ `elevated`, `flat`, `outline`, and `ghost` variants for `Testimonial`.
64
+ - **Input Recipes**: Added wrapper, label, helper-text, and error-message class
65
+ helpers so adapters can reuse the full input sub-element contract.
66
+ - **Contract Governance**: Added Claude, Codex, Copilot, and Jules agent
67
+ guidance, PR template requirements, maintenance instructions, release
68
+ readiness prompts, and CodeRabbit configuration for review hygiene.
69
+ - **Validation Shortcut**: Added `npm run check` as the canonical local and CI
70
+ validation gate.
71
+
72
+ ### Changed
73
+
74
+ - **Token Alignment**: Updated the package to consume
75
+ `@phcdevworks/spectre-tokens` `^2.6.0` and refreshed dependency metadata.
76
+ - **Runtime Contract**: Raised the Node.js requirement to `^22.13.0` or
77
+ `>=24.0.0`, documented npm `>=10.0.0`, and updated CI to validate on Node
78
+ 22.x and 24.x.
79
+ - **Validation Tooling**: Migrated build and validation scripts from `.mjs` to
80
+ TypeScript entry points executed with `node --experimental-strip-types`.
81
+ - **Package Metadata**: Repositioned the package description and keywords
82
+ around Layer 2 CSS bundles, Tailwind tooling, and class recipes; included
83
+ `CHANGELOG.md` in the published package files.
84
+ - **Documentation**: Expanded README, contributing, roadmap, TODO, and agent
85
+ guidance around the Spectre layer model, framework boundaries, contract
86
+ validation, package exports, and release-readiness workflows.
87
+
88
+ ### Fixed
89
+
90
+ - **State Parity**: Improved Badge, Card, IconBox, PricingCard, and Testimonial
91
+ recipe/CSS parity for forced hover, focus, active, disabled, loading, and
92
+ structural state coverage.
93
+ - **Selector Coverage**: Added testimonial attribute-selector support and
94
+ refreshed contract tests, export snapshots, and manifest entries for the new
95
+ public recipe helpers and variants.
96
+ - **Docs Drift**: Corrected README badges, package links, Node/npm guidance,
97
+ Jules automation wording, and stale agent-reference paths.
21
98
 
22
99
  ## [1.5.0] - 2026-05-04
23
100
 
package/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # @phcdevworks/spectre-ui
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@phcdevworks/spectre-ui)](https://www.npmjs.com/package/@phcdevworks/spectre-ui)
4
- [![CI](https://github.com/phcdevworks/spectre-ui/actions/workflows/ci.yml/badge.svg)](https://github.com/phcdevworks/spectre-ui/actions/workflows/ci.yml)
5
- [![GitHub issues](https://img.shields.io/github/issues/phcdevworks/spectre-ui)](https://github.com/phcdevworks/spectre-ui/issues)
6
- [![License](https://img.shields.io/github/license/phcdevworks/spectre-ui)](LICENSE)
4
+ [![CI](https://github.com/phcdevworks/spectre-ui/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/phcdevworks/spectre-ui/actions/workflows/ci.yml)
5
+ [![License](https://img.shields.io/npm/l/@phcdevworks/spectre-ui)](LICENSE)
6
+ [![Node](https://img.shields.io/node/v/@phcdevworks/spectre-ui)](https://nodejs.org)
7
7
 
8
8
  `@phcdevworks/spectre-ui` is **Layer 2 of the Spectre design suite**. It turns
9
9
  [`@phcdevworks/spectre-tokens`](https://github.com/phcdevworks/spectre-tokens)
@@ -17,7 +17,8 @@ styling contract without re-implementing class logic themselves.
17
17
  `@phcdevworks/spectre-tokens`) or building framework-specific components (that
18
18
  belongs in adapter packages such as `@phcdevworks/spectre-ui-astro`).
19
19
 
20
- [Contributing](CONTRIBUTING.md) | [Changelog](CHANGELOG.md) |
20
+ [Contributing](CONTRIBUTING.md) | [Code of Conduct](CODE_OF_CONDUCT.md) |
21
+ [Changelog](CHANGELOG.md) | [Roadmap](ROADMAP.md) |
21
22
  [Security Policy](SECURITY.md)
22
23
 
23
24
  ## Source of truth
@@ -26,51 +27,29 @@ belongs in adapter packages such as `@phcdevworks/spectre-ui-astro`).
26
27
  semantic meaning. `ui-contract.manifest.json` is the machine-readable contract
27
28
  authority for this package's public styling surface.
28
29
 
29
- | Layer | Path | Rule |
30
- |---|---|---|
31
- | Token authority | Published `@phcdevworks/spectre-tokens` package | Design values and semantic meaning start there |
32
- | UI contract authority | `ui-contract.manifest.json` | Governs public recipes, CSS entry points, and Tailwind exports |
33
- | Source CSS | `src/styles/` | Token-backed CSS classes and bundle entry points |
34
- | Source recipes | `src/recipes/` | Framework-agnostic class string APIs |
35
- | Tailwind helpers | `src/tailwind/` | Tailwind theme and preset integration |
36
- | Generated dist | `dist/` | **Never edit directly** — regenerated by `npm run build` |
30
+ | Layer | Path | Rule |
31
+ | --------------------- | ----------------------------------------------- | -------------------------------------------------------------- |
32
+ | Token authority | Published `@phcdevworks/spectre-tokens` package | Design values and semantic meaning start there |
33
+ | UI contract authority | `ui-contract.manifest.json` | Governs public recipes, CSS entry points, and Tailwind exports |
34
+ | Source CSS | `src/styles/` | Token-backed CSS classes and bundle entry points |
35
+ | Source recipes | `src/recipes/` | Framework-agnostic class string APIs |
36
+ | Tailwind helpers | `src/tailwind/` | Tailwind theme and preset integration |
37
+ | Generated dist | `dist/` | **Never edit directly** — regenerated by `npm run build` |
37
38
 
38
39
  After any contract-facing source change: run `npm run check` to validate the
39
40
  full UI contract.
40
41
 
41
42
  ## Architecture
42
43
 
43
- ```
44
- ┌─────────────────────────────┐
45
- │ @phcdevworks/spectre-tokens │ Layer 1 — design values, semantic tokens
46
- │ (design source of truth) │
47
- └──────────────┬──────────────┘
48
- │ consumed by
49
-
50
- ┌─────────────────────────────┐
51
- │ @phcdevworks/spectre-ui │ Layer 2 — THIS PACKAGE
52
- │ CSS bundles, recipes, │ translates tokens into structure
53
- │ Tailwind helpers │
54
- └──────────────┬──────────────┘
55
- │ consumed by
56
-
57
- ┌─────────────────────────────┐
58
- │ @phcdevworks/spectre- │ Layer 3 — canonical Lit web components
59
- │ components │ wraps CSS classes and recipes as
60
- │ │ framework-agnostic custom elements
61
- └──────────────┬──────────────┘
62
- │ alongside / consumed by
63
-
64
- ┌─────────────────────────────┐
65
- │ Adapters and apps │ Layer 4 — framework-specific delivery
66
- │ spectre-ui-astro, React, │ binds Spectre contracts to native
67
- │ Vue, WordPress, etc. │ framework ergonomics
68
- └─────────────────────────────┘
69
- ```
44
+ | Layer | Package or consumer | Responsibility | Relationship to this package |
45
+ | ----- | ---------------------------------------------------------- | ----------------------------------------------------------------------- | ---------------------------- |
46
+ | 1 | `@phcdevworks/spectre-tokens` | Defines design values and semantic token meaning | Upstream source of truth |
47
+ | 2 | `@phcdevworks/spectre-ui` | Translates tokens into CSS bundles, Tailwind helpers, and class recipes | This package |
48
+ | 3 | Adapters and apps, such as `@phcdevworks/spectre-ui-astro` | Deliver Spectre through framework-native ergonomics | Downstream consumers |
70
49
 
71
- This package owns Layer 2 only. It does not deliver components and it does not
72
- define tokens. It translates tokens into a stable contract that adapters and
73
- apps consume.
50
+ `@phcdevworks/spectre-components` is a separate component package that can wrap
51
+ this styling contract in Lit web components. This package owns Layer 2 only: it
52
+ does not deliver components and it does not define tokens.
74
53
 
75
54
  ## Key capabilities
76
55
 
@@ -92,8 +71,8 @@ apps consume.
92
71
  - Tailwind preset and theme helpers in `src/tailwind/`
93
72
  - Contract validation that keeps CSS, recipes, exports, and docs aligned
94
73
 
95
- This package is the correct place to define reusable styling structure on top
96
- of Spectre tokens.
74
+ This package is the correct place to define reusable styling structure on top of
75
+ Spectre tokens.
97
76
 
98
77
  ## What this package does not own
99
78
 
@@ -121,7 +100,10 @@ No framework needed. Import the CSS and use the `sp-*` classes directly:
121
100
  <!doctype html>
122
101
  <html>
123
102
  <head>
124
- <link rel="stylesheet" href="node_modules/@phcdevworks/spectre-ui/dist/index.css" />
103
+ <link
104
+ rel="stylesheet"
105
+ href="node_modules/@phcdevworks/spectre-ui/dist/index.css"
106
+ />
125
107
  </head>
126
108
  <body>
127
109
  <button class="sp-btn sp-btn--primary sp-btn--md">Save</button>
@@ -218,17 +200,17 @@ Do not use `@phcdevworks/spectre-ui` when you need to:
218
200
 
219
201
  ## What belongs here vs elsewhere
220
202
 
221
- | What | Where it lives |
222
- |---|---|
223
- | Semantic color values, spacing scale, type scale | `@phcdevworks/spectre-tokens` |
224
- | Token-to-CSS variable mapping | **here** — `src/styles/` |
225
- | Precompiled CSS bundles | **here** — built to `dist/*.css` |
226
- | Class recipe functions (input → class string) | **here** — `src/recipes/` |
227
- | Tailwind preset and theme helpers | **here** — `src/tailwind/` |
228
- | Astro, React, Vue, Lit, Svelte components | Adapter packages (e.g. `spectre-ui-astro`) |
229
- | WordPress shortcodes or PHP templates | A WordPress adapter package |
230
- | App-level layout, routing, or data fetching | Consuming apps |
231
- | New design decisions (new colors, new spacing) | `@phcdevworks/spectre-tokens` |
203
+ | What | Where it lives |
204
+ | ------------------------------------------------ | ------------------------------------------ |
205
+ | Semantic color values, spacing scale, type scale | `@phcdevworks/spectre-tokens` |
206
+ | Token-to-CSS variable mapping | **here** — `src/styles/` |
207
+ | Precompiled CSS bundles | **here** — built to `dist/*.css` |
208
+ | Class recipe functions (input → class string) | **here** — `src/recipes/` |
209
+ | Tailwind preset and theme helpers | **here** — `src/tailwind/` |
210
+ | Astro, React, Vue, Lit, Svelte components | Adapter packages (e.g. `spectre-ui-astro`) |
211
+ | WordPress shortcodes or PHP templates | A WordPress adapter package |
212
+ | App-level layout, routing, or data fetching | Consuming apps |
213
+ | New design decisions (new colors, new spacing) | `@phcdevworks/spectre-tokens` |
232
214
 
233
215
  Golden rule: this package consumes tokens and exposes class contracts. It does
234
216
  not define tokens and it does not deliver framework components.
@@ -240,17 +222,21 @@ not define tokens and it does not deliver framework components.
240
222
  All recipe functions accept a plain options object and return a class string.
241
223
  All options are optional and fall back to sensible defaults.
242
224
 
243
- | Recipe | Function | Variants | Sizes | Common boolean flags |
244
- |---|---|---|---|---|
245
- | Button | `getButtonClasses` | `primary` `secondary` `ghost` `danger` `success` `cta` `accent` | `sm` `md` `lg` | `disabled` `loading` `fullWidth` `pill` `iconOnly` |
246
- | Badge | `getBadgeClasses` | `primary` `secondary` `success` `warning` `danger` `neutral` `info` `ghost` `accent` `cta` | `sm` `md` `lg` | `interactive` `disabled` `loading` `fullWidth` |
247
- | Card | `getCardClasses` | `elevated` `flat` `outline` `ghost` | — | `interactive` `padded` `fullHeight` `disabled` `loading` |
248
- | Input | `getInputClasses` | — | `sm` `md` `lg` | `disabled` `loading` `fullWidth` `pill` |
249
- | Input state | `getInputClasses` | `state`: `default` `error` `success` `disabled` `loading` | — | — |
250
- | IconBox | `getIconBoxClasses` | `primary` `secondary` `success` `warning` `danger` `info` `neutral` `ghost` `accent` `cta` | `sm` `md` `lg` | `interactive` `disabled` `loading` `pill` `fullWidth` |
251
- | PricingCard | `getPricingCardClasses` | — | — | `featured` `interactive` `disabled` `loading` `fullHeight` |
252
- | Rating | `getRatingClasses` | — | `sm` `md` `lg` | `interactive` `disabled` `loading` `pill` `fullWidth` |
253
- | Testimonial | `getTestimonialClasses` | `elevated` `flat` `outline` `ghost` | — | `interactive` `disabled` `loading` `fullHeight` |
225
+ | Recipe | Function | Variants | Sizes | Common boolean flags |
226
+ | ----------- | ----------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------- | ----------------------------------------------------------------------- |
227
+ | Button | `getButtonClasses` | `primary` `secondary` `ghost` `danger` `success` `cta` `accent` | `sm` `md` `lg` | `disabled` `loading` `fullWidth` `pill` `iconOnly` |
228
+ | Badge | `getBadgeClasses` | `primary` `secondary` `success` `warning` `danger` `neutral` `info` `ghost` `accent` `cta` | `sm` `md` `lg` | `interactive` `disabled` `loading` `fullWidth` |
229
+ | Card | `getCardClasses` | `elevated` `flat` `outline` `ghost` | — | `interactive` `padded` `fullHeight` `disabled` `loading` |
230
+ | Input | `getInputClasses` | — | `sm` `md` `lg` | `disabled` `loading` `fullWidth` `pill` |
231
+ | Input state | `getInputClasses` | `state`: `default` `error` `success` `disabled` `loading` | — | — |
232
+ | IconBox | `getIconBoxClasses` | `primary` `secondary` `success` `warning` `danger` `info` `neutral` `ghost` `accent` `cta` | `sm` `md` `lg` | `interactive` `disabled` `loading` `pill` `fullWidth` |
233
+ | PricingCard | `getPricingCardClasses` | — | — | `featured` `interactive` `disabled` `loading` `fullHeight` |
234
+ | Rating | `getRatingClasses` | — | `sm` `md` `lg` | `interactive` `disabled` `loading` `pill` `fullWidth` |
235
+ | Testimonial | `getTestimonialClasses` | `elevated` `flat` `outline` `ghost` | — | `interactive` `disabled` `loading` `fullHeight` |
236
+ | Alert | `getAlertClasses` | `info` `success` `warning` `danger` `neutral` | `sm` `md` `lg` | `dismissed` |
237
+ | Avatar | `getAvatarClasses` | — | `sm` `md` `lg` `xl` | shape: `circle` `square` |
238
+ | Tag | `getTagClasses` | `default` `primary` `secondary` `success` `warning` `danger` `info` `neutral` `accent` `cta` `outline` `ghost` | `sm` `md` `lg` | `dismissible` `selected` `disabled` `loading` `interactive` `fullWidth` |
239
+ | Spinner | `getSpinnerClasses` | — | `sm` `md` `lg` | — |
254
240
 
255
241
  Each recipe family also exports sub-element helpers for its structural parts
256
242
  (labels, wrappers, sub-containers, text elements). See the full list below.
@@ -270,6 +256,8 @@ Root constants:
270
256
 
271
257
  Root recipe functions:
272
258
 
259
+ - `getAlertClasses`
260
+ - `getAvatarClasses`
273
261
  - `getBadgeClasses`
274
262
  - `getButtonClasses`
275
263
  - `getCardClasses`
@@ -277,6 +265,8 @@ Root recipe functions:
277
265
  - `getInputClasses`
278
266
  - `getPricingCardClasses`
279
267
  - `getRatingClasses`
268
+ - `getSpinnerClasses`
269
+ - `getTagClasses`
280
270
  - `getTestimonialClasses`
281
271
 
282
272
  Root recipe helper functions:
@@ -357,8 +347,8 @@ Practical guidance:
357
347
 
358
348
  - additive recipes, variants, states, and helpers are intended to be safe for
359
349
  existing consumers
360
- - semantic shifts may keep the same class or option name but still affect
361
- visual output
350
+ - semantic shifts may keep the same class or option name but still affect visual
351
+ output
362
352
  - renames, removals, and behavior changes to existing classes or options are
363
353
  breaking
364
354
  - generated JS, TypeScript declarations, CSS bundles, Tailwind exports, README
@@ -376,11 +366,11 @@ Tailwind helper:
376
366
  Contract-affecting changes should be classified in `CHANGELOG.md [Unreleased]`
377
367
  before release.
378
368
 
379
- | Classification | When to use | Examples |
380
- |---|---|---|
381
- | `additive` | New public styling surface that does not break existing consumers | Adding a recipe helper, variant, state, or CSS entry point |
382
- | `semantic change` | Public name remains but behavior or visual meaning shifts | Adjusting an existing class or recipe option to map to different token intent |
383
- | `breaking` | Existing consumers may need code changes | Renaming or removing a class, option, export, or CSS entry point |
369
+ | Classification | When to use | Examples |
370
+ | ----------------- | ----------------------------------------------------------------- | ----------------------------------------------------------------------------- |
371
+ | `additive` | New public styling surface that does not break existing consumers | Adding a recipe helper, variant, state, or CSS entry point |
372
+ | `semantic change` | Public name remains but behavior or visual meaning shifts | Adjusting an existing class or recipe option to map to different token intent |
373
+ | `breaking` | Existing consumers may need code changes | Renaming or removing a class, option, export, or CSS entry point |
384
374
 
385
375
  Renames and removals are always breaking regardless of perceived scope.
386
376
 
@@ -426,28 +416,28 @@ npm install
426
416
  npm run ci:verify
427
417
  ```
428
418
 
429
- This project requires Node.js `^22.13.0 || >=24.0.0` and npm `>=10.0.0`.
430
- The checked-in package manager is `npm@11.15.0`.
419
+ This project requires Node.js `^22.13.0 || >=24.0.0` and npm `>=10.0.0`. The
420
+ checked-in package manager is `npm@11.16.0`.
431
421
 
432
422
  ### Common commands
433
423
 
434
- | Command | What it does |
435
- |---|---|
436
- | `npm run check` | Full validation gate — run before every PR |
437
- | `npm run ci:verify` | Underlying verification sequence used by `npm run check` |
438
- | `npm test` | Build then run the contract and regression test suite |
439
- | `npm run build` | Emit TypeScript and CSS artifacts to `dist/` |
440
- | `npm run lint` | ESLint with TypeScript-aware config |
441
- | `npm run validate:exports` | Verify root export surface against snapshot |
442
- | `npm run validate:exports:update` | Update the export snapshot after adding a public export |
443
- | `npm run validate:tailwind` | Verify Tailwind exports and emitted subpath artifacts |
444
- | `npm run validate:tailwind:update` | Update the Tailwind export snapshot |
445
- | `npm run validate:tokens` | Check for token drift against latest published release |
424
+ | Command | What it does |
425
+ | ---------------------------------- | -------------------------------------------------------- |
426
+ | `npm run check` | Full validation gate — run before every PR |
427
+ | `npm run ci:verify` | Underlying verification sequence used by `npm run check` |
428
+ | `npm test` | Build then run the contract and regression test suite |
429
+ | `npm run build` | Emit TypeScript and CSS artifacts to `dist/` |
430
+ | `npm run lint` | ESLint with TypeScript-aware config |
431
+ | `npm run validate:exports` | Verify root export surface against snapshot |
432
+ | `npm run validate:exports:update` | Update the export snapshot after adding a public export |
433
+ | `npm run validate:tailwind` | Verify Tailwind exports and emitted subpath artifacts |
434
+ | `npm run validate:tailwind:update` | Update the Tailwind export snapshot |
435
+ | `npm run validate:tokens` | Check for token drift against latest published release |
446
436
 
447
437
  ### Troubleshooting
448
438
 
449
- **`validate:runtime` fails** — you are on the wrong Node version. Run
450
- `nvm use` to switch to the version in `.nvmrc`, or install Node 22 or 24.
439
+ **`validate:runtime` fails** — you are on the wrong Node version. Run `nvm use`
440
+ to switch to the version in `.nvmrc`, or install Node 22 or 24.
451
441
 
452
442
  **`validate:tokens` fails with a network error** — the check requires outbound
453
443
  npm registry access. In a restricted environment, run the other validators
@@ -458,8 +448,8 @@ automatically via the `pretest` hook. If you ran `vitest` directly, run
458
448
  `npm run build` first.
459
449
 
460
450
  **Lint fails locally but passes in CI** — confirm you are on the same Node
461
- version as CI (Node 22.x or 24.x). ESLint plugin resolution can differ
462
- across runtimes.
451
+ version as CI (Node 22.x or 24.x). ESLint plugin resolution can differ across
452
+ runtimes.
463
453
 
464
454
  **Export snapshot out of date** — run `npm run validate:exports:update` after
465
455
  adding a public export, then commit the updated `scripts/export-snapshot.json`.
@@ -475,6 +465,13 @@ adding a public export, then commit the updated `scripts/export-snapshot.json`.
475
465
  Planning artifacts for contract hardening live in [ROADMAP.md](ROADMAP.md) and
476
466
  [TODO.md](TODO.md).
477
467
 
468
+ The current roadmap focus is post-v1.7.0 expansion: consume newly published
469
+ Spectre token contracts for links, interactive surfaces, dividers, and common
470
+ application UI patterns before adding matching Layer 2 classes or recipes.
471
+ Planned upstream token work is tracked in
472
+ [`@phcdevworks/spectre-tokens`](https://github.com/phcdevworks/spectre-tokens),
473
+ but this package synchronizes only against published npm releases.
474
+
478
475
  ## Examples
479
476
 
480
477
  Use [`examples/examples.html`](examples/examples.html) as the visual index for
@@ -494,16 +491,16 @@ Run the full validation gate before any pull request:
494
491
  npm run check
495
492
  ```
496
493
 
497
- This runs: runtime check → lint → export validation → README validation →
498
- token drift check → build → Tailwind contract → CSS contract → tests. All
499
- steps must pass.
494
+ This runs: runtime check → lint → changelog validation → export validation →
495
+ README validation → token drift check → build → Tailwind contract → CSS contract
496
+ → tests. All steps must pass.
500
497
 
501
498
  ## AI and automation boundaries
502
499
 
503
500
  Claude Code (`claude-sonnet-4-6`) is the primary development agent for this
504
501
  repository. Codex handles releases and production stabilization. Jules handles
505
- small automated fixes and token sync passes. GitHub Copilot provides
506
- development support.
502
+ small automated fixes and token sync passes. GitHub Copilot provides development
503
+ support.
507
504
 
508
505
  Claude Code, Codex, and Copilot do not create git commits by default. Jules may
509
506
  commit only bounded automated maintenance when the `JULES.md` scope and
package/dist/base.css CHANGED
@@ -116,17 +116,24 @@
116
116
  --sp-color-white: #ffffff;
117
117
  --sp-color-black: #000000;
118
118
  --sp-space-0: 0rem;
119
+ --sp-space-1: 0.0625rem;
120
+ --sp-space-2: 0.125rem;
119
121
  --sp-space-4: 0.25rem;
122
+ --sp-space-6: 0.375rem;
120
123
  --sp-space-8: 0.5rem;
124
+ --sp-space-10: 0.625rem;
121
125
  --sp-space-12: 0.75rem;
126
+ --sp-space-14: 0.875rem;
122
127
  --sp-space-16: 1rem;
123
128
  --sp-space-20: 1.25rem;
124
129
  --sp-space-24: 1.5rem;
130
+ --sp-space-28: 1.75rem;
125
131
  --sp-space-32: 2rem;
126
132
  --sp-space-40: 2.5rem;
127
133
  --sp-space-48: 3rem;
128
134
  --sp-space-56: 3.5rem;
129
135
  --sp-space-64: 4rem;
136
+ --sp-space-72: 4.5rem;
130
137
  --sp-space-80: 5rem;
131
138
  --sp-space-96: 6rem;
132
139
  --sp-layout-section-padding-sm: 1.5rem;
@@ -142,12 +149,21 @@
142
149
  --sp-layout-container-padding-inline-md: 1.5rem;
143
150
  --sp-layout-container-padding-inline-lg: 2rem;
144
151
  --sp-layout-container-max-width: 72rem;
152
+ --sp-border-width-none: 0;
145
153
  --sp-border-width-base: 1px;
146
154
  --sp-border-width-thick: 2px;
155
+ --sp-border-style-none: none;
156
+ --sp-border-style-solid: solid;
157
+ --sp-border-style-dashed: dashed;
158
+ --sp-border-style-dotted: dotted;
147
159
  --sp-radius-none: 0;
148
160
  --sp-radius-sm: 2px;
149
161
  --sp-radius-md: 4px;
150
162
  --sp-radius-lg: 8px;
163
+ --sp-radius-xl: 12px;
164
+ --sp-radius-2xl: 16px;
165
+ --sp-radius-3xl: 24px;
166
+ --sp-radius-4xl: 32px;
151
167
  --sp-radius-pill: 999px;
152
168
  --sp-font-family-sans: system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif;
153
169
  --sp-font-family-serif: 'Times New Roman', Times, serif;
@@ -183,34 +199,21 @@
183
199
  --sp-font-6xl-line-height: 5rem;
184
200
  --sp-font-6xl-weight: 900;
185
201
  --sp-font-xs-letter-spacing: 0.02em;
186
- --sp-text-on-page-default: #141b24;
187
- --sp-text-on-page-muted: #4b576a;
188
- --sp-text-on-page-subtle: #657287;
189
- --sp-text-on-page-meta: #657287;
190
- --sp-text-on-surface-default: #141b24;
191
- --sp-text-on-surface-muted: #4b576a;
192
- --sp-text-on-surface-subtle: #657287;
193
- --sp-text-on-surface-meta: #657287;
194
- --sp-badge-neutral-bg: #eef1f6;
195
- --sp-badge-neutral-text: #374253;
196
- --sp-badge-info-bg: #e0f2fe;
197
- --sp-badge-info-text: #075985;
198
- --sp-badge-success-bg: #dcfce7;
199
- --sp-badge-success-text: #166534;
200
- --sp-badge-warning-bg: #fff1c2;
201
- --sp-badge-warning-text: #8f5200;
202
- --sp-badge-danger-bg: #fee2e2;
203
- --sp-badge-danger-text: #991b1b;
204
- --sp-icon-box-bg: #ffffff;
205
- --sp-icon-box-border: #d9dfeb;
206
- --sp-icon-box-icon-default: #0369a1;
207
- --sp-icon-box-icon-success: #16a34a;
208
- --sp-icon-box-icon-warning: #d48806;
209
- --sp-icon-box-icon-danger: #dc2626;
202
+ --sp-font-sm-letter-spacing: 0em;
203
+ --sp-font-md-letter-spacing: 0em;
204
+ --sp-font-lg-letter-spacing: 0em;
205
+ --sp-font-xl-letter-spacing: 0em;
206
+ --sp-font-2xl-letter-spacing: 0em;
207
+ --sp-font-3xl-letter-spacing: 0em;
208
+ --sp-font-4xl-letter-spacing: 0em;
209
+ --sp-font-5xl-letter-spacing: 0em;
210
+ --sp-font-6xl-letter-spacing: 0em;
210
211
  --sp-shadow-none: none;
211
212
  --sp-shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.06);
212
213
  --sp-shadow-md: 0 2px 6px -1px rgba(0, 0, 0, 0.08);
213
214
  --sp-shadow-lg: 0 6px 16px -4px rgba(0, 0, 0, 0.12);
215
+ --sp-shadow-xl: 0 12px 24px -6px rgba(0, 0, 0, 0.15);
216
+ --sp-shadow-2xl: 0 20px 48px -12px rgba(0, 0, 0, 0.20);
214
217
  --sp-breakpoint-sm: 640px;
215
218
  --sp-breakpoint-md: 768px;
216
219
  --sp-breakpoint-lg: 1024px;
@@ -224,20 +227,26 @@
224
227
  --sp-z-index-modal: 1400;
225
228
  --sp-z-index-popover: 1500;
226
229
  --sp-z-index-tooltip: 1600;
230
+ --sp-z-index-toast: 1700;
227
231
  --sp-duration-instant: 75ms;
228
232
  --sp-duration-fast: 150ms;
229
233
  --sp-duration-base: 200ms;
234
+ --sp-duration-relaxed: 250ms;
230
235
  --sp-duration-moderate: 300ms;
231
236
  --sp-duration-slow: 500ms;
232
237
  --sp-duration-slower: 700ms;
238
+ --sp-duration-long: 1000ms;
239
+ --sp-duration-slowest: 1200ms;
233
240
  --sp-easing-linear: linear;
234
241
  --sp-easing-in: cubic-bezier(0.4, 0, 1, 1);
235
242
  --sp-easing-out: cubic-bezier(0, 0, 0.2, 1);
236
243
  --sp-easing-inout: cubic-bezier(0.4, 0, 0.2, 1);
237
244
  --sp-easing-spring: cubic-bezier(0.4, 0, 0.2, 1);
245
+ --sp-easing-overshoot: cubic-bezier(0.34, 1.56, 0.64, 1);
238
246
  --sp-opacity-disabled: 0.38;
239
247
  --sp-opacity-hover: 0.92;
240
248
  --sp-opacity-active: 0.84;
249
+ --sp-opacity-loading: 0.6;
241
250
  --sp-opacity-focus: 1;
242
251
  --sp-opacity-overlay: 0.5;
243
252
  --sp-opacity-tooltip: 0.95;
@@ -279,6 +288,7 @@
279
288
  --sp-button-danger-text: #ffffff;
280
289
  --sp-button-danger-textdisabled: #8a96ad;
281
290
  --sp-button-danger-focusring: rgba(239, 68, 68, 0.4);
291
+ --sp-button-danger-focusvisible: rgba(239, 68, 68, 0.4);
282
292
  --sp-button-success-bg: #15803d;
283
293
  --sp-button-success-bghover: #166534;
284
294
  --sp-button-success-bgactive: #14532d;
@@ -286,6 +296,7 @@
286
296
  --sp-button-success-text: #ffffff;
287
297
  --sp-button-success-textdisabled: #8a96ad;
288
298
  --sp-button-success-focusring: rgba(34, 197, 94, 0.4);
299
+ --sp-button-success-focusvisible: rgba(34, 197, 94, 0.4);
289
300
  --sp-button-cta-bg: #1f57db;
290
301
  --sp-button-cta-bghover: #1946b4;
291
302
  --sp-button-cta-bgactive: #173b8f;
@@ -369,7 +380,7 @@
369
380
  --sp-button-text-default: #eef1f6;
370
381
  --sp-button-text-on-primary: #ffffff;
371
382
  --sp-badge-neutral-bg: #374253;
372
- --sp-badge-neutral-text: #eef1f6;
383
+ --sp-badge-neutral-text: #f7f8fb;
373
384
  --sp-badge-info-bg: #0c4a6e;
374
385
  --sp-badge-info-text: #e0f2fe;
375
386
  --sp-badge-success-bg: #166534;