@rak200/ui 0.2.12 → 0.2.14

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 CHANGED
@@ -86,8 +86,9 @@ components; `docs/` is what describes them.
86
86
 
87
87
  ## Status
88
88
 
89
- **v0.** Nine components — `<ui-button>`, `<ui-field>`, `<ui-dialog>`, `<ui-input>`,
90
- `<ui-textarea>`, `<ui-checkbox>`, `<ui-switch>`, `<ui-select>` and `<ui-icon>` — the token layer
89
+ **v0.** Twelve components — `<ui-button>`, `<ui-card>`, `<ui-field>`, `<ui-dialog>`, `<ui-input>`,
90
+ `<ui-textarea>`, `<ui-checkbox>`, `<ui-switch>`, `<ui-select>`, `<ui-radio-group>`, `<ui-radio>`
91
+ and `<ui-icon>` — the token layer
91
92
  under them, and an adopted glyph set, built to the ecosystem's full quality bar rather than
92
93
  sketched: type-checked at the strictest available setting, formatted, tested in a real browser and
93
94
  **asserted against axe** for WCAG A/AA, 100% coverage and **100% mutation score**, scanned, and
package/dist/card.d.ts ADDED
@@ -0,0 +1,41 @@
1
+ import { LitElement, type TemplateResult } from 'lit';
2
+ /**
3
+ * A container: a surface with a boundary, a corner and a lift.
4
+ *
5
+ * **Presentational, and deliberately not interactive.** A card that reacts to a click is a
6
+ * button or a link, and both already exist — here and in the platform. This element grows
7
+ * no `clickable` attribute, because the first thing such an attribute has to do is
8
+ * reimplement keyboard activation, the accessible name and the disabled semantics that
9
+ * `<button>` and `<a>` carry for free. `docs/card.md` sends a reader there rather than
10
+ * leaving them to find out.
11
+ *
12
+ * **It claims no role either.** There is no card element and no APG pattern for one, so
13
+ * the shadow root renders slots and nothing else: what a card *means* is the host's, and
14
+ * they say it by slotting a heading, or by writing `<article>` around this element when
15
+ * the content really is self-contained. A `role` invented here would be one every consumer
16
+ * inherits and none of them chose.
17
+ *
18
+ * **Three regions, ordered here rather than in the host's markup.** The slots are declared
19
+ * header, body, footer, so that is the order they render in whatever order the host wrote
20
+ * them — and an unfilled one costs nothing, because a `<slot>` is `display: contents` and
21
+ * contributes no box to lay out or to space.
22
+ *
23
+ * @example
24
+ * ```html
25
+ * <ui-card>
26
+ * <h3 slot="header">Monthly plan</h3>
27
+ * <p>Everything in the free tier, plus priority support.</p>
28
+ * <div slot="footer"><ui-button>Choose</ui-button></div>
29
+ * </ui-card>
30
+ * ```
31
+ */
32
+ export declare class UiCard extends LitElement {
33
+ static readonly styles: import("lit").CSSResult;
34
+ render(): TemplateResult;
35
+ }
36
+ declare global {
37
+ interface HTMLElementTagNameMap {
38
+ 'ui-card': UiCard;
39
+ }
40
+ }
41
+ //# sourceMappingURL=card.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card.d.ts","sourceRoot":"","sources":["../src/card.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAGjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,MAAO,SAAQ,UAAU;IAClC,gBAAyB,MAAM,0BAwC7B;IAEO,MAAM,IAAI,cAAc;CAOpC;AAQD,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,qBAAqB;QAC3B,SAAS,EAAE,MAAM,CAAC;KACrB;CACJ"}
package/dist/card.js ADDED
@@ -0,0 +1,88 @@
1
+ import { LitElement, css, html } from 'lit';
2
+ import { reference } from './reference.js';
3
+ /**
4
+ * A container: a surface with a boundary, a corner and a lift.
5
+ *
6
+ * **Presentational, and deliberately not interactive.** A card that reacts to a click is a
7
+ * button or a link, and both already exist — here and in the platform. This element grows
8
+ * no `clickable` attribute, because the first thing such an attribute has to do is
9
+ * reimplement keyboard activation, the accessible name and the disabled semantics that
10
+ * `<button>` and `<a>` carry for free. `docs/card.md` sends a reader there rather than
11
+ * leaving them to find out.
12
+ *
13
+ * **It claims no role either.** There is no card element and no APG pattern for one, so
14
+ * the shadow root renders slots and nothing else: what a card *means* is the host's, and
15
+ * they say it by slotting a heading, or by writing `<article>` around this element when
16
+ * the content really is self-contained. A `role` invented here would be one every consumer
17
+ * inherits and none of them chose.
18
+ *
19
+ * **Three regions, ordered here rather than in the host's markup.** The slots are declared
20
+ * header, body, footer, so that is the order they render in whatever order the host wrote
21
+ * them — and an unfilled one costs nothing, because a `<slot>` is `display: contents` and
22
+ * contributes no box to lay out or to space.
23
+ *
24
+ * @example
25
+ * ```html
26
+ * <ui-card>
27
+ * <h3 slot="header">Monthly plan</h3>
28
+ * <p>Everything in the free tier, plus priority support.</p>
29
+ * <div slot="footer"><ui-button>Choose</ui-button></div>
30
+ * </ui-card>
31
+ * ```
32
+ */
33
+ export class UiCard extends LitElement {
34
+ static { this.styles = css `
35
+ /* A column rather than a block, and the footer below is why: margin-block-start:
36
+ auto needs a flex line to push against. That is what makes a row of cards in a
37
+ grid line their footers up when the bodies are different lengths — the one thing
38
+ a footer slot buys that writing the element last does not.
39
+
40
+ The slots are left at their default display: contents, so the flex items are
41
+ the host's own elements. An empty region is then absent rather than
42
+ zero-height — gap never spaces a card that has no footer. */
43
+ :host {
44
+ display: flex;
45
+ flex-direction: column;
46
+ gap: calc(${reference('--ui-space')} * 2);
47
+ box-sizing: border-box;
48
+ padding: calc(${reference('--ui-space')} * 2);
49
+ font-family: ${reference('--ui-font')};
50
+ /* The pair, never half of it: a surface declared without the text colour that
51
+ was chosen against it inherits whatever the page set, and the contrast the
52
+ token layer measured stops holding at the one place it was measured for. */
53
+ color: ${reference('--ui-color-text')};
54
+ background: ${reference('--ui-color-surface')};
55
+ border: 1px solid ${reference('--ui-color-border')};
56
+ border-radius: ${reference('--ui-radius')};
57
+ /* The boundary and the shadow are one decision made twice, because each covers
58
+ where the other cannot. The shadow is what says *raised* on a light page and
59
+ nearly nothing on a dark one — it is black at a low alpha, and light-dark()
60
+ cannot carry a second value for it, since it takes colours and a shadow is
61
+ not one. The boundary is derived, so it mixes toward the text and is correct
62
+ in both schemes by construction. Drop either and the card loses its edge in
63
+ one scheme: measured, a bordered card on the dark surface is the only thing
64
+ separating it from the page behind it. */
65
+ box-shadow: ${reference('--ui-elevation-raised')};
66
+ }
67
+
68
+ /* Pushed to the bottom of whatever height the card ended up with. Written on the
69
+ slotted element rather than on a wrapper, because a wrapper would be a flex item
70
+ of its own — present, and therefore spaced by gap, even with nothing in it. */
71
+ slot[name='footer']::slotted(*) {
72
+ margin-block-start: auto;
73
+ }
74
+ `; }
75
+ render() {
76
+ return html `
77
+ <slot name="header"></slot>
78
+ <slot></slot>
79
+ <slot name="footer"></slot>
80
+ `;
81
+ }
82
+ }
83
+ // Stryker disable next-line StringLiteral: the registration runs once, at import, inside
84
+ // the warm process Stryker switches mutants in — so by the time a mutant on this line is
85
+ // active the element is already defined under the original name, and no test can observe
86
+ // the change. Outside the runner's reach, not an equivalent mutant.
87
+ customElements.define('ui-card', UiCard);
88
+ //# sourceMappingURL=card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card.js","sourceRoot":"","sources":["../src/card.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAuB,MAAM,KAAK,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,OAAO,MAAO,SAAQ,UAAU;aACT,WAAM,GAAG,GAAG,CAAA;;;;;;;;;;;;wBAYjB,SAAS,CAAC,YAAY,CAAC;;4BAEnB,SAAS,CAAC,YAAY,CAAC;2BACxB,SAAS,CAAC,WAAW,CAAC;;;;qBAI5B,SAAS,CAAC,iBAAiB,CAAC;0BACvB,SAAS,CAAC,oBAAoB,CAAC;gCACzB,SAAS,CAAC,mBAAmB,CAAC;6BACjC,SAAS,CAAC,aAAa,CAAC;;;;;;;;;0BAS3B,SAAS,CAAC,uBAAuB,CAAC;;;;;;;;;KASvD,CAAC;IAEO,MAAM;QACX,OAAO,IAAI,CAAA;;;;SAIV,CAAC;IACN,CAAC;;AAGL,yFAAyF;AACzF,yFAAyF;AACzF,yFAAyF;AACzF,oEAAoE;AACpE,cAAc,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC"}
package/dist/field.d.ts CHANGED
@@ -15,7 +15,12 @@ import { LitElement, type TemplateResult } from 'lit';
15
15
  *
16
16
  * **The control may sit below a wrapper**, and the same constraint is why: `<ui-input>` is
17
17
  * a box around a control that had to stay in the light DOM, so this element looks through
18
- * it. See {@link UiField.#control}.
18
+ * it. See {@link UiField.#control} — and the one wrapper it does *not* look through, which
19
+ * is a wrapper carrying a `role`, because a group is the control rather than a box for one.
20
+ *
21
+ * **Not every control can be labelled the platform's way**, and `<ui-radio-group>` is the
22
+ * first that cannot: `<label for>` reaches a labelable element and nothing else, so the
23
+ * name arrives as `aria-labelledby` there. See {@link UiField.#name}.
19
24
  *
20
25
  * @example
21
26
  * ```html
@@ -1 +1 @@
1
- {"version":3,"file":"field.d.ts","sourceRoot":"","sources":["../src/field.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAMjE;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,OAAQ,SAAQ,UAAU;;IACnC,gBAAyB,MAAM,0BAuB7B;IAeO,iBAAiB,IAAI,IAAI;IASzB,oBAAoB,IAAI,IAAI;IAK5B,YAAY,IAAI,IAAI;IAIpB,MAAM,IAAI,cAAc;CA2GpC;AAQD,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,qBAAqB;QAC3B,UAAU,EAAE,OAAO,CAAC;KACvB;CACJ"}
1
+ {"version":3,"file":"field.d.ts","sourceRoot":"","sources":["../src/field.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAMjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,qBAAa,OAAQ,SAAQ,UAAU;;IACnC,gBAAyB,MAAM,0BAuB7B;IAeO,iBAAiB,IAAI,IAAI;IASzB,oBAAoB,IAAI,IAAI;IAK5B,YAAY,IAAI,IAAI;IAIpB,MAAM,IAAI,cAAc;CA0JpC;AAQD,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,qBAAqB;QAC3B,UAAU,EAAE,OAAO,CAAC;KACvB;CACJ"}
package/dist/field.js CHANGED
@@ -18,7 +18,12 @@ let sequence = 0;
18
18
  *
19
19
  * **The control may sit below a wrapper**, and the same constraint is why: `<ui-input>` is
20
20
  * a box around a control that had to stay in the light DOM, so this element looks through
21
- * it. See {@link UiField.#control}.
21
+ * it. See {@link UiField.#control} — and the one wrapper it does *not* look through, which
22
+ * is a wrapper carrying a `role`, because a group is the control rather than a box for one.
23
+ *
24
+ * **Not every control can be labelled the platform's way**, and `<ui-radio-group>` is the
25
+ * first that cannot: `<label for>` reaches a labelable element and nothing else, so the
26
+ * name arrives as `aria-labelledby` there. See {@link UiField.#name}.
22
27
  *
23
28
  * @example
24
29
  * ```html
@@ -110,6 +115,14 @@ export class UiField extends LitElement {
110
115
  */
111
116
  #control() {
112
117
  const slotted = this.#slotted(null);
118
+ // A wrapper carrying a `role` is claiming to *be* the widget rather than to box
119
+ // one, and the descent stops there. `<ui-radio-group>` is the first: it sets
120
+ // `role="radiogroup"` on itself, and the thing this field names is that group —
121
+ // looking through it would reach the first radio, which names one option and
122
+ // leaves the group anonymous.
123
+ if (slotted?.hasAttribute('role') === true) {
124
+ return slotted;
125
+ }
113
126
  return slotted?.querySelector('input, textarea, select') ?? slotted;
114
127
  }
115
128
  /**
@@ -131,10 +144,7 @@ export class UiField extends LitElement {
131
144
  if (control.id === '') {
132
145
  control.id = `${uid}-control`;
133
146
  }
134
- const label = this.#slotted('label');
135
- if (label instanceof HTMLLabelElement) {
136
- label.htmlFor = control.id;
137
- }
147
+ this.#name(control, this.#slotted('label'), `${uid}-label`);
138
148
  const help = this.#describer(this.#slotted('help'), `${uid}-help`);
139
149
  const error = this.#describer(this.#slotted('error'), `${uid}-error`);
140
150
  // The error comes first: a screen reader announces descriptions in order, and the
@@ -158,6 +168,42 @@ export class UiField extends LitElement {
158
168
  control.setAttribute('aria-invalid', 'true');
159
169
  }
160
170
  }
171
+ /**
172
+ * Gives the control its accessible name from whatever fills the label slot.
173
+ *
174
+ * **`<label for>` is preferred wherever it reaches**, because it is the platform's own
175
+ * association and it does two things `aria-labelledby` does not: it names the control
176
+ * and it makes the label a click target for it. It only reaches a **labelable**
177
+ * element, though, and `<ui-radio-group>` is not one — a `<label for>` aimed at a
178
+ * custom element labels nothing, which axe reports at critical impact.
179
+ *
180
+ * Which elements are labelable is asked of the platform rather than listed here: those
181
+ * are exactly the ones it gives a `labels` collection to. A list kept in this file
182
+ * would be one the next labelable element ages out of, silently.
183
+ *
184
+ * The name is dropped when the slot empties, the way `aria-describedby` is: a group
185
+ * left pointing at a label that is no longer there has a dangling IDREF, which is the
186
+ * one failure mode nobody sees — the group simply stops having a name.
187
+ *
188
+ * @param fallbackId - Given to the label only on the path that needs one to point at.
189
+ * A host-supplied id survives, the same way the control's and the describers' do.
190
+ */
191
+ #name(control, label, fallbackId) {
192
+ if ('labels' in control) {
193
+ if (label instanceof HTMLLabelElement) {
194
+ label.htmlFor = control.id;
195
+ }
196
+ return;
197
+ }
198
+ if (label === undefined) {
199
+ control.removeAttribute('aria-labelledby');
200
+ return;
201
+ }
202
+ if (label.id === '') {
203
+ label.id = fallbackId;
204
+ }
205
+ control.setAttribute('aria-labelledby', label.id);
206
+ }
161
207
  /**
162
208
  * The id to describe the control by, or `undefined` when the element is absent or has
163
209
  * nothing to say. An element rendered empty — the shape a framework produces for
package/dist/field.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"field.js","sourceRoot":"","sources":["../src/field.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"field.js","sourceRoot":"","sources":["../src/field.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  export { UiButton, type ButtonVariant } from './button.js';
2
+ export { UiCard } from './card.js';
2
3
  export { UiCheckbox, UiSwitch } from './checkbox.js';
3
4
  export { UiDialog } from './dialog.js';
4
5
  export { UiField } from './field.js';
5
6
  export { UiIcon, register } from './icon.js';
6
7
  export { UiInput, UiTextarea } from './input.js';
8
+ export { UiRadio, UiRadioGroup, type RadioOrientation } from './radio.js';
7
9
  export { UiSelect } from './select.js';
8
10
  export { tokens, derivedTokens, defaults, formulas, darkScheme, tokenStyleSheet, type Token, type DerivedToken, } from './tokens.js';
9
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EACH,MAAM,EACN,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,eAAe,EACf,KAAK,KAAK,EACV,KAAK,YAAY,GACpB,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EACH,MAAM,EACN,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,eAAe,EACf,KAAK,KAAK,EACV,KAAK,YAAY,GACpB,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -1,9 +1,11 @@
1
1
  export { UiButton } from './button.js';
2
+ export { UiCard } from './card.js';
2
3
  export { UiCheckbox, UiSwitch } from './checkbox.js';
3
4
  export { UiDialog } from './dialog.js';
4
5
  export { UiField } from './field.js';
5
6
  export { UiIcon, register } from './icon.js';
6
7
  export { UiInput, UiTextarea } from './input.js';
8
+ export { UiRadio, UiRadioGroup } from './radio.js';
7
9
  export { UiSelect } from './select.js';
8
10
  export { tokens, derivedTokens, defaults, formulas, darkScheme, tokenStyleSheet, } from './tokens.js';
9
11
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAsB,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EACH,MAAM,EACN,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,eAAe,GAGlB,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAsB,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,YAAY,EAAyB,MAAM,YAAY,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EACH,MAAM,EACN,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,eAAe,GAGlB,MAAM,aAAa,CAAC"}
@@ -0,0 +1,107 @@
1
+ import { LitElement, type TemplateResult } from 'lit';
2
+ /** Which way a group lays its options out, and announces that it did. */
3
+ export type RadioOrientation = 'vertical' | 'horizontal';
4
+ /**
5
+ * One option's control, drawn from the token layer rather than replaced.
6
+ *
7
+ * **The `<input type="radio">` is yours.** You write it, you set its `name`, `value`,
8
+ * `checked` and `disabled`, and it stays in the light DOM — the shape every control in
9
+ * this kit has, and forced by the same constraint: an ARIA relationship by IDREF does not
10
+ * cross a shadow boundary, so a control rendered in here could not be labelled by the
11
+ * `<label>` around it.
12
+ *
13
+ * **This element carries no state and no name.** It is a drawing, and everything that
14
+ * makes a set of radios *a group* — one tab stop, arrow keys that move and select, one
15
+ * value out of the set — is the platform's, because they are native radios sharing a
16
+ * `name`. Wrapping each one changes none of that: measured in this suite, a group whose
17
+ * radios sit inside custom elements is still one group.
18
+ *
19
+ * @example
20
+ * ```html
21
+ * <label>
22
+ * <ui-radio><input type="radio" name="plan" value="free" /></ui-radio>
23
+ * Free
24
+ * </label>
25
+ * ```
26
+ */
27
+ export declare class UiRadio extends LitElement {
28
+ static readonly styles: import("lit").CSSResult;
29
+ render(): TemplateResult;
30
+ }
31
+ /**
32
+ * A set of radios, laid out and named as one thing.
33
+ *
34
+ * **It hand-rolls no roving tabindex and it brings no state machine**, and that is this
35
+ * element's whole claim rather than a gap in it. Issue #15 asked which of the two it would
36
+ * be, because the APG **Radio Group** pattern — one tab stop, arrow keys that move *and*
37
+ * select, wrapping at the ends — is the first behaviour in the v0 cut that could have
38
+ * justified Zag. Neither was needed: native radios sharing a `name` **are** that pattern,
39
+ * and this suite measures it here rather than trusting it, wrappers and all.
40
+ *
41
+ * That is the test `ROADMAP.md` states, applied: Zag arrives where the platform has **no
42
+ * element** for the pattern, not merely where the pattern has state. `ui-menu` is where
43
+ * that question is open; a radio group is not.
44
+ *
45
+ * **What is left for this element is what the platform leaves out**: the layout, the
46
+ * `role` that makes a set of radios a group to a screen reader, and the group-level name,
47
+ * description and error state — which {@link UiField} wires onto *this* element rather
48
+ * than onto an option, because a `<label for>` naming one radio names one option and
49
+ * leaves the group anonymous.
50
+ *
51
+ * @example
52
+ * ```html
53
+ * <ui-field>
54
+ * <label slot="label">Plan</label>
55
+ * <ui-radio-group>
56
+ * <label><ui-radio><input type="radio" name="plan" value="free" /></ui-radio> Free</label>
57
+ * <label><ui-radio><input type="radio" name="plan" value="pro" /></ui-radio> Pro</label>
58
+ * </ui-radio-group>
59
+ * </ui-field>
60
+ * ```
61
+ */
62
+ export declare class UiRadioGroup extends LitElement {
63
+ static readonly styles: import("lit").CSSResult;
64
+ static readonly properties: {
65
+ orientation: {
66
+ type: StringConstructor;
67
+ reflect: boolean;
68
+ };
69
+ };
70
+ /**
71
+ * Which way the options are laid out.
72
+ *
73
+ * A plain field rather than the `accessor` keyword, for the reason `src/button.ts`
74
+ * gives beside its own: the browser this suite runs in does not implement
75
+ * auto-accessors, and the module would fail to parse.
76
+ */
77
+ orientation: RadioOrientation;
78
+ /**
79
+ * Marks the element a group before anything asks what it is.
80
+ *
81
+ * In `connectedCallback` rather than at first render, and the timing is the point:
82
+ * {@link UiField} reads this attribute to decide that the group — and not the first
83
+ * radio inside it — is the thing to name, and it does so on its own first update,
84
+ * which lands before this element's. Set a microtask later, the role would arrive
85
+ * after the only reader that needs it.
86
+ *
87
+ * A `role` the host wrote is never overwritten, the same way `<ui-switch>` never
88
+ * overwrites one on the control it announces.
89
+ */
90
+ connectedCallback(): void;
91
+ /**
92
+ * Keeps the announced orientation on the drawn one.
93
+ *
94
+ * Written unconditionally rather than only for the horizontal case: the default a
95
+ * screen reader assumes for a `radiogroup` is not something a component should have an
96
+ * opinion about, and the attribute costs nothing to state.
97
+ */
98
+ willUpdate(): void;
99
+ render(): TemplateResult;
100
+ }
101
+ declare global {
102
+ interface HTMLElementTagNameMap {
103
+ 'ui-radio': UiRadio;
104
+ 'ui-radio-group': UiRadioGroup;
105
+ }
106
+ }
107
+ //# sourceMappingURL=radio.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"radio.d.ts","sourceRoot":"","sources":["../src/radio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAGjE,yEAAyE;AACzE,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,YAAY,CAAC;AAmCzD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,OAAQ,SAAQ,UAAU;IACnC,gBAAyB,MAAM,0BA8G7B;IAEO,MAAM,IAAI,cAAc;CAGpC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,YAAa,SAAQ,UAAU;IACxC,gBAAyB,MAAM,0BAiC7B;IAEF,gBAAyB,UAAU;;;;;MAEjC;IAEF;;;;;;OAMG;IACH,WAAW,EAAE,gBAAgB,CAAc;IAE3C;;;;;;;;;;;OAWG;IACM,iBAAiB,IAAI,IAAI;IAQlC;;;;;;OAMG;IACM,UAAU,IAAI,IAAI;IAIlB,MAAM,IAAI,cAAc;CAGpC;AAWD,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,qBAAqB;QAC3B,UAAU,EAAE,OAAO,CAAC;QACpB,gBAAgB,EAAE,YAAY,CAAC;KAClC;CACJ"}
package/dist/radio.js ADDED
@@ -0,0 +1,291 @@
1
+ import { LitElement, css, html } from 'lit';
2
+ import { reference } from './reference.js';
3
+ /**
4
+ * The size the control is drawn at, and a floor rather than a preference.
5
+ *
6
+ * The same measurement `src/checkbox.ts` carries, taken again on this element: a native
7
+ * radio is 13x13 in this engine, which is under WCAG 2.2's **2.5.8 Target Size (Minimum)**
8
+ * of 24x24 and escapes it only through that criterion's *user agent control* exception.
9
+ * Drawing it ourselves gives the exception up, so the floor becomes ours to hold, and
10
+ * `max()` is what holds it: a host who shrinks `--ui-space` cannot take this control below
11
+ * the floor without saying so in their own CSS.
12
+ *
13
+ * Written out rather than imported from the checkbox, for the reason `src/select.ts` gives
14
+ * about the box it shares with `src/input.ts` — and answered the same way, on the same
15
+ * terms: `tests/radio.test.ts` mounts both controls and asserts they agree on the size,
16
+ * the boundary, the fill and the focus ring, so something compares them and it fails when
17
+ * they drift.
18
+ */
19
+ const size = css `max(24px, calc(${reference('--ui-space')} * 3))`;
20
+ /** A mask layer covering the whole control, which the mark is then subtracted from. */
21
+ const whole = css `linear-gradient(#000, #000)`;
22
+ /**
23
+ * The mark, as a hole rather than a dot — the same decision `src/checkbox.ts` explains at
24
+ * length, reached here without a picture at all.
25
+ *
26
+ * A checkbox's tick needs a path and therefore a `data:` URI; a radio's mark is a circle,
27
+ * which is a gradient with a size. What both share is that the mark is **absent** rather
28
+ * than coloured: `mask-composite: exclude` punches it out of the accent fill, so what
29
+ * shows through is whatever the control sits on, and no colour is frozen anywhere a host
30
+ * could not override it.
31
+ */
32
+ const mark = css `radial-gradient(circle closest-side, #000 100%, transparent 100%)`;
33
+ /**
34
+ * One option's control, drawn from the token layer rather than replaced.
35
+ *
36
+ * **The `<input type="radio">` is yours.** You write it, you set its `name`, `value`,
37
+ * `checked` and `disabled`, and it stays in the light DOM — the shape every control in
38
+ * this kit has, and forced by the same constraint: an ARIA relationship by IDREF does not
39
+ * cross a shadow boundary, so a control rendered in here could not be labelled by the
40
+ * `<label>` around it.
41
+ *
42
+ * **This element carries no state and no name.** It is a drawing, and everything that
43
+ * makes a set of radios *a group* — one tab stop, arrow keys that move and select, one
44
+ * value out of the set — is the platform's, because they are native radios sharing a
45
+ * `name`. Wrapping each one changes none of that: measured in this suite, a group whose
46
+ * radios sit inside custom elements is still one group.
47
+ *
48
+ * @example
49
+ * ```html
50
+ * <label>
51
+ * <ui-radio><input type="radio" name="plan" value="free" /></ui-radio>
52
+ * Free
53
+ * </label>
54
+ * ```
55
+ */
56
+ export class UiRadio extends LitElement {
57
+ static { this.styles = css `
58
+ :host {
59
+ display: inline-flex;
60
+ }
61
+
62
+ /* Everything below reaches a control the *host* wrote, through ::slotted — the
63
+ whole shape of this component, and the same one ui-checkbox has.
64
+
65
+ appearance: none is its whole cost, and it is taken for the reason
66
+ ARCHITECTURE.md states as a debt rather than a free hand: it removes the
67
+ platform's dot, its target size and its behaviour under forced colors in one
68
+ declaration, and each of those is answered below. What it buys is a radio that
69
+ belongs beside the checkbox this kit already draws — a native 13px radio next to
70
+ a drawn 24px checkbox would argue cosmetically for a difference that is
71
+ semantic. */
72
+ ::slotted(input) {
73
+ appearance: none;
74
+ box-sizing: border-box;
75
+ /* The user agent puts 3px around a radio. Left in, it would sit inside the
76
+ host box and put the control off centre in any layout that aligns to it. */
77
+ margin: 0;
78
+ inline-size: ${size};
79
+ block-size: ${size};
80
+ /* A circle, and the one measurement here that is not a token: the shape is
81
+ what tells a radio from a checkbox before either is read, so it cannot
82
+ follow --ui-radius without a square radio becoming possible. */
83
+ border-radius: 50%;
84
+ background-color: ${reference('--ui-color-surface')};
85
+ background-repeat: no-repeat;
86
+ border: 1px solid ${reference('--ui-color-border')};
87
+ cursor: pointer;
88
+ /* The focus ring is deliberately not in this list, for the reason
89
+ src/button.ts gives beside its own: delaying the affordance that says *this
90
+ is where you are* is the opposite of what it exists to do. */
91
+ transition:
92
+ background-color ${reference('--ui-duration-state')}
93
+ ${reference('--ui-easing-state')},
94
+ border-color ${reference('--ui-duration-state')} ${reference('--ui-easing-state')};
95
+ }
96
+
97
+ /* The mark is a hole: the whole control, minus the circle, so what shows through
98
+ is whatever the control sits on. The docblock on the mask constant says why a
99
+ hole rather than a colour. */
100
+ ::slotted(input:checked) {
101
+ background-color: ${reference('--ui-color-accent')};
102
+ border-color: ${reference('--ui-color-accent')};
103
+ mask-image: ${whole}, ${mark};
104
+ mask-composite: exclude;
105
+ mask-size:
106
+ 100% 100%,
107
+ calc(${size} / 2);
108
+ mask-position: center;
109
+ mask-repeat: no-repeat;
110
+ }
111
+
112
+ /* Unselected, the boundary finishes the mix it already started — the same hover
113
+ ui-input and ui-checkbox have, because it is the same boundary. Selected, the
114
+ boundary is not what the eye is on, so the fill moves instead, the way
115
+ ui-button's does.
116
+
117
+ The disabled guard is measured rather than assumed: a disabled control still
118
+ matches :hover. */
119
+ ::slotted(input:hover:not(:disabled)) {
120
+ border-color: ${reference('--ui-color-text')};
121
+ }
122
+
123
+ ::slotted(input:checked:hover:not(:disabled)) {
124
+ background-color: ${reference('--ui-color-accent-hover')};
125
+ border-color: ${reference('--ui-color-accent-hover')};
126
+ }
127
+
128
+ /* A visible focus ring is not decoration: removing it is the single most common
129
+ way a component stops being usable by keyboard — and on a radio group it is the
130
+ only thing that says which option an arrow key just moved to. */
131
+ ::slotted(input:focus-visible) {
132
+ outline: 2px solid ${reference('--ui-color-focus')};
133
+ outline-offset: 2px;
134
+ }
135
+
136
+ ::slotted(input:disabled) {
137
+ cursor: not-allowed;
138
+ opacity: 0.5;
139
+ }
140
+
141
+ /* There is no error rule here, and its absence is the decision: what a radio group
142
+ gets wrong is the *choice*, not one option, so ui-radio-group paints the state
143
+ for the whole set. It does it by retargeting the boundary token over its own
144
+ subtree, which this rule reads without knowing anything about it. */
145
+
146
+ /* Forced colors replaces every author colour with one from the user's palette, so
147
+ the accent that says *selected* becomes the same Canvas as the surface that says
148
+ *not* — the state disappears, silently, for the people who turned the mode on to
149
+ see states more clearly. System colours are the ones forced colors keeps, so the
150
+ selected state names Highlight and the difference survives; the mark keeps
151
+ working untouched, because a mask has no colour to force.
152
+
153
+ Opacity is not a colour and is not forced, so the disabled control would still
154
+ be half-transparent against a palette chosen for contrast. GrayText is what that
155
+ mode has for *unavailable*, and it is a colour rather than a veil. */
156
+ @media (forced-colors: active) {
157
+ ::slotted(input:checked) {
158
+ background-color: Highlight;
159
+ border-color: Highlight;
160
+ }
161
+
162
+ ::slotted(input:disabled) {
163
+ border-color: GrayText;
164
+ opacity: 1;
165
+ }
166
+ }
167
+ `; }
168
+ render() {
169
+ return html `<slot></slot>`;
170
+ }
171
+ }
172
+ /**
173
+ * A set of radios, laid out and named as one thing.
174
+ *
175
+ * **It hand-rolls no roving tabindex and it brings no state machine**, and that is this
176
+ * element's whole claim rather than a gap in it. Issue #15 asked which of the two it would
177
+ * be, because the APG **Radio Group** pattern — one tab stop, arrow keys that move *and*
178
+ * select, wrapping at the ends — is the first behaviour in the v0 cut that could have
179
+ * justified Zag. Neither was needed: native radios sharing a `name` **are** that pattern,
180
+ * and this suite measures it here rather than trusting it, wrappers and all.
181
+ *
182
+ * That is the test `ROADMAP.md` states, applied: Zag arrives where the platform has **no
183
+ * element** for the pattern, not merely where the pattern has state. `ui-menu` is where
184
+ * that question is open; a radio group is not.
185
+ *
186
+ * **What is left for this element is what the platform leaves out**: the layout, the
187
+ * `role` that makes a set of radios a group to a screen reader, and the group-level name,
188
+ * description and error state — which {@link UiField} wires onto *this* element rather
189
+ * than onto an option, because a `<label for>` naming one radio names one option and
190
+ * leaves the group anonymous.
191
+ *
192
+ * @example
193
+ * ```html
194
+ * <ui-field>
195
+ * <label slot="label">Plan</label>
196
+ * <ui-radio-group>
197
+ * <label><ui-radio><input type="radio" name="plan" value="free" /></ui-radio> Free</label>
198
+ * <label><ui-radio><input type="radio" name="plan" value="pro" /></ui-radio> Pro</label>
199
+ * </ui-radio-group>
200
+ * </ui-field>
201
+ * ```
202
+ */
203
+ export class UiRadioGroup extends LitElement {
204
+ constructor() {
205
+ super(...arguments);
206
+ /**
207
+ * Which way the options are laid out.
208
+ *
209
+ * A plain field rather than the `accessor` keyword, for the reason `src/button.ts`
210
+ * gives beside its own: the browser this suite runs in does not implement
211
+ * auto-accessors, and the module would fail to parse.
212
+ */
213
+ this.orientation = 'vertical';
214
+ }
215
+ static { this.styles = css `
216
+ :host {
217
+ display: flex;
218
+ flex-direction: column;
219
+ gap: calc(${reference('--ui-space')} / 2);
220
+ }
221
+
222
+ /* Laid out by the attribute rather than by the host's own CSS, so the drawing and
223
+ the announcement cannot disagree: orientation sets both this rule and
224
+ aria-orientation, and a host who reached for flex-direction instead would
225
+ change one of the two. */
226
+ :host([orientation='horizontal']) {
227
+ flex-direction: row;
228
+ flex-wrap: wrap;
229
+ column-gap: calc(${reference('--ui-space')} * 2);
230
+ }
231
+
232
+ /* The error, painted for the whole set by retargeting the boundary token over this
233
+ subtree — which is the override surface the token layer already publishes,
234
+ pointed at the group's own descendants instead of at a page.
235
+
236
+ A custom property inherits through a shadow boundary and a selector does not, so
237
+ this is what reaches a control two elements down that this sheet cannot name:
238
+ ::slotted() stops at the group's own children, :host-context() is not
239
+ cross-engine, and :host(:has(...)) is invalid in this engine. The value still
240
+ arrives as a token reference, so a host who retunes danger retunes this too.
241
+
242
+ aria-invalid is not written here: ui-field sets it as part of the wiring it
243
+ already owns, so the message under the group and the boundary around its options
244
+ cannot disagree about whether there is an error. */
245
+ :host([aria-invalid='true']) {
246
+ --ui-color-border: ${reference('--ui-color-danger')};
247
+ }
248
+ `; }
249
+ static { this.properties = {
250
+ orientation: { type: String, reflect: true },
251
+ }; }
252
+ /**
253
+ * Marks the element a group before anything asks what it is.
254
+ *
255
+ * In `connectedCallback` rather than at first render, and the timing is the point:
256
+ * {@link UiField} reads this attribute to decide that the group — and not the first
257
+ * radio inside it — is the thing to name, and it does so on its own first update,
258
+ * which lands before this element's. Set a microtask later, the role would arrive
259
+ * after the only reader that needs it.
260
+ *
261
+ * A `role` the host wrote is never overwritten, the same way `<ui-switch>` never
262
+ * overwrites one on the control it announces.
263
+ */
264
+ connectedCallback() {
265
+ super.connectedCallback();
266
+ if (!this.hasAttribute('role')) {
267
+ this.setAttribute('role', 'radiogroup');
268
+ }
269
+ }
270
+ /**
271
+ * Keeps the announced orientation on the drawn one.
272
+ *
273
+ * Written unconditionally rather than only for the horizontal case: the default a
274
+ * screen reader assumes for a `radiogroup` is not something a component should have an
275
+ * opinion about, and the attribute costs nothing to state.
276
+ */
277
+ willUpdate() {
278
+ this.setAttribute('aria-orientation', this.orientation);
279
+ }
280
+ render() {
281
+ return html `<slot></slot>`;
282
+ }
283
+ }
284
+ // Stryker disable next-line StringLiteral: the registration runs once, at import, inside
285
+ // the warm process Stryker switches mutants in — so by the time a mutant on this line is
286
+ // active the element is already defined under the original name, and no test can observe
287
+ // the change. Outside the runner's reach, not an equivalent mutant.
288
+ customElements.define('ui-radio', UiRadio);
289
+ // Stryker disable next-line StringLiteral: the same, for the same reason.
290
+ customElements.define('ui-radio-group', UiRadioGroup);
291
+ //# sourceMappingURL=radio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"radio.js","sourceRoot":"","sources":["../src/radio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAuB,MAAM,KAAK,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAK3C;;;;;;;;;;;;;;;GAeG;AACH,MAAM,IAAI,GAAG,GAAG,CAAA,kBAAkB,SAAS,CAAC,YAAY,CAAC,QAAQ,CAAC;AAElE,uFAAuF;AACvF,MAAM,KAAK,GAAG,GAAG,CAAA,6BAA6B,CAAC;AAE/C;;;;;;;;;GASG;AACH,MAAM,IAAI,GAAG,GAAG,CAAA,mEAAmE,CAAC;AAEpF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,OAAO,OAAQ,SAAQ,UAAU;aACV,WAAM,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;2BAqBd,IAAI;0BACL,IAAI;;;;;gCAKE,SAAS,CAAC,oBAAoB,CAAC;;gCAE/B,SAAS,CAAC,mBAAmB,CAAC;;;;;;mCAM3B,SAAS,CAAC,qBAAqB,CAAC;sBAC7C,SAAS,CAAC,mBAAmB,CAAC;+BACrB,SAAS,CAAC,qBAAqB,CAAC,IAAI,SAAS,CAAC,mBAAmB,CAAC;;;;;;;gCAOjE,SAAS,CAAC,mBAAmB,CAAC;4BAClC,SAAS,CAAC,mBAAmB,CAAC;0BAChC,KAAK,KAAK,IAAI;;;;uBAIjB,IAAI;;;;;;;;;;;;;4BAaC,SAAS,CAAC,iBAAiB,CAAC;;;;gCAIxB,SAAS,CAAC,yBAAyB,CAAC;4BACxC,SAAS,CAAC,yBAAyB,CAAC;;;;;;;iCAO/B,SAAS,CAAC,kBAAkB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAmCzD,CAAC;IAEO,MAAM;QACX,OAAO,IAAI,CAAA,eAAe,CAAC;IAC/B,CAAC;;AAGL;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,OAAO,YAAa,SAAQ,UAAU;IAA5C;;QAwCI;;;;;;WAMG;QACH,gBAAW,GAAqB,UAAU,CAAC;IAoC/C,CAAC;aAlF4B,WAAM,GAAG,GAAG,CAAA;;;;wBAIjB,SAAS,CAAC,YAAY,CAAC;;;;;;;;;;+BAUhB,SAAS,CAAC,YAAY,CAAC;;;;;;;;;;;;;;;;;iCAiBrB,SAAS,CAAC,mBAAmB,CAAC;;KAE1D,AAjC8B,CAiC7B;aAEuB,eAAU,GAAG;QAClC,WAAW,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;KAC/C,AAFkC,CAEjC;IAWF;;;;;;;;;;;OAWG;IACM,iBAAiB;QACtB,KAAK,CAAC,iBAAiB,EAAE,CAAC;QAE1B,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QAC5C,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACM,UAAU;QACf,IAAI,CAAC,YAAY,CAAC,kBAAkB,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAC5D,CAAC;IAEQ,MAAM;QACX,OAAO,IAAI,CAAA,eAAe,CAAC;IAC/B,CAAC;;AAGL,yFAAyF;AACzF,yFAAyF;AACzF,yFAAyF;AACzF,oEAAoE;AACpE,cAAc,CAAC,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;AAE3C,0EAA0E;AAC1E,cAAc,CAAC,MAAM,CAAC,gBAAgB,EAAE,YAAY,CAAC,CAAC"}
package/dist/tokens.d.ts CHANGED
@@ -31,7 +31,7 @@
31
31
  * it does break is code that **enumerates** the set, an exhaustive `Record<Token, string>`
32
32
  * above all. The supported shape is the partial map, which is what a theme is anyway.
33
33
  */
34
- export declare const tokens: readonly ["--ui-color-accent", "--ui-color-accent-contrast", "--ui-color-surface", "--ui-color-text", "--ui-color-focus", "--ui-color-danger", "--ui-color-scrim", "--ui-radius", "--ui-space", "--ui-font", "--ui-duration-100", "--ui-easing-state", "--ui-easing-enter", "--ui-easing-exit", "--ui-icon-size", "--ui-icon-stroke"];
34
+ export declare const tokens: readonly ["--ui-color-accent", "--ui-color-accent-contrast", "--ui-color-surface", "--ui-color-text", "--ui-color-focus", "--ui-color-danger", "--ui-color-scrim", "--ui-radius", "--ui-space", "--ui-font", "--ui-duration-100", "--ui-easing-state", "--ui-easing-enter", "--ui-easing-exit", "--ui-icon-size", "--ui-icon-stroke", "--ui-elevation-100"];
35
35
  /** A CSS custom property this package defines and gives a default. */
36
36
  export type Token = (typeof tokens)[number];
37
37
  /**
@@ -44,7 +44,7 @@ export type Token = (typeof tokens)[number];
44
44
  * what it buys is an override surface a host can hold in their head: change the accent and
45
45
  * the hover and pressed colours follow, rather than being one more name each.
46
46
  */
47
- export declare const derivedTokens: readonly ["--ui-duration-state", "--ui-color-border", "--ui-color-text-muted", "--ui-color-hover", "--ui-color-pressed", "--ui-color-accent-hover", "--ui-color-accent-pressed"];
47
+ export declare const derivedTokens: readonly ["--ui-duration-state", "--ui-color-border", "--ui-color-text-muted", "--ui-color-hover", "--ui-color-pressed", "--ui-color-accent-hover", "--ui-color-accent-pressed", "--ui-elevation-raised"];
48
48
  /** A CSS custom property this package computes rather than declares. */
49
49
  export type DerivedToken = (typeof derivedTokens)[number];
50
50
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,MAAM,uUA2DT,CAAC;AAEX,sEAAsE;AACtE,MAAM,MAAM,KAAK,GAAG,CAAC,OAAO,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5C;;;;;;;;;GASG;AACH,eAAO,MAAM,aAAa,kLAmBhB,CAAC;AAEX,wEAAwE;AACxE,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1D;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAyCpD,CAAC;AAqBF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAoB3D,CAAC;AAEF;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAW/D,CAAC;AAKF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAsBxC"}
1
+ {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,MAAM,6VA4ET,CAAC;AAEX,sEAAsE;AACtE,MAAM,MAAM,KAAK,GAAG,CAAC,OAAO,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5C;;;;;;;;;GASG;AACH,eAAO,MAAM,aAAa,2MAwBhB,CAAC;AAEX,wEAAwE;AACxE,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1D;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CA+CpD,CAAC;AAqBF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAwB3D,CAAC;AAEF;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAW/D,CAAC;AAKF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAsBxC"}
package/dist/tokens.js CHANGED
@@ -90,6 +90,23 @@ export const tokens = [
90
90
  // size, and 2 is the weight the adopted set is drawn at.
91
91
  '--ui-icon-size',
92
92
  '--ui-icon-stroke',
93
+ // Elevation, arriving with `ui-card` — the category `ROADMAP.md` said would, after the
94
+ // first overlay arrived and brought none.
95
+ //
96
+ // A step in a scale, named by an ordinal with gaps, for the reason the duration scale
97
+ // gives above: elevation is *relative* by nature — a card sits above the page, a menu
98
+ // above the card — so the names have to be able to grow between each other. No
99
+ // component reads this one; they read `--ui-elevation-raised`, which points in here.
100
+ // No second step comes with it: a tooltip and a menu are the components that would
101
+ // judge one, and neither is written.
102
+ //
103
+ // **It carries no dark value, and cannot.** `darkScheme` is emitted through
104
+ // `light-dark()`, which takes colours — and a shadow is not a colour. So this is one
105
+ // value in both schemes, and on a dark page it does almost nothing: black on charcoal
106
+ // is black. What separates a raised surface there is the *boundary*, which is derived
107
+ // and therefore already scheme-correct — which is why `src/card.ts` draws both and
108
+ // says so beside them.
109
+ '--ui-elevation-100',
93
110
  ];
94
111
  /**
95
112
  * The roles computed from the grounds rather than declared beside them.
@@ -120,6 +137,11 @@ export const derivedTokens = [
120
137
  '--ui-color-pressed',
121
138
  '--ui-color-accent-hover',
122
139
  '--ui-color-accent-pressed',
140
+ // The purpose the elevation scale is read through, arriving with `ui-card`. `raised`
141
+ // is a role rather than a component: a card is the first surface lifted off the page
142
+ // and will not be the last, and the name a host retunes should not be the name of
143
+ // whichever component happened to need it first.
144
+ '--ui-elevation-raised',
123
145
  ];
124
146
  /**
125
147
  * The default value of every ground token, applied at `:root` by {@link tokenStyleSheet}.
@@ -168,6 +190,12 @@ export const defaults = {
168
190
  '--ui-easing-exit': 'ease-in',
169
191
  '--ui-icon-size': '1.25em',
170
192
  '--ui-icon-stroke': '2',
193
+ // Two layers rather than one, which is what makes a shadow read as *lift* instead of
194
+ // as a smudge: a tight, nearly opaque one draws the contact edge, and a wider, softer
195
+ // one is the cast. Both are black at a low alpha, so the shadow darkens whatever it
196
+ // falls on rather than tinting it — a coloured shadow is a decision this layer would
197
+ // have to defend at every hue a host might set.
198
+ '--ui-elevation-100': '0 1px 2px -1px rgb(0 0 0 / 0.1), 0 2px 6px -1px rgb(0 0 0 / 0.1)',
171
199
  };
172
200
  /**
173
201
  * A ground as it is written inside a formula: the name, with its own default behind it.
@@ -232,6 +260,10 @@ export const formulas = {
232
260
  // is 4.52 in light, a rounding error from failing, and a default nobody could then
233
261
  // retune without breaking a floor they were not thinking about.
234
262
  '--ui-color-text-muted': mix('--ui-color-text', 65, '--ui-color-surface'),
263
+ // A plain reference, like the duration purpose above: the scale is where the value
264
+ // lives, and a host who wants flatter cards moves the role rather than reverse
265
+ // engineering which step a card happens to read.
266
+ '--ui-elevation-raised': ground('--ui-elevation-100'),
235
267
  };
236
268
  /**
237
269
  * The grounds whose value differs when the page is rendered dark.
@@ -1 +1 @@
1
- {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rak200/ui",
3
- "version": "0.2.12",
3
+ "version": "0.2.14",
4
4
  "description": "Host-agnostic custom-element UI components for the rak200 ecosystem",
5
5
  "license": "MIT",
6
6
  "author": "rak200 <rak.ricardo@windowslive.com>",
@@ -45,7 +45,7 @@
45
45
  "test": "vitest run",
46
46
  "coverage": "coverage-floor",
47
47
  "scan": "rak200-scan",
48
- "mutation": "stryker run",
48
+ "mutation": "node tests/tooling/mutate-changed.mjs",
49
49
  "build": "tsc -p tsconfig.icons.json && tsc -p tsconfig.build.json",
50
50
  "storybook": "storybook dev -p 6006",
51
51
  "build-storybook": "storybook build"