@phcdevworks/spectre-ui 1.7.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 +22 -0
- package/README.md +82 -72
- package/dist/base.css +14 -0
- package/dist/components.css +110 -0
- package/dist/index.cjs +36 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +110 -0
- package/dist/index.d.cts +18 -1
- package/dist/index.d.ts +18 -1
- package/dist/index.js +36 -4
- package/dist/index.js.map +1 -1
- package/dist/utilities.css +14 -0
- package/package.json +7 -5
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,28 @@ 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
|
+
|
|
9
31
|
## [1.7.0] - 2026-06-03
|
|
10
32
|
|
|
11
33
|
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,21 @@ 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` | — |
|
|
237
240
|
|
|
238
241
|
Each recipe family also exports sub-element helpers for its structural parts
|
|
239
242
|
(labels, wrappers, sub-containers, text elements). See the full list below.
|
|
@@ -344,8 +347,8 @@ Practical guidance:
|
|
|
344
347
|
|
|
345
348
|
- additive recipes, variants, states, and helpers are intended to be safe for
|
|
346
349
|
existing consumers
|
|
347
|
-
- semantic shifts may keep the same class or option name but still affect
|
|
348
|
-
|
|
350
|
+
- semantic shifts may keep the same class or option name but still affect visual
|
|
351
|
+
output
|
|
349
352
|
- renames, removals, and behavior changes to existing classes or options are
|
|
350
353
|
breaking
|
|
351
354
|
- generated JS, TypeScript declarations, CSS bundles, Tailwind exports, README
|
|
@@ -363,11 +366,11 @@ Tailwind helper:
|
|
|
363
366
|
Contract-affecting changes should be classified in `CHANGELOG.md [Unreleased]`
|
|
364
367
|
before release.
|
|
365
368
|
|
|
366
|
-
| Classification
|
|
367
|
-
|
|
368
|
-
| `additive`
|
|
369
|
-
| `semantic change` | Public name remains but behavior or visual meaning shifts
|
|
370
|
-
| `breaking`
|
|
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 |
|
|
371
374
|
|
|
372
375
|
Renames and removals are always breaking regardless of perceived scope.
|
|
373
376
|
|
|
@@ -413,28 +416,28 @@ npm install
|
|
|
413
416
|
npm run ci:verify
|
|
414
417
|
```
|
|
415
418
|
|
|
416
|
-
This project requires Node.js `^22.13.0 || >=24.0.0` and npm `>=10.0.0`.
|
|
417
|
-
|
|
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`.
|
|
418
421
|
|
|
419
422
|
### Common commands
|
|
420
423
|
|
|
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`
|
|
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 |
|
|
433
436
|
|
|
434
437
|
### Troubleshooting
|
|
435
438
|
|
|
436
|
-
**`validate:runtime` fails** — you are on the wrong Node version. Run
|
|
437
|
-
|
|
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.
|
|
438
441
|
|
|
439
442
|
**`validate:tokens` fails with a network error** — the check requires outbound
|
|
440
443
|
npm registry access. In a restricted environment, run the other validators
|
|
@@ -445,8 +448,8 @@ automatically via the `pretest` hook. If you ran `vitest` directly, run
|
|
|
445
448
|
`npm run build` first.
|
|
446
449
|
|
|
447
450
|
**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
|
-
|
|
451
|
+
version as CI (Node 22.x or 24.x). ESLint plugin resolution can differ across
|
|
452
|
+
runtimes.
|
|
450
453
|
|
|
451
454
|
**Export snapshot out of date** — run `npm run validate:exports:update` after
|
|
452
455
|
adding a public export, then commit the updated `scripts/export-snapshot.json`.
|
|
@@ -462,6 +465,13 @@ adding a public export, then commit the updated `scripts/export-snapshot.json`.
|
|
|
462
465
|
Planning artifacts for contract hardening live in [ROADMAP.md](ROADMAP.md) and
|
|
463
466
|
[TODO.md](TODO.md).
|
|
464
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
|
+
|
|
465
475
|
## Examples
|
|
466
476
|
|
|
467
477
|
Use [`examples/examples.html`](examples/examples.html) as the visual index for
|
|
@@ -481,16 +491,16 @@ Run the full validation gate before any pull request:
|
|
|
481
491
|
npm run check
|
|
482
492
|
```
|
|
483
493
|
|
|
484
|
-
This runs: runtime check → lint →
|
|
485
|
-
token drift check → build → Tailwind contract → CSS contract
|
|
486
|
-
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.
|
|
487
497
|
|
|
488
498
|
## AI and automation boundaries
|
|
489
499
|
|
|
490
500
|
Claude Code (`claude-sonnet-4-6`) is the primary development agent for this
|
|
491
501
|
repository. Codex handles releases and production stabilization. Jules handles
|
|
492
|
-
small automated fixes and token sync passes. GitHub Copilot provides
|
|
493
|
-
|
|
502
|
+
small automated fixes and token sync passes. GitHub Copilot provides development
|
|
503
|
+
support.
|
|
494
504
|
|
|
495
505
|
Claude Code, Codex, and Copilot do not create git commits by default. Jules may
|
|
496
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,16 +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;
|
|
147
155
|
--sp-border-style-none: none;
|
|
148
156
|
--sp-border-style-solid: solid;
|
|
157
|
+
--sp-border-style-dashed: dashed;
|
|
158
|
+
--sp-border-style-dotted: dotted;
|
|
149
159
|
--sp-radius-none: 0;
|
|
150
160
|
--sp-radius-sm: 2px;
|
|
151
161
|
--sp-radius-md: 4px;
|
|
152
162
|
--sp-radius-lg: 8px;
|
|
153
163
|
--sp-radius-xl: 12px;
|
|
154
164
|
--sp-radius-2xl: 16px;
|
|
165
|
+
--sp-radius-3xl: 24px;
|
|
166
|
+
--sp-radius-4xl: 32px;
|
|
155
167
|
--sp-radius-pill: 999px;
|
|
156
168
|
--sp-font-family-sans: system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif;
|
|
157
169
|
--sp-font-family-serif: 'Times New Roman', Times, serif;
|
|
@@ -276,6 +288,7 @@
|
|
|
276
288
|
--sp-button-danger-text: #ffffff;
|
|
277
289
|
--sp-button-danger-textdisabled: #8a96ad;
|
|
278
290
|
--sp-button-danger-focusring: rgba(239, 68, 68, 0.4);
|
|
291
|
+
--sp-button-danger-focusvisible: rgba(239, 68, 68, 0.4);
|
|
279
292
|
--sp-button-success-bg: #15803d;
|
|
280
293
|
--sp-button-success-bghover: #166534;
|
|
281
294
|
--sp-button-success-bgactive: #14532d;
|
|
@@ -283,6 +296,7 @@
|
|
|
283
296
|
--sp-button-success-text: #ffffff;
|
|
284
297
|
--sp-button-success-textdisabled: #8a96ad;
|
|
285
298
|
--sp-button-success-focusring: rgba(34, 197, 94, 0.4);
|
|
299
|
+
--sp-button-success-focusvisible: rgba(34, 197, 94, 0.4);
|
|
286
300
|
--sp-button-cta-bg: #1f57db;
|
|
287
301
|
--sp-button-cta-bghover: #1946b4;
|
|
288
302
|
--sp-button-cta-bgactive: #173b8f;
|
package/dist/components.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,16 +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;
|
|
147
155
|
--sp-border-style-none: none;
|
|
148
156
|
--sp-border-style-solid: solid;
|
|
157
|
+
--sp-border-style-dashed: dashed;
|
|
158
|
+
--sp-border-style-dotted: dotted;
|
|
149
159
|
--sp-radius-none: 0;
|
|
150
160
|
--sp-radius-sm: 2px;
|
|
151
161
|
--sp-radius-md: 4px;
|
|
152
162
|
--sp-radius-lg: 8px;
|
|
153
163
|
--sp-radius-xl: 12px;
|
|
154
164
|
--sp-radius-2xl: 16px;
|
|
165
|
+
--sp-radius-3xl: 24px;
|
|
166
|
+
--sp-radius-4xl: 32px;
|
|
155
167
|
--sp-radius-pill: 999px;
|
|
156
168
|
--sp-font-family-sans: system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif;
|
|
157
169
|
--sp-font-family-serif: 'Times New Roman', Times, serif;
|
|
@@ -276,6 +288,7 @@
|
|
|
276
288
|
--sp-button-danger-text: #ffffff;
|
|
277
289
|
--sp-button-danger-textdisabled: #8a96ad;
|
|
278
290
|
--sp-button-danger-focusring: rgba(239, 68, 68, 0.4);
|
|
291
|
+
--sp-button-danger-focusvisible: rgba(239, 68, 68, 0.4);
|
|
279
292
|
--sp-button-success-bg: #15803d;
|
|
280
293
|
--sp-button-success-bghover: #166534;
|
|
281
294
|
--sp-button-success-bgactive: #14532d;
|
|
@@ -283,6 +296,7 @@
|
|
|
283
296
|
--sp-button-success-text: #ffffff;
|
|
284
297
|
--sp-button-success-textdisabled: #8a96ad;
|
|
285
298
|
--sp-button-success-focusring: rgba(34, 197, 94, 0.4);
|
|
299
|
+
--sp-button-success-focusvisible: rgba(34, 197, 94, 0.4);
|
|
286
300
|
--sp-button-cta-bg: #1f57db;
|
|
287
301
|
--sp-button-cta-bghover: #1946b4;
|
|
288
302
|
--sp-button-cta-bgactive: #173b8f;
|
|
@@ -417,12 +431,14 @@
|
|
|
417
431
|
--sp-component-button-danger-bg-disabled: var(--sp-button-danger-bgdisabled);
|
|
418
432
|
--sp-component-button-danger-text: var(--sp-button-danger-text);
|
|
419
433
|
--sp-component-button-danger-text-disabled: var(--sp-button-danger-textdisabled);
|
|
434
|
+
--sp-component-button-danger-focus-visible: var(--sp-button-danger-focusvisible);
|
|
420
435
|
--sp-component-button-success-bg: var(--sp-button-success-bg);
|
|
421
436
|
--sp-component-button-success-bg-hover: var(--sp-button-success-bghover);
|
|
422
437
|
--sp-component-button-success-bg-active: var(--sp-button-success-bgactive);
|
|
423
438
|
--sp-component-button-success-bg-disabled: var(--sp-button-success-bgdisabled);
|
|
424
439
|
--sp-component-button-success-text: var(--sp-button-success-text);
|
|
425
440
|
--sp-component-button-success-text-disabled: var(--sp-button-success-textdisabled);
|
|
441
|
+
--sp-component-button-success-focus-visible: var(--sp-button-success-focusvisible);
|
|
426
442
|
/* CTA button alignment restored to official tokens as they now use the brand palette (Blue). */
|
|
427
443
|
--sp-component-button-cta-bg: var(--sp-button-cta-bg);
|
|
428
444
|
--sp-component-button-cta-bg-hover: var(--sp-button-cta-bghover);
|
|
@@ -493,6 +509,9 @@
|
|
|
493
509
|
--sp-component-badge-info-text: var(--sp-badge-info-text);
|
|
494
510
|
--sp-component-badge-ghost-bg: var(--sp-button-ghost-bg);
|
|
495
511
|
--sp-component-badge-ghost-text: var(--sp-button-ghost-text);
|
|
512
|
+
--sp-component-badge-outline-bg: transparent;
|
|
513
|
+
--sp-component-badge-outline-text: var(--sp-badge-neutral-text);
|
|
514
|
+
--sp-component-badge-outline-border: var(--sp-button-secondary-border);
|
|
496
515
|
--sp-component-badge-accent-bg: var(--sp-button-accent-bg);
|
|
497
516
|
--sp-component-badge-accent-text: var(--sp-button-accent-text);
|
|
498
517
|
--sp-component-badge-cta-bg: var(--sp-button-cta-bg);
|
|
@@ -543,6 +562,9 @@
|
|
|
543
562
|
--sp-component-iconbox-accent-text: var(--sp-button-accent-text);
|
|
544
563
|
--sp-component-iconbox-cta-bg: var(--sp-button-cta-bg);
|
|
545
564
|
--sp-component-iconbox-cta-text: var(--sp-button-cta-text);
|
|
565
|
+
--sp-component-iconbox-outline-bg: transparent;
|
|
566
|
+
--sp-component-iconbox-outline-text: var(--sp-badge-neutral-text);
|
|
567
|
+
--sp-component-iconbox-outline-border: var(--sp-button-secondary-border);
|
|
546
568
|
|
|
547
569
|
/* testimonial roles */
|
|
548
570
|
--sp-component-testimonial-bg: var(--sp-surface-card);
|
|
@@ -664,6 +686,15 @@
|
|
|
664
686
|
--sp-component-spinner-border-width: var(--sp-border-width-thick);
|
|
665
687
|
--sp-component-spinner-track-color: var(--sp-color-neutral-200);
|
|
666
688
|
--sp-component-spinner-arc-color: var(--sp-button-primary-bg);
|
|
689
|
+
--sp-component-spinner-primary-arc: var(--sp-button-primary-bg);
|
|
690
|
+
--sp-component-spinner-secondary-arc: var(--sp-button-secondary-border);
|
|
691
|
+
--sp-component-spinner-success-arc: var(--sp-color-success-500);
|
|
692
|
+
--sp-component-spinner-warning-arc: var(--sp-color-warning-500);
|
|
693
|
+
--sp-component-spinner-danger-arc: var(--sp-color-error-500);
|
|
694
|
+
--sp-component-spinner-info-arc: var(--sp-color-info-500);
|
|
695
|
+
--sp-component-spinner-neutral-arc: var(--sp-color-neutral-500);
|
|
696
|
+
--sp-component-spinner-accent-arc: var(--sp-button-accent-bg);
|
|
697
|
+
--sp-component-spinner-cta-arc: var(--sp-button-cta-bg);
|
|
667
698
|
--sp-component-spinner-duration: var(--sp-duration-long);
|
|
668
699
|
--sp-component-spinner-easing: var(--sp-easing-linear);
|
|
669
700
|
}
|
|
@@ -724,6 +755,15 @@
|
|
|
724
755
|
|
|
725
756
|
--sp-component-spinner-track-color: var(--sp-color-neutral-700);
|
|
726
757
|
--sp-component-spinner-arc-color: var(--sp-color-brand-400);
|
|
758
|
+
--sp-component-spinner-primary-arc: var(--sp-color-brand-400);
|
|
759
|
+
--sp-component-spinner-secondary-arc: var(--sp-color-neutral-400);
|
|
760
|
+
--sp-component-spinner-success-arc: var(--sp-color-success-400);
|
|
761
|
+
--sp-component-spinner-warning-arc: var(--sp-color-warning-400);
|
|
762
|
+
--sp-component-spinner-danger-arc: var(--sp-color-error-400);
|
|
763
|
+
--sp-component-spinner-info-arc: var(--sp-color-info-400);
|
|
764
|
+
--sp-component-spinner-neutral-arc: var(--sp-color-neutral-400);
|
|
765
|
+
--sp-component-spinner-accent-arc: var(--sp-color-brand-400);
|
|
766
|
+
--sp-component-spinner-cta-arc: var(--sp-color-brand-400);
|
|
727
767
|
}
|
|
728
768
|
|
|
729
769
|
/* BUTTONS -------------------------------------------------------------- */
|
|
@@ -910,6 +950,12 @@
|
|
|
910
950
|
color: var(--sp-component-button-danger-text-disabled);
|
|
911
951
|
}
|
|
912
952
|
|
|
953
|
+
.sp-btn--danger:focus-visible,
|
|
954
|
+
.sp-btn--danger.sp-btn--focus,
|
|
955
|
+
.sp-btn--danger.is-focus {
|
|
956
|
+
box-shadow: 0 0 0 calc(var(--sp-focus-ring-width) + var(--sp-component-border-width)) var(--sp-component-button-danger-focus-visible);
|
|
957
|
+
}
|
|
958
|
+
|
|
913
959
|
/* success */
|
|
914
960
|
.sp-btn--success {
|
|
915
961
|
background-color: var(--sp-component-button-success-bg);
|
|
@@ -935,6 +981,12 @@
|
|
|
935
981
|
color: var(--sp-component-button-success-text-disabled);
|
|
936
982
|
}
|
|
937
983
|
|
|
984
|
+
.sp-btn--success:focus-visible,
|
|
985
|
+
.sp-btn--success.sp-btn--focus,
|
|
986
|
+
.sp-btn--success.is-focus {
|
|
987
|
+
box-shadow: 0 0 0 calc(var(--sp-focus-ring-width) + var(--sp-component-border-width)) var(--sp-component-button-success-focus-visible);
|
|
988
|
+
}
|
|
989
|
+
|
|
938
990
|
/* cta */
|
|
939
991
|
.sp-btn--cta {
|
|
940
992
|
background-color: var(--sp-component-button-cta-bg);
|
|
@@ -1351,6 +1403,12 @@
|
|
|
1351
1403
|
background-color: var(--sp-component-badge-ghost-bg-hover);
|
|
1352
1404
|
}
|
|
1353
1405
|
|
|
1406
|
+
.sp-badge--outline {
|
|
1407
|
+
background-color: var(--sp-component-badge-outline-bg);
|
|
1408
|
+
color: var(--sp-component-badge-outline-text);
|
|
1409
|
+
border-color: var(--sp-component-badge-outline-border);
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1354
1412
|
.sp-badge--accent {
|
|
1355
1413
|
background-color: var(--sp-component-badge-accent-bg);
|
|
1356
1414
|
color: var(--sp-component-badge-accent-text);
|
|
@@ -1548,6 +1606,12 @@
|
|
|
1548
1606
|
color: var(--sp-component-iconbox-cta-text);
|
|
1549
1607
|
}
|
|
1550
1608
|
|
|
1609
|
+
.sp-iconbox--outline {
|
|
1610
|
+
background-color: var(--sp-component-iconbox-outline-bg);
|
|
1611
|
+
color: var(--sp-component-iconbox-outline-text);
|
|
1612
|
+
border-color: var(--sp-component-iconbox-outline-border);
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1551
1615
|
.sp-iconbox--interactive {
|
|
1552
1616
|
cursor: pointer;
|
|
1553
1617
|
}
|
|
@@ -2316,6 +2380,52 @@
|
|
|
2316
2380
|
border: var(--sp-component-spinner-border-width) solid var(--sp-component-spinner-track-color);
|
|
2317
2381
|
border-top-color: var(--sp-component-spinner-arc-color);
|
|
2318
2382
|
animation: sp-spin var(--sp-component-spinner-duration) var(--sp-component-spinner-easing) infinite;
|
|
2383
|
+
transition: opacity var(--sp-duration-fast) var(--sp-easing-out);
|
|
2384
|
+
}
|
|
2385
|
+
|
|
2386
|
+
.sp-spinner--primary {
|
|
2387
|
+
border-top-color: var(--sp-component-spinner-primary-arc);
|
|
2388
|
+
}
|
|
2389
|
+
|
|
2390
|
+
.sp-spinner--secondary {
|
|
2391
|
+
border-top-color: var(--sp-component-spinner-secondary-arc);
|
|
2392
|
+
}
|
|
2393
|
+
|
|
2394
|
+
.sp-spinner--success {
|
|
2395
|
+
border-top-color: var(--sp-component-spinner-success-arc);
|
|
2396
|
+
}
|
|
2397
|
+
|
|
2398
|
+
.sp-spinner--warning {
|
|
2399
|
+
border-top-color: var(--sp-component-spinner-warning-arc);
|
|
2400
|
+
}
|
|
2401
|
+
|
|
2402
|
+
.sp-spinner--danger {
|
|
2403
|
+
border-top-color: var(--sp-component-spinner-danger-arc);
|
|
2404
|
+
}
|
|
2405
|
+
|
|
2406
|
+
.sp-spinner--info {
|
|
2407
|
+
border-top-color: var(--sp-component-spinner-info-arc);
|
|
2408
|
+
}
|
|
2409
|
+
|
|
2410
|
+
.sp-spinner--neutral {
|
|
2411
|
+
border-top-color: var(--sp-component-spinner-neutral-arc);
|
|
2412
|
+
}
|
|
2413
|
+
|
|
2414
|
+
.sp-spinner--accent {
|
|
2415
|
+
border-top-color: var(--sp-component-spinner-accent-arc);
|
|
2416
|
+
}
|
|
2417
|
+
|
|
2418
|
+
.sp-spinner--cta {
|
|
2419
|
+
border-top-color: var(--sp-component-spinner-cta-arc);
|
|
2420
|
+
}
|
|
2421
|
+
|
|
2422
|
+
.sp-spinner--disabled {
|
|
2423
|
+
opacity: var(--sp-opacity-disabled);
|
|
2424
|
+
}
|
|
2425
|
+
|
|
2426
|
+
.sp-spinner--loading,
|
|
2427
|
+
.sp-spinner[aria-busy="true"] {
|
|
2428
|
+
opacity: var(--sp-opacity-active);
|
|
2319
2429
|
}
|
|
2320
2430
|
|
|
2321
2431
|
.sp-spinner--sm {
|
package/dist/index.cjs
CHANGED
|
@@ -255,6 +255,7 @@ var BADGE_VARIANTS = {
|
|
|
255
255
|
neutral: true,
|
|
256
256
|
info: true,
|
|
257
257
|
ghost: true,
|
|
258
|
+
outline: true,
|
|
258
259
|
accent: true,
|
|
259
260
|
cta: true
|
|
260
261
|
};
|
|
@@ -296,6 +297,7 @@ function getBadgeClasses(opts = {}) {
|
|
|
296
297
|
neutral: "sp-badge--neutral",
|
|
297
298
|
info: "sp-badge--info",
|
|
298
299
|
ghost: "sp-badge--ghost",
|
|
300
|
+
outline: "sp-badge--outline",
|
|
299
301
|
accent: "sp-badge--accent",
|
|
300
302
|
cta: "sp-badge--cta"
|
|
301
303
|
};
|
|
@@ -331,7 +333,8 @@ var ICONBOX_VARIANTS = {
|
|
|
331
333
|
neutral: true,
|
|
332
334
|
ghost: true,
|
|
333
335
|
accent: true,
|
|
334
|
-
cta: true
|
|
336
|
+
cta: true,
|
|
337
|
+
outline: true
|
|
335
338
|
};
|
|
336
339
|
var ICONBOX_SIZES = {
|
|
337
340
|
sm: true,
|
|
@@ -373,7 +376,8 @@ function getIconBoxClasses(opts = {}) {
|
|
|
373
376
|
neutral: "sp-iconbox--neutral",
|
|
374
377
|
ghost: "sp-iconbox--ghost",
|
|
375
378
|
accent: "sp-iconbox--accent",
|
|
376
|
-
cta: "sp-iconbox--cta"
|
|
379
|
+
cta: "sp-iconbox--cta",
|
|
380
|
+
outline: "sp-iconbox--outline"
|
|
377
381
|
};
|
|
378
382
|
const variantClass = variantMap[variant];
|
|
379
383
|
const sizeMap = {
|
|
@@ -709,20 +713,48 @@ function getTagClasses(opts = {}) {
|
|
|
709
713
|
}
|
|
710
714
|
|
|
711
715
|
// src/recipes/spinner.ts
|
|
716
|
+
var SPINNER_VARIANTS = {
|
|
717
|
+
primary: true,
|
|
718
|
+
secondary: true,
|
|
719
|
+
success: true,
|
|
720
|
+
warning: true,
|
|
721
|
+
danger: true,
|
|
722
|
+
info: true,
|
|
723
|
+
neutral: true,
|
|
724
|
+
accent: true,
|
|
725
|
+
cta: true
|
|
726
|
+
};
|
|
712
727
|
var SPINNER_SIZES = {
|
|
713
728
|
sm: true,
|
|
714
729
|
md: true,
|
|
715
730
|
lg: true
|
|
716
731
|
};
|
|
717
732
|
function getSpinnerClasses(opts = {}) {
|
|
718
|
-
const {
|
|
733
|
+
const {
|
|
734
|
+
variant: variantInput,
|
|
735
|
+
size: sizeInput,
|
|
736
|
+
disabled = false,
|
|
737
|
+
loading = false
|
|
738
|
+
} = opts;
|
|
739
|
+
const variant = variantInput && resolveOption({
|
|
740
|
+
name: "spinner variant",
|
|
741
|
+
value: variantInput,
|
|
742
|
+
allowed: SPINNER_VARIANTS,
|
|
743
|
+
fallback: "primary"
|
|
744
|
+
});
|
|
719
745
|
const size = resolveOption({
|
|
720
746
|
name: "spinner size",
|
|
721
747
|
value: sizeInput,
|
|
722
748
|
allowed: SPINNER_SIZES,
|
|
723
749
|
fallback: "md"
|
|
724
750
|
});
|
|
725
|
-
return cx(
|
|
751
|
+
return cx(
|
|
752
|
+
"sp-spinner",
|
|
753
|
+
variant && `sp-spinner--${variant}`,
|
|
754
|
+
`sp-spinner--${size}`,
|
|
755
|
+
disabled && "sp-spinner--disabled",
|
|
756
|
+
loading && "sp-spinner--loading"
|
|
757
|
+
);
|
|
726
758
|
}
|
|
727
759
|
|
|
728
760
|
exports.getAlertClasses = getAlertClasses;
|