@threadlabs/looma 0.7.2 → 0.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@threadlabs/looma",
3
- "version": "0.7.2",
3
+ "version": "0.7.3",
4
4
  "type": "module",
5
5
  "description": "Looma components as HTML, Vue, and plain DOM, with design tokens.",
6
6
  "license": "MIT",
@@ -180,7 +180,7 @@
180
180
  }
181
181
 
182
182
  /* Disabled drops the tone rather than the shape: every variant keeps its own structure, so a
183
- disabled outline is still an outline and a disabled ghost is still text. Intent goes — an
183
+ disabled outline is still an outline and a disabled ghost still has no edge. Intent goes — an
184
184
  unavailable action says "unavailable", not "unavailable, and destructive" — and so do the
185
185
  highlight and shadow, because nothing that cannot be pressed should look raised. */
186
186
  :scope:disabled {
@@ -205,9 +205,11 @@
205
205
  }
206
206
 
207
207
  /* Ghost has no hover to fall back on, so disabled is the one state it has to state outright:
208
- it takes a surface, light and tinted, rather than reading as plain text. */
208
+ it takes a surface rather than reading as plain text. The surface is a wash of the faded tone,
209
+ the way hover washes the live one, so it stays light in every tone. An opaque mix toward the
210
+ hue came out a mid-grey slab for neutral, whose hue is the ink: louder than the enabled button. */
209
211
  :scope[data-ui-button-state~="variant=ghost"]:disabled {
210
- background-color: color-mix(in oklab, var(--_hue) 28%, var(--ui-surface));
212
+ background-color: oklch(from var(--_tone) l c h / 14%);
211
213
  border-color: transparent;
212
214
  }
213
215
 
@@ -280,14 +282,16 @@
280
282
  /* A soft halo that transitions in with the other box-shadow changes, layered on the raised shadow. */
281
283
 
282
284
  /* Disabled drops the tone rather than the shape: every variant keeps its own structure, so a
283
- disabled outline is still an outline and a disabled ghost is still text. Intent goes — an
285
+ disabled outline is still an outline and a disabled ghost still has no edge. Intent goes — an
284
286
  unavailable action says "unavailable", not "unavailable, and destructive" — and so do the
285
287
  highlight and shadow, because nothing that cannot be pressed should look raised. */
286
288
 
287
289
  /* A filled button keeps its fill, faded further so its text stays legible on it. */
288
290
 
289
291
  /* Ghost has no hover to fall back on, so disabled is the one state it has to state outright:
290
- it takes a surface, light and tinted, rather than reading as plain text. */
292
+ it takes a surface rather than reading as plain text. The surface is a wash of the faded tone,
293
+ the way hover washes the live one, so it stays light in every tone. An opaque mix toward the
294
+ hue came out a mid-grey slab for neutral, whose hue is the ink: louder than the enabled button. */
291
295
 
292
296
  @media (pointer: coarse) {
293
297
  }
package/vue/UiButton.vue CHANGED
@@ -230,7 +230,7 @@ const hostState = computed(() =>
230
230
  }
231
231
 
232
232
  /* Disabled drops the tone rather than the shape: every variant keeps its own structure, so a
233
- disabled outline is still an outline and a disabled ghost is still text. Intent goes — an
233
+ disabled outline is still an outline and a disabled ghost still has no edge. Intent goes — an
234
234
  unavailable action says "unavailable", not "unavailable, and destructive" — and so do the
235
235
  highlight and shadow, because nothing that cannot be pressed should look raised. */
236
236
  [data-component~="ui-button"]:disabled {
@@ -255,9 +255,11 @@ const hostState = computed(() =>
255
255
  }
256
256
 
257
257
  /* Ghost has no hover to fall back on, so disabled is the one state it has to state outright:
258
- it takes a surface, light and tinted, rather than reading as plain text. */
258
+ it takes a surface rather than reading as plain text. The surface is a wash of the faded tone,
259
+ the way hover washes the live one, so it stays light in every tone. An opaque mix toward the
260
+ hue came out a mid-grey slab for neutral, whose hue is the ink: louder than the enabled button. */
259
261
  [data-component~="ui-button"][data-ui-button-state~="variant=ghost"]:disabled {
260
- background-color: color-mix(in oklab, var(--_hue) 28%, var(--ui-surface));
262
+ background-color: oklch(from var(--_tone) l c h / 14%);
261
263
  border-color: transparent;
262
264
  }
263
265
 
@@ -41,6 +41,6 @@ var UiButton_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PUR
41
41
  }), [renderSlot(_ctx.$slots, "default", {}, void 0, true)], 16, _hoisted_1);
42
42
  };
43
43
  }
44
- }), [["__scopeId", "data-v-8513eb5d"]]);
44
+ }), [["__scopeId", "data-v-c6ef4679"]]);
45
45
  //#endregion
46
46
  export { UiButton_default as t };
@@ -204,7 +204,7 @@
204
204
  display: none;
205
205
  }
206
206
 
207
- [data-component~="ui-button"][data-v-8513eb5d] {
207
+ [data-component~="ui-button"][data-v-c6ef4679] {
208
208
  --_hue: var(--ui-accent);
209
209
  --_hue-hover: var(--ui-accent-hover);
210
210
  --_hue-active: var(--ui-accent-active);
@@ -223,15 +223,15 @@
223
223
  vertical-align: middle;
224
224
  color: var(--_tone-text);
225
225
  }
226
- [data-component~="ui-button"][data-ui-button-state~="align=start"][data-v-8513eb5d] {
226
+ [data-component~="ui-button"][data-ui-button-state~="align=start"][data-v-c6ef4679] {
227
227
  justify-content: flex-start;
228
228
  text-align: start;
229
229
  }
230
- [data-component~="ui-button"][data-ui-button-state~="stretch"][data-v-8513eb5d] {
230
+ [data-component~="ui-button"][data-ui-button-state~="stretch"][data-v-c6ef4679] {
231
231
  display: flex;
232
232
  inline-size: 100%;
233
233
  }
234
- [data-component~="ui-button"][data-v-8513eb5d] {
234
+ [data-component~="ui-button"][data-v-c6ef4679] {
235
235
  appearance: none;
236
236
  min-block-size: var(--ui-button-min-block-size, var(--ui-control-size-md));
237
237
  border-style: solid;
@@ -255,44 +255,44 @@
255
255
  margin: 0;
256
256
  }
257
257
  @supports (text-box-trim: trim-both) {
258
- [data-component~="ui-button"][data-v-8513eb5d] {
258
+ [data-component~="ui-button"][data-v-c6ef4679] {
259
259
  text-box-trim: trim-both;
260
260
  text-box-edge: cap alphabetic;
261
261
  }
262
262
  }
263
- [data-component~="ui-button"][data-ui-button-state~="size=sm"][data-v-8513eb5d] {
263
+ [data-component~="ui-button"][data-ui-button-state~="size=sm"][data-v-c6ef4679] {
264
264
  min-block-size: var(--ui-control-size-sm);
265
265
  padding: var(--ui-space-1) var(--ui-space-2);
266
266
  font-size: 0.875rem;
267
267
  }
268
- [data-component~="ui-button"][data-ui-button-state~="size=lg"][data-v-8513eb5d] {
268
+ [data-component~="ui-button"][data-ui-button-state~="size=lg"][data-v-c6ef4679] {
269
269
  min-block-size: var(--ui-control-size-lg);
270
270
  padding: var(--ui-space-3) var(--ui-space-4);
271
271
  font-size: 1rem;
272
272
  }
273
- [data-component~="ui-button"][data-v-8513eb5d]:hover:enabled {
273
+ [data-component~="ui-button"][data-v-c6ef4679]:hover:enabled {
274
274
  border-color: var(--ui-button-hover-border, var(--_tone-hover));
275
275
  background-color: var(--ui-button-hover-surface, oklch(from var(--_tone) l c h / 12%));
276
276
  }
277
277
 
278
278
  /* Pressed reads as pressed in: the highlight goes, and the shadow moves inside. */
279
- [data-component~="ui-button"][data-v-8513eb5d]:active:enabled {
279
+ [data-component~="ui-button"][data-v-c6ef4679]:active:enabled {
280
280
  background-color: var(--ui-button-active-surface, oklch(from var(--_tone) l c h / 18%));
281
281
  background-image: none;
282
282
  box-shadow: var(--ui-pressed);
283
283
  }
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] {
284
+ [data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-c6ef4679],
285
+ [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-c6ef4679] {
286
286
  border-color: var(--_tone);
287
287
  background-color: var(--_tone);
288
288
  color: var(--_on-tone);
289
289
  box-shadow: var(--ui-button-solid-shadow, var(--ui-raised));
290
290
  }
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 {
291
+ :is([data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-c6ef4679], [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-c6ef4679]):hover:enabled {
292
292
  background-color: var(--_tone-hover);
293
293
  border-color: var(--_tone-hover);
294
294
  }
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 {
295
+ :is([data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-c6ef4679], [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-c6ef4679]):active:enabled {
296
296
  background-color: var(--_tone-active);
297
297
  border-color: var(--_tone-active);
298
298
  background-image: none;
@@ -301,43 +301,43 @@
301
301
 
302
302
  /* Tone is the colour, variant is the volume. Every pairing works: a danger outline is a
303
303
  destructive secondary action, not a special case. */
304
- [data-component~="ui-button"][data-ui-button-state~="tone=neutral"][data-v-8513eb5d] {
304
+ [data-component~="ui-button"][data-ui-button-state~="tone=neutral"][data-v-c6ef4679] {
305
305
  --_hue: var(--ui-text);
306
306
  --_hue-hover: var(--ui-text);
307
307
  --_hue-active: var(--ui-text);
308
308
  --_hue-text: var(--ui-text);
309
309
  --_on-hue: var(--ui-surface);
310
310
  }
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] {
311
+ [data-component~="ui-button"][data-ui-button-state~="tone=danger"][data-v-c6ef4679],
312
+ [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-c6ef4679] {
313
313
  --_hue: var(--ui-danger);
314
314
  --_hue-hover: var(--ui-danger-hover);
315
315
  --_hue-active: var(--ui-danger-hover);
316
316
  --_hue-text: var(--ui-danger-hover);
317
317
  --_on-hue: var(--ui-on-danger);
318
318
  }
319
- [data-component~="ui-button"][data-ui-button-state~="tone=success"][data-v-8513eb5d] {
319
+ [data-component~="ui-button"][data-ui-button-state~="tone=success"][data-v-c6ef4679] {
320
320
  --_hue: var(--ui-success);
321
321
  --_hue-hover: color-mix(in srgb, var(--ui-success) 85%, #000);
322
322
  --_hue-active: color-mix(in srgb, var(--ui-success) 75%, #000);
323
323
  --_hue-text: color-mix(in srgb, var(--ui-success) 85%, #000);
324
324
  --_on-hue: var(--ui-surface);
325
325
  }
326
- [data-component~="ui-button"][data-ui-button-state~="tone=warning"][data-v-8513eb5d] {
326
+ [data-component~="ui-button"][data-ui-button-state~="tone=warning"][data-v-c6ef4679] {
327
327
  --_hue: var(--ui-warning);
328
328
  --_hue-hover: color-mix(in srgb, var(--ui-warning) 85%, #000);
329
329
  --_hue-active: color-mix(in srgb, var(--ui-warning) 75%, #000);
330
330
  --_hue-text: color-mix(in srgb, var(--ui-warning) 85%, #000);
331
331
  --_on-hue: var(--ui-surface);
332
332
  }
333
- [data-component~="ui-button"][data-ui-button-state~="tone=info"][data-v-8513eb5d] {
333
+ [data-component~="ui-button"][data-ui-button-state~="tone=info"][data-v-c6ef4679] {
334
334
  --_hue: var(--ui-info);
335
335
  --_hue-hover: color-mix(in srgb, var(--ui-info) 85%, #000);
336
336
  --_hue-active: color-mix(in srgb, var(--ui-info) 75%, #000);
337
337
  --_hue-text: color-mix(in srgb, var(--ui-info) 85%, #000);
338
338
  --_on-hue: var(--ui-surface);
339
339
  }
340
- [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-8513eb5d] {
340
+ [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-c6ef4679] {
341
341
  border-color: transparent;
342
342
  background: transparent;
343
343
  box-shadow: none;
@@ -345,34 +345,34 @@
345
345
  }
346
346
 
347
347
  /* 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 {
348
+ [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-c6ef4679]:hover:enabled {
349
349
  background-color: var(--ui-button-ghost-hover-surface, oklch(from var(--_tone) l c h / 10%));
350
350
  border-color: transparent;
351
351
  }
352
- [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-8513eb5d]:active:enabled {
352
+ [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-c6ef4679]:active:enabled {
353
353
  background-color: var(--ui-button-ghost-active-surface, oklch(from var(--_tone) l c h / 16%));
354
354
  border-color: transparent;
355
355
  box-shadow: var(--ui-pressed);
356
356
  }
357
357
 
358
358
  /* 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 {
359
+ [data-component~="ui-button"][data-v-c6ef4679]:focus-visible {
360
360
  outline: none;
361
361
  box-shadow:
362
362
  var(--ui-button-shadow, var(--ui-raised)),
363
363
  var(--ui-focus-halo);
364
364
  }
365
- [data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-8513eb5d]:focus-visible {
365
+ [data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-c6ef4679]:focus-visible {
366
366
  box-shadow:
367
367
  var(--ui-button-solid-shadow, var(--ui-raised)),
368
368
  var(--ui-focus-halo);
369
369
  }
370
370
 
371
371
  /* 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
372
+ disabled outline is still an outline and a disabled ghost still has no edge. Intent goes — an
373
373
  unavailable action says "unavailable", not "unavailable, and destructive" — and so do the
374
374
  highlight and shadow, because nothing that cannot be pressed should look raised. */
375
- [data-component~="ui-button"][data-v-8513eb5d]:disabled {
375
+ [data-component~="ui-button"][data-v-c6ef4679]:disabled {
376
376
  /* Derived from the tone itself, not from a separate disabled palette: faded toward the
377
377
  page, which desaturates it at the same time. Toward the page rather than toward white,
378
378
  so a dark theme dims where a light one lightens — the same rule, both schemes. */
@@ -389,25 +389,27 @@
389
389
  }
390
390
 
391
391
  /* 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 {
392
+ :is([data-component~="ui-button"][data-ui-button-state~="variant=solid"][data-v-c6ef4679], [data-component~="ui-button"][data-ui-button-state~="variant=danger"][data-v-c6ef4679]):disabled {
393
393
  --_tone: color-mix(in oklab, var(--_hue) 34%, var(--ui-surface));
394
394
  }
395
395
 
396
396
  /* 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));
397
+ it takes a surface rather than reading as plain text. The surface is a wash of the faded tone,
398
+ the way hover washes the live one, so it stays light in every tone. An opaque mix toward the
399
+ hue came out a mid-grey slab for neutral, whose hue is the ink: louder than the enabled button. */
400
+ [data-component~="ui-button"][data-ui-button-state~="variant=ghost"][data-v-c6ef4679]:disabled {
401
+ background-color: oklch(from var(--_tone) l c h / 14%);
400
402
  border-color: transparent;
401
403
  }
402
404
  @media (pointer: coarse) {
403
- [data-component~="ui-button"][data-v-8513eb5d] {
405
+ [data-component~="ui-button"][data-v-c6ef4679] {
404
406
  min-block-size: var(--ui-control-min-block-size);
405
407
  }
406
408
  }
407
409
 
408
410
  /* Link: an inline text action. No box, padding, or minimum height (inline targets are exempt under
409
411
  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] {
412
+ [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-c6ef4679] {
411
413
  display: inline;
412
414
  min-block-size: 0;
413
415
  padding: 0;
@@ -425,22 +427,22 @@
425
427
  color var(--ui-motion-fast) var(--ui-motion-ease),
426
428
  text-decoration-color var(--ui-motion-fast) var(--ui-motion-ease);
427
429
  }
428
- [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-8513eb5d]:hover:enabled {
430
+ [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-c6ef4679]:hover:enabled {
429
431
  color: var(--ui-button-link-hover-text, var(--ui-text-primary));
430
432
  text-decoration-color: currentColor;
431
433
  background: none;
432
434
  transform: none;
433
435
  }
434
- [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-8513eb5d]:active:enabled {
436
+ [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-c6ef4679]:active:enabled {
435
437
  background: none;
436
438
  transform: none;
437
439
  }
438
- [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-8513eb5d]:disabled {
440
+ [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-c6ef4679]:disabled {
439
441
  background: none;
440
442
  border-color: transparent;
441
443
  color: var(--ui-button-disabled-text, var(--ui-disabled-text));
442
444
  }
443
- [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-8513eb5d]:focus-visible {
445
+ [data-component~="ui-button"][data-ui-button-state~="variant=link"][data-v-c6ef4679]:focus-visible {
444
446
  box-shadow: none;
445
447
  /* Fallback keeps the ring if the token is missing: an unresolved var() would void the outline. */
446
448
  outline: 2px solid var(--ui-focus-ring);
@@ -448,7 +450,7 @@
448
450
  }
449
451
 
450
452
  /* A component that sets its display still honours the hidden attribute on its root. */
451
- [data-component~="ui-button"][hidden][data-v-8513eb5d] {
453
+ [data-component~="ui-button"][hidden][data-v-c6ef4679] {
452
454
  display: none;
453
455
  }
454
456