@threadlabs/looma 0.33.1 → 0.35.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.
Files changed (215) hide show
  1. package/components/shared/overlay.js +8 -2
  2. package/components/shared/surface-material.js +21 -0
  3. package/components/ui-badge/ui-badge.html +11 -3
  4. package/components/ui-button/ui-button.html +92 -51
  5. package/components/ui-card/ui-card.html +50 -6
  6. package/components/ui-checkbox/ui-checkbox.html +4 -2
  7. package/components/ui-curve-editor/curve.js +10 -0
  8. package/components/ui-curve-editor/ui-curve-editor.html +181 -0
  9. package/components/ui-curve-editor/ui-curve-editor.js +51 -0
  10. package/components/ui-dialog/ui-dialog.html +64 -1
  11. package/components/ui-dialog/ui-dialog.js +9 -1
  12. package/components/ui-icon-button/ui-icon-button.html +97 -31
  13. package/components/ui-input/ui-input.html +2 -1
  14. package/components/ui-input-group/ui-input-group.html +4 -1
  15. package/components/ui-light-editor/ui-light-editor.html +45 -0
  16. package/components/ui-light-editor/ui-light-editor.js +53 -0
  17. package/components/ui-menu/ui-menu.html +62 -0
  18. package/components/ui-menu/ui-menu.js +1 -1
  19. package/components/ui-number-input/arithmetic.js +47 -0
  20. package/components/ui-number-input/ui-number-input.html +63 -0
  21. package/components/ui-number-input/ui-number-input.js +47 -0
  22. package/components/ui-popover/ui-popover.html +66 -1
  23. package/components/ui-popover/ui-popover.js +1 -1
  24. package/components/ui-select/ui-select.html +9 -7
  25. package/components/ui-slider/ui-slider.html +84 -0
  26. package/components/ui-slider/ui-slider.js +29 -0
  27. package/components/ui-switch/ui-switch.html +3 -0
  28. package/components/ui-tabs/ui-tabs.html +6 -1
  29. package/components/ui-text/ui-text.html +31 -6
  30. package/components/ui-textarea/ui-textarea.html +2 -1
  31. package/components/ui-tooltip/ui-tooltip.html +60 -0
  32. package/components/ui-tooltip/ui-tooltip.js +1 -1
  33. package/dist/index.js +47 -43
  34. package/docs/README.md +59 -5
  35. package/docs/card.html +16 -2
  36. package/docs/card.js +17 -2
  37. package/docs/catalog.json +1640 -108
  38. package/docs/customizer-render.mjs +50 -11
  39. package/docs/customizer.js +137 -24
  40. package/docs/documentation.css +9 -1
  41. package/docs/index.d.ts +8 -3
  42. package/docs/index.mjs +1 -1
  43. package/docs/preview.js +2 -0
  44. package/docs/render.mjs +16 -7
  45. package/docs/site.mjs +78 -27
  46. package/docs/theme-session.mjs +53 -0
  47. package/docs/theme.mjs +189 -18
  48. package/docs/value-editors.mjs +33 -0
  49. package/package.json +2 -2
  50. package/styles/ui-badge.css +11 -6
  51. package/styles/ui-button.css +74 -49
  52. package/styles/ui-card.css +51 -4
  53. package/styles/ui-checkbox.css +4 -2
  54. package/styles/ui-curve-editor.css +109 -0
  55. package/styles/ui-dialog.css +136 -0
  56. package/styles/ui-icon-button.css +85 -28
  57. package/styles/ui-input-group.css +4 -1
  58. package/styles/ui-input.css +2 -1
  59. package/styles/ui-light-editor.css +28 -0
  60. package/styles/ui-menu.css +74 -0
  61. package/styles/ui-number-input.css +34 -0
  62. package/styles/ui-popover.css +76 -0
  63. package/styles/ui-select.css +9 -7
  64. package/styles/ui-slider.css +53 -0
  65. package/styles/ui-switch.css +3 -0
  66. package/styles/ui-tabs.css +6 -1
  67. package/styles/ui-text.css +23 -1
  68. package/styles/ui-textarea.css +2 -1
  69. package/styles/ui-tooltip.css +72 -0
  70. package/theme-light.css +1 -0
  71. package/theme-system.css +69 -17
  72. package/tokens.css +12 -2
  73. package/vanilla/UiButton.d.ts +1 -0
  74. package/vanilla/UiButton.js +195 -130
  75. package/vanilla/UiCard.d.ts +1 -0
  76. package/vanilla/UiCard.js +12 -12
  77. package/vanilla/UiCurveEditor.d.ts +28 -0
  78. package/vanilla/UiCurveEditor.js +134 -0
  79. package/vanilla/UiIconButton.d.ts +2 -1
  80. package/vanilla/UiIconButton.js +58 -31
  81. package/vanilla/UiLightEditor.d.ts +29 -0
  82. package/vanilla/UiLightEditor.js +102 -0
  83. package/vanilla/UiNumberInput.d.ts +33 -0
  84. package/vanilla/UiNumberInput.js +86 -0
  85. package/vanilla/UiSlider.d.ts +33 -0
  86. package/vanilla/UiSlider.js +125 -0
  87. package/vanilla/UiText.d.ts +2 -2
  88. package/vanilla/UiText.js +45 -11
  89. package/vanilla/index.js +4 -0
  90. package/vue/UiBadge.vue +29 -4
  91. package/vue/UiButton.d.ts +6 -0
  92. package/vue/UiButton.vue +188 -60
  93. package/vue/UiCard.d.ts +6 -0
  94. package/vue/UiCard.vue +80 -6
  95. package/vue/UiCheckbox.vue +4 -2
  96. package/vue/UiCurveEditor.d.ts +53 -0
  97. package/vue/UiCurveEditor.js +2 -0
  98. package/vue/UiCurveEditor.vue +427 -0
  99. package/vue/UiDialog.vue +181 -1
  100. package/vue/UiIconButton.d.ts +8 -2
  101. package/vue/UiIconButton.vue +190 -45
  102. package/vue/UiInput.vue +2 -1
  103. package/vue/UiInputGroup.vue +4 -1
  104. package/vue/UiLightEditor.d.ts +75 -0
  105. package/vue/UiLightEditor.js +2 -0
  106. package/vue/UiLightEditor.vue +402 -0
  107. package/vue/UiMenu.vue +91 -0
  108. package/vue/UiNumberInput.d.ts +83 -0
  109. package/vue/UiNumberInput.js +2 -0
  110. package/vue/UiNumberInput.vue +399 -0
  111. package/vue/UiPopover.vue +94 -1
  112. package/vue/UiSelect.vue +16 -10
  113. package/vue/UiSlider.d.ts +83 -0
  114. package/vue/UiSlider.js +2 -0
  115. package/vue/UiSlider.vue +412 -0
  116. package/vue/UiSwitch.vue +3 -0
  117. package/vue/UiTabs.vue +6 -1
  118. package/vue/UiText.d.ts +7 -5
  119. package/vue/UiText.vue +104 -22
  120. package/vue/UiTextarea.vue +2 -1
  121. package/vue/UiTooltip.vue +89 -0
  122. package/vue/chunks/UiActionBar.js +1 -1
  123. package/vue/chunks/UiAffordanceScope.js +2 -2
  124. package/vue/chunks/UiAvatar.js +2 -2
  125. package/vue/chunks/UiAvatarGroup.js +2 -2
  126. package/vue/chunks/UiBadge.js +3 -3
  127. package/vue/chunks/UiBreadcrumbItem.js +2 -2
  128. package/vue/chunks/UiBreadcrumbs.js +2 -2
  129. package/vue/chunks/UiButton.js +94 -11
  130. package/vue/chunks/UiCallout.js +2 -2
  131. package/vue/chunks/UiCard.js +34 -5
  132. package/vue/chunks/UiCheckbox.js +3 -3
  133. package/vue/chunks/UiCluster.js +2 -2
  134. package/vue/chunks/UiColorPicker.js +2 -2
  135. package/vue/chunks/UiCombobox.js +2 -2
  136. package/vue/chunks/UiContainer.js +2 -2
  137. package/vue/chunks/UiContextMenu.js +2 -2
  138. package/vue/chunks/UiCover.js +2 -2
  139. package/vue/chunks/UiCurveEditor.js +413 -0
  140. package/vue/chunks/UiDescriptionItem.js +2 -2
  141. package/vue/chunks/UiDescriptionList.js +2 -2
  142. package/vue/chunks/UiDialog.js +4 -4
  143. package/vue/chunks/UiDisclosure.js +2 -2
  144. package/vue/chunks/UiEditable.js +2 -2
  145. package/vue/chunks/UiEditorBlockActions.js +2 -2
  146. package/vue/chunks/UiEditorChipEditor.js +2 -2
  147. package/vue/chunks/UiEditorCodeLanguage.js +2 -2
  148. package/vue/chunks/UiEditorFootnoteEditor.js +2 -2
  149. package/vue/chunks/UiEditorImageToolbar.js +3 -3
  150. package/vue/chunks/UiEditorInsertTableGrid.js +2 -2
  151. package/vue/chunks/UiEditorLinkCard.js +3 -3
  152. package/vue/chunks/UiEditorLinkForm.js +3 -3
  153. package/vue/chunks/UiEditorMentionMenu.js +2 -2
  154. package/vue/chunks/UiEditorMentionMenuItem.js +2 -2
  155. package/vue/chunks/UiEditorSlashMenu.js +2 -2
  156. package/vue/chunks/UiEditorSlashMenuGroup.js +2 -2
  157. package/vue/chunks/UiEditorSlashMenuItem.js +2 -2
  158. package/vue/chunks/UiEditorSurface.js +2 -2
  159. package/vue/chunks/UiEditorTableContextMenu.js +2 -2
  160. package/vue/chunks/UiEditorTableOverlay.js +2 -2
  161. package/vue/chunks/UiEditorTableToolbar.js +2 -2
  162. package/vue/chunks/UiEditorToolbar.js +2 -2
  163. package/vue/chunks/UiFloatingActionButton.js +2 -2
  164. package/vue/chunks/UiFormField.js +2 -2
  165. package/vue/chunks/UiGrid.js +2 -2
  166. package/vue/chunks/UiIcon.js +2 -2
  167. package/vue/chunks/UiIconButton.js +77 -11
  168. package/vue/chunks/UiImage.js +2 -2
  169. package/vue/chunks/UiInput.js +3 -3
  170. package/vue/chunks/UiInputGroup.js +3 -3
  171. package/vue/chunks/UiLightEditor.js +347 -0
  172. package/vue/chunks/UiList.js +2 -2
  173. package/vue/chunks/UiListItem.js +2 -2
  174. package/vue/chunks/UiListbox.js +2 -2
  175. package/vue/chunks/UiMenu.js +3 -3
  176. package/vue/chunks/UiMenuGroup.js +2 -2
  177. package/vue/chunks/UiMenuItem.js +2 -2
  178. package/vue/chunks/UiMeter.js +2 -2
  179. package/vue/chunks/UiNavItem.js +2 -2
  180. package/vue/chunks/UiNumberInput.js +403 -0
  181. package/vue/chunks/UiPageHeader.js +2 -2
  182. package/vue/chunks/UiPopover.js +4 -4
  183. package/vue/chunks/UiRadio.js +2 -2
  184. package/vue/chunks/UiRadioGroup.js +2 -2
  185. package/vue/chunks/UiReel.js +2 -2
  186. package/vue/chunks/UiScrollArea.js +2 -2
  187. package/vue/chunks/UiSearchResultRow.js +2 -2
  188. package/vue/chunks/UiSearchShell.js +2 -2
  189. package/vue/chunks/UiSection.js +2 -2
  190. package/vue/chunks/UiSelect.js +3 -3
  191. package/vue/chunks/UiSeparator.js +2 -2
  192. package/vue/chunks/UiSidebar.js +2 -2
  193. package/vue/chunks/UiSlider.js +396 -0
  194. package/vue/chunks/UiSpinner.js +2 -2
  195. package/vue/chunks/UiStack.js +2 -2
  196. package/vue/chunks/UiStatusMessage.js +2 -2
  197. package/vue/chunks/UiSwatch.js +2 -2
  198. package/vue/chunks/UiSwitch.js +3 -3
  199. package/vue/chunks/UiSwitcher.js +2 -2
  200. package/vue/chunks/UiTable.js +2 -2
  201. package/vue/chunks/UiTabs.js +3 -3
  202. package/vue/chunks/UiText.js +53 -12
  203. package/vue/chunks/UiTextarea.js +3 -3
  204. package/vue/chunks/UiToast.js +2 -2
  205. package/vue/chunks/UiToastRegion.js +2 -2
  206. package/vue/chunks/UiTooltip.js +3 -3
  207. package/vue/chunks/UiTopBar.js +1 -1
  208. package/vue/chunks/UiTree.js +2 -2
  209. package/vue/chunks/UiTreeItem.js +2 -2
  210. package/vue/chunks/_plugin-vue_export-helper.js +68 -2
  211. package/vue/chunks/props.js +24 -1
  212. package/vue/components.css +3391 -2139
  213. package/vue/editor/index.js +623 -211
  214. package/vue/index.d.ts +4 -0
  215. package/vue/index.js +6 -2
@@ -0,0 +1,181 @@
1
+ <link rel="component" href="../ui-number-input/ui-number-input.html">
2
+ <template component="ui-curve-editor" module="./ui-curve-editor.js">
3
+ <defs>
4
+ <state name="point0" type="string" value="0.25"></state>
5
+ <state name="point1" type="string" value="0.1"></state>
6
+ <state name="point2" type="string" value="0.25"></state>
7
+ <state name="point3" type="string" value="1"></state>
8
+
9
+ <prop name="value" type="string" default="cubic-bezier(0.25, 0.1, 0.25, 1)"
10
+ >CSS cubic-bezier or a standard easing keyword. X stays within 0–1; Y is bounded to -1–2 for a limited overshoot.</prop>
11
+ <prop name="label" type="string" default="Value">Accessible name for the editing control.</prop>
12
+ <prop name="size" type="keyword" values="sm, md, lg" default="md">Shared field and button height.</prop>
13
+ <prop name="disabled" type="boolean" default="false">Prevents typing, stepping and pointer or keyboard changes while keeping the value visible.</prop>
14
+ <event name="input" type="object"><prop name="value" type="string" required></prop></event>
15
+ <event name="change" type="object"><prop name="value" type="string" required></prop></event>
16
+ </defs>
17
+ <span>
18
+ <span class="plot-frame" from:aria-label="$label" role="group"><span class="plot" $ref="plot">
19
+ <svg viewBox="0 0 100 100" preserveAspectRatio="none" aria-hidden="true">
20
+ <path class="guide" d="M0 66.667 H100 M0 33.333 H100"></path>
21
+ <path $ref="firstLine" class="guide" d="M0 66.667 L25 63.333"></path>
22
+ <path $ref="secondLine" class="guide" d="M100 33.333 L25 33.333"></path>
23
+ <path $ref="curve" d="M0 66.667 C25 63.333 25 33.333 100 33.333"></path>
24
+ </svg>
25
+ <button $ref="first" class="handle" type="button" from:disabled="$disabled" aria-label="First curve handle. Arrow keys adjust; Shift moves faster.">
26
+ </button>
27
+ <button
28
+ $ref="second"
29
+ class="handle second"
30
+ type="button"
31
+ from:disabled="$disabled"
32
+ aria-label="Second curve handle. Arrow keys adjust; Shift moves faster."
33
+ >
34
+ </button>
35
+ </span></span>
36
+ <span class="coordinates">
37
+ <span class="coordinate"><span>X1</span><ui-number-input
38
+ data-curve-coordinate="0"
39
+ from:value="$point0"
40
+ min="0"
41
+ max="1"
42
+ step="0.01"
43
+ label="First handle X"
44
+ from:size="$size"
45
+ from:disabled="$disabled"
46
+ ></ui-number-input></span>
47
+ <span class="coordinate"><span>Y1</span><ui-number-input
48
+ data-curve-coordinate="1"
49
+ from:value="$point1"
50
+ min="-1"
51
+ max="2"
52
+ step="0.01"
53
+ label="First handle Y"
54
+ from:size="$size"
55
+ from:disabled="$disabled"
56
+ ></ui-number-input></span>
57
+ <span class="coordinate"><span>X2</span><ui-number-input
58
+ data-curve-coordinate="2"
59
+ from:value="$point2"
60
+ min="0"
61
+ max="1"
62
+ step="0.01"
63
+ label="Second handle X"
64
+ from:size="$size"
65
+ from:disabled="$disabled"
66
+ ></ui-number-input></span>
67
+ <span class="coordinate"><span>Y2</span><ui-number-input
68
+ data-curve-coordinate="3"
69
+ from:value="$point3"
70
+ min="-1"
71
+ max="2"
72
+ step="0.01"
73
+ label="Second handle Y"
74
+ from:size="$size"
75
+ from:disabled="$disabled"
76
+ ></ui-number-input></span>
77
+ </span>
78
+ <output $ref="result">{$value}</output>
79
+ </span>
80
+ <style>
81
+ :host {
82
+ display: grid !important;
83
+ gap: var(--ui-space-3) !important;
84
+ margin: 0 !important;
85
+ padding: 0 !important;
86
+ min-inline-size: 0;
87
+ }
88
+ .plot-frame {
89
+ box-sizing: border-box !important;
90
+ display: block !important;
91
+ block-size: 12rem;
92
+ padding: max(var(--ui-space-4), 0.75rem, calc(var(--ui-control-min-block-size) / 2)) !important;
93
+ margin: 0 !important;
94
+ border: var(--ui-border-width) solid var(--ui-control-border);
95
+ border-radius: var(--ui-field-radius, var(--ui-radius-md));
96
+ background: var(--ui-control-surface, var(--ui-surface));
97
+ }
98
+ .plot {
99
+ position: relative;
100
+ display: block !important;
101
+ inline-size: 100%;
102
+ block-size: 100%;
103
+ }
104
+ svg {
105
+ inline-size: 100%;
106
+ block-size: 100%;
107
+ overflow: visible;
108
+ }
109
+ path {
110
+ fill: none;
111
+ stroke: var(--ui-accent-solid);
112
+ stroke-width: 2;
113
+ vector-effect: non-scaling-stroke;
114
+ }
115
+ .guide {
116
+ stroke: var(--ui-control-border);
117
+ stroke-width: 1;
118
+ }
119
+ .handle {
120
+ position: absolute;
121
+ left: 25%;
122
+ top: 63.333%;
123
+ translate: -50% -50%;
124
+ inline-size: max(1.5rem, var(--ui-control-min-block-size));
125
+ block-size: max(1.5rem, var(--ui-control-min-block-size));
126
+ border: 0;
127
+ border-radius: 50%;
128
+ background: transparent;
129
+ color: var(--ui-text-primary);
130
+ touch-action: none;
131
+ cursor: grab;
132
+ padding: 0 !important;
133
+ margin: 0 !important;
134
+ }
135
+ .second {
136
+ top: 33.333%;
137
+ }
138
+ .handle::after {
139
+ content: "";
140
+ position: absolute;
141
+ inset: 25%;
142
+ border: var(--ui-border-width) solid var(--ui-accent-solid);
143
+ background: var(--ui-surface-raised);
144
+ border-radius: 50%;
145
+ box-shadow: var(--ui-shadow-xs);
146
+ }
147
+ .handle::before {
148
+ content: "";
149
+ position: absolute;
150
+ inset: 40%;
151
+ background: var(--ui-accent-solid);
152
+ border-radius: 50%;
153
+ z-index: 1;
154
+ }
155
+ .handle:focus-visible {
156
+ outline: var(--ui-focus-width) solid var(--ui-control-focus, var(--ui-accent-solid));
157
+ outline-offset: var(--ui-space-1);
158
+ }
159
+ .handle:disabled {
160
+ cursor: not-allowed;
161
+ }
162
+ .coordinates {
163
+ display: grid !important;
164
+ grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
165
+ gap: var(--ui-space-2) !important;
166
+ }
167
+ .coordinate {
168
+ display: grid !important;
169
+ gap: var(--ui-space-1) !important;
170
+ font-size: var(--ui-font-size-sm);
171
+ }
172
+ output {
173
+ overflow-wrap: anywhere;
174
+ font-family: var(--ui-font-mono, monospace);
175
+ font-size: var(--ui-font-size-sm);
176
+ }
177
+ :host[hidden] {
178
+ display: none !important;
179
+ }
180
+ </style>
181
+ </template>
@@ -0,0 +1,51 @@
1
+ import { curvePoints, curveText } from "./curve.js";
2
+
3
+ export function connect(host) {
4
+ const { plot, first, second, firstLine, secondLine, curve, result } = host.refs;
5
+ const fields = [...host.element.querySelectorAll("[data-curve-coordinate]")];
6
+ let points = [.25, .1, .25, 1]; let external; let drag;
7
+ const limit = () => { points = curvePoints(curveText(points)); };
8
+ const paint = () => {
9
+ limit();
10
+ const x = index => points[index] * 100;
11
+ const y = index => (2 - points[index]) / 3 * 100;
12
+ for (const [index, handle] of [[0, first], [2, second]]) {
13
+ handle.style.left = `${x(index)}%`; handle.style.top = `${y(index + 1)}%`;
14
+ handle.setAttribute("aria-description", `X ${points[index]}, Y ${points[index + 1]}`);
15
+ }
16
+ firstLine.setAttribute("d", `M0 66.667 L${x(0)} ${y(1)}`);
17
+ secondLine.setAttribute("d", `M100 33.333 L${x(2)} ${y(3)}`);
18
+ curve.setAttribute("d", `M0 66.667 C${x(0)} ${y(1)} ${x(2)} ${y(3)} 100 33.333`);
19
+ fields.forEach((field, index) => { host.state[`point${index}`] = String(points[index]); });
20
+ result.value = curveText(points); result.textContent = curveText(points);
21
+ };
22
+ const emit = type => host.dispatch(type, { value: curveText(points) });
23
+ const move = event => {
24
+ if (!drag || event.pointerId !== drag.id || host.props.disabled.value) return;
25
+ const rect = plot.getBoundingClientRect();
26
+ if (!rect.width || !rect.height) return;
27
+ points[drag.index] = (event.clientX - rect.left) / rect.width;
28
+ points[drag.index + 1] = 2 - (event.clientY - rect.top) / rect.height * 3;
29
+ paint(); emit("input");
30
+ };
31
+ const finish = event => { if (drag?.id !== event.pointerId) return; drag = undefined; if (!host.props.disabled.value) emit("change"); };
32
+ const cleanups = [];
33
+ for (const [index, handle] of [[0, first], [2, second]]) {
34
+ const down = event => { if (host.props.disabled.value || event.button !== 0) return; event.preventDefault(); handle.focus(); drag = { id: event.pointerId, index }; handle.setPointerCapture(event.pointerId); };
35
+ const key = event => {
36
+ if (host.props.disabled.value || !["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown"].includes(event.key)) return;
37
+ event.preventDefault(); const step = event.shiftKey ? .1 : .01;
38
+ points[index + (event.key === "ArrowUp" || event.key === "ArrowDown" ? 1 : 0)] += (event.key === "ArrowLeft" || event.key === "ArrowDown" ? -step : step);
39
+ paint(); emit("input"); emit("change");
40
+ };
41
+ for (const [type, callback] of [["pointerdown", down], ["pointermove", move], ["pointerup", finish], ["pointercancel", finish], ["keydown", key]]) {
42
+ handle.addEventListener(type, callback); cleanups.push(() => handle.removeEventListener(type, callback));
43
+ }
44
+ }
45
+ fields.forEach((field, index) => {
46
+ const edit = event => { event.stopPropagation(); if (host.props.disabled.value) return; points[index] = Number(event.detail.value); paint(); emit(event.type); };
47
+ for (const type of ["input", "change"]) { field.addEventListener(type, edit); cleanups.push(() => field.removeEventListener(type, edit)); }
48
+ });
49
+ const stop = host.effect(() => { const value = host.props.value.value; if (value === external) return; external = value; try { points = curvePoints(value); } catch { /* Keep the last valid curve. */ } paint(); });
50
+ return () => { stop(); cleanups.forEach(cleanup => cleanup()); };
51
+ }
@@ -13,7 +13,8 @@
13
13
  closerequest when modal, none when not.</prop>
14
14
  <prop name="alert" type="boolean" default="false"
15
15
  >Use alert dialog semantics and require an explicit action instead of the header close button. An alert dialog is always modal.</prop>
16
- <prop name="size" type="keyword" values="sm, md, lg, fullscreen" default="md">Choose a compact, standard, wide, or viewport-filling dialog.</prop>
16
+ <prop name="size" type="keyword" values="sm, md, lg, fullscreen" default="md"
17
+ >Choose a compact, standard, wide, or viewport-filling dialog. Shared surface separation adapts to dialog purpose and rendered size.</prop>
17
18
  <prop name="label" type="string">Visible title in the dialog header; also its accessible name.</prop>
18
19
  <prop name="for" type="string" default="">ID of the control that opens the dialog.</prop>
19
20
  <state type="boolean" name="internalOpen" value="false"></state>
@@ -75,6 +76,7 @@
75
76
  }
76
77
 
77
78
  :host {
79
+ --_ui-material-scale: 1;
78
80
  /* Hooks do not inherit, so the parts below read them from the root. */
79
81
  --_ui-dialog-duration: var(--ui-dialog-duration);
80
82
 
@@ -107,6 +109,67 @@
107
109
  overlay var(--ui-dialog-duration, var(--ui-motion-base)) var(--ui-motion-ease) allow-discrete;
108
110
  }
109
111
 
112
+ /* Purpose and measured size shape one shared separation lever. The content plane stays opaque;
113
+ transparency, saturation and edge light belong to the surrounding decorative material. */
114
+ :host {
115
+ --_ui-material-glassiness: clamp(0, var(--ui-glassiness, 0), 1);
116
+ --_ui-material-separation: clamp(0, var(--ui-surface-separation, 0), 1);
117
+ --_ui-material-active: clamp(0, calc((var(--_ui-material-glassiness) + var(--_ui-material-separation)) * 100000), 1);
118
+ --_ui-material-rim: calc((var(--_ui-material-separation) + var(--_ui-material-glassiness) * 0.25) * var(--_ui-material-scale, 1) * 8px);
119
+ --_ui-material-content-color: var(--ui-dialog-surface, var(--ui-material-content, var(--ui-overlay-surface, var(--ui-surface-elevated))));
120
+ --_ui-material-rim-color: color-mix(in srgb, var(--ui-material-glass, var(--ui-surface-elevated)) calc(var(--_ui-material-active) * 100%), transparent);
121
+ background:
122
+ var(--ui-surface-highlight, linear-gradient(transparent, transparent)) padding-box,
123
+ linear-gradient(var(--_ui-material-content-color), var(--_ui-material-content-color)) padding-box,
124
+ linear-gradient(var(--_ui-material-rim-color), var(--_ui-material-rim-color)) border-box,
125
+ var(--_ui-material-content-color) padding-box;
126
+ border-width: calc(var(--ui-border-width) + var(--_ui-material-rim));
127
+ border-color: var(
128
+ --ui-dialog-border,
129
+ color-mix(in oklab, var(--ui-overlay-border, var(--ui-border-strong)) calc((1 - var(--_ui-material-active)) * 100%), transparent)
130
+ );
131
+ box-shadow: var(
132
+ --ui-dialog-shadow,
133
+ var(
134
+ --ui-overlay-shadow,
135
+ 0 calc(var(--_ui-material-separation) * var(--_ui-material-scale, 1) * 8px) calc(
136
+ var(--_ui-material-separation) * var(--_ui-material-scale, 1) * 24px
137
+ ) color-mix(in oklab, var(--ui-text-primary) 15%, transparent),
138
+ var(--ui-material-glow, 0 0 transparent),
139
+ inset 0 0 0 calc(var(--_ui-material-active) * var(--ui-border-width)) var(--ui-material-edge, var(--ui-border-strong)),
140
+ var(--ui-elevation-dialog, var(--ui-shadow-xl))
141
+ )
142
+ );
143
+ backdrop-filter: blur(calc(var(--_ui-material-glassiness) * var(--_ui-material-scale, 1) * 18px))
144
+ saturate(calc(1 + var(--_ui-material-glassiness) * var(--_ui-material-scale, 1) * 0.18));
145
+ -webkit-backdrop-filter: blur(calc(var(--_ui-material-glassiness) * var(--_ui-material-scale, 1) * 18px))
146
+ saturate(calc(1 + var(--_ui-material-glassiness) * var(--_ui-material-scale, 1) * 0.18));
147
+ }
148
+
149
+ @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
150
+ :host {
151
+ background: var(--_ui-material-content-color);
152
+ }
153
+ }
154
+
155
+ @media (prefers-reduced-transparency: reduce) {
156
+ :host {
157
+ background: var(--_ui-material-content-color);
158
+ backdrop-filter: none;
159
+ -webkit-backdrop-filter: none;
160
+ }
161
+ }
162
+
163
+ @media (forced-colors: active) {
164
+ :host {
165
+ background: Canvas;
166
+ border-color: CanvasText;
167
+ box-shadow: none;
168
+ backdrop-filter: none;
169
+ -webkit-backdrop-filter: none;
170
+ }
171
+ }
172
+
110
173
  :host[open] {
111
174
  display: flex !important;
112
175
  visibility: visible;
@@ -1,4 +1,5 @@
1
- import { closeDialog, closeOverlay, createIdResolver, openOverlay, requestTopOverlayClose, showDialog } from "../shared/overlay.js";
1
+ import { updateSurfaceMaterial } from "../shared/surface-material.js";
2
+ import { closeDialog, closeOverlay, createIdResolver, openOverlay, observeOverlayViewport, requestTopOverlayClose, showDialog } from "../shared/overlay.js";
2
3
 
3
4
  function inferredLabel(element, explicit) {
4
5
  if (String(explicit ?? "").trim()) return String(explicit).trim();
@@ -18,6 +19,7 @@ function observeContentHeight(dialog, refs) {
18
19
  };
19
20
  const observer = new owner.ResizeObserver(() => {
20
21
  if (!dialog.open) { reset(); return; }
22
+ updateSurfaceMaterial(dialog, "dialog");
21
23
  const previous = animation ? parseFloat(owner.getComputedStyle(dialog).height) : lastHeight;
22
24
  animation?.cancel();
23
25
  animation = null;
@@ -63,6 +65,7 @@ export function connect(host) {
63
65
  let lastFor = "";
64
66
  let lastExternalOpen = Boolean(host.props.open.value);
65
67
  let lastOpen;
68
+ let stopMaterialViewport = null;
66
69
  host.state.internalOpen = lastExternalOpen;
67
70
 
68
71
  const requestClose = (reason, input) => {
@@ -126,9 +129,13 @@ export function connect(host) {
126
129
  dialog.setAttribute("closedby", closedBy);
127
130
  if (open) {
128
131
  showDialog(dialog, modal);
132
+ updateSurfaceMaterial(dialog, "dialog");
133
+ stopMaterialViewport ??= observeOverlayViewport(document, () => updateSurfaceMaterial(dialog, "dialog"));
129
134
  openOverlay({ id: overlayId, modal, element, modalElement: dialog, dismissible: true, canClose: (reason) => reason === "light-dismiss" ? closedBy === "any" : reason !== "escape" || closedBy !== "none", requestClose });
130
135
  } else {
131
136
  resize.reset();
137
+ stopMaterialViewport?.();
138
+ stopMaterialViewport = null;
132
139
  closeDialog(dialog);
133
140
  closeOverlay(document, overlayId);
134
141
  }
@@ -176,6 +183,7 @@ export function connect(host) {
176
183
  ids.stop();
177
184
  observer.disconnect();
178
185
  resize.destroy();
186
+ stopMaterialViewport?.();
179
187
  dialog?.removeEventListener("close", onClose, true);
180
188
  dialog?.removeEventListener("cancel", onCancel);
181
189
  closeButton?.removeEventListener("click", onCloseClick);
@@ -1,6 +1,12 @@
1
1
  <link rel="component" href="../ui-spinner/ui-spinner.html">
2
2
  <template component="ui-icon-button" module="./ui-icon-button.js">
3
3
  <defs>
4
+ <prop name="preset" type="keyword" values="none, primary, standard, quiet, destructive" default="none"
5
+ >The same shortcuts as Button: primary is solid accent, standard is solid neutral, quiet is ghost neutral, and destructive is solid danger. A named preset
6
+ wins over variant and tone; none preserves independent choices.</prop>
7
+ <!-- Computed maps read every member in HTML Next. auto keeps an omitted tone concrete so the preset map can resolve, while retaining the existing variant-dependent appearance. -->
8
+ <computed name="appearance" from="{ none: $variant, primary: 'solid', standard: 'solid', quiet: 'ghost', destructive: 'solid' }[$preset]"></computed>
9
+ <computed name="colorTone" from="{ none: $tone, primary: 'accent', standard: 'neutral', quiet: 'neutral', destructive: 'danger' }[$preset]"></computed>
4
10
  <prop name="disabled" type="boolean" default="false"
5
11
  >Disables the button, so it cannot be pressed or focused, and gives it a flat neutral surface and muted icon.</prop>
6
12
  <prop name="loading" type="boolean" default="false"
@@ -17,9 +23,10 @@
17
23
  <prop name="variant" type="keyword" values="ghost, outline, solid" default="ghost"
18
24
  >Emphasis. ghost shows only the icon until it is hovered, for toolbars and dense rows; outline adds a border on the default surface; solid fills with the
19
25
  accent colour, for the one primary action in a group.</prop>
20
- <prop name="tone" type="keyword" values="accent, neutral"
21
- >Colour for every variant. When omitted, ghost and outline keep their neutral appearance and solid keeps its accent fill. Set accent for a coloured action
22
- or neutral for a quiet one. Native aria-pressed="true" keeps an outline toggle visibly pressed; the consumer owns that state.</prop>
26
+ <prop name="tone" type="keyword" values="auto, accent, neutral, danger, success, warning, info" default="auto"
27
+ >Colour for every variant. auto preserves the existing variant-specific default. When omitted, ghost and outline keep their neutral appearance and solid
28
+ keeps its accent fill. Set accent for a coloured action or neutral for a quiet one. danger, success, warning and info share Button's intent colors. Native
29
+ aria-pressed="true" keeps an outline toggle visibly pressed; the consumer owns that state.</prop>
23
30
  <prop name="anticipatory" type="boolean" default="false"
24
31
  >Keeps the button out of sight until it is wanted: at rest a fine pointer sees only a small guide dot, and the button appears on hover, on focus, or when
25
32
  the pointer comes near inside a ui-affordance-scope. Touch devices and the solid variant always show it.</prop>
@@ -32,6 +39,8 @@
32
39
  <prop name="round" type="boolean" default="false">Use a fully circular shape.</prop>
33
40
  </defs>
34
41
  <button
42
+ from:data-appearance="$appearance"
43
+ from:data-tone="$colorTone"
35
44
  from:disabled="$disabled"
36
45
  type="button"
37
46
  from:aria-label="$label"
@@ -124,7 +133,9 @@
124
133
  :host {
125
134
  /* Optional inherited action-group values keep text and icon actions under the same light.
126
135
  One fine top/start highlight follows the bottom/end lowlight at a joined action seam.
127
- A single ambient lift avoids stacking a face gradient or another inset bevel. */
136
+ The shared theme supplies reflections and glow independently of the resting lift. */
137
+ --_tone-highlight: var(--ui-accent-highlight, none);
138
+ --_tone-glow: var(--ui-accent-glow, 0 0 transparent);
128
139
  --_ui-action-start: 1px;
129
140
  --_ui-action-edge: var(
130
141
  --ui-action-edge,
@@ -144,7 +155,9 @@
144
155
  --_ui-action-start: -1px;
145
156
  }
146
157
 
147
- :host([tone="accent"]) {
158
+ :host[data-tone="accent"] {
159
+ --_tone-highlight: var(--ui-accent-highlight, none);
160
+ --_tone-glow: var(--ui-accent-glow, 0 0 transparent);
148
161
  --_icon-button-border: var(--ui-accent-solid);
149
162
  --_icon-button-hover-border: var(--ui-accent-hover);
150
163
  --_icon-button-text: var(--ui-accent-subtle-text, var(--ui-accent-solid));
@@ -152,11 +165,65 @@
152
165
  color: var(--_icon-button-text);
153
166
  }
154
167
 
168
+ :host[data-tone="danger"] {
169
+ --_tone-highlight: var(--ui-danger-highlight, none);
170
+ --_tone-glow: var(--ui-danger-glow, 0 0 transparent);
171
+ --_icon-button-border: var(--ui-danger);
172
+ --_icon-button-hover-border: var(--ui-danger-hover);
173
+ --_icon-button-text: var(--ui-danger-subtle-text);
174
+ --_icon-button-outline-surface: color-mix(in srgb, var(--ui-danger) 5%, var(--ui-surface-default));
175
+ --_icon-button-solid-surface: var(--ui-danger);
176
+ --_icon-button-solid-hover-surface: var(--ui-danger-hover);
177
+ --_icon-button-solid-text: var(--ui-danger-on-strong);
178
+ color: var(--_icon-button-text);
179
+ }
180
+
181
+ :host[data-tone="success"] {
182
+ --_tone-highlight: var(--ui-success-highlight, none);
183
+ --_tone-glow: var(--ui-success-glow, 0 0 transparent);
184
+ --_icon-button-border: var(--ui-success);
185
+ --_icon-button-hover-border: var(--ui-success-hover);
186
+ --_icon-button-text: var(--ui-success-subtle-text);
187
+ --_icon-button-outline-surface: color-mix(in srgb, var(--ui-success) 5%, var(--ui-surface-default));
188
+ --_icon-button-solid-surface: var(--ui-success);
189
+ --_icon-button-solid-hover-surface: var(--ui-success-hover);
190
+ --_icon-button-solid-text: var(--ui-success-on-strong);
191
+ color: var(--_icon-button-text);
192
+ }
193
+
194
+ :host[data-tone="warning"] {
195
+ --_tone-highlight: var(--ui-warning-highlight, none);
196
+ --_tone-glow: var(--ui-warning-glow, 0 0 transparent);
197
+ --_icon-button-border: var(--ui-warning);
198
+ --_icon-button-hover-border: var(--ui-warning-hover);
199
+ --_icon-button-text: var(--ui-warning-subtle-text);
200
+ --_icon-button-outline-surface: color-mix(in srgb, var(--ui-warning) 5%, var(--ui-surface-default));
201
+ --_icon-button-solid-surface: var(--ui-warning);
202
+ --_icon-button-solid-hover-surface: var(--ui-warning-hover);
203
+ --_icon-button-solid-text: var(--ui-warning-on-strong);
204
+ color: var(--_icon-button-text);
205
+ }
206
+
207
+ :host[data-tone="info"] {
208
+ --_tone-highlight: var(--ui-info-highlight, none);
209
+ --_tone-glow: var(--ui-info-glow, 0 0 transparent);
210
+ --_icon-button-border: var(--ui-info);
211
+ --_icon-button-hover-border: var(--ui-info-hover);
212
+ --_icon-button-text: var(--ui-info-subtle-text);
213
+ --_icon-button-outline-surface: color-mix(in srgb, var(--ui-info) 5%, var(--ui-surface-default));
214
+ --_icon-button-solid-surface: var(--ui-info);
215
+ --_icon-button-solid-hover-surface: var(--ui-info-hover);
216
+ --_icon-button-solid-text: var(--ui-info-on-strong);
217
+ color: var(--_icon-button-text);
218
+ }
219
+
155
220
  /* Omitted tone retains the existing accent solid; explicit neutral is additive. */
156
- :host([tone="neutral"]) {
157
- --_icon-button-solid-surface: var(--ui-text-primary);
158
- --_icon-button-solid-hover-surface: var(--ui-text-primary);
159
- --_icon-button-solid-text: var(--ui-surface-default);
221
+ :host[data-tone="neutral"] {
222
+ --_tone-highlight: var(--ui-neutral-highlight, none);
223
+ --_tone-glow: var(--ui-neutral-glow, 0 0 transparent);
224
+ --_icon-button-solid-surface: var(--ui-neutral-surface);
225
+ --_icon-button-solid-hover-surface: var(--ui-neutral-hover);
226
+ --_icon-button-solid-text: var(--ui-text);
160
227
  }
161
228
 
162
229
  :host([anticipatory]) {
@@ -198,13 +265,13 @@
198
265
  }
199
266
 
200
267
  @media (hover: hover) and (pointer: fine) {
201
- :host([anticipatory]):not(:host([revealed]), :host([variant="solid"]), :host([loading]), :host([pending]), :disabled, [aria-pressed="true"], [data-ui-proximity="near"], :hover, :focus-visible) {
268
+ :host([anticipatory]):not(:host([revealed]), :host[data-appearance="solid"], :host([loading]), :host([pending]), :disabled, [aria-pressed="true"], [data-ui-proximity="near"], :hover, :focus-visible) {
202
269
  border-color: transparent;
203
270
  background-color: transparent;
204
271
  box-shadow: none;
205
272
  }
206
273
 
207
- :host([anticipatory]):not(:host([revealed]), :host([variant="solid"]), :host([loading]), :host([pending]), :disabled, [aria-pressed="true"], [data-ui-proximity="near"], :hover, :focus-visible)
274
+ :host([anticipatory]):not(:host([revealed]), :host[data-appearance="solid"], :host([loading]), :host([pending]), :disabled, [aria-pressed="true"], [data-ui-proximity="near"], :hover, :focus-visible)
208
275
  .content {
209
276
  opacity: 0;
210
277
  transform: scale(0.65);
@@ -212,7 +279,7 @@
212
279
  }
213
280
  }
214
281
 
215
- :host([anticipatory]):is(:host([revealed]), :host([variant="solid"]), [aria-pressed="true"], [data-ui-proximity="near"], :hover, :focus-visible)::before {
282
+ :host([anticipatory]):is(:host([revealed]), :host[data-appearance="solid"], [aria-pressed="true"], [data-ui-proximity="near"], :hover, :focus-visible)::before {
216
283
  opacity: 0;
217
284
  }
218
285
 
@@ -321,19 +388,19 @@
321
388
  border-radius: var(--ui-radius-round);
322
389
  }
323
390
 
324
- :host([variant="outline"]) {
391
+ :host[data-appearance="outline"] {
325
392
  border-color: var(--ui-icon-button-border, var(--_icon-button-border, var(--ui-control-border, var(--ui-border-strong))));
326
393
  background-color: var(--ui-icon-button-outline-surface, var(--_icon-button-outline-surface, var(--ui-surface-default)));
327
- background-image: none;
394
+ background-image: var(--ui-surface-highlight, none);
328
395
  color: var(--ui-icon-button-outline-text, var(--_icon-button-text, var(--ui-text-primary)));
329
- box-shadow: var(--ui-action-shadow, var(--_ui-action-shadow));
396
+ box-shadow: var(--ui-action-shadow, var(--_ui-action-shadow)), var(--_tone-glow);
330
397
  }
331
398
 
332
- :host([variant="solid"]) {
399
+ :host[data-appearance="solid"] {
333
400
  background-color: var(--ui-icon-button-solid-surface, var(--_icon-button-solid-surface, var(--ui-accent-solid)));
334
- background-image: none;
401
+ background-image: var(--_tone-highlight);
335
402
  color: var(--ui-icon-button-solid-text, var(--_icon-button-solid-text, var(--ui-text-on-accent)));
336
- box-shadow: var(--ui-icon-button-solid-shadow, var(--ui-action-shadow, var(--_ui-action-shadow)));
403
+ box-shadow: var(--ui-icon-button-solid-shadow, var(--ui-action-shadow, var(--_ui-action-shadow))), var(--_tone-glow);
337
404
  }
338
405
 
339
406
  :host:hover:enabled:not([aria-disabled="true"]) {
@@ -342,27 +409,26 @@
342
409
  color: var(--ui-icon-button-hover-text, var(--_icon-button-text, var(--ui-text-primary)));
343
410
  }
344
411
 
345
- :host([variant="outline"]):hover:enabled:not([aria-disabled="true"]) {
412
+ :host[data-appearance="outline"]:hover:enabled:not([aria-disabled="true"]) {
346
413
  border-color: var(--ui-icon-button-hover-border, var(--_icon-button-hover-border, var(--ui-control-border-hover, var(--ui-control-border))));
347
414
  }
348
415
 
349
- :host([variant="solid"]):hover:enabled:not([aria-disabled="true"]) {
416
+ :host[data-appearance="solid"]:hover:enabled:not([aria-disabled="true"]) {
350
417
  background-color: var(--ui-icon-button-solid-hover-surface, var(--_icon-button-solid-hover-surface, var(--ui-accent-hover)));
351
418
  }
352
419
 
353
- :host([variant="solid"][tone="accent"]):hover:enabled:not([aria-disabled="true"]),
354
- :host([variant="solid"][tone="neutral"]):hover:enabled:not([aria-disabled="true"]) {
420
+ :host[data-appearance="solid"]:hover:enabled:not([aria-disabled="true"]) {
355
421
  color: var(--ui-icon-button-solid-text, var(--_icon-button-solid-text, var(--ui-text-on-accent)));
356
422
  }
357
423
 
358
- :host([variant="ghost"])[aria-expanded="true"]:enabled:not([aria-disabled="true"]) {
424
+ :host[data-appearance="ghost"][aria-expanded="true"]:enabled:not([aria-disabled="true"]) {
359
425
  background-color: var(--ui-icon-button-active-surface, color-mix(in srgb, currentColor 16%, transparent));
360
426
  color: var(--ui-icon-button-hover-text, var(--_icon-button-text, var(--ui-text-primary)));
361
427
  box-shadow: var(--ui-pressed);
362
428
  }
363
429
 
364
430
  /* Native toggle state persists after pointer release, including during loading. */
365
- :host([variant="outline"])[aria-pressed="true"]:enabled {
431
+ :host[data-appearance="outline"][aria-pressed="true"]:enabled {
366
432
  background-color: var(--ui-icon-button-active-surface, color-mix(in srgb, currentColor 12%, var(--ui-surface-default)));
367
433
  background-image: none;
368
434
  box-shadow: var(--ui-pressed);
@@ -397,35 +463,35 @@
397
463
  box-shadow: var(--ui-focus-halo);
398
464
  }
399
465
 
400
- :host([variant="outline"]):focus-visible {
466
+ :host[data-appearance="outline"]:focus-visible {
401
467
  box-shadow:
402
468
  var(--ui-action-shadow, var(--_ui-action-shadow)),
403
469
  var(--ui-focus-halo);
404
470
  }
405
471
 
406
- :host([variant="solid"]):focus-visible {
472
+ :host[data-appearance="solid"]:focus-visible {
407
473
  box-shadow:
408
474
  var(--ui-icon-button-solid-shadow, var(--ui-action-shadow, var(--_ui-action-shadow))),
409
475
  var(--ui-focus-halo);
410
476
  }
411
477
 
412
- :host:is(:host([variant="outline"]), :host([variant="solid"])):active:enabled:not([aria-disabled="true"]) {
478
+ :host:is(:host[data-appearance="outline"], :host[data-appearance="solid"]):active:enabled:not([aria-disabled="true"]) {
413
479
  background-image: none;
414
480
  box-shadow: var(--ui-pressed);
415
481
  }
416
482
 
417
- :host([variant="outline"])[aria-pressed="true"]:enabled:focus-visible {
483
+ :host[data-appearance="outline"][aria-pressed="true"]:enabled:focus-visible {
418
484
  box-shadow:
419
485
  var(--ui-pressed),
420
486
  var(--ui-focus-halo);
421
487
  }
422
488
 
423
489
  @media (forced-colors: active) {
424
- :host([variant="outline"])[aria-pressed="true"]:enabled {
490
+ :host[data-appearance="outline"][aria-pressed="true"]:enabled {
425
491
  outline: var(--ui-focus-width) solid Highlight;
426
492
  outline-offset: calc(-2 * var(--ui-focus-width));
427
493
  }
428
- :host([variant="outline"])[aria-pressed="true"]:enabled:focus-visible {
494
+ :host[data-appearance="outline"][aria-pressed="true"]:enabled:focus-visible {
429
495
  outline-offset: var(--ui-focus-width);
430
496
  }
431
497
  }
@@ -442,7 +508,7 @@
442
508
  background-image: none;
443
509
  }
444
510
 
445
- :host([variant="ghost"]):disabled {
511
+ :host[data-appearance="ghost"]:disabled {
446
512
  border-color: transparent;
447
513
  }
448
514
 
@@ -108,7 +108,8 @@
108
108
  border: var(--ui-input-border-width, var(--_ui-default-input-border-width, var(--ui-border-width))) solid
109
109
  var(--ui-input-border, var(--_ui-default-input-border, var(--ui-control-border, var(--ui-border-strong))));
110
110
  border-radius: var(--ui-input-radius, var(--_ui-default-input-radius, var(--ui-field-radius, var(--ui-radius-md))));
111
- background: var(--ui-input-surface, var(--_ui-default-input-surface, var(--ui-control-surface, var(--ui-surface-elevated))));
111
+ background-color: var(--ui-input-surface, var(--_ui-default-input-surface, var(--ui-control-surface, var(--ui-surface-elevated))));
112
+ background-image: var(--_ui-default-input-highlight, var(--ui-surface-highlight, none));
112
113
  color: var(--ui-text-primary);
113
114
  font: inherit;
114
115
  line-height: var(--ui-line-height-tight);
@@ -53,6 +53,7 @@
53
53
  --_ui-default-input-focus-outline: none;
54
54
  --_ui-default-input-radius: 0;
55
55
  --_ui-default-input-surface: transparent;
56
+ --_ui-default-input-highlight: none;
56
57
  --_ui-default-textarea-border-width: 0;
57
58
  --_ui-default-textarea-border: transparent;
58
59
  --_ui-default-textarea-border-hover: transparent;
@@ -64,6 +65,7 @@
64
65
  --_ui-default-textarea-focus-outline: none;
65
66
  --_ui-default-textarea-radius: 0;
66
67
  --_ui-default-textarea-surface: transparent;
68
+ --_ui-default-textarea-highlight: none;
67
69
 
68
70
  display: flex !important;
69
71
  align-items: stretch !important;
@@ -74,7 +76,8 @@
74
76
  /* The frame reads the shared control tokens with a lone Input's fallbacks, so the two match. */
75
77
  border: var(--ui-border-width) solid var(--ui-control-border, var(--ui-border-strong));
76
78
  border-radius: var(--ui-input-group-radius, var(--ui-field-radius, var(--ui-radius-md)));
77
- background: var(--ui-control-surface, var(--ui-surface-elevated));
79
+ background-color: var(--ui-control-surface, var(--ui-surface-elevated));
80
+ background-image: var(--ui-surface-highlight, none);
78
81
  box-shadow: var(--ui-control-inset);
79
82
  overflow: hidden;
80
83
  /* A press anywhere in the frame focuses the input. */