@adia-ai/web-components 0.5.10 → 0.5.12

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.
@@ -0,0 +1,172 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://adiaui.dev/a2ui/v0_9/components/ColorInput.json",
4
+ "title": "ColorInput",
5
+ "description": "Compact form-bearing color input — opens a popover-anchored\n`<color-picker-ui>` from an inline swatch button. §302 (v0.5.12,\nFEEDBACK-29 re-bucket from v0.6.0). Canonicalizes the USAGE.md §221f\nOption B recipe (popover + button + color-picker) into a single\nform-associated tag for inline form contexts (settings drawer \"source\ncolor\" field, swatch-row inline-edit, etc.).",
6
+ "type": "object",
7
+ "allOf": [
8
+ {
9
+ "$ref": "common_types.json#/$defs/ComponentCommon"
10
+ },
11
+ {
12
+ "$ref": "common_types.json#/$defs/CatalogComponentCommon"
13
+ }
14
+ ],
15
+ "properties": {
16
+ "component": {
17
+ "const": "ColorInput"
18
+ },
19
+ "disabled": {
20
+ "description": "Disables the trigger button + suppresses popover.",
21
+ "type": "boolean",
22
+ "default": false
23
+ },
24
+ "format": {
25
+ "description": "Output format for the value property + event detail. Hex (`#rrggbb`) or OKLCH (`oklch(L C H)`).",
26
+ "type": "string",
27
+ "enum": [
28
+ "hex",
29
+ "oklch"
30
+ ],
31
+ "default": "hex"
32
+ },
33
+ "name": {
34
+ "description": "Form field name.",
35
+ "type": "string",
36
+ "default": ""
37
+ },
38
+ "open": {
39
+ "description": "Reflects the popover's open state. Set programmatically to open/close the picker without a click.",
40
+ "type": "boolean",
41
+ "default": false
42
+ },
43
+ "placement": {
44
+ "description": "Popover placement relative to the trigger.",
45
+ "type": "string",
46
+ "enum": [
47
+ "top",
48
+ "bottom",
49
+ "left",
50
+ "right",
51
+ "top-start",
52
+ "top-end",
53
+ "bottom-start",
54
+ "bottom-end"
55
+ ],
56
+ "default": "bottom-start"
57
+ },
58
+ "value": {
59
+ "description": "Current color as a string in the active [format].",
60
+ "type": "string",
61
+ "default": "#3b82f6"
62
+ }
63
+ },
64
+ "required": [
65
+ "component"
66
+ ],
67
+ "unevaluatedProperties": false,
68
+ "x-adiaui": {
69
+ "anti_patterns": [],
70
+ "category": "input",
71
+ "composes": [
72
+ "button-ui",
73
+ "popover-ui",
74
+ "color-picker-ui"
75
+ ],
76
+ "events": {
77
+ "change": {
78
+ "description": "Fired when the color is committed (pointerup / Enter / picker close). Bubbles from inner picker.",
79
+ "detail": {
80
+ "hex": {
81
+ "description": "Hex form (`#rrggbb`).",
82
+ "type": "string"
83
+ },
84
+ "oklch": {
85
+ "description": "OKLCH string (`oklch(L C H)`).",
86
+ "type": "string"
87
+ },
88
+ "value": {
89
+ "description": "Color in the active [format] (hex or oklch).",
90
+ "type": "string"
91
+ }
92
+ }
93
+ },
94
+ "input": {
95
+ "description": "Fired during continuous drag of the inner picker. Bubbles from inner picker.",
96
+ "detail": {
97
+ "hex": {
98
+ "type": "string"
99
+ },
100
+ "oklch": {
101
+ "type": "string"
102
+ },
103
+ "value": {
104
+ "description": "Color in the active [format].",
105
+ "type": "string"
106
+ }
107
+ }
108
+ }
109
+ },
110
+ "examples": [
111
+ {
112
+ "description": "Inline compact color input — popover-anchored picker on click.",
113
+ "a2ui": "[\n {\n \"id\": \"root\",\n \"component\": \"ColorInput\",\n \"name\": \"brand\",\n \"value\": \"#3b82f6\"\n }\n]",
114
+ "name": "color-input-basic"
115
+ },
116
+ {
117
+ "description": "Compact picker exposing OKLCH value form.",
118
+ "a2ui": "[\n {\n \"id\": \"root\",\n \"component\": \"ColorInput\",\n \"name\": \"accent\",\n \"format\": \"oklch\",\n \"value\": \"oklch(0.7 0.15 220)\"\n }\n]",
119
+ "name": "color-input-oklch"
120
+ }
121
+ ],
122
+ "keywords": [
123
+ "color-input",
124
+ "color",
125
+ "input",
126
+ "picker",
127
+ "swatch",
128
+ "inline",
129
+ "compact"
130
+ ],
131
+ "name": "UIColorInput",
132
+ "related": [
133
+ "color-picker",
134
+ "popover",
135
+ "button",
136
+ "swatch"
137
+ ],
138
+ "slots": {},
139
+ "states": [
140
+ {
141
+ "description": "Default, ready for interaction.",
142
+ "name": "idle"
143
+ },
144
+ {
145
+ "description": "Popover is open; picker visible.",
146
+ "attribute": "open",
147
+ "name": "open"
148
+ },
149
+ {
150
+ "description": "Non-interactive; dimmed.",
151
+ "attribute": "disabled",
152
+ "name": "disabled"
153
+ }
154
+ ],
155
+ "synonyms": {
156
+ "color-field": [
157
+ "color-input"
158
+ ],
159
+ "inline-color-picker": [
160
+ "color-input"
161
+ ]
162
+ },
163
+ "tag": "color-input-ui",
164
+ "tokens": {
165
+ "--color-input-swatch-size": {
166
+ "description": "Diameter (em) of the inline swatch circle inside the trigger button. Default 1em."
167
+ }
168
+ },
169
+ "traits": [],
170
+ "version": 1
171
+ }
172
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * <color-input-ui> — compact form-bearing color input.
3
+ *
4
+ * §302 (v0.5.12, FEEDBACK-29 re-bucket). Light-DOM composition of
5
+ * <popover-ui> + <button-ui> + <color-picker-ui>. The host element
6
+ * carries form-control sizing tokens; inner button + popover keep
7
+ * their own primitive styling.
8
+ */
9
+
10
+ @scope (color-input-ui) {
11
+ :scope {
12
+ --color-input-swatch-size: 1em;
13
+
14
+ display: inline-flex;
15
+ vertical-align: middle;
16
+ }
17
+
18
+ :scope[disabled] {
19
+ opacity: 0.55;
20
+ pointer-events: none;
21
+ }
22
+
23
+ :scope > popover-ui {
24
+ display: inline-flex;
25
+ }
26
+
27
+ /* Inline swatch chip inside the trigger button. The button-ui owns its
28
+ * own padding + height; the swatch is sized in em so it tracks the
29
+ * button's font-size + density automatically. */
30
+ .color-input__swatch {
31
+ display: inline-block;
32
+ inline-size: var(--color-input-swatch-size);
33
+ block-size: var(--color-input-swatch-size);
34
+ border-radius: 50%;
35
+ background: var(--swatch-color, transparent);
36
+ border: 1px solid var(--a-ui-border, currentColor);
37
+ margin-inline-end: var(--a-space-2, 0.5em);
38
+ flex: 0 0 auto;
39
+ }
40
+
41
+ .color-input__value {
42
+ font-variant-numeric: tabular-nums;
43
+ font-family: var(--a-font-family-mono, monospace);
44
+ font-size: 0.92em;
45
+ color: var(--a-ui-text, currentColor);
46
+ }
47
+ }
@@ -0,0 +1,71 @@
1
+ /**
2
+ * `<color-input-ui>` — compact form-bearing color input.
3
+ *
4
+ * §302 (v0.5.12, FEEDBACK-29 re-bucket from v0.6.0). Canonicalizes the
5
+ * USAGE.md §221f recipe (popover + button + color-picker) into a single
6
+ * form-associated tag for inline form contexts (settings drawer "source
7
+ * color" field, swatch-row inline-edit). Light-DOM composition; the
8
+ * inner picker fires `change` + `input` which this element re-emits
9
+ * with a flattened detail payload that always carries both hex + oklch
10
+ * string forms regardless of `[format]`.
11
+ *
12
+ * Hand-authored (FORM_BEARING in dts-codegen) because the rich event
13
+ * detail (parallel hex+oklch views) can't be expressed by the
14
+ * yaml `events:` shape alone.
15
+ *
16
+ * @see https://ui-kit.exe.xyz/site/components/color-input
17
+ */
18
+
19
+ import { UIFormElement } from '../../core/form.js';
20
+
21
+ /**
22
+ * Output format selected by the `[format]` attribute. Drives the shape of
23
+ * `value` (and the matching `detail.value` field). Both `hex` and `oklch`
24
+ * forms are always present on the event detail regardless of `[format]`.
25
+ */
26
+ export type ColorInputFormat = 'hex' | 'oklch';
27
+
28
+ /**
29
+ * Detail payload for both `change` (commit) and `input` (continuous drag)
30
+ * events. `value` mirrors the current `[format]`; `hex` and `oklch` are
31
+ * always populated parallel views, so consumers don't need to parse the
32
+ * string.
33
+ */
34
+ export interface ColorInputChangeEventDetail {
35
+ /** Format-respecting string. Equals `hex` when `[format="hex"]`; equals `oklch` when `[format="oklch"]`. */
36
+ value: string;
37
+ /** Hex form (`#rrggbb`). Gamut-mapped to sRGB. */
38
+ hex: string;
39
+ /** OKLCH string (`oklch(L C H)`, fixed precision). */
40
+ oklch: string;
41
+ }
42
+ export type ColorInputChangeEvent = CustomEvent<ColorInputChangeEventDetail>;
43
+ export type ColorInputInputEvent = CustomEvent<ColorInputChangeEventDetail>;
44
+
45
+ export class UIColorInput extends UIFormElement {
46
+ /** Form field name. */
47
+ name: string;
48
+ /** Current color string in the active `format`. */
49
+ value: string;
50
+ /** Output format — drives the shape of `value`. Detail always carries both `hex` and `oklch`. */
51
+ format: ColorInputFormat;
52
+ /** Disables the trigger button + suppresses the popover. */
53
+ disabled: boolean;
54
+ /** Popover placement relative to the trigger button. */
55
+ placement: 'top' | 'bottom' | 'left' | 'right' | 'top-start' | 'top-end' | 'bottom-start' | 'bottom-end';
56
+ /** Reflects the inner popover's open state. Set programmatically to open/close without a click. */
57
+ open: boolean;
58
+
59
+ /** Open the picker programmatically. */
60
+ showPicker(): void;
61
+ /** Close the picker programmatically. */
62
+ hidePicker(): void;
63
+
64
+ addEventListener<K extends keyof HTMLElementEventMap>(
65
+ type: K,
66
+ listener: (this: UIColorInput, ev: HTMLElementEventMap[K]) => unknown,
67
+ options?: boolean | AddEventListenerOptions,
68
+ ): void;
69
+ addEventListener(type: 'change', listener: (ev: ColorInputChangeEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
70
+ addEventListener(type: 'input', listener: (ev: ColorInputInputEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
71
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * `<color-input-ui>` — auto-registers the tag on import.
3
+ *
4
+ * For non-side-effect class import (test isolation, tag override), use
5
+ * the `class` subpath:
6
+ *
7
+ * import { UIColorInput } from '@adia-ai/web-components/components/color-input/class';
8
+ *
9
+ * Per ADR-0027, this module does NOT auto-import the composed primitives
10
+ * (`<popover-ui>`, `<button-ui>`, `<color-picker-ui>`). Consumers must
11
+ * register them explicitly before mounting `<color-input-ui>`:
12
+ *
13
+ * import '@adia-ai/web-components/components/popover';
14
+ * import '@adia-ai/web-components/components/button';
15
+ * import '@adia-ai/web-components/components/color-picker';
16
+ * import '@adia-ai/web-components/components/color-input';
17
+ *
18
+ * @see ../../USAGE.md#registration--auto-vs-explicit
19
+ */
20
+
21
+ import { defineIfFree } from '../../core/register.js';
22
+ import { UIColorInput } from './class.js';
23
+
24
+ defineIfFree('color-input-ui', UIColorInput);
25
+
26
+ export { UIColorInput };
@@ -0,0 +1,145 @@
1
+ $schema: ../../../../scripts/schemas/component.yaml.schema.json
2
+ name: UIColorInput
3
+ tag: color-input-ui
4
+ component: ColorInput
5
+ category: input
6
+ version: 1
7
+ description: |-
8
+ Compact form-bearing color input — opens a popover-anchored
9
+ `<color-picker-ui>` from an inline swatch button. §302 (v0.5.12,
10
+ FEEDBACK-29 re-bucket from v0.6.0). Canonicalizes the USAGE.md §221f
11
+ Option B recipe (popover + button + color-picker) into a single
12
+ form-associated tag for inline form contexts (settings drawer "source
13
+ color" field, swatch-row inline-edit, etc.).
14
+ # Per ADR-0027 — primitives that programmatically create other primitives
15
+ # do NOT auto-import them. The consumer (or demo shell) explicitly imports
16
+ # the composed primitives. This element creates `<button-ui>` +
17
+ # `<popover-ui>` + `<color-picker-ui>` light-DOM children but assumes the
18
+ # consumer has already imported their auto-register modules.
19
+ composes:
20
+ - button-ui
21
+ - popover-ui
22
+ - color-picker-ui
23
+ props:
24
+ name:
25
+ description: Form field name.
26
+ type: string
27
+ default: ""
28
+ value:
29
+ description: Current color as a string in the active [format].
30
+ type: string
31
+ default: "#3b82f6"
32
+ format:
33
+ description: Output format for the value property + event detail. Hex (`#rrggbb`) or OKLCH (`oklch(L C H)`).
34
+ type: string
35
+ default: hex
36
+ reflect: true
37
+ enum:
38
+ - hex
39
+ - oklch
40
+ disabled:
41
+ description: Disables the trigger button + suppresses popover.
42
+ type: boolean
43
+ default: false
44
+ reflect: true
45
+ placement:
46
+ description: Popover placement relative to the trigger.
47
+ type: string
48
+ default: bottom-start
49
+ reflect: true
50
+ enum:
51
+ - top
52
+ - bottom
53
+ - left
54
+ - right
55
+ - top-start
56
+ - top-end
57
+ - bottom-start
58
+ - bottom-end
59
+ open:
60
+ description: Reflects the popover's open state. Set programmatically to open/close the picker without a click.
61
+ type: boolean
62
+ default: false
63
+ reflect: true
64
+ events:
65
+ change:
66
+ description: Fired when the color is committed (pointerup / Enter / picker close). Bubbles from inner picker.
67
+ detail:
68
+ value:
69
+ type: string
70
+ description: Color in the active [format] (hex or oklch).
71
+ hex:
72
+ type: string
73
+ description: Hex form (`#rrggbb`).
74
+ oklch:
75
+ type: string
76
+ description: OKLCH string (`oklch(L C H)`).
77
+ input:
78
+ description: Fired during continuous drag of the inner picker. Bubbles from inner picker.
79
+ detail:
80
+ value:
81
+ type: string
82
+ description: Color in the active [format].
83
+ hex:
84
+ type: string
85
+ oklch:
86
+ type: string
87
+ slots: {}
88
+ states:
89
+ - name: idle
90
+ description: Default, ready for interaction.
91
+ - name: open
92
+ description: Popover is open; picker visible.
93
+ attribute: open
94
+ - name: disabled
95
+ description: Non-interactive; dimmed.
96
+ attribute: disabled
97
+ traits: []
98
+ tokens:
99
+ --color-input-swatch-size:
100
+ description: Diameter (em) of the inline swatch circle inside the trigger button. Default 1em.
101
+ a2ui:
102
+ rules: []
103
+ anti_patterns: []
104
+ examples:
105
+ - name: color-input-basic
106
+ description: Inline compact color input — popover-anchored picker on click.
107
+ a2ui: >-
108
+ [
109
+ {
110
+ "id": "root",
111
+ "component": "ColorInput",
112
+ "name": "brand",
113
+ "value": "#3b82f6"
114
+ }
115
+ ]
116
+ - name: color-input-oklch
117
+ description: Compact picker exposing OKLCH value form.
118
+ a2ui: >-
119
+ [
120
+ {
121
+ "id": "root",
122
+ "component": "ColorInput",
123
+ "name": "accent",
124
+ "format": "oklch",
125
+ "value": "oklch(0.7 0.15 220)"
126
+ }
127
+ ]
128
+ keywords:
129
+ - color-input
130
+ - color
131
+ - input
132
+ - picker
133
+ - swatch
134
+ - inline
135
+ - compact
136
+ synonyms:
137
+ color-field:
138
+ - color-input
139
+ inline-color-picker:
140
+ - color-input
141
+ related:
142
+ - color-picker
143
+ - popover
144
+ - button
145
+ - swatch
@@ -47,6 +47,7 @@ export { UIBadge } from './badge/badge.js';
47
47
  export { UIBreadcrumb } from './breadcrumb/breadcrumb.js';
48
48
  export { UICommand } from './command/command.js';
49
49
  export { UIColorPicker } from './color-picker/color-picker.js';
50
+ export { UIColorInput } from './color-input/color-input.js';
50
51
  export { UINoodles } from './noodles/noodles.js';
51
52
  export { UITable } from './table/table.js';
52
53
  export { UITableToolbar } from './table-toolbar/table-toolbar.js';
@@ -0,0 +1,38 @@
1
+ /**
2
+ * `<stat-ui>` — Metric/KPI display. Value + label + optional change indicator and trend.
3
+ *
4
+ * @see https://ui-kit.exe.xyz/site/components/stat
5
+ *
6
+ * HAND-AUTHORED (v0.5.12 §253 FB-30 close-out). The codegen pipeline's
7
+ * `isCssOnly()` check at `scripts/build/dts-codegen.mjs:186-194` looks for
8
+ * `${dirname}.js` — but stat ships `stat-ui.js` (irregular filename; the
9
+ * v0.6.0 §303 rename will normalize to `stat.js`). Pre-§303 the codegen
10
+ * false-positives `isCssOnly` and skips this directory entirely. Hand-author
11
+ * this file matching `stat.yaml` props until §303 lands.
12
+ *
13
+ * Filename mirrors the JS file (`stat-ui.js` → `stat-ui.d.ts`) so TypeScript
14
+ * resolves the side-effect import `import '@adia-ai/web-components/components/stat/stat-ui.js'`
15
+ * to a typed module. Post-§303, both files rename to `stat.{js,d.ts}` and
16
+ * codegen takes over.
17
+ */
18
+
19
+ import { UIElement } from '../../core/element.js';
20
+
21
+ export class UIStat extends UIElement {
22
+ /** Eyebrow label describing the metric. */
23
+ label: string;
24
+ /** Primary metric value (large display number / string). */
25
+ value: string;
26
+ /** Change indicator text (e.g. "+12%", "-3%"). Slotted as a badge next to value. */
27
+ change: string;
28
+ /**
29
+ * Trend direction or narrative subtitle. Canonical values color the change
30
+ * badge: `up` = success (green), `down` = danger (red), `flat`/`neutral` =
31
+ * muted. Any other string renders as caption-style text under the primary
32
+ * value (not enum-validated; yaml documents the canonical set but the type
33
+ * stays `string` for narrative subtitles).
34
+ */
35
+ trend: string;
36
+ /** Icon name displayed in the icon slot (Phosphor icon registry). */
37
+ icon: string;
38
+ }
@@ -167,6 +167,14 @@ export class UISwatch extends UIElement {
167
167
  selectable: { type: Boolean, default: false, reflect: true },
168
168
  selected: { type: Boolean, default: false, reflect: true },
169
169
  autoContrast: { type: Boolean, default: false, reflect: true },
170
+ // §253 (v0.5.12, FB-23 §1): label position relative to the tile.
171
+ // `below` (default) = current shape="block" stacked layout.
172
+ // `overlay` = label sits ON the tile via absolute positioning;
173
+ // pair with `[auto-contrast]` for OKLab-L-driven legibility.
174
+ // Only meaningful when shape="block"; other shapes ignore this prop.
175
+ // CSS-only behavior; no JS runtime delta beyond yaml-declared
176
+ // reflective attribute. Unblocks Tokens Studio C1.3 dogfood.
177
+ labelPosition: { type: String, default: 'below', reflect: true, attribute: 'label-position' },
170
178
  };
171
179
 
172
180
  static template = () => null;
@@ -14,7 +14,7 @@
14
14
  ],
15
15
  "properties": {
16
16
  "autoContrast": {
17
- "description": "When set, computes the swatch color's OKLab L and switches the label /\ndetail color between light + dark so it remains legible against the\ntile background. Only applies to shape=\"block\" (where the label sits\nON the tile). Uses a 1px canvas probe to handle any CSS color form\n(oklch / hex / hsl / named / var() references).\n",
17
+ "description": "When set, computes the swatch color's OKLab L and switches the label /\ndetail color between light + dark so it remains legible against the\ntile background. Active when `label-position=\"overlay\"` (where the\nlabel sits ON the tile). Uses a 1px canvas probe to handle any CSS\ncolor form (oklch / hex / hsl / named / var() references).\n",
18
18
  "type": "boolean",
19
19
  "default": false
20
20
  },
@@ -51,6 +51,15 @@
51
51
  "type": "string",
52
52
  "default": ""
53
53
  },
54
+ "labelPosition": {
55
+ "description": "§253 (v0.5.12, FB-23 §1). Position the label relative to the tile.\n`below` (default) stacks label under the tile (current shape=\"block\"\nlayout — `flex-direction: column`). `overlay` renders the label\nINSIDE the tile via absolute positioning; pair with `[auto-contrast]`\nto keep the label legible against the tile color (`data-on-light` /\n`data-on-dark` classes auto-stamped per OKLab-L probe). Only meaningful\nwhen `shape=\"block\"` (other shapes are too small for in-tile labels).\nUnblocks Tokens Studio's C1.3 dogfood migration (label-inside-the-tile\npattern; blocked 3 cycles on this design call).",
56
+ "type": "string",
57
+ "enum": [
58
+ "below",
59
+ "overlay"
60
+ ],
61
+ "default": "below"
62
+ },
54
63
  "selectable": {
55
64
  "description": "When set, makes the swatch keyboard-focusable + clickable. Sets role=\"button\" + tabindex=\"0\". Dispatches a \"select\" event on activation (click / Enter / Space).",
56
65
  "type": "boolean",
@@ -141,6 +141,38 @@
141
141
  white-space: nowrap;
142
142
  }
143
143
 
144
+ /* ═══════ §253 (v0.5.12, FB-23 §1): label-position="overlay" ═══════
145
+ Renders the label INSIDE the block tile via absolute positioning.
146
+ Pair with [auto-contrast] for OKLab-L-driven legibility (existing
147
+ `data-on-light` / `data-on-dark` classes stamp on the label per
148
+ the OKLab-L probe; see auto-contrast rules below).
149
+
150
+ The host becomes the positioning context (default flex-column flow
151
+ for the tile + detail line remains); the label is pulled out of
152
+ flow + absolutely positioned to overlap the tile's full bounds
153
+ (`top: 0; height: var(--_block-h)`). Tile is the first flex child
154
+ with the same height, so the absolute label aligns exactly to it.
155
+
156
+ Only meaningful when `shape="block"` (other shapes are too small
157
+ for in-tile labels). Unblocks Tokens Studio's C1.3 dogfood
158
+ migration (label-inside-the-tile pattern; blocked 3 cycles on this
159
+ design call). */
160
+ :scope[shape="block"][label-position="overlay"] {
161
+ position: relative;
162
+ }
163
+ :scope[shape="block"][label-position="overlay"] > [data-label] {
164
+ position: absolute;
165
+ top: 0;
166
+ inset-inline: 0;
167
+ height: var(--_block-h, var(--swatch-tile-lg));
168
+ display: flex;
169
+ align-items: center;
170
+ justify-content: center;
171
+ margin-block-start: 0; /* override the below-tile margin */
172
+ padding: var(--a-space-1) var(--a-space-2);
173
+ pointer-events: none; /* don't intercept clicks on the tile */
174
+ }
175
+
144
176
  /* ═══════ Sizes ═══════
145
177
  Override the dot/square diameter (`--_size`) and the block-shape
146
178
  height (`--_block-h`) for each size preset. Line/dashed widths use
@@ -31,9 +31,9 @@ export type SwatchSelectEvent = CustomEvent<SwatchSelectEventDetail>;
31
31
  export class UISwatch extends UIElement {
32
32
  /** When set, computes the swatch color's OKLab L and switches the label /
33
33
  detail color between light + dark so it remains legible against the
34
- tile background. Only applies to shape="block" (where the label sits
35
- ON the tile). Uses a 1px canvas probe to handle any CSS color form
36
- (oklch / hex / hsl / named / var() references).
34
+ tile background. Active when `label-position="overlay"` (where the
35
+ label sits ON the tile). Uses a 1px canvas probe to handle any CSS
36
+ color form (oklch / hex / hsl / named / var() references).
37
37
  */
38
38
  autoContrast: boolean;
39
39
  /** Optional marker(s) rendered in the upper-right of the tile. Single value
@@ -54,6 +54,16 @@ are silently dropped.
54
54
  detail: string;
55
55
  /** Optional label rendered next to (or below, for shape="block") the swatch. Use the default slot for richer content. */
56
56
  label: string;
57
+ /** §253 (v0.5.12, FB-23 §1). Position the label relative to the tile.
58
+ `below` (default) stacks label under the tile (current shape="block"
59
+ layout — `flex-direction: column`). `overlay` renders the label
60
+ INSIDE the tile via absolute positioning; pair with `[auto-contrast]`
61
+ to keep the label legible against the tile color (`data-on-light` /
62
+ `data-on-dark` classes auto-stamped per OKLab-L probe). Only meaningful
63
+ when `shape="block"` (other shapes are too small for in-tile labels).
64
+ Unblocks Tokens Studio's C1.3 dogfood migration (label-inside-the-tile
65
+ pattern; blocked 3 cycles on this design call). */
66
+ labelPosition: 'below' | 'overlay';
57
67
  /** When set, makes the swatch keyboard-focusable + clickable. Sets role="button" + tabindex="0". Dispatches a "select" event on activation (click / Enter / Space). */
58
68
  selectable: boolean;
59
69
  /** Reflected visual selected state. Pair with [selectable] to make the swatch behave like a radio-style picker. Sets aria-pressed. */
@@ -80,12 +80,30 @@ props:
80
80
  description: |
81
81
  When set, computes the swatch color's OKLab L and switches the label /
82
82
  detail color between light + dark so it remains legible against the
83
- tile background. Only applies to shape="block" (where the label sits
84
- ON the tile). Uses a 1px canvas probe to handle any CSS color form
85
- (oklch / hex / hsl / named / var() references).
83
+ tile background. Active when `label-position="overlay"` (where the
84
+ label sits ON the tile). Uses a 1px canvas probe to handle any CSS
85
+ color form (oklch / hex / hsl / named / var() references).
86
86
  type: boolean
87
87
  default: false
88
88
  reflect: true
89
+ labelPosition:
90
+ description: |-
91
+ §253 (v0.5.12, FB-23 §1). Position the label relative to the tile.
92
+ `below` (default) stacks label under the tile (current shape="block"
93
+ layout — `flex-direction: column`). `overlay` renders the label
94
+ INSIDE the tile via absolute positioning; pair with `[auto-contrast]`
95
+ to keep the label legible against the tile color (`data-on-light` /
96
+ `data-on-dark` classes auto-stamped per OKLab-L probe). Only meaningful
97
+ when `shape="block"` (other shapes are too small for in-tile labels).
98
+ Unblocks Tokens Studio's C1.3 dogfood migration (label-inside-the-tile
99
+ pattern; blocked 3 cycles on this design call).
100
+ type: string
101
+ default: below
102
+ reflect: true
103
+ attribute: label-position
104
+ enum:
105
+ - below
106
+ - overlay
89
107
  events:
90
108
  select:
91
109
  description: Fired when a selectable swatch is activated (click / Enter / Space). detail carries the swatch's value, color, and label.