@phcdevworks/spectre-ui 1.7.0 → 1.9.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 +91 -0
- package/README.md +98 -72
- package/dist/base.css +110 -0
- package/dist/components.css +658 -7
- package/dist/index.cjs +191 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +658 -7
- package/dist/index.d.cts +99 -1
- package/dist/index.d.ts +99 -1
- package/dist/index.js +181 -8
- package/dist/index.js.map +1 -1
- package/dist/utilities.css +110 -0
- package/package.json +15 -10
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,97 @@ reflects package releases published to npm.
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [1.9.0] - 2026-06-10
|
|
10
|
+
|
|
11
|
+
Release Title: Component Recipe Expansion
|
|
12
|
+
|
|
13
|
+
Contract change type: additive
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- **Nav Recipe**: Added `getNavClasses`, `getNavLinksClasses`, and
|
|
18
|
+
`getNavLinkClasses` recipes plus `.sp-nav`, `.sp-nav__links`, and
|
|
19
|
+
`.sp-nav__link` CSS in `src/styles/components.css`. Consumes the new
|
|
20
|
+
`component.nav` tokens (`nav.bg`, `nav.text`, `nav.link`, `nav.linkHover`,
|
|
21
|
+
`nav.linkActive`, `nav.border`) published in
|
|
22
|
+
`@phcdevworks/spectre-tokens@2.9.0`. `getNavClasses` supports `bordered`,
|
|
23
|
+
`sticky`, and `fullWidth`; `getNavLinkClasses` supports `active`, `disabled`,
|
|
24
|
+
`hovered`, and `focused`. This is the first of the five Phase 4 component
|
|
25
|
+
recipes in `TODO.md`. Raised the `components.css` size budget in
|
|
26
|
+
`tests/css-entrypoints.test.ts` from 92000 to 96000 bytes.
|
|
27
|
+
|
|
28
|
+
- **Toast Recipe**: Added `getToastClasses` and `getToastIconClasses` recipes
|
|
29
|
+
plus `.sp-toast` and `.sp-toast__icon` CSS in `src/styles/components.css`.
|
|
30
|
+
Consumes the new `component.toast` tokens (`toast.{success,warning,danger,info}.{bg,text,border,icon}`)
|
|
31
|
+
published in `@phcdevworks/spectre-tokens@2.9.0`. `getToastClasses` supports
|
|
32
|
+
`info`, `success`, `warning`, and `danger` variants plus `dismissed` and
|
|
33
|
+
`fullWidth`; `getToastIconClasses` mirrors the same variants for icon color.
|
|
34
|
+
This is the second of the five Phase 4 component recipes in `TODO.md`.
|
|
35
|
+
Raised the `components.css` size budget in `tests/css-entrypoints.test.ts`
|
|
36
|
+
from 96000 to 100000 bytes.
|
|
37
|
+
|
|
38
|
+
- **Tooltip Recipe**: Added `getTooltipClasses` recipe plus `.sp-tooltip` CSS
|
|
39
|
+
in `src/styles/components.css`. Consumes the new `component.tooltip` tokens
|
|
40
|
+
(`tooltip.bg`, `tooltip.text`, `tooltip.border`) along with the existing
|
|
41
|
+
`--sp-opacity-tooltip` and `--sp-z-index-tooltip` primitives published in
|
|
42
|
+
`@phcdevworks/spectre-tokens@2.9.0`. `getTooltipClasses` supports `top`,
|
|
43
|
+
`bottom`, `left`, and `right` placements plus a `visible` flag. This is the
|
|
44
|
+
third of the five Phase 4 component recipes in `TODO.md`.
|
|
45
|
+
|
|
46
|
+
- **Dropdown Recipe**: Added `getDropdownClasses`, `getDropdownMenuClasses`,
|
|
47
|
+
and `getDropdownItemClasses` recipes plus `.sp-dropdown`,
|
|
48
|
+
`.sp-dropdown__menu`, and `.sp-dropdown__item` CSS in
|
|
49
|
+
`src/styles/components.css`. Consumes the new `component.dropdown` tokens
|
|
50
|
+
(`dropdown.bg`, `dropdown.border`, `dropdown.item.default`,
|
|
51
|
+
`dropdown.item.hover`, `dropdown.item.active`, `dropdown.item.text`)
|
|
52
|
+
published in `@phcdevworks/spectre-tokens@2.9.0`. `getDropdownClasses`
|
|
53
|
+
supports `fullWidth`; `getDropdownMenuClasses` supports `bottom-start`,
|
|
54
|
+
`bottom-end`, `top-start`, and `top-end` placements plus an `open` flag;
|
|
55
|
+
`getDropdownItemClasses` supports `active`, `disabled`, `hovered`, and
|
|
56
|
+
`focused`. This is the fourth of the five Phase 4 component recipes in
|
|
57
|
+
`TODO.md`. Raised the `components.css` size budget in
|
|
58
|
+
`tests/css-entrypoints.test.ts` from 100000 to 105000 bytes.
|
|
59
|
+
|
|
60
|
+
- **Modal Recipe**: Added `getModalClasses` and `getModalOverlayClasses`
|
|
61
|
+
recipes plus `.sp-modal` and `.sp-modal-overlay` CSS in
|
|
62
|
+
`src/styles/components.css`. Consumes the new `component.modal` tokens
|
|
63
|
+
(`modal.bg`, `modal.shadow`, `modal.border`, `modal.overlay`) along with the
|
|
64
|
+
existing `--sp-z-index-modal` primitive published in
|
|
65
|
+
`@phcdevworks/spectre-tokens@2.9.0`. `getModalClasses` supports `open` and
|
|
66
|
+
`fullWidth`; `getModalOverlayClasses` supports `open`. This is the fifth and
|
|
67
|
+
final of the five Phase 4 component recipes in `TODO.md`.
|
|
68
|
+
|
|
69
|
+
### Changed
|
|
70
|
+
|
|
71
|
+
- **Token Alignment**: Updated `@phcdevworks/spectre-tokens` dependency to
|
|
72
|
+
`^2.9.0`. The published bundle now carries the five Phase 4 `component.*`
|
|
73
|
+
token groups (`nav`, `toast`, `tooltip`, `dropdown`, `modal`) for light and
|
|
74
|
+
dark modes, unblocking the matching recipe work in `TODO.md`. Raised the
|
|
75
|
+
`components.css` size budget in `tests/css-entrypoints.test.ts` from 88000 to
|
|
76
|
+
92000 bytes to account for the additional bundled token variables.
|
|
77
|
+
|
|
78
|
+
## [1.8.0] - 2026-06-07
|
|
79
|
+
|
|
80
|
+
Release Title: Spinner Contract and Token Focus Alignment
|
|
81
|
+
|
|
82
|
+
Contract change type: additive
|
|
83
|
+
|
|
84
|
+
### Added
|
|
85
|
+
|
|
86
|
+
- **Spinner Component**: Added standard brand and status variants (`primary`,
|
|
87
|
+
`secondary`, `success`, `warning`, `danger`, `info`, `neutral`, `accent`,
|
|
88
|
+
`cta`) and states (`disabled`, `loading` with `[aria-busy="true"]` support).
|
|
89
|
+
- Added `@phcdevworks/spectre-manifest` as a devDependency. `spectre.manifest.json`
|
|
90
|
+
at the repo root declares this package's ecosystem role, layer, exports, and
|
|
91
|
+
allowed dependency targets. `check:ecosystem` validates it in the check pipeline.
|
|
92
|
+
- **Token Alignment**: Updated `@phcdevworks/spectre-tokens` dependency to
|
|
93
|
+
`^2.8.0`.
|
|
94
|
+
- **Button Focus Ring Parity**: Consumed `buttons.danger.focusVisible` and
|
|
95
|
+
`buttons.success.focusVisible` tokens newly published in `2.8.0`. Danger and
|
|
96
|
+
success button variants now render a semantically correct focus ring (red and
|
|
97
|
+
green alpha respectively) on `:focus-visible`, matching the parity already
|
|
98
|
+
present for primary, secondary, ghost, and accent variants.
|
|
99
|
+
|
|
9
100
|
## [1.7.0] - 2026-06-03
|
|
10
101
|
|
|
11
102
|
Release Title: Tag Variant Expansion and Token Alignment
|
package/README.md
CHANGED
|
@@ -27,25 +27,25 @@ belongs in adapter packages such as `@phcdevworks/spectre-ui-astro`).
|
|
|
27
27
|
semantic meaning. `ui-contract.manifest.json` is the machine-readable contract
|
|
28
28
|
authority for this package's public styling surface.
|
|
29
29
|
|
|
30
|
-
| Layer
|
|
31
|
-
|
|
32
|
-
| Token authority
|
|
33
|
-
| UI contract authority | `ui-contract.manifest.json`
|
|
34
|
-
| Source CSS
|
|
35
|
-
| Source recipes
|
|
36
|
-
| Tailwind helpers
|
|
37
|
-
| Generated dist
|
|
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` |
|
|
38
38
|
|
|
39
39
|
After any contract-facing source change: run `npm run check` to validate the
|
|
40
40
|
full UI contract.
|
|
41
41
|
|
|
42
42
|
## Architecture
|
|
43
43
|
|
|
44
|
-
| Layer | Package or consumer
|
|
45
|
-
|
|
46
|
-
| 1
|
|
47
|
-
| 2
|
|
48
|
-
| 3
|
|
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 |
|
|
49
49
|
|
|
50
50
|
`@phcdevworks/spectre-components` is a separate component package that can wrap
|
|
51
51
|
this styling contract in Lit web components. This package owns Layer 2 only: it
|
|
@@ -71,8 +71,8 @@ does not deliver components and it does not define tokens.
|
|
|
71
71
|
- Tailwind preset and theme helpers in `src/tailwind/`
|
|
72
72
|
- Contract validation that keeps CSS, recipes, exports, and docs aligned
|
|
73
73
|
|
|
74
|
-
This package is the correct place to define reusable styling structure on top
|
|
75
|
-
|
|
74
|
+
This package is the correct place to define reusable styling structure on top of
|
|
75
|
+
Spectre tokens.
|
|
76
76
|
|
|
77
77
|
## What this package does not own
|
|
78
78
|
|
|
@@ -100,7 +100,10 @@ No framework needed. Import the CSS and use the `sp-*` classes directly:
|
|
|
100
100
|
<!doctype html>
|
|
101
101
|
<html>
|
|
102
102
|
<head>
|
|
103
|
-
<link
|
|
103
|
+
<link
|
|
104
|
+
rel="stylesheet"
|
|
105
|
+
href="node_modules/@phcdevworks/spectre-ui/dist/index.css"
|
|
106
|
+
/>
|
|
104
107
|
</head>
|
|
105
108
|
<body>
|
|
106
109
|
<button class="sp-btn sp-btn--primary sp-btn--md">Save</button>
|
|
@@ -197,17 +200,17 @@ Do not use `@phcdevworks/spectre-ui` when you need to:
|
|
|
197
200
|
|
|
198
201
|
## What belongs here vs elsewhere
|
|
199
202
|
|
|
200
|
-
| What
|
|
201
|
-
|
|
202
|
-
| Semantic color values, spacing scale, type scale | `@phcdevworks/spectre-tokens`
|
|
203
|
-
| Token-to-CSS variable mapping
|
|
204
|
-
| Precompiled CSS bundles
|
|
205
|
-
| Class recipe functions (input → class string)
|
|
206
|
-
| Tailwind preset and theme helpers
|
|
207
|
-
| Astro, React, Vue, Lit, Svelte components
|
|
208
|
-
| WordPress shortcodes or PHP templates
|
|
209
|
-
| App-level layout, routing, or data fetching
|
|
210
|
-
| New design decisions (new colors, new spacing)
|
|
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` |
|
|
211
214
|
|
|
212
215
|
Golden rule: this package consumes tokens and exposes class contracts. It does
|
|
213
216
|
not define tokens and it does not deliver framework components.
|
|
@@ -219,21 +222,26 @@ not define tokens and it does not deliver framework components.
|
|
|
219
222
|
All recipe functions accept a plain options object and return a class string.
|
|
220
223
|
All options are optional and fall back to sensible defaults.
|
|
221
224
|
|
|
222
|
-
| Recipe
|
|
223
|
-
|
|
224
|
-
| Button
|
|
225
|
-
| Badge
|
|
226
|
-
| Card
|
|
227
|
-
| Input
|
|
228
|
-
| Input state | `getInputClasses`
|
|
229
|
-
| IconBox
|
|
230
|
-
| PricingCard | `getPricingCardClasses` | —
|
|
231
|
-
| Rating
|
|
232
|
-
| Testimonial | `getTestimonialClasses` | `elevated` `flat` `outline` `ghost`
|
|
233
|
-
| Alert
|
|
234
|
-
| Avatar
|
|
235
|
-
| Tag
|
|
236
|
-
| Spinner
|
|
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` | — |
|
|
240
|
+
| Nav | `getNavClasses` | — | — | `bordered` `sticky` `fullWidth` |
|
|
241
|
+
| Toast | `getToastClasses` | `info` `success` `warning` `danger` | — | `dismissed` `fullWidth` |
|
|
242
|
+
| Tooltip | `getTooltipClasses` | placement: `top` `bottom` `left` `right` | — | `visible` |
|
|
243
|
+
| Dropdown | `getDropdownClasses` | menu placement: `bottom-start` `bottom-end` `top-start` `top-end` | — | `fullWidth`, item: `active` `disabled` |
|
|
244
|
+
| Modal | `getModalClasses` | — | — | `open` `fullWidth` |
|
|
237
245
|
|
|
238
246
|
Each recipe family also exports sub-element helpers for its structural parts
|
|
239
247
|
(labels, wrappers, sub-containers, text elements). See the full list below.
|
|
@@ -258,20 +266,30 @@ Root recipe functions:
|
|
|
258
266
|
- `getBadgeClasses`
|
|
259
267
|
- `getButtonClasses`
|
|
260
268
|
- `getCardClasses`
|
|
269
|
+
- `getDropdownClasses`
|
|
261
270
|
- `getIconBoxClasses`
|
|
262
271
|
- `getInputClasses`
|
|
272
|
+
- `getModalClasses`
|
|
273
|
+
- `getNavClasses`
|
|
263
274
|
- `getPricingCardClasses`
|
|
264
275
|
- `getRatingClasses`
|
|
265
276
|
- `getSpinnerClasses`
|
|
266
277
|
- `getTagClasses`
|
|
267
278
|
- `getTestimonialClasses`
|
|
279
|
+
- `getToastClasses`
|
|
280
|
+
- `getTooltipClasses`
|
|
268
281
|
|
|
269
282
|
Root recipe helper functions:
|
|
270
283
|
|
|
284
|
+
- `getDropdownItemClasses`
|
|
285
|
+
- `getDropdownMenuClasses`
|
|
271
286
|
- `getInputErrorMessageClasses`
|
|
272
287
|
- `getInputHelperTextClasses`
|
|
273
288
|
- `getInputLabelClasses`
|
|
274
289
|
- `getInputWrapperClasses`
|
|
290
|
+
- `getModalOverlayClasses`
|
|
291
|
+
- `getNavLinkClasses`
|
|
292
|
+
- `getNavLinksClasses`
|
|
275
293
|
- `getPricingCardBadgeClasses`
|
|
276
294
|
- `getPricingCardDescriptionClasses`
|
|
277
295
|
- `getPricingCardPriceClasses`
|
|
@@ -284,6 +302,7 @@ Root recipe helper functions:
|
|
|
284
302
|
- `getTestimonialAuthorNameClasses`
|
|
285
303
|
- `getTestimonialAuthorTitleClasses`
|
|
286
304
|
- `getTestimonialQuoteClasses`
|
|
305
|
+
- `getToastIconClasses`
|
|
287
306
|
|
|
288
307
|
The root package also re-exports the related recipe option, variant, size, and
|
|
289
308
|
state TypeScript types defined by those recipes.
|
|
@@ -344,8 +363,8 @@ Practical guidance:
|
|
|
344
363
|
|
|
345
364
|
- additive recipes, variants, states, and helpers are intended to be safe for
|
|
346
365
|
existing consumers
|
|
347
|
-
- semantic shifts may keep the same class or option name but still affect
|
|
348
|
-
|
|
366
|
+
- semantic shifts may keep the same class or option name but still affect visual
|
|
367
|
+
output
|
|
349
368
|
- renames, removals, and behavior changes to existing classes or options are
|
|
350
369
|
breaking
|
|
351
370
|
- generated JS, TypeScript declarations, CSS bundles, Tailwind exports, README
|
|
@@ -363,11 +382,11 @@ Tailwind helper:
|
|
|
363
382
|
Contract-affecting changes should be classified in `CHANGELOG.md [Unreleased]`
|
|
364
383
|
before release.
|
|
365
384
|
|
|
366
|
-
| Classification
|
|
367
|
-
|
|
368
|
-
| `additive`
|
|
369
|
-
| `semantic change` | Public name remains but behavior or visual meaning shifts
|
|
370
|
-
| `breaking`
|
|
385
|
+
| Classification | When to use | Examples |
|
|
386
|
+
| ----------------- | ----------------------------------------------------------------- | ----------------------------------------------------------------------------- |
|
|
387
|
+
| `additive` | New public styling surface that does not break existing consumers | Adding a recipe helper, variant, state, or CSS entry point |
|
|
388
|
+
| `semantic change` | Public name remains but behavior or visual meaning shifts | Adjusting an existing class or recipe option to map to different token intent |
|
|
389
|
+
| `breaking` | Existing consumers may need code changes | Renaming or removing a class, option, export, or CSS entry point |
|
|
371
390
|
|
|
372
391
|
Renames and removals are always breaking regardless of perceived scope.
|
|
373
392
|
|
|
@@ -413,28 +432,28 @@ npm install
|
|
|
413
432
|
npm run ci:verify
|
|
414
433
|
```
|
|
415
434
|
|
|
416
|
-
This project requires Node.js `^22.13.0 || >=24.0.0` and npm `>=10.0.0`.
|
|
417
|
-
|
|
435
|
+
This project requires Node.js `^22.13.0 || >=24.0.0` and npm `>=10.0.0`. The
|
|
436
|
+
checked-in package manager is `npm@11.16.0`.
|
|
418
437
|
|
|
419
438
|
### Common commands
|
|
420
439
|
|
|
421
|
-
| Command
|
|
422
|
-
|
|
423
|
-
| `npm run check`
|
|
424
|
-
| `npm run ci:verify`
|
|
425
|
-
| `npm test`
|
|
426
|
-
| `npm run build`
|
|
427
|
-
| `npm run lint`
|
|
428
|
-
| `npm run validate:exports`
|
|
429
|
-
| `npm run validate:exports:update`
|
|
430
|
-
| `npm run validate:tailwind`
|
|
431
|
-
| `npm run validate:tailwind:update` | Update the Tailwind export snapshot
|
|
432
|
-
| `npm run validate:tokens`
|
|
440
|
+
| Command | What it does |
|
|
441
|
+
| ---------------------------------- | -------------------------------------------------------- |
|
|
442
|
+
| `npm run check` | Full validation gate — run before every PR |
|
|
443
|
+
| `npm run ci:verify` | Underlying verification sequence used by `npm run check` |
|
|
444
|
+
| `npm test` | Build then run the contract and regression test suite |
|
|
445
|
+
| `npm run build` | Emit TypeScript and CSS artifacts to `dist/` |
|
|
446
|
+
| `npm run lint` | ESLint with TypeScript-aware config |
|
|
447
|
+
| `npm run validate:exports` | Verify root export surface against snapshot |
|
|
448
|
+
| `npm run validate:exports:update` | Update the export snapshot after adding a public export |
|
|
449
|
+
| `npm run validate:tailwind` | Verify Tailwind exports and emitted subpath artifacts |
|
|
450
|
+
| `npm run validate:tailwind:update` | Update the Tailwind export snapshot |
|
|
451
|
+
| `npm run validate:tokens` | Check for token drift against latest published release |
|
|
433
452
|
|
|
434
453
|
### Troubleshooting
|
|
435
454
|
|
|
436
|
-
**`validate:runtime` fails** — you are on the wrong Node version. Run
|
|
437
|
-
|
|
455
|
+
**`validate:runtime` fails** — you are on the wrong Node version. Run `nvm use`
|
|
456
|
+
to switch to the version in `.nvmrc`, or install Node 22 or 24.
|
|
438
457
|
|
|
439
458
|
**`validate:tokens` fails with a network error** — the check requires outbound
|
|
440
459
|
npm registry access. In a restricted environment, run the other validators
|
|
@@ -445,8 +464,8 @@ automatically via the `pretest` hook. If you ran `vitest` directly, run
|
|
|
445
464
|
`npm run build` first.
|
|
446
465
|
|
|
447
466
|
**Lint fails locally but passes in CI** — confirm you are on the same Node
|
|
448
|
-
version as CI (Node 22.x or 24.x). ESLint plugin resolution can differ
|
|
449
|
-
|
|
467
|
+
version as CI (Node 22.x or 24.x). ESLint plugin resolution can differ across
|
|
468
|
+
runtimes.
|
|
450
469
|
|
|
451
470
|
**Export snapshot out of date** — run `npm run validate:exports:update` after
|
|
452
471
|
adding a public export, then commit the updated `scripts/export-snapshot.json`.
|
|
@@ -462,6 +481,13 @@ adding a public export, then commit the updated `scripts/export-snapshot.json`.
|
|
|
462
481
|
Planning artifacts for contract hardening live in [ROADMAP.md](ROADMAP.md) and
|
|
463
482
|
[TODO.md](TODO.md).
|
|
464
483
|
|
|
484
|
+
The current roadmap focus is post-v1.7.0 expansion: consume newly published
|
|
485
|
+
Spectre token contracts for links, interactive surfaces, dividers, and common
|
|
486
|
+
application UI patterns before adding matching Layer 2 classes or recipes.
|
|
487
|
+
Planned upstream token work is tracked in
|
|
488
|
+
[`@phcdevworks/spectre-tokens`](https://github.com/phcdevworks/spectre-tokens),
|
|
489
|
+
but this package synchronizes only against published npm releases.
|
|
490
|
+
|
|
465
491
|
## Examples
|
|
466
492
|
|
|
467
493
|
Use [`examples/examples.html`](examples/examples.html) as the visual index for
|
|
@@ -481,16 +507,16 @@ Run the full validation gate before any pull request:
|
|
|
481
507
|
npm run check
|
|
482
508
|
```
|
|
483
509
|
|
|
484
|
-
This runs: runtime check → lint →
|
|
485
|
-
token drift check → build → Tailwind contract → CSS contract
|
|
486
|
-
steps must pass.
|
|
510
|
+
This runs: runtime check → lint → changelog validation → export validation →
|
|
511
|
+
README validation → token drift check → build → Tailwind contract → CSS contract
|
|
512
|
+
→ tests. All steps must pass.
|
|
487
513
|
|
|
488
514
|
## AI and automation boundaries
|
|
489
515
|
|
|
490
516
|
Claude Code (`claude-sonnet-4-6`) is the primary development agent for this
|
|
491
517
|
repository. Codex handles releases and production stabilization. Jules handles
|
|
492
|
-
small automated fixes and token sync passes. GitHub Copilot provides
|
|
493
|
-
|
|
518
|
+
small automated fixes and token sync passes. GitHub Copilot provides development
|
|
519
|
+
support.
|
|
494
520
|
|
|
495
521
|
Claude Code, Codex, and Copilot do not create git commits by default. Jules may
|
|
496
522
|
commit only bounded automated maintenance when the `JULES.md` scope and
|
package/dist/base.css
CHANGED
|
@@ -37,6 +37,41 @@
|
|
|
37
37
|
--sp-icon-box-icon-success: #16a34a;
|
|
38
38
|
--sp-icon-box-icon-warning: #d48806;
|
|
39
39
|
--sp-icon-box-icon-danger: #dc2626;
|
|
40
|
+
--sp-nav-bg: #ffffff;
|
|
41
|
+
--sp-nav-text: #141b24;
|
|
42
|
+
--sp-nav-link: #374253;
|
|
43
|
+
--sp-nav-link-hover: #1f57db;
|
|
44
|
+
--sp-nav-link-active: #1946b4;
|
|
45
|
+
--sp-nav-border: #d9dfeb;
|
|
46
|
+
--sp-modal-bg: #ffffff;
|
|
47
|
+
--sp-modal-shadow: 0 20px 48px -12px rgba(0, 0, 0, 0.20);
|
|
48
|
+
--sp-modal-border: #d9dfeb;
|
|
49
|
+
--sp-modal-overlay: rgba(0, 0, 0, 0.6);
|
|
50
|
+
--sp-toast-success-bg: #f0fdf4;
|
|
51
|
+
--sp-toast-success-text: #166534;
|
|
52
|
+
--sp-toast-success-border: #bbf7d0;
|
|
53
|
+
--sp-toast-success-icon: #16a34a;
|
|
54
|
+
--sp-toast-warning-bg: #fffbea;
|
|
55
|
+
--sp-toast-warning-text: #8f5200;
|
|
56
|
+
--sp-toast-warning-border: #ffe08a;
|
|
57
|
+
--sp-toast-warning-icon: #d48806;
|
|
58
|
+
--sp-toast-danger-bg: #fef2f2;
|
|
59
|
+
--sp-toast-danger-text: #991b1b;
|
|
60
|
+
--sp-toast-danger-border: #fecaca;
|
|
61
|
+
--sp-toast-danger-icon: #dc2626;
|
|
62
|
+
--sp-toast-info-bg: #f0f9ff;
|
|
63
|
+
--sp-toast-info-text: #0c4a6e;
|
|
64
|
+
--sp-toast-info-border: #bae6fd;
|
|
65
|
+
--sp-toast-info-icon: #0369a1;
|
|
66
|
+
--sp-tooltip-bg: #141b24;
|
|
67
|
+
--sp-tooltip-text: #ffffff;
|
|
68
|
+
--sp-tooltip-border: #374253;
|
|
69
|
+
--sp-dropdown-bg: #ffffff;
|
|
70
|
+
--sp-dropdown-border: #d9dfeb;
|
|
71
|
+
--sp-dropdown-item-default: transparent;
|
|
72
|
+
--sp-dropdown-item-hover: #eef1f6;
|
|
73
|
+
--sp-dropdown-item-active: #f0f9ff;
|
|
74
|
+
--sp-dropdown-item-text: #141b24;
|
|
40
75
|
--sp-color-brand-50: #eef4ff;
|
|
41
76
|
--sp-color-brand-100: #d9e7ff;
|
|
42
77
|
--sp-color-brand-200: #b9d2ff;
|
|
@@ -116,17 +151,24 @@
|
|
|
116
151
|
--sp-color-white: #ffffff;
|
|
117
152
|
--sp-color-black: #000000;
|
|
118
153
|
--sp-space-0: 0rem;
|
|
154
|
+
--sp-space-1: 0.0625rem;
|
|
155
|
+
--sp-space-2: 0.125rem;
|
|
119
156
|
--sp-space-4: 0.25rem;
|
|
157
|
+
--sp-space-6: 0.375rem;
|
|
120
158
|
--sp-space-8: 0.5rem;
|
|
159
|
+
--sp-space-10: 0.625rem;
|
|
121
160
|
--sp-space-12: 0.75rem;
|
|
161
|
+
--sp-space-14: 0.875rem;
|
|
122
162
|
--sp-space-16: 1rem;
|
|
123
163
|
--sp-space-20: 1.25rem;
|
|
124
164
|
--sp-space-24: 1.5rem;
|
|
165
|
+
--sp-space-28: 1.75rem;
|
|
125
166
|
--sp-space-32: 2rem;
|
|
126
167
|
--sp-space-40: 2.5rem;
|
|
127
168
|
--sp-space-48: 3rem;
|
|
128
169
|
--sp-space-56: 3.5rem;
|
|
129
170
|
--sp-space-64: 4rem;
|
|
171
|
+
--sp-space-72: 4.5rem;
|
|
130
172
|
--sp-space-80: 5rem;
|
|
131
173
|
--sp-space-96: 6rem;
|
|
132
174
|
--sp-layout-section-padding-sm: 1.5rem;
|
|
@@ -142,16 +184,21 @@
|
|
|
142
184
|
--sp-layout-container-padding-inline-md: 1.5rem;
|
|
143
185
|
--sp-layout-container-padding-inline-lg: 2rem;
|
|
144
186
|
--sp-layout-container-max-width: 72rem;
|
|
187
|
+
--sp-border-width-none: 0;
|
|
145
188
|
--sp-border-width-base: 1px;
|
|
146
189
|
--sp-border-width-thick: 2px;
|
|
147
190
|
--sp-border-style-none: none;
|
|
148
191
|
--sp-border-style-solid: solid;
|
|
192
|
+
--sp-border-style-dashed: dashed;
|
|
193
|
+
--sp-border-style-dotted: dotted;
|
|
149
194
|
--sp-radius-none: 0;
|
|
150
195
|
--sp-radius-sm: 2px;
|
|
151
196
|
--sp-radius-md: 4px;
|
|
152
197
|
--sp-radius-lg: 8px;
|
|
153
198
|
--sp-radius-xl: 12px;
|
|
154
199
|
--sp-radius-2xl: 16px;
|
|
200
|
+
--sp-radius-3xl: 24px;
|
|
201
|
+
--sp-radius-4xl: 32px;
|
|
155
202
|
--sp-radius-pill: 999px;
|
|
156
203
|
--sp-font-family-sans: system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif;
|
|
157
204
|
--sp-font-family-serif: 'Times New Roman', Times, serif;
|
|
@@ -216,6 +263,7 @@
|
|
|
216
263
|
--sp-z-index-popover: 1500;
|
|
217
264
|
--sp-z-index-tooltip: 1600;
|
|
218
265
|
--sp-z-index-toast: 1700;
|
|
266
|
+
--sp-duration-reduced: 0.01ms;
|
|
219
267
|
--sp-duration-instant: 75ms;
|
|
220
268
|
--sp-duration-fast: 150ms;
|
|
221
269
|
--sp-duration-base: 200ms;
|
|
@@ -243,6 +291,7 @@
|
|
|
243
291
|
--sp-focus-ring-style: solid;
|
|
244
292
|
--sp-min-touch-target: 44px;
|
|
245
293
|
--sp-min-text-size: 16px;
|
|
294
|
+
--sp-reduced-motion: 0.01ms;
|
|
246
295
|
--sp-button-primary-bg: #0369a1;
|
|
247
296
|
--sp-button-primary-bghover: #075985;
|
|
248
297
|
--sp-button-primary-bgactive: #0c4a6e;
|
|
@@ -276,6 +325,7 @@
|
|
|
276
325
|
--sp-button-danger-text: #ffffff;
|
|
277
326
|
--sp-button-danger-textdisabled: #8a96ad;
|
|
278
327
|
--sp-button-danger-focusring: rgba(239, 68, 68, 0.4);
|
|
328
|
+
--sp-button-danger-focusvisible: rgba(239, 68, 68, 0.4);
|
|
279
329
|
--sp-button-success-bg: #15803d;
|
|
280
330
|
--sp-button-success-bghover: #166534;
|
|
281
331
|
--sp-button-success-bgactive: #14532d;
|
|
@@ -283,6 +333,7 @@
|
|
|
283
333
|
--sp-button-success-text: #ffffff;
|
|
284
334
|
--sp-button-success-textdisabled: #8a96ad;
|
|
285
335
|
--sp-button-success-focusring: rgba(34, 197, 94, 0.4);
|
|
336
|
+
--sp-button-success-focusvisible: rgba(34, 197, 94, 0.4);
|
|
286
337
|
--sp-button-cta-bg: #1f57db;
|
|
287
338
|
--sp-button-cta-bghover: #1946b4;
|
|
288
339
|
--sp-button-cta-bgactive: #173b8f;
|
|
@@ -341,6 +392,30 @@
|
|
|
341
392
|
--sp-animation-pulse-duration: 1200ms;
|
|
342
393
|
--sp-animation-pulse-easing: cubic-bezier(0.4, 0, 0.2, 1);
|
|
343
394
|
--sp-animation-pulse-keyframes: pulse;
|
|
395
|
+
--sp-animation-reduced-motion-fadein-duration: 0.01ms;
|
|
396
|
+
--sp-animation-reduced-motion-fadein-easing: linear;
|
|
397
|
+
--sp-animation-reduced-motion-fadein-keyframes: fade-in;
|
|
398
|
+
--sp-animation-reduced-motion-fadeout-duration: 0.01ms;
|
|
399
|
+
--sp-animation-reduced-motion-fadeout-easing: linear;
|
|
400
|
+
--sp-animation-reduced-motion-fadeout-keyframes: fade-out;
|
|
401
|
+
--sp-animation-reduced-motion-slideup-duration: 0.01ms;
|
|
402
|
+
--sp-animation-reduced-motion-slideup-easing: linear;
|
|
403
|
+
--sp-animation-reduced-motion-slideup-keyframes: slide-up;
|
|
404
|
+
--sp-animation-reduced-motion-slidedown-duration: 0.01ms;
|
|
405
|
+
--sp-animation-reduced-motion-slidedown-easing: linear;
|
|
406
|
+
--sp-animation-reduced-motion-slidedown-keyframes: slide-down;
|
|
407
|
+
--sp-animation-reduced-motion-scalein-duration: 0.01ms;
|
|
408
|
+
--sp-animation-reduced-motion-scalein-easing: linear;
|
|
409
|
+
--sp-animation-reduced-motion-scalein-keyframes: scale-in;
|
|
410
|
+
--sp-animation-reduced-motion-bounce-duration: 0.01ms;
|
|
411
|
+
--sp-animation-reduced-motion-bounce-easing: linear;
|
|
412
|
+
--sp-animation-reduced-motion-bounce-keyframes: bounce;
|
|
413
|
+
--sp-animation-reduced-motion-shake-duration: 0.01ms;
|
|
414
|
+
--sp-animation-reduced-motion-shake-easing: linear;
|
|
415
|
+
--sp-animation-reduced-motion-shake-keyframes: shake;
|
|
416
|
+
--sp-animation-reduced-motion-pulse-duration: 0.01ms;
|
|
417
|
+
--sp-animation-reduced-motion-pulse-easing: linear;
|
|
418
|
+
--sp-animation-reduced-motion-pulse-keyframes: pulse;
|
|
344
419
|
}
|
|
345
420
|
:root[data-spectre-theme="dark"] {
|
|
346
421
|
--sp-surface-page: #141b24;
|
|
@@ -381,6 +456,41 @@
|
|
|
381
456
|
--sp-icon-box-icon-success: #4ade80;
|
|
382
457
|
--sp-icon-box-icon-warning: #ffc21a;
|
|
383
458
|
--sp-icon-box-icon-danger: #f87171;
|
|
459
|
+
--sp-nav-bg: #141b24;
|
|
460
|
+
--sp-nav-text: #f7f8fb;
|
|
461
|
+
--sp-nav-link: #b7c1d4;
|
|
462
|
+
--sp-nav-link-hover: #5a92ff;
|
|
463
|
+
--sp-nav-link-active: #8ab6ff;
|
|
464
|
+
--sp-nav-border: #374253;
|
|
465
|
+
--sp-modal-bg: #222b38;
|
|
466
|
+
--sp-modal-shadow: 0 20px 48px -12px rgba(0, 0, 0, 0.20);
|
|
467
|
+
--sp-modal-border: #374253;
|
|
468
|
+
--sp-modal-overlay: rgba(0, 0, 0, 0.6);
|
|
469
|
+
--sp-toast-success-bg: #14532d;
|
|
470
|
+
--sp-toast-success-text: #dcfce7;
|
|
471
|
+
--sp-toast-success-border: #15803d;
|
|
472
|
+
--sp-toast-success-icon: #4ade80;
|
|
473
|
+
--sp-toast-warning-bg: #734000;
|
|
474
|
+
--sp-toast-warning-text: #fff1c2;
|
|
475
|
+
--sp-toast-warning-border: #ad6800;
|
|
476
|
+
--sp-toast-warning-icon: #ffc21a;
|
|
477
|
+
--sp-toast-danger-bg: #7f1d1d;
|
|
478
|
+
--sp-toast-danger-text: #fee2e2;
|
|
479
|
+
--sp-toast-danger-border: #b91c1c;
|
|
480
|
+
--sp-toast-danger-icon: #f87171;
|
|
481
|
+
--sp-toast-info-bg: #082f49;
|
|
482
|
+
--sp-toast-info-text: #e0f2fe;
|
|
483
|
+
--sp-toast-info-border: #075985;
|
|
484
|
+
--sp-toast-info-icon: #38bdf8;
|
|
485
|
+
--sp-tooltip-bg: #f7f8fb;
|
|
486
|
+
--sp-tooltip-text: #141b24;
|
|
487
|
+
--sp-tooltip-border: #b7c1d4;
|
|
488
|
+
--sp-dropdown-bg: #222b38;
|
|
489
|
+
--sp-dropdown-border: #374253;
|
|
490
|
+
--sp-dropdown-item-default: transparent;
|
|
491
|
+
--sp-dropdown-item-hover: #374253;
|
|
492
|
+
--sp-dropdown-item-active: #082f49;
|
|
493
|
+
--sp-dropdown-item-text: #eef1f6;
|
|
384
494
|
}
|
|
385
495
|
@layer base {
|
|
386
496
|
|