@threadlabs/looma 0.6.0 → 0.6.2

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 (71) hide show
  1. package/components/ui-avatar/ui-avatar.html +13 -0
  2. package/components/ui-avatar-group/ui-avatar-group.html +7 -2
  3. package/components/ui-avatar-group/ui-avatar-group.js +3 -3
  4. package/components/ui-badge/ui-badge.html +14 -0
  5. package/components/ui-button/ui-button.html +2 -2
  6. package/components/ui-cluster/ui-cluster.html +1 -1
  7. package/components/ui-combobox/ui-combobox.html +112 -46
  8. package/components/ui-combobox/ui-combobox.js +14 -2
  9. package/components/ui-editor-insert-table-grid/ui-editor-insert-table-grid.html +3 -3
  10. package/components/ui-editor-table-context-menu/ui-editor-table-context-menu.html +2 -2
  11. package/components/ui-editor-table-toolbar/ui-editor-table-toolbar.html +2 -2
  12. package/components/ui-editor-toolbar/ui-editor-toolbar.html +5 -3
  13. package/components/ui-menu-item/ui-menu-item.html +13 -0
  14. package/components/ui-stack/ui-stack.html +1 -1
  15. package/components/ui-tabs/ui-tabs.html +13 -0
  16. package/components/ui-toast-region/ui-toast-region.html +2 -2
  17. package/components/ui-tooltip/ui-tooltip.html +3 -0
  18. package/components/ui-tooltip/ui-tooltip.js +24 -3
  19. package/dist/index.js +1 -1
  20. package/package.json +1 -1
  21. package/styles/ui-avatar-group.css +7 -2
  22. package/styles/ui-avatar.css +19 -0
  23. package/styles/ui-badge.css +21 -1
  24. package/styles/ui-cluster.css +1 -1
  25. package/styles/ui-combobox.css +52 -1
  26. package/styles/ui-editor-insert-table-grid.css +2 -2
  27. package/styles/ui-editor-table-context-menu.css +1 -1
  28. package/styles/ui-editor-table-toolbar.css +1 -1
  29. package/styles/ui-editor-toolbar.css +5 -3
  30. package/styles/ui-menu-item.css +20 -1
  31. package/styles/ui-stack.css +1 -1
  32. package/styles/ui-tabs.css +19 -0
  33. package/styles/ui-toast-region.css +2 -2
  34. package/tokens.css +4 -0
  35. package/vanilla/UiCombobox.js +141 -119
  36. package/vanilla/UiEditorInsertTableGrid.js +1 -1
  37. package/vanilla/UiEditorTableContextMenu.js +1 -1
  38. package/vanilla/UiEditorTableToolbar.js +1 -1
  39. package/vanilla/UiTooltip.d.ts +1 -0
  40. package/vanilla/UiTooltip.js +1 -1
  41. package/vue/UiAvatar.vue +13 -0
  42. package/vue/UiAvatarGroup.vue +7 -2
  43. package/vue/UiBadge.vue +14 -0
  44. package/vue/UiCluster.vue +1 -1
  45. package/vue/UiCombobox.vue +135 -53
  46. package/vue/UiEditorInsertTableGrid.vue +3 -3
  47. package/vue/UiEditorTableContextMenu.vue +2 -2
  48. package/vue/UiEditorTableToolbar.vue +2 -2
  49. package/vue/UiEditorToolbar.vue +5 -3
  50. package/vue/UiMenuItem.vue +13 -0
  51. package/vue/UiStack.vue +1 -1
  52. package/vue/UiTabs.vue +13 -0
  53. package/vue/UiToastRegion.vue +2 -2
  54. package/vue/UiTooltip.d.ts +4 -0
  55. package/vue/UiTooltip.vue +6 -0
  56. package/vue/chunks/UiAvatar.js +1 -1
  57. package/vue/chunks/UiAvatarGroup.js +1 -1
  58. package/vue/chunks/UiBadge.js +1 -1
  59. package/vue/chunks/UiCluster.js +1 -1
  60. package/vue/chunks/UiCombobox.js +66 -41
  61. package/vue/chunks/UiEditorInsertTableGrid.js +3 -3
  62. package/vue/chunks/UiEditorTableContextMenu.js +2 -2
  63. package/vue/chunks/UiEditorTableToolbar.js +2 -2
  64. package/vue/chunks/UiEditorToolbar.js +1 -1
  65. package/vue/chunks/UiMenuItem.js +1 -1
  66. package/vue/chunks/UiStack.js +1 -1
  67. package/vue/chunks/UiTabs.js +1 -1
  68. package/vue/chunks/UiToastRegion.js +1 -1
  69. package/vue/chunks/UiTooltip.js +5 -2
  70. package/vue/components.css +322 -211
  71. package/vue/editor/index.js +2 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@threadlabs/looma",
3
- "version": "0.6.0",
3
+ "version": "0.6.2",
4
4
  "type": "module",
5
5
  "description": "Looma components as HTML, Vue, and plain DOM, with design tokens.",
6
6
  "license": "MIT",
@@ -1,6 +1,11 @@
1
1
  /* Generated by HTML Next 1.0.0-alpha.2. Do not edit. */
2
2
  @scope ([data-component~="ui-avatar-group"]) to ([data-component], [data-slotted]) {
3
3
  :scope {
4
+ /* Avatars separate with a tight, crisp edge, matching Looma's 1px borders rather than the
5
+ * diffuse elevation overlays use. */
6
+ --_overlap-shadow: -2px 0 2px -1px rgba(0, 0, 0, 0.22);
7
+ --_edge-ring: 0 0 0 1px rgba(0, 0, 0, 0.08);
8
+
4
9
  display: flex;
5
10
  align-items: center;
6
11
  flex-direction: row;
@@ -22,8 +27,8 @@
22
27
  background: var(--ui-surface-elevated);
23
28
  color: var(--ui-text-primary);
24
29
  box-shadow:
25
- var(--ui-avatar-group-overlap-shadow, -2px 0 5px -1px rgb(0 0 0 / 0.28)),
26
- 0 0 0 1px rgb(0 0 0 / 0.06);
30
+ var(--ui-avatar-group-overlap-shadow, var(--_overlap-shadow)),
31
+ var(--ui-avatar-group-edge-ring, var(--_edge-ring));
27
32
  font: inherit;
28
33
  font-size: 0.75rem;
29
34
  font-weight: 600;
@@ -25,6 +25,19 @@
25
25
  block-size: 100%;
26
26
  }
27
27
 
28
+ /* Centre the glyphs, not the line box: a label without descenders otherwise reads high. */
29
+ /* Centre the glyphs, not the line box: a label without descenders otherwise reads high.
30
+ * Trimming applies to block containers, so the box is a block with centred content. */
31
+ @supports (text-box-trim: trim-both) {
32
+ .fallback {
33
+ display: block;
34
+ text-align: center;
35
+ align-content: center;
36
+ text-box-trim: trim-both;
37
+ text-box-edge: cap alphabetic;
38
+ }
39
+ }
40
+
28
41
  [hidden] {
29
42
  display: none;
30
43
  }
@@ -43,5 +56,11 @@
43
56
  object-fit: cover;
44
57
  }
45
58
 
59
+ /* Centre the glyphs, not the line box: a label without descenders otherwise reads high. */
60
+ /* Centre the glyphs, not the line box: a label without descenders otherwise reads high.
61
+ * Trimming applies to block containers, so the box is a block with centred content. */
62
+ @supports (text-box-trim: trim-both) {
63
+ }
64
+
46
65
  /* A component that sets its display still honours the hidden attribute on its root. */
47
66
  }
@@ -21,6 +21,20 @@
21
21
  white-space: nowrap;
22
22
  }
23
23
 
24
+ /* Centre the glyphs, not the line box: a label without descenders otherwise reads high. */
25
+ /* Centre the glyphs, not the line box: a label without descenders otherwise reads high.
26
+ * Trimming applies to block containers, so the box is a block with centred content. */
27
+ @supports (text-box-trim: trim-both) {
28
+ :scope {
29
+ display: block;
30
+ min-block-size: var(--ui-badge-min-block-size, 1.5rem);
31
+ text-align: center;
32
+ align-content: center;
33
+ text-box-trim: trim-both;
34
+ text-box-edge: cap alphabetic;
35
+ }
36
+ }
37
+
24
38
  :scope[data-ui-badge-state~="tone=accent"] {
25
39
  --_badge-surface: var(--ui-accent-strong-surface, var(--ui-accent-solid));
26
40
  --_badge-border: var(--ui-accent-strong-surface, var(--ui-accent-solid));
@@ -87,5 +101,11 @@
87
101
  }
88
102
  }
89
103
  @scope ([data-component~="ui-badge"]) to ([data-component]) {
90
- /* A component that sets its display still honours the hidden attribute on its root. */
104
+ /* Centre the glyphs, not the line box: a label without descenders otherwise reads high. */
105
+ /* Centre the glyphs, not the line box: a label without descenders otherwise reads high.
106
+ * Trimming applies to block containers, so the box is a block with centred content. */
107
+ @supports (text-box-trim: trim-both) {
108
+ }
109
+
110
+ /* A component that sets its display still honours the hidden attribute on its root. */
91
111
  }
@@ -5,7 +5,7 @@
5
5
  display: flex;
6
6
  flex-wrap: wrap;
7
7
  align-items: center;
8
- gap: var(--ui-layout-gap, var(--_layout-gap));
8
+ gap: var(--ui-cluster-gap, var(--_layout-gap));
9
9
  min-inline-size: 0;
10
10
  max-inline-size: 100%;
11
11
  margin: 0;
@@ -12,7 +12,17 @@
12
12
  font-size: var(--ui-combobox-label-font-size, 0.875rem);
13
13
  font-weight: 500;
14
14
  }
15
+ /* The field and anything that annotates it sit on one row; the help button is beside the box,
16
+ not inside it, because a control's box holds its value. */
17
+ .control {
18
+ display: flex;
19
+ align-items: center;
20
+ gap: var(--ui-space-2);
21
+ min-inline-size: 0;
22
+ }
23
+
15
24
  .field {
25
+ flex: 1 1 auto;
16
26
  display: flex;
17
27
  min-inline-size: 0;
18
28
  border: 1px solid var(--ui-control-border, var(--ui-border-default));
@@ -27,6 +37,44 @@
27
37
  var(--ui-control-inset),
28
38
  var(--ui-control-focus-halo-shadow);
29
39
  }
40
+ /* A ghost icon button: the affordance is the mark, not a box around it. */
41
+ .help {
42
+ flex: none;
43
+ display: inline-flex;
44
+ align-items: center;
45
+ justify-content: center;
46
+ inline-size: var(--ui-control-size-sm);
47
+ block-size: var(--ui-control-size-sm);
48
+ padding: 0;
49
+ border: 0;
50
+ border-radius: var(--ui-radius-round);
51
+ background: transparent;
52
+ color: var(--ui-text-secondary);
53
+ cursor: pointer;
54
+ transition: background-color var(--ui-motion-fast) var(--ui-motion-ease), color var(--ui-motion-fast) var(--ui-motion-ease);
55
+ }
56
+
57
+ .help:hover:enabled,
58
+ .help[aria-expanded="true"] {
59
+ background: color-mix(in srgb, currentColor 8%, transparent);
60
+ color: var(--ui-text-primary);
61
+ }
62
+
63
+ .help:focus-visible {
64
+ outline: none;
65
+ box-shadow: var(--ui-focus-halo);
66
+ }
67
+
68
+ .help:disabled {
69
+ color: var(--ui-disabled-text);
70
+ cursor: not-allowed;
71
+ }
72
+
73
+ .help-icon {
74
+ inline-size: var(--ui-icon-size-sm);
75
+ block-size: var(--ui-icon-size-sm);
76
+ }
77
+
30
78
  input::selection {
31
79
  background: color-mix(in srgb, var(--ui-accent-solid) 20%, transparent);
32
80
  color: inherit;
@@ -202,7 +250,10 @@
202
250
  }
203
251
  }
204
252
  @scope ([data-component~="ui-combobox"]) to ([data-component]) {
205
- @media (pointer: coarse) {
253
+ /* The field and anything that annotates it sit on one row; the help button is beside the box,
254
+ not inside it, because a control's box holds its value. */
255
+ /* A ghost icon button: the affordance is the mark, not a box around it. */
256
+ @media (pointer: coarse) {
206
257
  }
207
258
  @media (forced-colors: active) {
208
259
  }
@@ -16,8 +16,8 @@
16
16
 
17
17
  .grid {
18
18
  display: grid;
19
- grid-template-columns: repeat(var(--ui-editor-table-grid-cols, 8), 1.25rem);
20
- grid-template-rows: repeat(var(--ui-editor-table-grid-rows, 8), 1.25rem);
19
+ grid-template-columns: repeat(var(--_cols, 8), 1.25rem);
20
+ grid-template-rows: repeat(var(--_rows, 8), 1.25rem);
21
21
  gap: 2px;
22
22
  margin-bottom: var(--ui-space-2);
23
23
  }
@@ -74,7 +74,7 @@
74
74
  height: 1rem;
75
75
  border-radius: 999px;
76
76
  border: 1px solid var(--ui-border);
77
- background: var(--ui-editor-table-context-swatch, #fff);
77
+ background: var(--_swatch, #fff);
78
78
  box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.35);
79
79
  flex-shrink: 0;
80
80
  }
@@ -172,7 +172,7 @@
172
172
  flex: 0 0 14px;
173
173
  border: 1px solid color-mix(in srgb, var(--ui-border) 80%, #000);
174
174
  border-radius: 3px;
175
- background: var(--ui-editor-table-toolbar-swatch);
175
+ background: var(--_swatch);
176
176
  }
177
177
 
178
178
  .swatch.default {
@@ -10,9 +10,10 @@
10
10
  gap: var(--ui-editor-toolbar-gap, 2px);
11
11
  padding: var(--ui-editor-toolbar-padding-block, 6px) var(--ui-editor-toolbar-padding-inline, 12px);
12
12
  min-height: var(--ui-editor-toolbar-min-height, 48px);
13
- overflow-x: auto;
14
- scrollbar-width: none;
15
- white-space: nowrap;
13
+ /* More controls than the column is wide is normal at a readable measure, so the row wraps.
14
+ Scrolling hid the tail behind an invisible scrollbar. */
15
+ flex-wrap: wrap;
16
+ row-gap: var(--ui-editor-toolbar-row-gap, var(--ui-editor-toolbar-gap, 2px));
16
17
  background: var(--ui-editor-toolbar-surface, var(--ui-surface));
17
18
  border-bottom: 1px solid var(--ui-editor-toolbar-border, var(--ui-border));
18
19
  }
@@ -22,6 +23,7 @@
22
23
  }
23
24
 
24
25
  :scope[data-ui-editor-toolbar-state~="floating"] {
26
+ flex-wrap: nowrap;
25
27
  position: static;
26
28
  top: auto;
27
29
  width: max-content;
@@ -15,6 +15,19 @@
15
15
  transition: background-color var(--ui-motion-fast) var(--ui-motion-ease), color var(--ui-motion-fast) var(--ui-motion-ease);
16
16
  }
17
17
 
18
+ /* Centre the glyphs, not the line box: a label without descenders otherwise reads high. */
19
+ /* Centre the glyphs, not the line box: a label without descenders otherwise reads high.
20
+ * Trimming applies to block containers, so the box is a block with centred content. */
21
+ @supports (text-box-trim: trim-both) {
22
+ :scope {
23
+ display: block;
24
+ min-block-size: var(--ui-menu-item-min-block-size, var(--ui-control-size-md, 2.5rem));
25
+ align-content: center;
26
+ text-box-trim: trim-both;
27
+ text-box-edge: cap alphabetic;
28
+ }
29
+ }
30
+
18
31
  :scope:is(:hover, :focus-visible):not([aria-disabled="true"]) {
19
32
  background: var(--ui-menu-item-hover-surface, var(--ui-surface-subtle));
20
33
  }
@@ -30,5 +43,11 @@
30
43
  }
31
44
  }
32
45
  @scope ([data-component~="ui-menu-item"]) to ([data-component]) {
33
- /* A component that sets its display still honours the hidden attribute on its root. */
46
+ /* Centre the glyphs, not the line box: a label without descenders otherwise reads high. */
47
+ /* Centre the glyphs, not the line box: a label without descenders otherwise reads high.
48
+ * Trimming applies to block containers, so the box is a block with centred content. */
49
+ @supports (text-box-trim: trim-both) {
50
+ }
51
+
52
+ /* A component that sets its display still honours the hidden attribute on its root. */
34
53
  }
@@ -5,7 +5,7 @@
5
5
  display: flex;
6
6
  flex-direction: column;
7
7
  align-items: stretch;
8
- gap: var(--ui-layout-gap, var(--_layout-gap));
8
+ gap: var(--ui-stack-gap, var(--_layout-gap));
9
9
  min-inline-size: 0;
10
10
  max-inline-size: 100%;
11
11
  margin: 0;
@@ -54,6 +54,19 @@
54
54
  border-color var(--ui-motion-fast) var(--ui-motion-ease);
55
55
  }
56
56
 
57
+ /* Centre the glyphs, not the line box: a label without descenders otherwise reads high. */
58
+ /* Centre the glyphs, not the line box: a label without descenders otherwise reads high.
59
+ * Trimming applies to block containers, so the box is a block with centred content. */
60
+ @supports (text-box-trim: trim-both) {
61
+ .list button {
62
+ display: block;
63
+ text-align: center;
64
+ align-content: center;
65
+ text-box-trim: trim-both;
66
+ text-box-edge: cap alphabetic;
67
+ }
68
+ }
69
+
57
70
  :scope[data-ui-tabs-state~="stretch"] .list {
58
71
  grid-auto-columns: minmax(max-content, 1fr);
59
72
  }
@@ -117,6 +130,12 @@
117
130
  }
118
131
  @scope ([data-component~="ui-tabs"]) to ([data-component]) {
119
132
  /* Density resolves into the tab row's own values; the public tokens still override them. */
133
+
134
+ /* Centre the glyphs, not the line box: a label without descenders otherwise reads high. */
135
+ /* Centre the glyphs, not the line box: a label without descenders otherwise reads high.
136
+ * Trimming applies to block containers, so the box is a block with centred content. */
137
+ @supports (text-box-trim: trim-both) {
138
+ }
120
139
  :where([data-slotted], [data-slotted] *):is(*) {
121
140
  padding: var(--ui-space-4);
122
141
  }
@@ -58,12 +58,12 @@
58
58
  background: var(--ui-surface-elevated);
59
59
  color: var(--ui-text-primary);
60
60
  box-shadow: var(--ui-elevation-overlay, var(--ui-shadow-lg));
61
- animation: ui-toast-enter var(--ui-toast-enter-duration, 0.32s) var(--ui-motion-ease-out, cubic-bezier(0.16, 1, 0.3, 1)) both;
61
+ animation: ui-toast-enter var(--ui-toast-region-enter-duration, 0.32s) var(--ui-motion-ease-out, cubic-bezier(0.16, 1, 0.3, 1)) both;
62
62
  }
63
63
 
64
64
  /* Leaving slides on down and fades; the controller removes the toast when this ends. */
65
65
  .toast.closing {
66
- animation: ui-toast-exit var(--ui-toast-exit-duration, 0.22s) var(--ui-motion-ease) both;
66
+ animation: ui-toast-exit var(--ui-toast-region-exit-duration, 0.22s) var(--ui-motion-ease) both;
67
67
  pointer-events: none;
68
68
  }
69
69
 
package/tokens.css CHANGED
@@ -98,8 +98,12 @@
98
98
  --ui-font-size-ui: calc(var(--ui-font-size) * 0.9375);
99
99
  --ui-font-size-md: var(--ui-font-size);
100
100
  --ui-font-size-lg: calc(var(--ui-font-size) * 1.125);
101
+ --ui-font-size-xl: calc(var(--ui-font-size) * 1.25);
102
+ --ui-font-size-2xl: calc(var(--ui-font-size) * 1.5);
101
103
  --ui-line-height-tight: 1.2;
102
104
  --ui-line-height-md: var(--ui-line-height);
105
+ /* Prose, not controls: the editor's document body reads at a looser line height. */
106
+ --ui-line-height-relaxed: calc(var(--ui-line-height) * 1.15);
103
107
  --ui-font-normal: 400;
104
108
  --ui-font-semibold: 600;
105
109
  --ui-font-bold: 700;