@threadlabs/looma 0.7.2 → 0.7.4

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.
@@ -1,24 +1,27 @@
1
1
  import { t as _plugin_vue_export_helper_default } from "./_plugin-vue_export-helper.js";
2
- import { computed, createElementBlock, defineComponent, mergeProps, openBlock, renderSlot } from "vue";
3
- //#region .build/vue/UiButton.vue?vue&type=script&setup=true&lang.ts
4
- var _hoisted_1 = ["disabled", "data-ui-button-state"];
2
+ import { computed, createBlock, defineComponent, mergeProps, openBlock, renderSlot, resolveDynamicComponent, withCtx } from "vue";
5
3
  //#endregion
6
4
  //#region .build/vue/UiButton.vue
7
5
  var UiButton_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
8
6
  inheritAttrs: false,
9
7
  __name: "UiButton",
10
8
  props: {
9
+ as: { default: "button" },
11
10
  align: { default: "center" },
12
11
  disabled: {
13
12
  type: Boolean,
14
13
  default: false
15
14
  },
15
+ href: {},
16
+ rel: {},
16
17
  size: { default: "md" },
17
18
  stretch: {
18
19
  type: Boolean,
19
20
  default: false
20
21
  },
22
+ target: {},
21
23
  tone: { default: "accent" },
24
+ type: { default: "button" },
22
25
  variant: { default: "outline" }
23
26
  },
24
27
  setup(__props) {
@@ -31,16 +34,55 @@ var UiButton_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PUR
31
34
  props.variant && `variant variant=${props.variant}`,
32
35
  props.tone && `tone tone=${props.tone}`
33
36
  ].filter(Boolean).join(" "));
37
+ function text(value) {
38
+ if (Array.isArray(value)) return value.map(text).join(" ");
39
+ return value === null || value === void 0 || typeof value === "object" ? "" : String(value);
40
+ }
41
+ function attribute(value) {
42
+ if (value === null || value === void 0 || value === false || typeof value === "object" && !Array.isArray(value)) return void 0;
43
+ return value === true ? "" : text(value);
44
+ }
34
45
  return (_ctx, _cache) => {
35
- return openBlock(), createElementBlock("button", mergeProps({
36
- "data-component": "ui-button",
37
- type: "button"
38
- }, _ctx.$attrs, {
39
- disabled: __props.disabled,
46
+ return openBlock(), createBlock(resolveDynamicComponent(__props.as), mergeProps({ "data-component": "ui-button" }, _ctx.$attrs, {
47
+ type: attribute({
48
+ true: __props.type,
49
+ false: null
50
+ }[`${!__props.href}`]),
51
+ disabled: attribute({
52
+ true: true,
53
+ false: null
54
+ }[`${__props.disabled && !__props.href}`]),
55
+ href: attribute({
56
+ true: null,
57
+ false: __props.href
58
+ }[`${__props.disabled}`]),
59
+ target: __props.target,
60
+ rel: __props.rel,
61
+ "aria-disabled": typeof {
62
+ true: "true",
63
+ false: null
64
+ }[`${Boolean(__props.disabled && __props.href)}`] === "boolean" ? String({
65
+ true: "true",
66
+ false: null
67
+ }[`${Boolean(__props.disabled && __props.href)}`]) : attribute({
68
+ true: "true",
69
+ false: null
70
+ }[`${Boolean(__props.disabled && __props.href)}`]),
40
71
  "data-ui-button-state": hostState.value || void 0
41
- }), [renderSlot(_ctx.$slots, "default", {}, void 0, true)], 16, _hoisted_1);
72
+ }), {
73
+ default: withCtx(() => [renderSlot(_ctx.$slots, "default", {}, void 0, true)]),
74
+ _: 3
75
+ }, 16, [
76
+ "type",
77
+ "disabled",
78
+ "href",
79
+ "target",
80
+ "rel",
81
+ "aria-disabled",
82
+ "data-ui-button-state"
83
+ ]);
42
84
  };
43
85
  }
44
- }), [["__scopeId", "data-v-8513eb5d"]]);
86
+ }), [["__scopeId", "data-v-852dd10e"]]);
45
87
  //#endregion
46
88
  export { UiButton_default as t };
@@ -113,7 +113,7 @@
113
113
  display: none;
114
114
  }
115
115
 
116
- [data-component~="ui-badge"][data-v-90c7d1bb] {
116
+ [data-component~="ui-badge"][data-v-c0ffc4d8] {
117
117
  --_badge-surface: var(--ui-surface-subtle);
118
118
  --_badge-text: var(--ui-text-secondary);
119
119
  --_badge-border: color-mix(in srgb, var(--ui-text-secondary) 30%, transparent);
@@ -139,7 +139,7 @@
139
139
  /* Centre the glyphs, not the line box: a label without descenders otherwise reads high.
140
140
  * Trimming applies to block containers, so the box is a block with centred content. */
141
141
  @supports (text-box-trim: trim-both) {
142
- [data-component~="ui-badge"][data-v-90c7d1bb] {
142
+ [data-component~="ui-badge"][data-v-c0ffc4d8] {
143
143
  display: block;
144
144
  min-block-size: var(--ui-badge-min-block-size, 1.5rem);
145
145
  text-align: center;
@@ -148,63 +148,88 @@
148
148
  text-box-edge: cap alphabetic;
149
149
  }
150
150
  }
151
- [data-component~="ui-badge"][data-ui-badge-state~="tone=accent"][data-v-90c7d1bb] {
151
+ [data-component~="ui-badge"][data-ui-badge-state~="tone=accent"][data-v-c0ffc4d8] {
152
152
  --_badge-surface: var(--ui-accent-strong-surface, var(--ui-accent-solid));
153
153
  --_badge-border: var(--ui-accent-strong-surface, var(--ui-accent-solid));
154
154
  --_badge-text: var(--ui-accent-on-strong, var(--ui-text-on-accent));
155
155
  }
156
- [data-component~="ui-badge"][data-ui-badge-state~="tone=danger"][data-v-90c7d1bb] {
156
+ [data-component~="ui-badge"][data-ui-badge-state~="tone=danger"][data-v-c0ffc4d8] {
157
157
  --_badge-surface: var(--ui-danger-strong-surface, var(--ui-danger-solid));
158
158
  --_badge-border: var(--ui-danger-strong-surface, var(--ui-danger-solid));
159
159
  --_badge-text: var(--ui-danger-on-strong, var(--ui-text-on-accent));
160
160
  }
161
- [data-component~="ui-badge"][data-ui-badge-state~="tone=success"][data-v-90c7d1bb] {
161
+ [data-component~="ui-badge"][data-ui-badge-state~="tone=success"][data-v-c0ffc4d8] {
162
162
  --_badge-surface: var(--ui-success-strong-surface, var(--ui-success-solid));
163
163
  --_badge-border: var(--ui-success-strong-surface, var(--ui-success-solid));
164
164
  --_badge-text: var(--ui-success-on-strong, var(--ui-text-on-accent));
165
165
  }
166
- [data-component~="ui-badge"][data-ui-badge-state~="tone=warning"][data-v-90c7d1bb] {
166
+ [data-component~="ui-badge"][data-ui-badge-state~="tone=warning"][data-v-c0ffc4d8] {
167
167
  --_badge-surface: var(--ui-warning-strong-surface, var(--ui-warning-solid));
168
168
  --_badge-border: var(--ui-warning-strong-surface, var(--ui-warning-solid));
169
169
  --_badge-text: var(--ui-warning-on-strong, var(--ui-text-on-accent));
170
170
  }
171
- [data-component~="ui-badge"][data-ui-badge-state~="tone=info"][data-v-90c7d1bb] {
171
+ [data-component~="ui-badge"][data-ui-badge-state~="tone=info"][data-v-c0ffc4d8] {
172
172
  --_badge-surface: var(--ui-info-strong-surface, var(--ui-info-solid));
173
173
  --_badge-border: var(--ui-info-strong-surface, var(--ui-info-solid));
174
174
  --_badge-text: var(--ui-info-on-strong, var(--ui-text-on-accent));
175
175
  }
176
- [data-component~="ui-badge"][data-ui-badge-state~="variant=subtle"][data-ui-badge-state~="tone=accent"][data-v-90c7d1bb] {
176
+ [data-component~="ui-badge"][data-ui-badge-state~="variant=subtle"][data-ui-badge-state~="tone=accent"][data-v-c0ffc4d8] {
177
177
  --_badge-surface: var(--ui-accent-soft);
178
178
  --_badge-border: var(--ui-accent-soft);
179
179
  --_badge-text: var(--ui-accent-subtle-text, var(--ui-accent-solid));
180
180
  }
181
- [data-component~="ui-badge"][data-ui-badge-state~="variant=subtle"][data-ui-badge-state~="tone=danger"][data-v-90c7d1bb] {
181
+ [data-component~="ui-badge"][data-ui-badge-state~="variant=subtle"][data-ui-badge-state~="tone=danger"][data-v-c0ffc4d8] {
182
182
  --_badge-surface: var(--ui-danger-soft);
183
183
  --_badge-border: var(--ui-danger-soft);
184
184
  --_badge-text: var(--ui-danger-subtle-text, var(--ui-danger-solid));
185
185
  }
186
- [data-component~="ui-badge"][data-ui-badge-state~="variant=subtle"][data-ui-badge-state~="tone=success"][data-v-90c7d1bb] {
186
+ [data-component~="ui-badge"][data-ui-badge-state~="variant=subtle"][data-ui-badge-state~="tone=success"][data-v-c0ffc4d8] {
187
187
  --_badge-surface: var(--ui-success-soft);
188
188
  --_badge-border: var(--ui-success-soft);
189
189
  --_badge-text: var(--ui-success-subtle-text, var(--ui-success-solid));
190
190
  }
191
- [data-component~="ui-badge"][data-ui-badge-state~="variant=subtle"][data-ui-badge-state~="tone=warning"][data-v-90c7d1bb] {
191
+ [data-component~="ui-badge"][data-ui-badge-state~="variant=subtle"][data-ui-badge-state~="tone=warning"][data-v-c0ffc4d8] {
192
192
  --_badge-surface: var(--ui-warning-soft);
193
193
  --_badge-border: var(--ui-warning-soft);
194
194
  --_badge-text: var(--ui-warning-subtle-text, var(--ui-warning-solid));
195
195
  }
196
- [data-component~="ui-badge"][data-ui-badge-state~="variant=subtle"][data-ui-badge-state~="tone=info"][data-v-90c7d1bb] {
196
+ [data-component~="ui-badge"][data-ui-badge-state~="variant=subtle"][data-ui-badge-state~="tone=info"][data-v-c0ffc4d8] {
197
197
  --_badge-surface: var(--ui-info-soft);
198
198
  --_badge-border: var(--ui-info-soft);
199
199
  --_badge-text: var(--ui-info-subtle-text, var(--ui-info-solid));
200
200
  }
201
201
 
202
+ /* A tag is flat at the start and points at the end. The point is cut from the box, so it has no
203
+ outline to follow: the edge is the fill. The end padding grows by the point's depth so the
204
+ label never runs into it. */
205
+ [data-component~="ui-badge"][data-ui-badge-state~="shape=tag"][data-v-c0ffc4d8] {
206
+ --_badge-point: var(--ui-badge-point, var(--ui-space-2));
207
+
208
+ border-color: transparent;
209
+ border-radius: 0;
210
+ padding-inline-end: calc(var(--ui-badge-padding-inline, var(--ui-space-2)) + var(--_badge-point));
211
+ clip-path: polygon(
212
+ 0 0,
213
+ calc(100% - var(--_badge-point)) 0,
214
+ 100% 50%,
215
+ calc(100% - var(--_badge-point)) 100%,
216
+ 0 100%
217
+ );
218
+ }
219
+ [data-component~="ui-badge"][data-ui-badge-state~="shape=tag"][data-v-c0ffc4d8]:dir(rtl) {
220
+ padding-inline-end: var(--ui-badge-padding-inline, var(--ui-space-2));
221
+ padding-inline-start: calc(
222
+ var(--ui-badge-padding-inline, var(--ui-space-2)) + var(--_badge-point)
223
+ );
224
+ clip-path: polygon(var(--_badge-point) 0, 100% 0, 100% 100%, var(--_badge-point) 100%, 0 50%);
225
+ }
226
+
202
227
  /* A component that sets its display still honours the hidden attribute on its root. */
203
- [data-component~="ui-badge"][hidden][data-v-90c7d1bb] {
228
+ [data-component~="ui-badge"][hidden][data-v-c0ffc4d8] {
204
229
  display: none;
205
230
  }
206
231
 
207
- [data-component~="ui-button"][data-v-8513eb5d] {
232
+ [data-component~="ui-button"][data-v-852dd10e] {
208
233
  --_hue: var(--ui-accent);
209
234
  --_hue-hover: var(--ui-accent-hover);
210
235
  --_hue-active: var(--ui-accent-active);
@@ -223,15 +248,15 @@
223
248
  vertical-align: middle;
224
249
  color: var(--_tone-text);
225
250
  }
226
- [data-component~="ui-button"][data-ui-button-state~="align=start"][data-v-8513eb5d] {
251
+ [data-component~="ui-button"][data-ui-button-state~="align=start"][data-v-852dd10e] {
227
252
  justify-content: flex-start;
228
253
  text-align: start;
229
254
  }
230
- [data-component~="ui-button"][data-ui-button-state~="stretch"][data-v-8513eb5d] {
255
+ [data-component~="ui-button"][data-ui-button-state~="stretch"][data-v-852dd10e] {
231
256
  display: flex;
232
257
  inline-size: 100%;
233
258
  }
234
- [data-component~="ui-button"][data-v-8513eb5d] {
259
+ [data-component~="ui-button"][data-v-852dd10e] {
235
260
  appearance: none;
236
261
  min-block-size: var(--ui-button-min-block-size, var(--ui-control-size-md));
237
262
  border-style: solid;
@@ -242,6 +267,7 @@
242
267
  color: var(--ui-button-text, var(--_tone-text));
243
268
  font: inherit;
244
269
  font-weight: var(--ui-font-medium);
270
+ text-decoration: none;
245
271
  line-height: var(--ui-line-height-tight);
246
272
  padding: var(--ui-space-2) var(--ui-space-3);
247
273
  background-image: var(--ui-raised-highlight);
@@ -255,44 +281,47 @@
255
281
  margin: 0;
256
282
  }
257
283
  @supports (text-box-trim: trim-both) {
258
- [data-component~="ui-button"][data-v-8513eb5d] {
284
+ [data-component~="ui-button"][data-v-852dd10e] {
259
285
  text-box-trim: trim-both;
260
286
  text-box-edge: cap alphabetic;
261
287
  }
262
288
  }
263
- [data-component~="ui-button"][data-ui-button-state~="size=sm"][data-v-8513eb5d] {
289
+ [data-component~="ui-button"][data-ui-button-state~="size=sm"][data-v-852dd10e] {
264
290
  min-block-size: var(--ui-control-size-sm);
265
291
  padding: var(--ui-space-1) var(--ui-space-2);
266
292
  font-size: 0.875rem;
267
293
  }
268
- [data-component~="ui-button"][data-ui-button-state~="size=lg"][data-v-8513eb5d] {
294
+ [data-component~="ui-button"][data-ui-button-state~="size=lg"][data-v-852dd10e] {
269
295
  min-block-size: var(--ui-control-size-lg);
270
296
  padding: var(--ui-space-3) var(--ui-space-4);
271
297
  font-size: 1rem;
272
298
  }
273
- [data-component~="ui-button"][data-v-8513eb5d]:hover:enabled {
299
+
300
+ /* A link is never :enabled, so interactive states test "not unavailable" instead: for a button that
301
+ is exactly :enabled, at the same specificity, and it also matches a link that can be followed. */
302
+ [data-component~="ui-button"][data-v-852dd10e]:hover:not(:disabled, [aria-disabled="true"]) {
274
303
  border-color: var(--ui-button-hover-border, var(--_tone-hover));
275
304
  background-color: var(--ui-button-hover-surface, oklch(from var(--_tone) l c h / 12%));
276
305
  }
277
306
 
278
307
  /* Pressed reads as pressed in: the highlight goes, and the shadow moves inside. */
279
- [data-component~="ui-button"][data-v-8513eb5d]:active:enabled {
308
+ [data-component~="ui-button"][data-v-852dd10e]:active:not(:disabled, [aria-disabled="true"]) {
280
309
  background-color: var(--ui-button-active-surface, oklch(from var(--_tone) l c h / 18%));
281
310
  background-image: none;
282
311
  box-shadow: var(--ui-pressed);
283
312
  }
284
- [data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-8513eb5d],
285
- [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-8513eb5d] {
313
+ [data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-852dd10e],
314
+ [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-852dd10e] {
286
315
  border-color: var(--_tone);
287
316
  background-color: var(--_tone);
288
317
  color: var(--_on-tone);
289
318
  box-shadow: var(--ui-button-solid-shadow, var(--ui-raised));
290
319
  }
291
- :is([data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-8513eb5d], [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-8513eb5d]):hover:enabled {
320
+ :is([data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-852dd10e], [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-852dd10e]):hover:not(:disabled, [aria-disabled="true"]) {
292
321
  background-color: var(--_tone-hover);
293
322
  border-color: var(--_tone-hover);
294
323
  }
295
- :is([data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-8513eb5d], [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-8513eb5d]):active:enabled {
324
+ :is([data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-852dd10e], [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-852dd10e]):active:not(:disabled, [aria-disabled="true"]) {
296
325
  background-color: var(--_tone-active);
297
326
  border-color: var(--_tone-active);
298
327
  background-image: none;
@@ -301,43 +330,43 @@
301
330
 
302
331
  /* Tone is the colour, variant is the volume. Every pairing works: a danger outline is a
303
332
  destructive secondary action, not a special case. */
304
- [data-component~="ui-button"][data-ui-button-state~="tone=neutral"][data-v-8513eb5d] {
333
+ [data-component~="ui-button"][data-ui-button-state~="tone=neutral"][data-v-852dd10e] {
305
334
  --_hue: var(--ui-text);
306
335
  --_hue-hover: var(--ui-text);
307
336
  --_hue-active: var(--ui-text);
308
337
  --_hue-text: var(--ui-text);
309
338
  --_on-hue: var(--ui-surface);
310
339
  }
311
- [data-component~="ui-button"][data-ui-button-state~="tone=danger"][data-v-8513eb5d],
312
- [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-8513eb5d] {
340
+ [data-component~="ui-button"][data-ui-button-state~="tone=danger"][data-v-852dd10e],
341
+ [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-852dd10e] {
313
342
  --_hue: var(--ui-danger);
314
343
  --_hue-hover: var(--ui-danger-hover);
315
344
  --_hue-active: var(--ui-danger-hover);
316
345
  --_hue-text: var(--ui-danger-hover);
317
346
  --_on-hue: var(--ui-on-danger);
318
347
  }
319
- [data-component~="ui-button"][data-ui-button-state~="tone=success"][data-v-8513eb5d] {
348
+ [data-component~="ui-button"][data-ui-button-state~="tone=success"][data-v-852dd10e] {
320
349
  --_hue: var(--ui-success);
321
350
  --_hue-hover: color-mix(in srgb, var(--ui-success) 85%, #000);
322
351
  --_hue-active: color-mix(in srgb, var(--ui-success) 75%, #000);
323
352
  --_hue-text: color-mix(in srgb, var(--ui-success) 85%, #000);
324
353
  --_on-hue: var(--ui-surface);
325
354
  }
326
- [data-component~="ui-button"][data-ui-button-state~="tone=warning"][data-v-8513eb5d] {
355
+ [data-component~="ui-button"][data-ui-button-state~="tone=warning"][data-v-852dd10e] {
327
356
  --_hue: var(--ui-warning);
328
357
  --_hue-hover: color-mix(in srgb, var(--ui-warning) 85%, #000);
329
358
  --_hue-active: color-mix(in srgb, var(--ui-warning) 75%, #000);
330
359
  --_hue-text: color-mix(in srgb, var(--ui-warning) 85%, #000);
331
360
  --_on-hue: var(--ui-surface);
332
361
  }
333
- [data-component~="ui-button"][data-ui-button-state~="tone=info"][data-v-8513eb5d] {
362
+ [data-component~="ui-button"][data-ui-button-state~="tone=info"][data-v-852dd10e] {
334
363
  --_hue: var(--ui-info);
335
364
  --_hue-hover: color-mix(in srgb, var(--ui-info) 85%, #000);
336
365
  --_hue-active: color-mix(in srgb, var(--ui-info) 75%, #000);
337
366
  --_hue-text: color-mix(in srgb, var(--ui-info) 85%, #000);
338
367
  --_on-hue: var(--ui-surface);
339
368
  }
340
- [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-8513eb5d] {
369
+ [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-852dd10e] {
341
370
  border-color: transparent;
342
371
  background: transparent;
343
372
  box-shadow: none;
@@ -345,34 +374,34 @@
345
374
  }
346
375
 
347
376
  /* Tints derive from the text colour, not a surface token, so hover and press show on any background. */
348
- [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-8513eb5d]:hover:enabled {
377
+ [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-852dd10e]:hover:not(:disabled, [aria-disabled="true"]) {
349
378
  background-color: var(--ui-button-ghost-hover-surface, oklch(from var(--_tone) l c h / 10%));
350
379
  border-color: transparent;
351
380
  }
352
- [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-8513eb5d]:active:enabled {
381
+ [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-852dd10e]:active:not(:disabled, [aria-disabled="true"]) {
353
382
  background-color: var(--ui-button-ghost-active-surface, oklch(from var(--_tone) l c h / 16%));
354
383
  border-color: transparent;
355
384
  box-shadow: var(--ui-pressed);
356
385
  }
357
386
 
358
387
  /* A soft halo that transitions in with the other box-shadow changes, layered on the raised shadow. */
359
- [data-component~="ui-button"][data-v-8513eb5d]:focus-visible {
388
+ [data-component~="ui-button"][data-v-852dd10e]:focus-visible {
360
389
  outline: none;
361
390
  box-shadow:
362
391
  var(--ui-button-shadow, var(--ui-raised)),
363
392
  var(--ui-focus-halo);
364
393
  }
365
- [data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-8513eb5d]:focus-visible {
394
+ [data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-852dd10e]:focus-visible {
366
395
  box-shadow:
367
396
  var(--ui-button-solid-shadow, var(--ui-raised)),
368
397
  var(--ui-focus-halo);
369
398
  }
370
399
 
371
400
  /* Disabled drops the tone rather than the shape: every variant keeps its own structure, so a
372
- disabled outline is still an outline and a disabled ghost is still text. Intent goes — an
401
+ disabled outline is still an outline and a disabled ghost still has no edge. Intent goes — an
373
402
  unavailable action says "unavailable", not "unavailable, and destructive" — and so do the
374
403
  highlight and shadow, because nothing that cannot be pressed should look raised. */
375
- [data-component~="ui-button"][data-v-8513eb5d]:disabled {
404
+ [data-component~="ui-button"][data-v-852dd10e]:is(:disabled, [aria-disabled="true"]) {
376
405
  /* Derived from the tone itself, not from a separate disabled palette: faded toward the
377
406
  page, which desaturates it at the same time. Toward the page rather than toward white,
378
407
  so a dark theme dims where a light one lightens — the same rule, both schemes. */
@@ -389,25 +418,27 @@
389
418
  }
390
419
 
391
420
  /* A filled button keeps its fill, faded further so its text stays legible on it. */
392
- :is([data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-8513eb5d], [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-8513eb5d]):disabled {
421
+ :is([data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-852dd10e], [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-852dd10e]):is(:disabled, [aria-disabled="true"]) {
393
422
  --_tone: color-mix(in oklab, var(--_hue) 34%, var(--ui-surface));
394
423
  }
395
424
 
396
425
  /* Ghost has no hover to fall back on, so disabled is the one state it has to state outright:
397
- it takes a surface, light and tinted, rather than reading as plain text. */
398
- [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-8513eb5d]:disabled {
399
- background-color: color-mix(in oklab, var(--_hue) 28%, var(--ui-surface));
426
+ it takes a surface rather than reading as plain text. The surface is a wash of the faded tone,
427
+ the way hover washes the live one, so it stays light in every tone. An opaque mix toward the
428
+ hue came out a mid-grey slab for neutral, whose hue is the ink: louder than the enabled button. */
429
+ [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-852dd10e]:is(:disabled, [aria-disabled="true"]) {
430
+ background-color: oklch(from var(--_tone) l c h / 14%);
400
431
  border-color: transparent;
401
432
  }
402
433
  @media (pointer: coarse) {
403
- [data-component~="ui-button"][data-v-8513eb5d] {
434
+ [data-component~="ui-button"][data-v-852dd10e] {
404
435
  min-block-size: var(--ui-control-min-block-size);
405
436
  }
406
437
  }
407
438
 
408
439
  /* Link: an inline text action. No box, padding, or minimum height (inline targets are exempt under
409
440
  WCAG 2.5.8); the inherited font; an underline that strengthens on hover; a visible focus ring. */
410
- [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-8513eb5d] {
441
+ [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-852dd10e] {
411
442
  display: inline;
412
443
  min-block-size: 0;
413
444
  padding: 0;
@@ -425,22 +456,22 @@
425
456
  color var(--ui-motion-fast) var(--ui-motion-ease),
426
457
  text-decoration-color var(--ui-motion-fast) var(--ui-motion-ease);
427
458
  }
428
- [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-8513eb5d]:hover:enabled {
459
+ [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-852dd10e]:hover:not(:disabled, [aria-disabled="true"]) {
429
460
  color: var(--ui-button-link-hover-text, var(--ui-text-primary));
430
461
  text-decoration-color: currentColor;
431
462
  background: none;
432
463
  transform: none;
433
464
  }
434
- [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-8513eb5d]:active:enabled {
465
+ [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-852dd10e]:active:not(:disabled, [aria-disabled="true"]) {
435
466
  background: none;
436
467
  transform: none;
437
468
  }
438
- [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-8513eb5d]:disabled {
469
+ [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-852dd10e]:is(:disabled, [aria-disabled="true"]) {
439
470
  background: none;
440
471
  border-color: transparent;
441
472
  color: var(--ui-button-disabled-text, var(--ui-disabled-text));
442
473
  }
443
- [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-8513eb5d]:focus-visible {
474
+ [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-852dd10e]:focus-visible {
444
475
  box-shadow: none;
445
476
  /* Fallback keeps the ring if the token is missing: an unresolved var() would void the outline. */
446
477
  outline: 2px solid var(--ui-focus-ring);
@@ -448,7 +479,7 @@
448
479
  }
449
480
 
450
481
  /* A component that sets its display still honours the hidden attribute on its root. */
451
- [data-component~="ui-button"][hidden][data-v-8513eb5d] {
482
+ [data-component~="ui-button"][hidden][data-v-852dd10e] {
452
483
  display: none;
453
484
  }
454
485