@phcdevworks/spectre-components 1.3.0 → 1.5.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/README.md +504 -202
- package/dist/alert.cjs +455 -0
- package/dist/alert.cjs.map +1 -0
- package/dist/alert.d.cts +68 -0
- package/dist/alert.d.ts +68 -0
- package/dist/alert.js +450 -0
- package/dist/alert.js.map +1 -0
- package/dist/avatar.cjs +454 -0
- package/dist/avatar.cjs.map +1 -0
- package/dist/avatar.d.cts +74 -0
- package/dist/avatar.d.ts +74 -0
- package/dist/avatar.js +449 -0
- package/dist/avatar.js.map +1 -0
- package/dist/badge.cjs +454 -0
- package/dist/badge.cjs.map +1 -0
- package/dist/badge.d.cts +62 -0
- package/dist/badge.d.ts +62 -0
- package/dist/badge.js +449 -0
- package/dist/badge.js.map +1 -0
- package/dist/button.cjs.map +1 -1
- package/dist/button.d.cts +2 -2
- package/dist/button.d.ts +2 -2
- package/dist/button.js.map +1 -1
- package/dist/card.cjs +448 -0
- package/dist/card.cjs.map +1 -0
- package/dist/card.d.cts +68 -0
- package/dist/card.d.ts +68 -0
- package/dist/card.js +444 -0
- package/dist/card.js.map +1 -0
- package/dist/fieldset.cjs +14 -0
- package/dist/fieldset.cjs.map +1 -1
- package/dist/fieldset.d.cts +6 -0
- package/dist/fieldset.d.ts +6 -0
- package/dist/fieldset.js +14 -0
- package/dist/fieldset.js.map +1 -1
- package/dist/form-BumNzIay.d.cts +28 -0
- package/dist/form-BumNzIay.d.ts +28 -0
- package/dist/icon-box.cjs +466 -0
- package/dist/icon-box.cjs.map +1 -0
- package/dist/icon-box.d.cts +74 -0
- package/dist/icon-box.d.ts +74 -0
- package/dist/icon-box.js +461 -0
- package/dist/icon-box.js.map +1 -0
- package/dist/index.cjs +1123 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js +1090 -2
- package/dist/index.js.map +1 -1
- package/dist/input.cjs.map +1 -1
- package/dist/input.d.cts +2 -2
- package/dist/input.d.ts +2 -2
- package/dist/input.js.map +1 -1
- package/dist/pricing-card.cjs +432 -0
- package/dist/pricing-card.cjs.map +1 -0
- package/dist/pricing-card.d.cts +60 -0
- package/dist/pricing-card.d.ts +60 -0
- package/dist/pricing-card.js +429 -0
- package/dist/pricing-card.js.map +1 -0
- package/dist/rating.cjs +377 -0
- package/dist/rating.cjs.map +1 -0
- package/dist/rating.d.cts +68 -0
- package/dist/rating.d.ts +68 -0
- package/dist/rating.js +373 -0
- package/dist/rating.js.map +1 -0
- package/dist/select.cjs +14 -0
- package/dist/select.cjs.map +1 -1
- package/dist/select.d.cts +7 -1
- package/dist/select.d.ts +7 -1
- package/dist/select.js +14 -0
- package/dist/select.js.map +1 -1
- package/dist/spinner.cjs +356 -0
- package/dist/spinner.cjs.map +1 -0
- package/dist/spinner.d.cts +52 -0
- package/dist/spinner.d.ts +52 -0
- package/dist/spinner.js +351 -0
- package/dist/spinner.js.map +1 -0
- package/dist/tag.cjs +473 -0
- package/dist/tag.cjs.map +1 -0
- package/dist/tag.d.cts +80 -0
- package/dist/tag.d.ts +80 -0
- package/dist/tag.js +468 -0
- package/dist/tag.js.map +1 -0
- package/dist/testimonial.cjs +444 -0
- package/dist/testimonial.cjs.map +1 -0
- package/dist/testimonial.d.cts +62 -0
- package/dist/testimonial.d.ts +62 -0
- package/dist/testimonial.js +440 -0
- package/dist/testimonial.js.map +1 -0
- package/dist/textarea.cjs.map +1 -1
- package/dist/textarea.d.cts +1 -1
- package/dist/textarea.d.ts +1 -1
- package/dist/textarea.js.map +1 -1
- package/package.json +68 -13
- package/dist/form-yR_u97J-.d.cts +0 -10
- package/dist/form-yR_u97J-.d.ts +0 -10
package/README.md
CHANGED
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
`@phcdevworks/spectre-components` is the **Layer 3** Lit-based web component
|
|
9
9
|
package of the Spectre design system. It turns Spectre tokens
|
|
10
10
|
(`@phcdevworks/spectre-tokens`) and Spectre UI styling contracts
|
|
11
|
-
(`@phcdevworks/spectre-ui`) into reusable, accessible, framework-agnostic
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
(`@phcdevworks/spectre-ui`) into reusable, accessible, framework-agnostic custom
|
|
12
|
+
elements — the canonical component implementation layer for Spectre, designed to
|
|
13
|
+
be consumed directly or wrapped by downstream adapter packages.
|
|
14
14
|
|
|
15
15
|
[Contributing](CONTRIBUTING.md) | [Code of Conduct](CODE_OF_CONDUCT.md) |
|
|
16
16
|
[Changelog](CHANGELOG.md) | [Roadmap](ROADMAP.md) |
|
|
@@ -22,23 +22,23 @@ designed to be consumed directly or wrapped by downstream adapter packages.
|
|
|
22
22
|
styling contract that maps Spectre tokens to visual output. It ships CSS rules
|
|
23
23
|
and JavaScript class-name helpers — nothing more.
|
|
24
24
|
|
|
25
|
-
This package sits above that. It owns **behavior**: the Lit element classes
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
This package sits above that. It owns **behavior**: the Lit element classes that
|
|
26
|
+
apply those CSS recipes, forward ARIA attributes to native elements, manage
|
|
27
|
+
focus delegation, handle content projection, validate properties, and expose a
|
|
28
|
+
stable TypeScript API surface for downstream adapters.
|
|
29
29
|
|
|
30
30
|
The separation keeps each layer focused:
|
|
31
31
|
|
|
32
|
-
| Layer
|
|
33
|
-
|
|
34
|
-
| L1
|
|
35
|
-
| L2
|
|
32
|
+
| Layer | Package | Owns |
|
|
33
|
+
| ------ | ------------------------------------- | -------------------------------------- |
|
|
34
|
+
| L1 | `@phcdevworks/spectre-tokens` | Design values and semantic meaning |
|
|
35
|
+
| L2 | `@phcdevworks/spectre-ui` | CSS recipes and styling contracts |
|
|
36
36
|
| **L3** | **`@phcdevworks/spectre-components`** | **Lit web component behavior and API** |
|
|
37
|
-
| L4
|
|
37
|
+
| L4 | Downstream adapters | Framework-specific delivery |
|
|
38
38
|
|
|
39
|
-
If you only need CSS class names, use `@phcdevworks/spectre-ui` directly. If
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
If you only need CSS class names, use `@phcdevworks/spectre-ui` directly. If you
|
|
40
|
+
need ready-to-use HTML elements with behavior, accessibility, and a typed API,
|
|
41
|
+
use this package.
|
|
42
42
|
|
|
43
43
|
## Key capabilities
|
|
44
44
|
|
|
@@ -57,16 +57,17 @@ API, use this package.
|
|
|
57
57
|
|
|
58
58
|
- You are building UI with the Spectre design system and want standards-based
|
|
59
59
|
custom elements with baked-in behavior and accessibility.
|
|
60
|
-
- You want typed form controls (`sp-button`, `sp-input`, `sp-select`, etc.)
|
|
61
|
-
|
|
60
|
+
- You want typed form controls (`sp-button`, `sp-input`, `sp-select`, etc.) and
|
|
61
|
+
display primitives (`sp-badge`, `sp-card`, `sp-rating`, etc.) that work in any
|
|
62
|
+
framework or in plain HTML.
|
|
62
63
|
- You are writing a framework adapter (React, Vue, Astro) and need a reliable,
|
|
63
64
|
stable element layer to wrap.
|
|
64
65
|
|
|
65
66
|
## When not to use this package
|
|
66
67
|
|
|
67
68
|
- You only need CSS class names — use `@phcdevworks/spectre-ui` directly.
|
|
68
|
-
- You are adding routing, shell logic, or app-startup orchestration — those
|
|
69
|
-
|
|
69
|
+
- You are adding routing, shell logic, or app-startup orchestration — those are
|
|
70
|
+
out of scope here.
|
|
70
71
|
- You need framework-specific component files (JSX, SFCs, Astro components) —
|
|
71
72
|
those belong in a downstream adapter package.
|
|
72
73
|
|
|
@@ -89,19 +90,30 @@ consumption.
|
|
|
89
90
|
<html lang="en">
|
|
90
91
|
<head>
|
|
91
92
|
<!-- Spectre CSS layers must load before any markup is rendered -->
|
|
92
|
-
<link
|
|
93
|
-
|
|
93
|
+
<link
|
|
94
|
+
rel="stylesheet"
|
|
95
|
+
href="/node_modules/@phcdevworks/spectre-tokens/index.css"
|
|
96
|
+
/>
|
|
97
|
+
<link
|
|
98
|
+
rel="stylesheet"
|
|
99
|
+
href="/node_modules/@phcdevworks/spectre-ui/index.css"
|
|
100
|
+
/>
|
|
94
101
|
</head>
|
|
95
102
|
<body>
|
|
96
103
|
<sp-label for="email">Email address</sp-label>
|
|
97
|
-
<sp-input
|
|
104
|
+
<sp-input
|
|
105
|
+
id="email"
|
|
106
|
+
name="email"
|
|
107
|
+
type="email"
|
|
108
|
+
placeholder="you@example.com"
|
|
109
|
+
></sp-input>
|
|
98
110
|
|
|
99
111
|
<sp-button variant="primary" type="submit">Send</sp-button>
|
|
100
112
|
<sp-button variant="ghost" type="button">Cancel</sp-button>
|
|
101
113
|
|
|
102
114
|
<script type="module">
|
|
103
|
-
import { defineSpectreComponents } from '/node_modules/@phcdevworks/spectre-components/dist/index.js'
|
|
104
|
-
defineSpectreComponents()
|
|
115
|
+
import { defineSpectreComponents } from '/node_modules/@phcdevworks/spectre-components/dist/index.js'
|
|
116
|
+
defineSpectreComponents()
|
|
105
117
|
</script>
|
|
106
118
|
</body>
|
|
107
119
|
</html>
|
|
@@ -110,18 +122,18 @@ consumption.
|
|
|
110
122
|
### JavaScript / TypeScript module
|
|
111
123
|
|
|
112
124
|
```ts
|
|
113
|
-
import '@phcdevworks/spectre-tokens/index.css'
|
|
114
|
-
import '@phcdevworks/spectre-ui/index.css'
|
|
125
|
+
import '@phcdevworks/spectre-tokens/index.css'
|
|
126
|
+
import '@phcdevworks/spectre-ui/index.css'
|
|
115
127
|
|
|
116
128
|
// Register everything at once
|
|
117
|
-
import { defineSpectreComponents } from '@phcdevworks/spectre-components'
|
|
118
|
-
defineSpectreComponents()
|
|
129
|
+
import { defineSpectreComponents } from '@phcdevworks/spectre-components'
|
|
130
|
+
defineSpectreComponents()
|
|
119
131
|
|
|
120
132
|
// Or register only what you use
|
|
121
|
-
import { defineSpectreButton } from '@phcdevworks/spectre-components/button'
|
|
122
|
-
import { defineSpectreInput } from '@phcdevworks/spectre-components/input'
|
|
123
|
-
defineSpectreButton()
|
|
124
|
-
defineSpectreInput()
|
|
133
|
+
import { defineSpectreButton } from '@phcdevworks/spectre-components/button'
|
|
134
|
+
import { defineSpectreInput } from '@phcdevworks/spectre-components/input'
|
|
135
|
+
defineSpectreButton()
|
|
136
|
+
defineSpectreInput()
|
|
125
137
|
```
|
|
126
138
|
|
|
127
139
|
### Full form example
|
|
@@ -154,10 +166,11 @@ defineSpectreInput();
|
|
|
154
166
|
|
|
155
167
|
### Framework integration note
|
|
156
168
|
|
|
157
|
-
These are standard HTML custom elements. They work in every major framework
|
|
158
|
-
|
|
169
|
+
These are standard HTML custom elements. They work in every major framework that
|
|
170
|
+
supports the Custom Elements standard:
|
|
159
171
|
|
|
160
172
|
**React 19+** — supports custom element properties and events natively:
|
|
173
|
+
|
|
161
174
|
```tsx
|
|
162
175
|
// React 19: properties and events work directly
|
|
163
176
|
<sp-input name="email" type="email" onInput={(e) => setValue(e.target.value)} />
|
|
@@ -165,27 +178,38 @@ that supports the Custom Elements standard:
|
|
|
165
178
|
|
|
166
179
|
**React 18 and below** — set attributes via `ref` for properties, listen for
|
|
167
180
|
native events on the element:
|
|
181
|
+
|
|
168
182
|
```tsx
|
|
169
|
-
const inputRef = useRef(null)
|
|
183
|
+
const inputRef = useRef(null)
|
|
170
184
|
useEffect(() => {
|
|
171
|
-
if (inputRef.current) inputRef.current.invalid = true
|
|
172
|
-
}, [])
|
|
173
|
-
|
|
185
|
+
if (inputRef.current) inputRef.current.invalid = true
|
|
186
|
+
}, [])
|
|
187
|
+
|
|
188
|
+
return <sp-input ref={inputRef} name="email" />
|
|
174
189
|
```
|
|
175
190
|
|
|
176
|
-
**Vue 3** — supports custom elements out of the box with `v-bind` and
|
|
177
|
-
|
|
178
|
-
|
|
191
|
+
**Vue 3** — supports custom elements out of the box with `v-bind` and `v-on`
|
|
192
|
+
directive compatibility. Mark the `sp-*` prefix in `compilerOptions` as a custom
|
|
193
|
+
element to suppress unknown-element warnings:
|
|
194
|
+
|
|
179
195
|
```ts
|
|
180
196
|
// vite.config.ts
|
|
181
|
-
plugins: [
|
|
197
|
+
plugins: [
|
|
198
|
+
vue({
|
|
199
|
+
template: {
|
|
200
|
+
compilerOptions: { isCustomElement: (tag) => tag.startsWith('sp-') }
|
|
201
|
+
}
|
|
202
|
+
})
|
|
203
|
+
]
|
|
182
204
|
```
|
|
205
|
+
|
|
183
206
|
```html
|
|
184
207
|
<sp-input name="email" :invalid="hasError" @change="handleChange" />
|
|
185
208
|
```
|
|
186
209
|
|
|
187
|
-
**Astro** — use components as static custom elements or with `client:load`
|
|
188
|
-
|
|
210
|
+
**Astro** — use components as static custom elements or with `client:load` when
|
|
211
|
+
JavaScript interactivity is needed:
|
|
212
|
+
|
|
189
213
|
```astro
|
|
190
214
|
---
|
|
191
215
|
import '@phcdevworks/spectre-tokens/index.css';
|
|
@@ -210,25 +234,25 @@ All components follow WCAG 2.1 AA baseline expectations by default.
|
|
|
210
234
|
inner native element so screen readers receive them on the correct target.
|
|
211
235
|
|
|
212
236
|
**Native element semantics** — every component renders a real native element
|
|
213
|
-
(`<button>`, `<input>`, `<textarea>`, `<select>`, `<label>`, `<fieldset>`)
|
|
214
|
-
|
|
237
|
+
(`<button>`, `<input>`, `<textarea>`, `<select>`, `<label>`, `<fieldset>`) or a
|
|
238
|
+
semantic light-DOM container with forwarded ARIA attributes, so browser
|
|
239
|
+
accessibility APIs work without customization.
|
|
215
240
|
|
|
216
241
|
**State communication**
|
|
217
242
|
|
|
218
|
-
| State
|
|
219
|
-
|
|
220
|
-
| `loading`
|
|
221
|
-
| `invalid`
|
|
243
|
+
| State | ARIA effect |
|
|
244
|
+
| ---------- | ---------------------------------------------------- |
|
|
245
|
+
| `loading` | `aria-busy="true"` on the native element |
|
|
246
|
+
| `invalid` | `aria-invalid="true"` on the native element |
|
|
222
247
|
| `disabled` | native `disabled` attribute (removes from tab order) |
|
|
223
|
-
| `required` | native `required` attribute
|
|
248
|
+
| `required` | native `required` attribute |
|
|
224
249
|
|
|
225
|
-
**Focus delegation** — `.focus()` and `.blur()` called on the host are
|
|
226
|
-
|
|
227
|
-
expected.
|
|
250
|
+
**Focus delegation** — `.focus()` and `.blur()` called on the host are delegated
|
|
251
|
+
to the inner native element so external `focus()` calls work as expected.
|
|
228
252
|
|
|
229
|
-
**Label association** — use `<sp-label for="id">` paired with `id` on the
|
|
230
|
-
|
|
231
|
-
|
|
253
|
+
**Label association** — use `<sp-label for="id">` paired with `id` on the target
|
|
254
|
+
control, or wrap controls inside a `<sp-fieldset>`. The `for` attribute forwards
|
|
255
|
+
to the native `<label>` element.
|
|
232
256
|
|
|
233
257
|
**Keyboard behavior** — provided entirely by the native element inside each
|
|
234
258
|
component. No custom keyboard handling is layered on top.
|
|
@@ -236,19 +260,23 @@ component. No custom keyboard handling is layered on top.
|
|
|
236
260
|
## Light DOM rendering
|
|
237
261
|
|
|
238
262
|
All components render in **light DOM** (`createRenderRoot() { return this; }`).
|
|
239
|
-
This is intentional: it allows `@phcdevworks/spectre-ui` global CSS to reach
|
|
240
|
-
|
|
263
|
+
This is intentional: it allows `@phcdevworks/spectre-ui` global CSS to reach the
|
|
264
|
+
native element directly without Shadow DOM piercing.
|
|
241
265
|
|
|
242
|
-
As a result, these components have no `::part()` exports — the native element
|
|
243
|
-
|
|
244
|
-
|
|
266
|
+
As a result, these components have no `::part()` exports — the native element is
|
|
267
|
+
directly selectable using standard CSS combinators or the stable internal data
|
|
268
|
+
attributes:
|
|
245
269
|
|
|
246
270
|
```css
|
|
247
271
|
/* Target the native input inside sp-input */
|
|
248
|
-
sp-input input {
|
|
272
|
+
sp-input input {
|
|
273
|
+
font-size: 0.875rem;
|
|
274
|
+
}
|
|
249
275
|
|
|
250
276
|
/* Stable internal hook — won't break if markup restructures */
|
|
251
|
-
sp-input [data-sp-input-native] {
|
|
277
|
+
sp-input [data-sp-input-native] {
|
|
278
|
+
font-size: 0.875rem;
|
|
279
|
+
}
|
|
252
280
|
```
|
|
253
281
|
|
|
254
282
|
Do not switch any component from light DOM to Shadow DOM without a
|
|
@@ -262,26 +290,26 @@ Renders a `<button>` with Spectre variant, size, loading, and pill support.
|
|
|
262
290
|
|
|
263
291
|
**Attributes**
|
|
264
292
|
|
|
265
|
-
| Attribute
|
|
266
|
-
|
|
267
|
-
| `variant`
|
|
268
|
-
| `size`
|
|
269
|
-
| `type`
|
|
270
|
-
| `label`
|
|
271
|
-
| `loading`
|
|
272
|
-
| `loading-label`
|
|
273
|
-
| `disabled`
|
|
274
|
-
| `full-width`
|
|
275
|
-
| `pill`
|
|
276
|
-
| `name`
|
|
277
|
-
| `value`
|
|
278
|
-
| `form`
|
|
279
|
-
| `autofocus`
|
|
280
|
-
| `id`
|
|
281
|
-
| `title`
|
|
282
|
-
| `aria-label`
|
|
283
|
-
| `aria-labelledby`
|
|
284
|
-
| `aria-describedby` | string
|
|
293
|
+
| Attribute | Type | Default | Description |
|
|
294
|
+
| ------------------ | --------------------------------------------------------------------- | --------- | -------------------------------------------------------- |
|
|
295
|
+
| `variant` | `primary \| secondary \| ghost \| danger \| success \| cta \| accent` | `primary` | Visual style |
|
|
296
|
+
| `size` | `sm \| md \| lg` | `md` | Control size |
|
|
297
|
+
| `type` | `button \| submit \| reset` | `button` | Native button type |
|
|
298
|
+
| `label` | string | — | Text label (overridden by content projection) |
|
|
299
|
+
| `loading` | boolean | `false` | Busy state — disables the button and shows loading label |
|
|
300
|
+
| `loading-label` | string | `Loading` | Accessible text shown during loading |
|
|
301
|
+
| `disabled` | boolean | `false` | Disables the button |
|
|
302
|
+
| `full-width` | boolean | `false` | Spans full container width |
|
|
303
|
+
| `pill` | boolean | `false` | Pill / fully-rounded corners |
|
|
304
|
+
| `name` | string | — | Form field name |
|
|
305
|
+
| `value` | string | `''` | Submitted value |
|
|
306
|
+
| `form` | string | — | Associates with a form by ID |
|
|
307
|
+
| `autofocus` | boolean | `false` | Autofocus on page load |
|
|
308
|
+
| `id` | string | — | Forwarded to the native `<button>` |
|
|
309
|
+
| `title` | string | — | Forwarded to the native `<button>` |
|
|
310
|
+
| `aria-label` | string | — | Forwarded to the native `<button>` |
|
|
311
|
+
| `aria-labelledby` | string | — | Forwarded to the native `<button>` |
|
|
312
|
+
| `aria-describedby` | string | — | Forwarded to the native `<button>` |
|
|
285
313
|
|
|
286
314
|
**Events** — native button events bubble normally (`click`, `focus`, `blur`).
|
|
287
315
|
|
|
@@ -305,28 +333,28 @@ Renders an `<input>` with state, size, and type support.
|
|
|
305
333
|
|
|
306
334
|
**Attributes**
|
|
307
335
|
|
|
308
|
-
| Attribute
|
|
309
|
-
|
|
310
|
-
| `type`
|
|
311
|
-
| `size`
|
|
312
|
-
| `name`
|
|
313
|
-
| `value`
|
|
314
|
-
| `placeholder`
|
|
315
|
-
| `disabled`
|
|
316
|
-
| `loading`
|
|
317
|
-
| `readonly`
|
|
318
|
-
| `required`
|
|
319
|
-
| `invalid`
|
|
320
|
-
| `success`
|
|
321
|
-
| `full-width`
|
|
322
|
-
| `pill`
|
|
323
|
-
| `autocomplete`
|
|
324
|
-
| `inputmode`
|
|
325
|
-
| `min` / `max` / `step`
|
|
326
|
-
| `minlength` / `maxlength` | number
|
|
327
|
-
| `form`
|
|
328
|
-
| `autofocus`
|
|
329
|
-
| `id` / `title` / `aria-*` | string
|
|
336
|
+
| Attribute | Type | Default | Description |
|
|
337
|
+
| ------------------------- | ---------------------------------------------------------------------------------------------------------------- | ------- | ----------------------------- |
|
|
338
|
+
| `type` | `text \| email \| password \| search \| tel \| url \| number \| date \| datetime-local \| month \| time \| week` | `text` | Native input type |
|
|
339
|
+
| `size` | `sm \| md \| lg` | `md` | Control size |
|
|
340
|
+
| `name` | string | — | Form field name |
|
|
341
|
+
| `value` | string | `''` | Current value |
|
|
342
|
+
| `placeholder` | string | — | Placeholder text |
|
|
343
|
+
| `disabled` | boolean | `false` | Disables the input |
|
|
344
|
+
| `loading` | boolean | `false` | Busy state |
|
|
345
|
+
| `readonly` | boolean | `false` | Read-only mode |
|
|
346
|
+
| `required` | boolean | `false` | Marks field as required |
|
|
347
|
+
| `invalid` | boolean | `false` | Error state (`aria-invalid`) |
|
|
348
|
+
| `success` | boolean | `false` | Success state |
|
|
349
|
+
| `full-width` | boolean | `false` | Spans full container width |
|
|
350
|
+
| `pill` | boolean | `false` | Pill / fully-rounded corners |
|
|
351
|
+
| `autocomplete` | string | — | Native autocomplete hint |
|
|
352
|
+
| `inputmode` | string | — | Virtual keyboard hint |
|
|
353
|
+
| `min` / `max` / `step` | string | — | Numeric/date range |
|
|
354
|
+
| `minlength` / `maxlength` | number | — | Character length constraints |
|
|
355
|
+
| `form` | string | — | Associates with a form by ID |
|
|
356
|
+
| `autofocus` | boolean | `false` | Autofocus on page load |
|
|
357
|
+
| `id` / `title` / `aria-*` | string | — | Forwarded to native `<input>` |
|
|
330
358
|
|
|
331
359
|
**Events** — `input` and `change` fire from the native `<input>` and bubble.
|
|
332
360
|
|
|
@@ -338,30 +366,32 @@ Renders an `<input>` with state, size, and type support.
|
|
|
338
366
|
|
|
339
367
|
Renders a `<textarea>` with row control and resize support.
|
|
340
368
|
|
|
341
|
-
**Attributes** — same as `sp-input` except no `type`, `min`, `max`, `step`, and
|
|
369
|
+
**Attributes** — same as `sp-input` except no `type`, `min`, `max`, `step`, and
|
|
370
|
+
adds:
|
|
342
371
|
|
|
343
|
-
| Attribute | Type
|
|
344
|
-
|
|
345
|
-
| `rows`
|
|
372
|
+
| Attribute | Type | Default | Description |
|
|
373
|
+
| --------- | ------ | ------- | ------------------ |
|
|
374
|
+
| `rows` | number | `2` | Visible row height |
|
|
346
375
|
|
|
347
376
|
**Events** — `input` and `change` fire from the native `<textarea>`.
|
|
348
377
|
|
|
349
|
-
**Internal target** — `[data-sp-textarea-native]` selects the native
|
|
378
|
+
**Internal target** — `[data-sp-textarea-native]` selects the native
|
|
379
|
+
`<textarea>`.
|
|
350
380
|
|
|
351
381
|
---
|
|
352
382
|
|
|
353
383
|
### sp-select
|
|
354
384
|
|
|
355
|
-
Renders a `<select>`. Pass `<option>` elements as children — they are
|
|
356
|
-
|
|
385
|
+
Renders a `<select>`. Pass `<option>` elements as children — they are projected
|
|
386
|
+
into the native select element.
|
|
357
387
|
|
|
358
388
|
**Attributes** — same as `sp-input` minus `type`, `placeholder`, `readonly`,
|
|
359
389
|
`inputmode`, `min`, `max`, `step`, `minlength`, `maxlength`.
|
|
360
390
|
|
|
361
391
|
**Events** — `input` and `change` fire from the native `<select>`.
|
|
362
392
|
|
|
363
|
-
**Content projection** — `<option>` and `<optgroup>` children are moved into
|
|
364
|
-
|
|
393
|
+
**Content projection** — `<option>` and `<optgroup>` children are moved into the
|
|
394
|
+
native `<select>`:
|
|
365
395
|
|
|
366
396
|
```html
|
|
367
397
|
<sp-select name="country" required>
|
|
@@ -383,18 +413,18 @@ Renders a `<label>` wrapping an `<input type="checkbox">` with indicator.
|
|
|
383
413
|
|
|
384
414
|
**Attributes**
|
|
385
415
|
|
|
386
|
-
| Attribute
|
|
387
|
-
|
|
388
|
-
| `name`
|
|
389
|
-
| `value`
|
|
390
|
-
| `checked`
|
|
391
|
-
| `label`
|
|
392
|
-
| `disabled`
|
|
393
|
-
| `loading`
|
|
394
|
-
| `required`
|
|
395
|
-
| `invalid`
|
|
396
|
-
| `success`
|
|
397
|
-
| `form` / `autofocus` / `id` / `title` / `aria-*` | —
|
|
416
|
+
| Attribute | Type | Default | Description |
|
|
417
|
+
| ------------------------------------------------ | ------- | ------- | --------------------------------------------- |
|
|
418
|
+
| `name` | string | — | Form field name |
|
|
419
|
+
| `value` | string | `on` | Submitted value when checked |
|
|
420
|
+
| `checked` | boolean | `false` | Checked state |
|
|
421
|
+
| `label` | string | — | Text label (overridden by content projection) |
|
|
422
|
+
| `disabled` | boolean | `false` | Disables the checkbox |
|
|
423
|
+
| `loading` | boolean | `false` | Busy state |
|
|
424
|
+
| `required` | boolean | `false` | Marks field as required |
|
|
425
|
+
| `invalid` | boolean | `false` | Error state |
|
|
426
|
+
| `success` | boolean | `false` | Success state |
|
|
427
|
+
| `form` / `autofocus` / `id` / `title` / `aria-*` | — | — | Forwarded to native `<input>` |
|
|
398
428
|
|
|
399
429
|
**Events** — `input` and `change` fire from the native checkbox input.
|
|
400
430
|
|
|
@@ -413,8 +443,8 @@ markup):
|
|
|
413
443
|
|
|
414
444
|
### sp-radio
|
|
415
445
|
|
|
416
|
-
Renders a `<label>` wrapping an `<input type="radio">` with indicator.
|
|
417
|
-
|
|
446
|
+
Renders a `<label>` wrapping an `<input type="radio">` with indicator. Group
|
|
447
|
+
multiple `sp-radio` elements by giving them the same `name`.
|
|
418
448
|
|
|
419
449
|
**Attributes** — same as `sp-checkbox`. `value` defaults to `on`.
|
|
420
450
|
|
|
@@ -433,15 +463,15 @@ Group multiple `sp-radio` elements by giving them the same `name`.
|
|
|
433
463
|
|
|
434
464
|
### sp-label
|
|
435
465
|
|
|
436
|
-
Renders a `<label>` with `for` forwarding. Use to associate a visible label
|
|
437
|
-
|
|
466
|
+
Renders a `<label>` with `for` forwarding. Use to associate a visible label with
|
|
467
|
+
any form control.
|
|
438
468
|
|
|
439
469
|
**Attributes**
|
|
440
470
|
|
|
441
|
-
| Attribute
|
|
442
|
-
|
|
443
|
-
| `for`
|
|
444
|
-
| `id` / `title` / `aria-*` | string | —
|
|
471
|
+
| Attribute | Type | Default | Description |
|
|
472
|
+
| ------------------------- | ------ | ------- | ------------------------------------------------------------ |
|
|
473
|
+
| `for` | string | — | ID of the associated control (forwarded to native `<label>`) |
|
|
474
|
+
| `id` / `title` / `aria-*` | string | — | Forwarded to native `<label>` |
|
|
445
475
|
|
|
446
476
|
**Content projection** — children become the label text (supports rich markup):
|
|
447
477
|
|
|
@@ -461,14 +491,14 @@ Renders a `<fieldset>` with optional legend and group-level state.
|
|
|
461
491
|
|
|
462
492
|
**Attributes**
|
|
463
493
|
|
|
464
|
-
| Attribute
|
|
465
|
-
|
|
466
|
-
| `legend`
|
|
467
|
-
| `disabled`
|
|
468
|
-
| `loading`
|
|
469
|
-
| `invalid`
|
|
470
|
-
| `success`
|
|
471
|
-
| `form` / `name` / `id` / `title` / `aria-*` | string
|
|
494
|
+
| Attribute | Type | Default | Description |
|
|
495
|
+
| ------------------------------------------- | ------- | ------- | ---------------------------------- |
|
|
496
|
+
| `legend` | string | — | Text for the `<legend>` element |
|
|
497
|
+
| `disabled` | boolean | `false` | Disables all controls in the group |
|
|
498
|
+
| `loading` | boolean | `false` | Busy state |
|
|
499
|
+
| `invalid` | boolean | `false` | Group-level error state |
|
|
500
|
+
| `success` | boolean | `false` | Group-level success state |
|
|
501
|
+
| `form` / `name` / `id` / `title` / `aria-*` | string | — | Forwarded to native `<fieldset>` |
|
|
472
502
|
|
|
473
503
|
**Content projection** — children are placed inside the native `<fieldset>`
|
|
474
504
|
alongside the legend:
|
|
@@ -483,7 +513,246 @@ alongside the legend:
|
|
|
483
513
|
</sp-fieldset>
|
|
484
514
|
```
|
|
485
515
|
|
|
486
|
-
**Internal target** — `[data-sp-fieldset-native]` selects the native
|
|
516
|
+
**Internal target** — `[data-sp-fieldset-native]` selects the native
|
|
517
|
+
`<fieldset>`.
|
|
518
|
+
|
|
519
|
+
---
|
|
520
|
+
|
|
521
|
+
### sp-badge
|
|
522
|
+
|
|
523
|
+
Renders a `<span>` display primitive backed by the Spectre badge recipe.
|
|
524
|
+
|
|
525
|
+
**Attributes**
|
|
526
|
+
|
|
527
|
+
| Attribute | Type | Default | Description |
|
|
528
|
+
| ------------------------- | -------------------------------------------------------------------------------------------------------------- | --------- | -------------------------------- |
|
|
529
|
+
| `variant` | `primary \| secondary \| ghost \| danger \| success \| warning \| info \| accent \| cta \| neutral \| outline` | `primary` | Visual style |
|
|
530
|
+
| `size` | `sm \| md \| lg` | `md` | Badge size |
|
|
531
|
+
| `disabled` | boolean | `false` | Disabled visual state |
|
|
532
|
+
| `loading` | boolean | `false` | Busy visual state |
|
|
533
|
+
| `full-width` | boolean | `false` | Spans full container width |
|
|
534
|
+
| `id` / `title` / `aria-*` | string | — | Forwarded to the native `<span>` |
|
|
535
|
+
|
|
536
|
+
**Content projection** — children become the badge content.
|
|
537
|
+
|
|
538
|
+
**Internal target** — `[data-sp-badge-native]` selects the native `<span>`.
|
|
539
|
+
|
|
540
|
+
---
|
|
541
|
+
|
|
542
|
+
### sp-card
|
|
543
|
+
|
|
544
|
+
Renders a `<div>` container backed by the Spectre card recipe.
|
|
545
|
+
|
|
546
|
+
**Attributes**
|
|
547
|
+
|
|
548
|
+
| Attribute | Type | Default | Description |
|
|
549
|
+
| ------------------------- | -------------------------------------- | ---------- | ------------------------------- |
|
|
550
|
+
| `variant` | `elevated \| flat \| outline \| ghost` | `elevated` | Visual style |
|
|
551
|
+
| `padded` | boolean | `true` | Applies card padding |
|
|
552
|
+
| `full-height` | boolean | `false` | Spans full container height |
|
|
553
|
+
| `interactive` | boolean | `false` | Applies interactive styling |
|
|
554
|
+
| `disabled` | boolean | `false` | Disabled visual state |
|
|
555
|
+
| `loading` | boolean | `false` | Busy visual state |
|
|
556
|
+
| `id` / `title` / `aria-*` | string | — | Forwarded to the native `<div>` |
|
|
557
|
+
|
|
558
|
+
**Content projection** — children become the card content.
|
|
559
|
+
|
|
560
|
+
**Internal target** — `[data-sp-card-native]` selects the native `<div>`.
|
|
561
|
+
|
|
562
|
+
---
|
|
563
|
+
|
|
564
|
+
### sp-icon-box
|
|
565
|
+
|
|
566
|
+
Renders a `<div>` icon container backed by the Spectre icon-box recipe.
|
|
567
|
+
|
|
568
|
+
**Attributes**
|
|
569
|
+
|
|
570
|
+
| Attribute | Type | Default | Description |
|
|
571
|
+
| ------------------------- | -------------------------------------------------------------------------------------------------------------- | --------- | ------------------------------- |
|
|
572
|
+
| `variant` | `primary \| secondary \| ghost \| danger \| success \| warning \| info \| accent \| cta \| neutral \| outline` | `primary` | Visual style |
|
|
573
|
+
| `size` | `sm \| md \| lg` | `md` | Icon-box size |
|
|
574
|
+
| `disabled` | boolean | `false` | Disabled visual state |
|
|
575
|
+
| `loading` | boolean | `false` | Busy visual state |
|
|
576
|
+
| `interactive` | boolean | `false` | Applies interactive styling |
|
|
577
|
+
| `pill` | boolean | `false` | Pill / fully-rounded corners |
|
|
578
|
+
| `full-width` | boolean | `false` | Spans full container width |
|
|
579
|
+
| `id` / `title` / `aria-*` | string | — | Forwarded to the native `<div>` |
|
|
580
|
+
|
|
581
|
+
**Content projection** — children become the icon-box content.
|
|
582
|
+
|
|
583
|
+
**Internal target** — `[data-sp-icon-box-native]` selects the native `<div>`.
|
|
584
|
+
|
|
585
|
+
---
|
|
586
|
+
|
|
587
|
+
### sp-rating
|
|
588
|
+
|
|
589
|
+
Renders a read-only rating visualization with generated star spans.
|
|
590
|
+
|
|
591
|
+
**Attributes**
|
|
592
|
+
|
|
593
|
+
| Attribute | Type | Default | Description |
|
|
594
|
+
| ------------------------- | ---------------- | ------- | -------------------------------------- |
|
|
595
|
+
| `value` | number | `0` | Filled star count |
|
|
596
|
+
| `max` | number | `5` | Total star count |
|
|
597
|
+
| `size` | `sm \| md \| lg` | `md` | Rating size |
|
|
598
|
+
| `label` | string | — | Optional visible text beside the stars |
|
|
599
|
+
| `disabled` | boolean | `false` | Disabled visual state |
|
|
600
|
+
| `loading` | boolean | `false` | Busy visual state |
|
|
601
|
+
| `id` / `title` / `aria-*` | string | — | Forwarded to the rating container |
|
|
602
|
+
|
|
603
|
+
**Accessibility** — renders `role="img"` and computes an accessible label like
|
|
604
|
+
`Rating: 4 out of 5` unless `aria-label` is provided.
|
|
605
|
+
|
|
606
|
+
**Internal target** — `[data-sp-rating-native]` selects the rating container.
|
|
607
|
+
|
|
608
|
+
---
|
|
609
|
+
|
|
610
|
+
### sp-testimonial
|
|
611
|
+
|
|
612
|
+
Renders a `<div>` testimonial container backed by the Spectre testimonial
|
|
613
|
+
recipe.
|
|
614
|
+
|
|
615
|
+
**Attributes**
|
|
616
|
+
|
|
617
|
+
| Attribute | Type | Default | Description |
|
|
618
|
+
| ------------------------- | -------------------------------------- | ---------- | ------------------------------- |
|
|
619
|
+
| `variant` | `elevated \| flat \| outline \| ghost` | `elevated` | Visual style |
|
|
620
|
+
| `full-height` | boolean | `false` | Spans full container height |
|
|
621
|
+
| `interactive` | boolean | `false` | Applies interactive styling |
|
|
622
|
+
| `disabled` | boolean | `false` | Disabled visual state |
|
|
623
|
+
| `loading` | boolean | `false` | Busy visual state |
|
|
624
|
+
| `id` / `title` / `aria-*` | string | — | Forwarded to the native `<div>` |
|
|
625
|
+
|
|
626
|
+
**Content projection** — children become the testimonial content.
|
|
627
|
+
|
|
628
|
+
**Internal target** — `[data-sp-testimonial-native]` selects the native `<div>`.
|
|
629
|
+
|
|
630
|
+
---
|
|
631
|
+
|
|
632
|
+
### sp-alert
|
|
633
|
+
|
|
634
|
+
Renders a `<div role="alert">` display primitive backed by the Spectre alert
|
|
635
|
+
recipe.
|
|
636
|
+
|
|
637
|
+
**Attributes**
|
|
638
|
+
|
|
639
|
+
| Attribute | Type | Default | Description |
|
|
640
|
+
| ------------------------- | ------------------------------------------------- | ------- | ------------------------------- |
|
|
641
|
+
| `variant` | `info \| success \| warning \| danger \| neutral` | `info` | Visual style |
|
|
642
|
+
| `size` | `sm \| md \| lg` | `md` | Alert size |
|
|
643
|
+
| `dismissed` | boolean | `false` | Dismissed visual state |
|
|
644
|
+
| `disabled` | boolean | `false` | Disabled visual state |
|
|
645
|
+
| `loading` | boolean | `false` | Busy visual state |
|
|
646
|
+
| `full-width` | boolean | `false` | Spans full container width |
|
|
647
|
+
| `id` / `title` / `aria-*` | string | — | Forwarded to the native `<div>` |
|
|
648
|
+
|
|
649
|
+
**Content projection** — children become the alert content.
|
|
650
|
+
|
|
651
|
+
**Accessibility** — renders `role="alert"` and reflects the `loading` state to
|
|
652
|
+
`aria-busy`.
|
|
653
|
+
|
|
654
|
+
**Internal target** — `[data-sp-alert-native]` selects the native `<div>`.
|
|
655
|
+
|
|
656
|
+
---
|
|
657
|
+
|
|
658
|
+
### sp-avatar
|
|
659
|
+
|
|
660
|
+
Renders a `<div>` avatar container backed by the Spectre avatar recipe.
|
|
661
|
+
|
|
662
|
+
**Attributes**
|
|
663
|
+
|
|
664
|
+
| Attribute | Type | Default | Description |
|
|
665
|
+
| ------------------------- | ---------------------------- | -------- | -------------------------------- |
|
|
666
|
+
| `size` | `xs \| sm \| md \| lg \| xl` | `md` | Avatar size |
|
|
667
|
+
| `shape` | `circle \| square` | `circle` | Avatar shape |
|
|
668
|
+
| `interactive` | boolean | `false` | Applies interactive styling |
|
|
669
|
+
| `disabled` | boolean | `false` | Disabled visual state |
|
|
670
|
+
| `loading` | boolean | `false` | Busy visual state |
|
|
671
|
+
| `full-width` | boolean | `false` | Spans full container width |
|
|
672
|
+
| `placeholder` | boolean | `false` | Placeholder background and color |
|
|
673
|
+
| `id` / `title` / `aria-*` | string | — | Forwarded to the native `<div>` |
|
|
674
|
+
|
|
675
|
+
**Content projection** — children become the avatar content (an `<img>`,
|
|
676
|
+
initials, or an icon).
|
|
677
|
+
|
|
678
|
+
**Accessibility** — reflects the `loading` state to `aria-busy`.
|
|
679
|
+
|
|
680
|
+
**Internal target** — `[data-sp-avatar-native]` selects the native `<div>`.
|
|
681
|
+
|
|
682
|
+
---
|
|
683
|
+
|
|
684
|
+
### sp-spinner
|
|
685
|
+
|
|
686
|
+
Renders a `<div role="status">` loading indicator backed by the Spectre spinner
|
|
687
|
+
recipe.
|
|
688
|
+
|
|
689
|
+
**Attributes**
|
|
690
|
+
|
|
691
|
+
| Attribute | Type | Default | Description |
|
|
692
|
+
| ------------------------- | ------------------------------------------------------------------------------------------ | ------- | ------------------------------- |
|
|
693
|
+
| `variant` | `primary \| secondary \| success \| warning \| danger \| info \| neutral \| accent \| cta` | — | Arc color |
|
|
694
|
+
| `size` | `sm \| md \| lg` | `md` | Spinner size |
|
|
695
|
+
| `disabled` | boolean | `false` | Disabled visual state |
|
|
696
|
+
| `loading` | boolean | `true` | Busy visual state |
|
|
697
|
+
| `id` / `title` / `aria-*` | string | — | Forwarded to the native `<div>` |
|
|
698
|
+
|
|
699
|
+
**Accessibility** — renders `role="status"` and reflects the `loading` state to
|
|
700
|
+
`aria-busy`. Defaults `aria-label` to `Loading` unless `aria-label` is provided.
|
|
701
|
+
|
|
702
|
+
**Internal target** — `[data-sp-spinner-native]` selects the native `<div>`.
|
|
703
|
+
|
|
704
|
+
---
|
|
705
|
+
|
|
706
|
+
### sp-tag
|
|
707
|
+
|
|
708
|
+
Renders a `<span>` tag/chip backed by the Spectre tag recipe.
|
|
709
|
+
|
|
710
|
+
**Attributes**
|
|
711
|
+
|
|
712
|
+
| Attribute | Type | Default | Description |
|
|
713
|
+
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------- | --------- | --------------------------------- |
|
|
714
|
+
| `variant` | `default \| primary \| secondary \| success \| warning \| danger \| info \| neutral \| accent \| cta \| outline \| ghost` | `default` | Tag color |
|
|
715
|
+
| `size` | `sm \| md \| lg` | `md` | Tag size |
|
|
716
|
+
| `interactive` | boolean | `false` | Applies interactive styling |
|
|
717
|
+
| `selected` | boolean | `false` | Selected/active visual state |
|
|
718
|
+
| `dismissible` | boolean | `false` | Reserves space for a dismiss icon |
|
|
719
|
+
| `disabled` | boolean | `false` | Disabled visual state |
|
|
720
|
+
| `loading` | boolean | `false` | Busy visual state |
|
|
721
|
+
| `full-width` | boolean | `false` | Spans full container width |
|
|
722
|
+
| `id` / `title` / `aria-*` | string | — | Forwarded to the native `<span>` |
|
|
723
|
+
|
|
724
|
+
**Content projection** — children become the tag label (and any projected
|
|
725
|
+
dismiss icon).
|
|
726
|
+
|
|
727
|
+
**Accessibility** — reflects the `loading` state to `aria-busy`.
|
|
728
|
+
|
|
729
|
+
**Internal target** — `[data-sp-tag-native]` selects the native `<span>`.
|
|
730
|
+
|
|
731
|
+
---
|
|
732
|
+
|
|
733
|
+
### sp-pricing-card
|
|
734
|
+
|
|
735
|
+
Renders a `<div>` pricing card container backed by the Spectre pricing-card
|
|
736
|
+
recipe.
|
|
737
|
+
|
|
738
|
+
**Attributes**
|
|
739
|
+
|
|
740
|
+
| Attribute | Type | Default | Description |
|
|
741
|
+
| ------------------------- | ------- | ------- | ------------------------------- |
|
|
742
|
+
| `featured` | boolean | `false` | Highlights the card as featured |
|
|
743
|
+
| `interactive` | boolean | `false` | Applies interactive styling |
|
|
744
|
+
| `disabled` | boolean | `false` | Disabled visual state |
|
|
745
|
+
| `loading` | boolean | `false` | Busy visual state |
|
|
746
|
+
| `full-height` | boolean | `false` | Spans full container height |
|
|
747
|
+
| `id` / `title` / `aria-*` | string | — | Forwarded to the native `<div>` |
|
|
748
|
+
|
|
749
|
+
**Content projection** — children become the pricing card content (heading,
|
|
750
|
+
price, feature list, call-to-action, etc.).
|
|
751
|
+
|
|
752
|
+
**Accessibility** — reflects the `loading` state to `aria-busy`.
|
|
753
|
+
|
|
754
|
+
**Internal target** — `[data-sp-pricing-card-native]` selects the native
|
|
755
|
+
`<div>`.
|
|
487
756
|
|
|
488
757
|
## Package exports / API surface
|
|
489
758
|
|
|
@@ -495,52 +764,81 @@ helper.
|
|
|
495
764
|
**Bulk registration**
|
|
496
765
|
|
|
497
766
|
```ts
|
|
498
|
-
import { defineSpectreComponents } from '@phcdevworks/spectre-components'
|
|
499
|
-
defineSpectreComponents()
|
|
767
|
+
import { defineSpectreComponents } from '@phcdevworks/spectre-components'
|
|
768
|
+
defineSpectreComponents() // registers all sp-* elements
|
|
500
769
|
```
|
|
501
770
|
|
|
502
771
|
**Per-component helpers** (same as individual entry points):
|
|
503
772
|
`defineSpectreButton`, `defineSpectreInput`, `defineSpectreTextarea`,
|
|
504
773
|
`defineSpectreSelect`, `defineSpectreCheckbox`, `defineSpectreRadio`,
|
|
505
|
-
`defineSpectreLabel`, `defineSpectreFieldset`
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
`
|
|
509
|
-
|
|
510
|
-
`
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
`
|
|
514
|
-
`
|
|
515
|
-
`
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
`
|
|
520
|
-
`
|
|
774
|
+
`defineSpectreLabel`, `defineSpectreFieldset`, `defineSpectreBadge`,
|
|
775
|
+
`defineSpectreCard`, `defineSpectreIconBox`, `defineSpectreRating`,
|
|
776
|
+
`defineSpectreTestimonial`, `defineSpectreAlert`, `defineSpectreAvatar`,
|
|
777
|
+
`defineSpectreSpinner`, `defineSpectreTag`, `defineSpectrePricingCard`
|
|
778
|
+
|
|
779
|
+
**Element classes**: `SpectreButtonElement`, `SpectreInputElement`,
|
|
780
|
+
`SpectreTextareaElement`, `SpectreSelectElement`, `SpectreCheckboxElement`,
|
|
781
|
+
`SpectreRadioElement`, `SpectreLabelElement`, `SpectreFieldsetElement`,
|
|
782
|
+
`SpectreBadgeElement`, `SpectreCardElement`, `SpectreIconBoxElement`,
|
|
783
|
+
`SpectreRatingElement`, `SpectreTestimonialElement`, `SpectreAlertElement`,
|
|
784
|
+
`SpectreAvatarElement`, `SpectreSpinnerElement`, `SpectreTagElement`,
|
|
785
|
+
`SpectrePricingCardElement`
|
|
786
|
+
|
|
787
|
+
**Button constants and types**: `spectreButtonVariants`, `spectreButtonSizes`,
|
|
788
|
+
`spectreButtonTypes`, `SpectreButtonVariant`, `SpectreButtonSize`,
|
|
789
|
+
`SpectreButtonType`, `SpectreButtonProps`
|
|
790
|
+
|
|
791
|
+
**Input / textarea / select constants and types**: `spectreInputSizes`,
|
|
792
|
+
`spectreInputTypes`, `SpectreInputSize`, `SpectreInputType`,
|
|
793
|
+
`SpectreInputProps`, `SpectreTextareaProps`, `SpectreSelectProps`
|
|
521
794
|
|
|
522
795
|
**Props interfaces** (checkbox / radio / label / fieldset):
|
|
523
796
|
`SpectreCheckboxProps`, `SpectreRadioProps`, `SpectreLabelProps`,
|
|
524
797
|
`SpectreFieldsetProps`
|
|
525
798
|
|
|
799
|
+
**Display constants and types**: `spectreBadgeVariants`, `spectreBadgeSizes`,
|
|
800
|
+
`spectreCardVariants`, `spectreIconBoxVariants`, `spectreIconBoxSizes`,
|
|
801
|
+
`spectreRatingSizes`, `spectreTestimonialVariants`, `spectreAlertVariants`,
|
|
802
|
+
`spectreAlertSizes`, `spectreAvatarShapes`, `spectreAvatarSizes`,
|
|
803
|
+
`spectreSpinnerVariants`, `spectreSpinnerSizes`, `spectreTagVariants`,
|
|
804
|
+
`spectreTagSizes`, `SpectreBadgeVariant`, `SpectreBadgeSize`,
|
|
805
|
+
`SpectreCardVariant`, `SpectreIconBoxVariant`, `SpectreIconBoxSize`,
|
|
806
|
+
`SpectreRatingSize`, `SpectreTestimonialVariant`, `SpectreAlertVariant`,
|
|
807
|
+
`SpectreAlertSize`, `SpectreAvatarShape`, `SpectreAvatarSize`,
|
|
808
|
+
`SpectreSpinnerVariant`, `SpectreSpinnerSize`, `SpectreTagVariant`,
|
|
809
|
+
`SpectreTagSize`, `SpectreBadgeProps`, `SpectreCardProps`,
|
|
810
|
+
`SpectreIconBoxProps`, `SpectreRatingProps`, `SpectreTestimonialProps`,
|
|
811
|
+
`SpectreAlertProps`, `SpectreAvatarProps`, `SpectreSpinnerProps`,
|
|
812
|
+
`SpectreTagProps`, `SpectrePricingCardProps`
|
|
813
|
+
|
|
526
814
|
### Subpath entry points
|
|
527
815
|
|
|
528
816
|
Each entry point registers only that component and exports only its surface:
|
|
529
817
|
|
|
530
|
-
| Entry point
|
|
531
|
-
|
|
532
|
-
| `.../button`
|
|
533
|
-
| `.../input`
|
|
534
|
-
| `.../textarea`
|
|
535
|
-
| `.../select`
|
|
536
|
-
| `.../checkbox`
|
|
537
|
-
| `.../radio`
|
|
538
|
-
| `.../label`
|
|
539
|
-
| `.../fieldset`
|
|
818
|
+
| Entry point | Registers | Key exports |
|
|
819
|
+
| ------------------ | ----------------- | ---------------------------------------------------------------------------------------- |
|
|
820
|
+
| `.../button` | `sp-button` | `defineSpectreButton`, `SpectreButtonElement`, button constants and types |
|
|
821
|
+
| `.../input` | `sp-input` | `defineSpectreInput`, `SpectreInputElement`, input constants and types |
|
|
822
|
+
| `.../textarea` | `sp-textarea` | `defineSpectreTextarea`, `SpectreTextareaElement`, `SpectreTextareaProps` |
|
|
823
|
+
| `.../select` | `sp-select` | `defineSpectreSelect`, `SpectreSelectElement`, `SpectreSelectProps` |
|
|
824
|
+
| `.../checkbox` | `sp-checkbox` | `defineSpectreCheckbox`, `SpectreCheckboxElement`, `SpectreCheckboxProps` |
|
|
825
|
+
| `.../radio` | `sp-radio` | `defineSpectreRadio`, `SpectreRadioElement`, `SpectreRadioProps` |
|
|
826
|
+
| `.../label` | `sp-label` | `defineSpectreLabel`, `SpectreLabelElement`, `SpectreLabelProps` |
|
|
827
|
+
| `.../fieldset` | `sp-fieldset` | `defineSpectreFieldset`, `SpectreFieldsetElement`, `SpectreFieldsetProps` |
|
|
828
|
+
| `.../badge` | `sp-badge` | `defineSpectreBadge`, `SpectreBadgeElement`, badge constants and types |
|
|
829
|
+
| `.../card` | `sp-card` | `defineSpectreCard`, `SpectreCardElement`, card constants and types |
|
|
830
|
+
| `.../icon-box` | `sp-icon-box` | `defineSpectreIconBox`, `SpectreIconBoxElement`, icon-box constants and types |
|
|
831
|
+
| `.../rating` | `sp-rating` | `defineSpectreRating`, `SpectreRatingElement`, rating constants and types |
|
|
832
|
+
| `.../testimonial` | `sp-testimonial` | `defineSpectreTestimonial`, `SpectreTestimonialElement`, testimonial constants and types |
|
|
833
|
+
| `.../alert` | `sp-alert` | `defineSpectreAlert`, `SpectreAlertElement`, alert constants and types |
|
|
834
|
+
| `.../avatar` | `sp-avatar` | `defineSpectreAvatar`, `SpectreAvatarElement`, avatar constants and types |
|
|
835
|
+
| `.../spinner` | `sp-spinner` | `defineSpectreSpinner`, `SpectreSpinnerElement`, spinner constants and types |
|
|
836
|
+
| `.../tag` | `sp-tag` | `defineSpectreTag`, `SpectreTagElement`, tag constants and types |
|
|
837
|
+
| `.../pricing-card` | `sp-pricing-card` | `defineSpectrePricingCard`, `SpectrePricingCardElement`, `SpectrePricingCardProps` |
|
|
540
838
|
|
|
541
839
|
Size constants are shared between input, textarea, and select. Import
|
|
542
|
-
`spectreInputSizes` / `SpectreInputSize` from `.../input` when needed
|
|
543
|
-
|
|
840
|
+
`spectreInputSizes` / `SpectreInputSize` from `.../input` when needed alongside
|
|
841
|
+
textarea or select.
|
|
544
842
|
|
|
545
843
|
## Relationship to the rest of Spectre
|
|
546
844
|
|
|
@@ -552,8 +850,8 @@ spectre-components → Lit web component behavior ← you are here
|
|
|
552
850
|
```
|
|
553
851
|
|
|
554
852
|
The Golden Rule: **tokens define meaning, UI defines structure, components
|
|
555
|
-
define behavior, adapters define delivery.** This package only owns the
|
|
556
|
-
|
|
853
|
+
define behavior, adapters define delivery.** This package only owns the behavior
|
|
854
|
+
layer.
|
|
557
855
|
|
|
558
856
|
## Development
|
|
559
857
|
|
|
@@ -561,20 +859,23 @@ behavior layer.
|
|
|
561
859
|
git clone https://github.com/phcdevworks/spectre-components.git
|
|
562
860
|
cd spectre-components
|
|
563
861
|
npm install
|
|
564
|
-
npm run check #
|
|
862
|
+
npm run check # full release validation gate
|
|
565
863
|
```
|
|
566
864
|
|
|
567
|
-
Requires Node.js `^22.
|
|
568
|
-
|
|
569
|
-
| Command
|
|
570
|
-
|
|
571
|
-
| `npm run check`
|
|
572
|
-
| `npm run build`
|
|
573
|
-
| `npm test`
|
|
574
|
-
| `npm run lint`
|
|
575
|
-
| `npm run check:exports`
|
|
576
|
-
| `npm run
|
|
577
|
-
| `npm run
|
|
865
|
+
Requires Node.js `^22.13.0 || >=24.0.0` and npm `11.16.0`.
|
|
866
|
+
|
|
867
|
+
| Command | Purpose |
|
|
868
|
+
| -------------------------- | ----------------------------------------------------------------------------------------------------- |
|
|
869
|
+
| `npm run check` | Full validation (lint → typecheck → test → build → export, contract, invariant, and ecosystem checks) |
|
|
870
|
+
| `npm run build` | Compile ESM + CJS with declarations into `dist/` |
|
|
871
|
+
| `npm test` | Run Vitest suite under happy-dom |
|
|
872
|
+
| `npm run lint` | ESLint |
|
|
873
|
+
| `npm run check:exports` | Verify built subpath exports resolve correctly |
|
|
874
|
+
| `npm run check:contract` | Verify built exports match `components.contract.json` |
|
|
875
|
+
| `npm run check:invariants` | Verify light-DOM and no-hardcoded-visual invariants |
|
|
876
|
+
| `npm run check:ecosystem` | Validate `spectre.manifest.json` |
|
|
877
|
+
| `npm run dev` | tsup watch mode |
|
|
878
|
+
| `npm run clean` | Remove `dist/` and `coverage/` |
|
|
578
879
|
|
|
579
880
|
Key source areas:
|
|
580
881
|
|
|
@@ -582,27 +883,27 @@ Key source areas:
|
|
|
582
883
|
- `src/utils/` — `base.ts`, `projectable.ts`, `form.ts`, `dom.ts`
|
|
583
884
|
- `src/index.ts` — root public API and bulk registration helper
|
|
584
885
|
- `tests/` — component behavior coverage (Vitest + happy-dom)
|
|
585
|
-
- `scripts/check-exports.
|
|
886
|
+
- `scripts/check-exports.ts` — post-build export resolution check
|
|
586
887
|
|
|
587
888
|
## Troubleshooting
|
|
588
889
|
|
|
589
|
-
**Build fails with type errors** — TypeScript 6 is required. Run
|
|
590
|
-
|
|
890
|
+
**Build fails with type errors** — TypeScript 6 is required. Run `npm install`,
|
|
891
|
+
then `npm run build`.
|
|
591
892
|
|
|
592
893
|
**Tests fail in CI but pass locally** — Tests run under happy-dom. Confirm you
|
|
593
|
-
are on Node `^22.
|
|
894
|
+
are on Node `^22.13.0 || >=24.0.0`. CI tests both versions.
|
|
594
895
|
|
|
595
896
|
**Custom element already defined** — Each `defineSpectre*()` helper is
|
|
596
897
|
idempotent; calling it twice is safe. If you see conflicts, two different
|
|
597
898
|
versions of this package may be loaded in the same page.
|
|
598
899
|
|
|
599
|
-
**Styles are not applying** — The Spectre CSS layers must load before
|
|
600
|
-
|
|
900
|
+
**Styles are not applying** — The Spectre CSS layers must load before components
|
|
901
|
+
are registered. Import `@phcdevworks/spectre-tokens/index.css` and
|
|
601
902
|
`@phcdevworks/spectre-ui/index.css` at the top of your entry module.
|
|
602
903
|
|
|
603
904
|
**Properties not reflecting in React 18** — React 18 sets custom element
|
|
604
|
-
properties as attributes. Use a `ref` to set properties imperatively, or
|
|
605
|
-
|
|
905
|
+
properties as attributes. Use a `ref` to set properties imperatively, or upgrade
|
|
906
|
+
to React 19 which supports custom elements fully.
|
|
606
907
|
|
|
607
908
|
## Validation
|
|
608
909
|
|
|
@@ -612,8 +913,9 @@ Run the full validation gate before any pull request:
|
|
|
612
913
|
npm run check
|
|
613
914
|
```
|
|
614
915
|
|
|
615
|
-
This runs: lint → typecheck → tests → build → export validation
|
|
616
|
-
|
|
916
|
+
This runs: lint → typecheck → tests → build → export validation → contract
|
|
917
|
+
validation → invariant checks → ecosystem manifest validation. All steps must
|
|
918
|
+
pass.
|
|
617
919
|
|
|
618
920
|
## AI and automation boundaries
|
|
619
921
|
|
|
@@ -640,10 +942,10 @@ Contribution boundaries:
|
|
|
640
942
|
|
|
641
943
|
- Components must consume `@phcdevworks/spectre-ui` class helpers — do not
|
|
642
944
|
recreate CSS locally.
|
|
643
|
-
- Design values must come from `@phcdevworks/spectre-tokens` — do not
|
|
644
|
-
|
|
645
|
-
- Component tags, properties, events, slots, and ARIA behavior are stable API
|
|
646
|
-
|
|
945
|
+
- Design values must come from `@phcdevworks/spectre-tokens` — do not hardcode
|
|
946
|
+
colors, spacing, or other visual primitives.
|
|
947
|
+
- Component tags, properties, events, slots, and ARIA behavior are stable API —
|
|
948
|
+
breaking changes require a semver major bump.
|
|
647
949
|
- Render in light DOM only — Shadow DOM changes require design-system approval.
|
|
648
950
|
- No framework-specific code — no JSX, SFCs, or Astro components in this
|
|
649
951
|
package.
|