@threadlabs/looma 0.12.7 → 0.13.1

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 (196) hide show
  1. package/components/ui-action-bar/ui-action-bar.html +10 -1
  2. package/components/ui-avatar/ui-avatar.html +18 -0
  3. package/components/ui-avatar-group/ui-avatar-group.html +24 -2
  4. package/components/ui-avatar-group/ui-avatar-group.js +3 -1
  5. package/components/ui-badge/ui-badge.html +42 -0
  6. package/components/ui-button/ui-button.html +70 -0
  7. package/components/ui-callout/ui-callout.html +55 -4
  8. package/components/ui-checkbox/ui-checkbox.html +15 -2
  9. package/components/ui-cluster/ui-cluster.html +7 -1
  10. package/components/ui-combobox/ui-combobox.html +64 -10
  11. package/components/ui-container/ui-container.html +12 -1
  12. package/components/ui-context-menu/ui-context-menu.html +10 -1
  13. package/components/ui-dialog/ui-dialog.html +21 -4
  14. package/components/ui-disclosure/ui-disclosure.html +22 -3
  15. package/components/ui-editor-slash-menu/ui-editor-slash-menu.html +2 -2
  16. package/components/ui-editor-table-context-menu/ui-editor-table-context-menu.html +2 -2
  17. package/components/ui-editor-table-overlay/ui-editor-table-overlay.html +8 -8
  18. package/components/ui-editor-table-toolbar/ui-editor-table-toolbar.html +3 -3
  19. package/components/ui-floating-action-button/ui-floating-action-button.html +14 -0
  20. package/components/ui-form-field/ui-form-field.html +10 -1
  21. package/components/ui-grid/ui-grid.html +11 -1
  22. package/components/ui-icon/ui-icon.html +17 -3
  23. package/components/ui-icon-button/ui-icon-button.html +81 -3
  24. package/components/ui-input/ui-input.html +67 -12
  25. package/components/ui-input-group/ui-input-group.html +14 -13
  26. package/components/ui-list/ui-list.html +10 -0
  27. package/components/ui-list-item/ui-list-item.html +22 -1
  28. package/components/ui-menu/ui-menu.html +17 -5
  29. package/components/ui-menu-item/ui-menu-item.html +30 -3
  30. package/components/ui-nav-item/ui-nav-item.html +14 -0
  31. package/components/ui-popover/ui-popover.html +6 -0
  32. package/components/ui-radio/ui-radio.html +15 -2
  33. package/components/ui-reel/ui-reel.html +15 -2
  34. package/components/ui-search-result-row/ui-search-result-row.html +34 -0
  35. package/components/ui-search-shell/ui-search-shell.html +65 -11
  36. package/components/ui-select/ui-select.html +14 -0
  37. package/components/ui-separator/ui-separator.html +9 -2
  38. package/components/ui-sidebar/ui-sidebar.html +22 -1
  39. package/components/ui-stack/ui-stack.html +7 -1
  40. package/components/ui-switch/ui-switch.html +20 -2
  41. package/components/ui-switcher/ui-switcher.html +18 -5
  42. package/components/ui-tabs/ui-tabs.html +21 -2
  43. package/components/ui-textarea/ui-textarea.html +14 -0
  44. package/components/ui-toast-region/ui-toast-region.html +16 -2
  45. package/components/ui-tooltip/ui-tooltip.html +62 -13
  46. package/components/ui-top-bar/ui-top-bar.html +34 -1
  47. package/components/ui-tree/ui-tree.html +27 -4
  48. package/components/ui-tree-item/ui-tree-item.html +39 -10
  49. package/components/ui-tree-item/ui-tree-item.js +1 -1
  50. package/dist/index.js +1 -1
  51. package/package.json +1 -1
  52. package/styles/ui-action-bar.css +14 -3
  53. package/styles/ui-avatar-group.css +26 -4
  54. package/styles/ui-avatar.css +22 -2
  55. package/styles/ui-badge.css +46 -2
  56. package/styles/ui-button.css +74 -2
  57. package/styles/ui-callout.css +59 -6
  58. package/styles/ui-checkbox.css +19 -4
  59. package/styles/ui-cluster.css +10 -2
  60. package/styles/ui-combobox.css +67 -12
  61. package/styles/ui-container.css +14 -2
  62. package/styles/ui-context-menu.css +14 -3
  63. package/styles/ui-dialog.css +25 -6
  64. package/styles/ui-disclosure.css +26 -5
  65. package/styles/ui-editor-slash-menu.css +2 -2
  66. package/styles/ui-editor-table-context-menu.css +2 -2
  67. package/styles/ui-editor-table-overlay.css +8 -8
  68. package/styles/ui-editor-table-toolbar.css +3 -3
  69. package/styles/ui-floating-action-button.css +18 -2
  70. package/styles/ui-form-field.css +14 -3
  71. package/styles/ui-grid.css +14 -2
  72. package/styles/ui-icon-button.css +85 -5
  73. package/styles/ui-icon.css +21 -5
  74. package/styles/ui-input-group.css +14 -13
  75. package/styles/ui-input.css +72 -14
  76. package/styles/ui-list-item.css +26 -3
  77. package/styles/ui-list.css +14 -2
  78. package/styles/ui-menu-item.css +34 -5
  79. package/styles/ui-menu.css +21 -6
  80. package/styles/ui-nav-item.css +18 -2
  81. package/styles/ui-popover.css +10 -2
  82. package/styles/ui-radio.css +19 -4
  83. package/styles/ui-reel.css +18 -3
  84. package/styles/ui-search-result-row.css +38 -2
  85. package/styles/ui-search-shell.css +69 -13
  86. package/styles/ui-select.css +18 -2
  87. package/styles/ui-separator.css +14 -2
  88. package/styles/ui-sidebar.css +26 -3
  89. package/styles/ui-stack.css +10 -2
  90. package/styles/ui-switch.css +24 -4
  91. package/styles/ui-switcher.css +21 -6
  92. package/styles/ui-tabs.css +25 -4
  93. package/styles/ui-textarea.css +18 -2
  94. package/styles/ui-toast-region.css +20 -4
  95. package/styles/ui-tooltip.css +66 -15
  96. package/styles/ui-top-bar.css +38 -3
  97. package/styles/ui-tree-item.css +43 -12
  98. package/styles/ui-tree.css +33 -6
  99. package/vanilla/UiAvatarGroup.d.ts +1 -0
  100. package/vanilla/UiAvatarGroup.js +1 -1
  101. package/vue/UiActionBar.vue +12 -3
  102. package/vue/UiAvatar.vue +18 -0
  103. package/vue/UiAvatarGroup.d.ts +2 -0
  104. package/vue/UiAvatarGroup.vue +40 -4
  105. package/vue/UiBadge.vue +42 -0
  106. package/vue/UiButton.vue +70 -0
  107. package/vue/UiCallout.vue +55 -4
  108. package/vue/UiCheckbox.vue +15 -2
  109. package/vue/UiCluster.vue +6 -0
  110. package/vue/UiCombobox.vue +64 -10
  111. package/vue/UiContainer.vue +10 -0
  112. package/vue/UiContextMenu.vue +10 -1
  113. package/vue/UiDialog.vue +21 -4
  114. package/vue/UiDisclosure.vue +22 -3
  115. package/vue/UiEditorSlashMenu.vue +2 -2
  116. package/vue/UiEditorTableContextMenu.vue +2 -2
  117. package/vue/UiEditorTableOverlay.vue +8 -8
  118. package/vue/UiEditorTableToolbar.vue +3 -3
  119. package/vue/UiFloatingActionButton.vue +14 -0
  120. package/vue/UiFormField.vue +10 -1
  121. package/vue/UiGrid.vue +10 -0
  122. package/vue/UiIcon.vue +17 -3
  123. package/vue/UiIconButton.vue +81 -3
  124. package/vue/UiInput.vue +89 -14
  125. package/vue/UiInputGroup.vue +14 -13
  126. package/vue/UiList.vue +12 -2
  127. package/vue/UiListItem.vue +30 -9
  128. package/vue/UiMenu.vue +17 -5
  129. package/vue/UiMenuItem.vue +42 -4
  130. package/vue/UiNavItem.vue +17 -3
  131. package/vue/UiPopover.vue +6 -0
  132. package/vue/UiRadio.vue +15 -2
  133. package/vue/UiReel.vue +14 -1
  134. package/vue/UiSearchResultRow.vue +34 -0
  135. package/vue/UiSearchShell.vue +66 -12
  136. package/vue/UiSelect.vue +14 -0
  137. package/vue/UiSeparator.vue +9 -2
  138. package/vue/UiSidebar.vue +22 -1
  139. package/vue/UiStack.vue +6 -0
  140. package/vue/UiSwitch.vue +20 -2
  141. package/vue/UiSwitcher.vue +17 -4
  142. package/vue/UiTabs.vue +22 -3
  143. package/vue/UiTextarea.vue +14 -0
  144. package/vue/UiToastRegion.vue +16 -2
  145. package/vue/UiTooltip.vue +62 -13
  146. package/vue/UiTopBar.vue +34 -1
  147. package/vue/UiTree.vue +28 -5
  148. package/vue/UiTreeItem.vue +46 -11
  149. package/vue/chunks/UiActionBar.js +1 -1
  150. package/vue/chunks/UiAvatar.js +1 -1
  151. package/vue/chunks/UiAvatarGroup.js +8 -4
  152. package/vue/chunks/UiBadge.js +1 -1
  153. package/vue/chunks/UiButton.js +1 -1
  154. package/vue/chunks/UiCallout.js +1 -1
  155. package/vue/chunks/UiCheckbox.js +1 -1
  156. package/vue/chunks/UiCluster.js +1 -1
  157. package/vue/chunks/UiCombobox.js +1 -1
  158. package/vue/chunks/UiContainer.js +1 -1
  159. package/vue/chunks/UiContextMenu.js +1 -1
  160. package/vue/chunks/UiDialog.js +1 -1
  161. package/vue/chunks/UiDisclosure.js +1 -1
  162. package/vue/chunks/UiEditorSlashMenu.js +1 -1
  163. package/vue/chunks/UiEditorTableContextMenu.js +1 -1
  164. package/vue/chunks/UiEditorTableOverlay.js +1 -1
  165. package/vue/chunks/UiEditorTableToolbar.js +1 -1
  166. package/vue/chunks/UiFloatingActionButton.js +1 -1
  167. package/vue/chunks/UiFormField.js +1 -1
  168. package/vue/chunks/UiGrid.js +1 -1
  169. package/vue/chunks/UiIcon.js +1 -1
  170. package/vue/chunks/UiIconButton.js +1 -1
  171. package/vue/chunks/UiInput.js +1 -1
  172. package/vue/chunks/UiInputGroup.js +1 -1
  173. package/vue/chunks/UiList.js +1 -1
  174. package/vue/chunks/UiListItem.js +1 -1
  175. package/vue/chunks/UiMenu.js +1 -1
  176. package/vue/chunks/UiMenuItem.js +1 -1
  177. package/vue/chunks/UiNavItem.js +1 -1
  178. package/vue/chunks/UiPopover.js +1 -1
  179. package/vue/chunks/UiRadio.js +1 -1
  180. package/vue/chunks/UiReel.js +1 -1
  181. package/vue/chunks/UiSearchResultRow.js +1 -1
  182. package/vue/chunks/UiSearchShell.js +1 -1
  183. package/vue/chunks/UiSelect.js +1 -1
  184. package/vue/chunks/UiSeparator.js +1 -1
  185. package/vue/chunks/UiSidebar.js +1 -1
  186. package/vue/chunks/UiStack.js +1 -1
  187. package/vue/chunks/UiSwitch.js +1 -1
  188. package/vue/chunks/UiSwitcher.js +1 -1
  189. package/vue/chunks/UiTabs.js +1 -1
  190. package/vue/chunks/UiTextarea.js +1 -1
  191. package/vue/chunks/UiToastRegion.js +1 -1
  192. package/vue/chunks/UiTooltip.js +1 -1
  193. package/vue/chunks/UiTopBar.js +1 -1
  194. package/vue/chunks/UiTree.js +1 -1
  195. package/vue/chunks/UiTreeItem.js +1 -1
  196. package/vue/components.css +1934 -897
@@ -220,8 +220,8 @@ useComponentHost(controllerModule.default, {
220
220
  }
221
221
 
222
222
  .icon {
223
- --ui-icon-size: 1rem;
224
- --ui-icon-stroke-width: var(--ui-editor-toolbar-icon-stroke-width, 1.75);
223
+ --_ui-default-icon-size: 1rem;
224
+ --_ui-default-icon-stroke-width: var(--ui-editor-toolbar-icon-stroke-width, 1.75);
225
225
  }
226
226
 
227
227
  .body {
@@ -201,8 +201,8 @@ useComponentHost(controllerModule.default, {
201
201
  }
202
202
 
203
203
  [data-component~="ui-editor-table-context-menu"] button {
204
- --ui-icon-size: 1rem;
205
- --ui-icon-stroke-width: var(--ui-editor-toolbar-icon-stroke-width, 1.75);
204
+ --_ui-default-icon-size: 1rem;
205
+ --_ui-default-icon-stroke-width: var(--ui-editor-toolbar-icon-stroke-width, 1.75);
206
206
  }
207
207
 
208
208
  [data-component~="ui-editor-table-context-menu"] button:hover:not(:disabled) {
@@ -333,8 +333,8 @@ useComponentHost(controllerModule.default, {
333
333
  }
334
334
 
335
335
  .handle {
336
- --ui-icon-size: 14px;
337
- --ui-icon-stroke-width: 2;
336
+ --_ui-default-icon-size: 14px;
337
+ --_ui-default-icon-stroke-width: 2;
338
338
  }
339
339
 
340
340
  .handle[data-ui-proximity="near"],
@@ -482,8 +482,8 @@ useComponentHost(controllerModule.default, {
482
482
 
483
483
  .selector:hover,
484
484
  .cell-menu:hover {
485
- background: var(--ui-icon-button-hover-surface, var(--ui-surface-muted));
486
- color: var(--ui-icon-button-hover-text, var(--ui-text-primary));
485
+ background: var(--ui-surface-muted);
486
+ color: var(--ui-text-primary);
487
487
  box-shadow: var(--ui-shadow-xs, 0 1px 2px rgb(0 0 0 / 0.05));
488
488
  }
489
489
 
@@ -507,8 +507,8 @@ useComponentHost(controllerModule.default, {
507
507
  display: block;
508
508
  width: 14px;
509
509
  height: 14px;
510
- --ui-icon-size: 14px;
511
- --ui-icon-stroke-width: 2;
510
+ --_ui-default-icon-size: 14px;
511
+ --_ui-default-icon-stroke-width: 2;
512
512
  opacity: 0;
513
513
  transform: scale(0.72);
514
514
  transition:
@@ -570,8 +570,8 @@ useComponentHost(controllerModule.default, {
570
570
  }
571
571
 
572
572
  .cell-menu {
573
- --ui-icon-size: 15px;
574
- --ui-icon-stroke-width: 2;
573
+ --_ui-default-icon-size: 15px;
574
+ --_ui-default-icon-stroke-width: 2;
575
575
  }
576
576
 
577
577
  [data-component~="ui-editor-table-overlay"][hidden] {
@@ -318,13 +318,13 @@ useComponentHost(controllerModule.default, {
318
318
  }
319
319
 
320
320
  [data-component~="ui-editor-table-toolbar"] {
321
- --ui-icon-size: var(--ui-editor-toolbar-icon-size, 1rem);
322
- --ui-icon-stroke-width: var(--ui-editor-toolbar-icon-stroke-width, 1.75);
321
+ --_ui-default-icon-size: var(--ui-editor-toolbar-icon-size, 1rem);
322
+ --_ui-default-icon-stroke-width: var(--ui-editor-toolbar-icon-stroke-width, 1.75);
323
323
  }
324
324
 
325
325
  .chevron {
326
326
  display: inline-flex;
327
- --ui-icon-size: 0.875rem;
327
+ --_ui-default-icon-size: 0.875rem;
328
328
  }
329
329
 
330
330
  [data-component~="ui-editor-table-toolbar"] .icon-button {
@@ -39,6 +39,20 @@ const hostState = computed(() =>
39
39
  </template>
40
40
 
41
41
  <style scoped>
42
+ /* This component's hooks style the element they are set on, and never a nested one. */
43
+ @property --ui-floating-action-button-inset-block-end {
44
+ syntax: "*";
45
+ inherits: false;
46
+ }
47
+ @property --ui-floating-action-button-inset-inline-end {
48
+ syntax: "*";
49
+ inherits: false;
50
+ }
51
+ @property --ui-floating-action-button-z-index {
52
+ syntax: "*";
53
+ inherits: false;
54
+ }
55
+
42
56
  [data-component~="ui-floating-action-button"] {
43
57
  position: fixed;
44
58
  inset-block-end: calc(
@@ -40,7 +40,16 @@ useComponentHost(controllerModule.default, {
40
40
  </template>
41
41
 
42
42
  <style scoped>
43
+ /* This component's hooks style the element they are set on, and never a nested one. */
44
+ @property --ui-form-field-help-min-block-size {
45
+ syntax: "*";
46
+ inherits: false;
47
+ }
48
+
43
49
  [data-component~="ui-form-field"] {
50
+ /* Hooks do not inherit, so the parts below read them from the root. */
51
+ --_ui-form-field-help-min-block-size: var(--ui-form-field-help-min-block-size);
52
+
44
53
  display: grid;
45
54
  gap: var(--ui-space-2);
46
55
  min-inline-size: 0;
@@ -68,7 +77,7 @@ useComponentHost(controllerModule.default, {
68
77
  }
69
78
 
70
79
  .help > :slotted(*) {
71
- min-block-size: var(--ui-form-field-help-min-block-size, 0);
80
+ min-block-size: var(--_ui-form-field-help-min-block-size, 0);
72
81
  }
73
82
 
74
83
  /* An error reads in the danger colour, the one the invalid control's border takes. */
package/vue/UiGrid.vue CHANGED
@@ -25,6 +25,16 @@ const hostState = computed(() =>
25
25
  </template>
26
26
 
27
27
  <style scoped>
28
+ /* This component's hooks style the element they are set on, and never a nested one. */
29
+ @property --ui-grid-gap {
30
+ syntax: "*";
31
+ inherits: false;
32
+ }
33
+ @property --ui-grid-min {
34
+ syntax: "*";
35
+ inherits: false;
36
+ }
37
+
28
38
  [data-component~="ui-grid"] {
29
39
  --_grid-gap: var(--ui-space-4);
30
40
  --_grid-min: 12rem;
package/vue/UiIcon.vue CHANGED
@@ -80,17 +80,31 @@ useComponentHost(controllerModule.default, {
80
80
  </template>
81
81
 
82
82
  <style scoped>
83
+ /* This component's hooks style the element they are set on, and never a nested one. */
84
+ @property --ui-icon-size {
85
+ syntax: "*";
86
+ inherits: false;
87
+ }
88
+ @property --ui-icon-stroke-width {
89
+ syntax: "*";
90
+ inherits: false;
91
+ }
92
+
83
93
  [data-component~="ui-icon"] {
94
+ /* Hooks do not inherit, so the svg reads the stroke from the root. A Looma component that
95
+ sizes the icons it renders sets --_ui-default-icon-*, which the icon's own hooks override. */
96
+ --_ui-icon-stroke-width: var(--ui-icon-stroke-width, var(--_ui-default-icon-stroke-width));
97
+
84
98
  display: inline-flex;
85
99
  flex: none;
86
- inline-size: var(--ui-icon-size, 1em);
87
- block-size: var(--ui-icon-size, 1em);
100
+ inline-size: var(--ui-icon-size, var(--_ui-default-icon-size, 1em));
101
+ block-size: var(--ui-icon-size, var(--_ui-default-icon-size, 1em));
88
102
  }
89
103
 
90
104
  svg {
91
105
  inline-size: 100%;
92
106
  block-size: 100%;
93
- stroke-width: var(--ui-icon-stroke-width, 2);
107
+ stroke-width: var(--_ui-icon-stroke-width, 2);
94
108
  }
95
109
 
96
110
  /* A component that sets its display still honours the hidden attribute on its root. */
@@ -60,7 +60,85 @@ useComponentHost(controllerModule.default, {
60
60
  </template>
61
61
 
62
62
  <style scoped>
63
+ /* This component's hooks style the element they are set on, and never a nested one. */
64
+ @property --ui-icon-button-active-scale {
65
+ syntax: "*";
66
+ inherits: false;
67
+ }
68
+ @property --ui-icon-button-border {
69
+ syntax: "*";
70
+ inherits: false;
71
+ }
72
+ @property --ui-icon-button-disabled-filter {
73
+ syntax: "*";
74
+ inherits: false;
75
+ }
76
+ @property --ui-icon-button-disabled-opacity {
77
+ syntax: "*";
78
+ inherits: false;
79
+ }
80
+ @property --ui-icon-button-hover-border {
81
+ syntax: "*";
82
+ inherits: false;
83
+ }
84
+ @property --ui-icon-button-hover-surface {
85
+ syntax: "*";
86
+ inherits: false;
87
+ }
88
+ @property --ui-icon-button-hover-text {
89
+ syntax: "*";
90
+ inherits: false;
91
+ }
92
+ @property --ui-icon-button-icon-size {
93
+ syntax: "*";
94
+ inherits: false;
95
+ }
96
+ @property --ui-icon-button-icon-stroke-width {
97
+ syntax: "*";
98
+ inherits: false;
99
+ }
100
+ @property --ui-icon-button-outline-surface {
101
+ syntax: "*";
102
+ inherits: false;
103
+ }
104
+ @property --ui-icon-button-outline-text {
105
+ syntax: "*";
106
+ inherits: false;
107
+ }
108
+ @property --ui-icon-button-radius {
109
+ syntax: "*";
110
+ inherits: false;
111
+ }
112
+ @property --ui-icon-button-size {
113
+ syntax: "*";
114
+ inherits: false;
115
+ }
116
+ @property --ui-icon-button-solid-hover-surface {
117
+ syntax: "*";
118
+ inherits: false;
119
+ }
120
+ @property --ui-icon-button-solid-shadow {
121
+ syntax: "*";
122
+ inherits: false;
123
+ }
124
+ @property --ui-icon-button-solid-surface {
125
+ syntax: "*";
126
+ inherits: false;
127
+ }
128
+ @property --ui-icon-button-solid-text {
129
+ syntax: "*";
130
+ inherits: false;
131
+ }
132
+ @property --ui-icon-button-surface {
133
+ syntax: "*";
134
+ inherits: false;
135
+ }
136
+
63
137
  [data-component~="ui-icon-button"] {
138
+ /* Hooks do not inherit, so the parts below read them from the root. */
139
+ --_ui-icon-button-icon-size: var(--ui-icon-button-icon-size);
140
+ --_ui-icon-button-icon-stroke-width: var(--ui-icon-button-icon-stroke-width);
141
+
64
142
  display: inline-flex;
65
143
  color: var(--ui-text-secondary);
66
144
  }
@@ -242,10 +320,10 @@ html[data-ui-input-modality="touch"] [data-component~="ui-icon-button"]::after {
242
320
  }
243
321
 
244
322
  :slotted(svg) {
245
- inline-size: var(--ui-icon-button-icon-size, var(--_icon-button-icon-default));
246
- block-size: var(--ui-icon-button-icon-size, var(--_icon-button-icon-default));
323
+ inline-size: var(--_ui-icon-button-icon-size, var(--_icon-button-icon-default));
324
+ block-size: var(--_ui-icon-button-icon-size, var(--_icon-button-icon-default));
247
325
  flex-shrink: 0;
248
- stroke-width: var(--ui-icon-button-icon-stroke-width, 1.75);
326
+ stroke-width: var(--_ui-icon-button-icon-stroke-width, 1.75);
249
327
  }
250
328
 
251
329
  /* A component that sets its display still honours the hidden attribute on its root. */
package/vue/UiInput.vue CHANGED
@@ -55,23 +55,83 @@ useComponentHost(controllerModule.default, {
55
55
  </template>
56
56
 
57
57
  <style scoped>
58
+ /* This component's hooks style the element they are set on, and never a nested one. An Input
59
+ Group sets --_ui-default-input-* for the input inside it, below the input's own hooks. */
60
+ @property --ui-input-border {
61
+ syntax: "*";
62
+ inherits: false;
63
+ }
64
+ @property --ui-input-border-hover {
65
+ syntax: "*";
66
+ inherits: false;
67
+ }
68
+ @property --ui-input-border-width {
69
+ syntax: "*";
70
+ inherits: false;
71
+ }
72
+ @property --ui-input-focus-border {
73
+ syntax: "*";
74
+ inherits: false;
75
+ }
76
+ @property --ui-input-focus-outline {
77
+ syntax: "*";
78
+ inherits: false;
79
+ }
80
+ @property --ui-input-focus-shadow {
81
+ syntax: "*";
82
+ inherits: false;
83
+ }
84
+ @property --ui-input-invalid-border {
85
+ syntax: "*";
86
+ inherits: false;
87
+ }
88
+ @property --ui-input-invalid-focus-shadow {
89
+ syntax: "*";
90
+ inherits: false;
91
+ }
92
+ @property --ui-input-min-block-size {
93
+ syntax: "*";
94
+ inherits: false;
95
+ }
96
+ @property --ui-input-radius {
97
+ syntax: "*";
98
+ inherits: false;
99
+ }
100
+ @property --ui-input-shadow {
101
+ syntax: "*";
102
+ inherits: false;
103
+ }
104
+ @property --ui-input-surface {
105
+ syntax: "*";
106
+ inherits: false;
107
+ }
108
+
58
109
  [data-component~="ui-input"] {
59
110
  box-sizing: border-box;
60
111
  display: inline-block;
61
112
  inline-size: 100%;
62
113
  min-inline-size: 0;
63
- min-block-size: var(--ui-input-min-block-size, var(--ui-control-size-md));
114
+ min-block-size: var(
115
+ --ui-input-min-block-size,
116
+ var(--_ui-default-input-min-block-size, var(--ui-control-size-md))
117
+ );
64
118
  margin: 0;
65
119
  padding: var(--ui-space-2) var(--ui-space-3);
66
120
  appearance: none;
67
- border: var(--ui-input-border-width, 1px) solid
68
- var(--ui-input-border, var(--ui-control-border, var(--ui-border-strong)));
69
- border-radius: var(--ui-input-radius, var(--ui-radius-md));
70
- background: var(--ui-input-surface, var(--ui-control-surface, var(--ui-surface-elevated)));
121
+ border: var(--ui-input-border-width, var(--_ui-default-input-border-width, 1px)) solid
122
+ var(
123
+ --ui-input-border,
124
+ var(--_ui-default-input-border, var(--ui-control-border, var(--ui-border-strong)))
125
+ );
126
+ border-radius: var(--ui-input-radius, var(--_ui-default-input-radius, var(--ui-radius-md)));
127
+ background: var(
128
+ --ui-input-surface,
129
+ var(--_ui-default-input-surface, var(--ui-control-surface, var(--ui-surface-elevated)))
130
+ );
71
131
  color: var(--ui-text-primary);
72
132
  font: inherit;
73
133
  line-height: var(--ui-line-height-md);
74
- box-shadow: var(--ui-input-shadow, var(--ui-control-inset));
134
+ box-shadow: var(--ui-input-shadow, var(--_ui-default-input-shadow, var(--ui-control-inset)));
75
135
  transition:
76
136
  border-color var(--ui-motion-fast) var(--ui-motion-ease),
77
137
  box-shadow var(--ui-motion-fast) var(--ui-motion-ease),
@@ -92,31 +152,43 @@ useComponentHost(controllerModule.default, {
92
152
  [data-component~="ui-input"]:hover:not(:focus):not(:disabled) {
93
153
  border-color: var(
94
154
  --ui-input-border-hover,
95
- var(--ui-control-border-hover, var(--ui-text-secondary))
155
+ var(--_ui-default-input-border-hover, var(--ui-control-border-hover, var(--ui-text-secondary)))
96
156
  );
97
157
  }
98
158
 
99
159
  [data-component~="ui-input"]:focus-visible {
100
- border-color: var(--ui-input-focus-border, var(--ui-control-focus, var(--ui-accent-solid)));
160
+ border-color: var(
161
+ --ui-input-focus-border,
162
+ var(--_ui-default-input-focus-border, var(--ui-control-focus, var(--ui-accent-solid)))
163
+ );
101
164
  outline: none;
102
165
  box-shadow: var(
103
166
  --ui-input-focus-shadow,
104
- var(--ui-control-inset),
105
- var(--ui-control-focus-halo-shadow)
167
+ var(
168
+ --_ui-default-input-focus-shadow,
169
+ var(--ui-control-inset),
170
+ var(--ui-control-focus-halo-shadow)
171
+ )
106
172
  );
107
173
  }
108
174
 
109
175
  /* The app's invalid flag, or the browser's own verdict once the user has left an invalid field. */
110
176
  [data-component~="ui-input"][aria-invalid="true"],
111
177
  [data-component~="ui-input"]:is(:user-invalid, [data-user-invalid]) {
112
- border-color: var(--ui-input-invalid-border, var(--ui-danger-solid));
178
+ border-color: var(
179
+ --ui-input-invalid-border,
180
+ var(--_ui-default-input-invalid-border, var(--ui-danger-solid))
181
+ );
113
182
  }
114
183
 
115
184
  [data-component~="ui-input"]:is([aria-invalid="true"], :is(:user-invalid, [data-user-invalid])):focus-visible {
116
185
  box-shadow: var(
117
186
  --ui-input-invalid-focus-shadow,
118
- var(--ui-control-inset),
119
- 0 0 0 3px color-mix(in srgb, var(--ui-danger-solid) 22%, transparent)
187
+ var(
188
+ --_ui-default-input-invalid-focus-shadow,
189
+ var(--ui-control-inset),
190
+ 0 0 0 3px color-mix(in srgb, var(--ui-danger-solid) 22%, transparent)
191
+ )
120
192
  );
121
193
  }
122
194
 
@@ -130,7 +202,10 @@ useComponentHost(controllerModule.default, {
130
202
  /* Forced colors drop box shadows, so the focus ring becomes an outline. */
131
203
  @media (forced-colors: active) {
132
204
  [data-component~="ui-input"]:focus-visible {
133
- outline: var(--ui-input-focus-outline, 2px solid Highlight);
205
+ outline: var(
206
+ --ui-input-focus-outline,
207
+ var(--_ui-default-input-focus-outline, 2px solid Highlight)
208
+ );
134
209
  outline-offset: 1px;
135
210
  }
136
211
  }
@@ -57,19 +57,20 @@ useComponentHost(controllerModule.default, {
57
57
  thing the field is for ("Continue" after a site's address), so it reads as the field's action
58
58
  and not the form's. */
59
59
  [data-component~="ui-input-group"] {
60
- /* The group's own border and height stand for the input's, so the group is a lone Input's height. */
61
- --ui-input-border-width: 0;
62
- --ui-input-min-block-size: 0;
63
- --ui-input-border: transparent;
64
- --ui-input-border-hover: transparent;
65
- --ui-input-focus-border: transparent;
66
- --ui-input-invalid-border: transparent;
67
- --ui-input-invalid-focus-shadow: none;
68
- --ui-input-shadow: none;
69
- --ui-input-focus-shadow: none;
70
- --ui-input-focus-outline: none;
71
- --ui-input-radius: 0;
72
- --ui-input-surface: transparent;
60
+ /* The group's own border and height stand for the input's, so the group is a lone Input's height.
61
+ Hooks do not inherit, so these are defaults for the input; its own hooks still win. */
62
+ --_ui-default-input-border-width: 0;
63
+ --_ui-default-input-min-block-size: 0;
64
+ --_ui-default-input-border: transparent;
65
+ --_ui-default-input-border-hover: transparent;
66
+ --_ui-default-input-focus-border: transparent;
67
+ --_ui-default-input-invalid-border: transparent;
68
+ --_ui-default-input-invalid-focus-shadow: none;
69
+ --_ui-default-input-shadow: none;
70
+ --_ui-default-input-focus-shadow: none;
71
+ --_ui-default-input-focus-outline: none;
72
+ --_ui-default-input-radius: 0;
73
+ --_ui-default-input-surface: transparent;
73
74
 
74
75
  display: flex;
75
76
  align-items: stretch;
package/vue/UiList.vue CHANGED
@@ -36,9 +36,19 @@ const hostState = computed(() =>
36
36
  </template>
37
37
 
38
38
  <style scoped>
39
+ /* This component's hooks style the element they are set on, and never a nested one. */
40
+ @property --ui-list-gap {
41
+ syntax: "*";
42
+ inherits: false;
43
+ }
44
+ @property --ui-list-min-item-width {
45
+ syntax: "*";
46
+ inherits: false;
47
+ }
48
+
39
49
  /* A list of items (ui-list-item). It owns the spacing between them, so a view never sets it. The
40
- explicit list role keeps the list announced as one: some browsers drop it from a list with no
41
- markers. */
50
+ explicit list role keeps the list announced as one: some browsers drop it from a list with no
51
+ markers. */
42
52
  [data-component~="ui-list"] {
43
53
  display: flex;
44
54
  flex-direction: column;
@@ -39,16 +39,37 @@ const hostState = computed(() =>
39
39
  </template>
40
40
 
41
41
  <style scoped>
42
+ /* This component's hooks style the element they are set on, and never a nested one. */
43
+ @property --ui-list-item-gap {
44
+ syntax: "*";
45
+ inherits: false;
46
+ }
47
+ @property --ui-list-item-icon-size {
48
+ syntax: "*";
49
+ inherits: false;
50
+ }
51
+ @property --ui-list-item-padding-block {
52
+ syntax: "*";
53
+ inherits: false;
54
+ }
55
+ @property --ui-list-item-padding-inline {
56
+ syntax: "*";
57
+ inherits: false;
58
+ }
59
+
42
60
  /* One entry in a list: something to recognise (leading, usually an icon), its name (the default
43
- slot), one line about it (description), and what it offers (trailing, such as a button or a
44
- badge). The title and description are one line each and end in an ellipsis, so every item in a
45
- list has the same height.
46
-
47
- A link in the title is the whole item: its hit area stretches over the item, so the icon and the
48
- padding follow it too, and the item takes the link's focus ring. The link stays a real link, so
49
- a router, a modified click, and "open in new tab" all work. Trailing controls sit above it and
50
- stay their own. */
61
+ slot), one line about it (description), and what it offers (trailing, such as a button or a
62
+ badge). The title and description are one line each and end in an ellipsis, so every item in a
63
+ list has the same height.
64
+
65
+ A link in the title is the whole item: its hit area stretches over the item, so the icon and the
66
+ padding follow it too, and the item takes the link's focus ring. The link stays a real link, so
67
+ a router, a modified click, and "open in new tab" all work. Trailing controls sit above it and
68
+ stay their own. */
51
69
  [data-component~="ui-list-item"] {
70
+ /* Hooks do not inherit, so the parts below read them from the root. */
71
+ --_ui-list-item-icon-size: var(--ui-list-item-icon-size);
72
+
52
73
  position: relative;
53
74
  box-sizing: border-box;
54
75
  display: flex;
@@ -106,7 +127,7 @@ const hostState = computed(() =>
106
127
 
107
128
  .leading {
108
129
  color: var(--ui-text-muted);
109
- font-size: var(--ui-list-item-icon-size, var(--ui-font-size-lg));
130
+ font-size: var(--_ui-list-item-icon-size, var(--ui-font-size-lg));
110
131
  }
111
132
 
112
133
  /* Trailing controls take their own clicks, above the title link's stretched hit area. */
package/vue/UiMenu.vue CHANGED
@@ -110,17 +110,29 @@ useComponentHost(controllerModule.default, {
110
110
  </template>
111
111
 
112
112
  <style scoped>
113
- /* Compact sets the part tokens its items read, so nothing has to rescale a global. */
113
+ /* This component's hooks style the element they are set on, and never a nested one. */
114
+ @property --ui-menu-viewport-gap {
115
+ syntax: "*";
116
+ inherits: false;
117
+ }
118
+
119
+ /* Compact sets its items' defaults, so nothing has to rescale a global; an item's own hooks
120
+ still win. */
114
121
  [data-component~="ui-menu"][data-ui-menu-state~="density=compact"] {
115
- --ui-menu-item-padding-block: var(--ui-space-1);
116
- --ui-menu-item-padding-inline: var(--ui-space-2);
117
- --ui-menu-item-font-size: var(--ui-font-size-sm);
118
- --ui-menu-item-radius: var(--ui-radius-sm);
122
+ --_ui-default-menu-item-padding-block: var(--ui-space-1);
123
+ --_ui-default-menu-item-padding-inline: var(--ui-space-2);
124
+ --_ui-default-menu-item-font-size: var(--ui-font-size-sm);
125
+ --_ui-default-menu-item-radius: var(--ui-radius-sm);
119
126
  padding: var(--ui-space-1);
120
127
  gap: 0;
121
128
  }
122
129
 
123
130
  [data-component~="ui-menu"] {
131
+ /* A menu nested in a compact one starts again from its own density. */
132
+ --_ui-default-menu-item-padding-block: initial;
133
+ --_ui-default-menu-item-padding-inline: initial;
134
+ --_ui-default-menu-item-font-size: initial;
135
+ --_ui-default-menu-item-radius: initial;
124
136
  display: flex;
125
137
  flex-direction: column;
126
138
  box-sizing: border-box;
@@ -28,16 +28,54 @@ withDefaults(
28
28
  </template>
29
29
 
30
30
  <style scoped>
31
+ /* This component's hooks style the element they are set on, and never a nested one. */
32
+ @property --ui-menu-item-font-size {
33
+ syntax: "*";
34
+ inherits: false;
35
+ }
36
+ @property --ui-menu-item-hover-surface {
37
+ syntax: "*";
38
+ inherits: false;
39
+ }
40
+ @property --ui-menu-item-min-block-size {
41
+ syntax: "*";
42
+ inherits: false;
43
+ }
44
+ @property --ui-menu-item-padding-block {
45
+ syntax: "*";
46
+ inherits: false;
47
+ }
48
+ @property --ui-menu-item-padding-inline {
49
+ syntax: "*";
50
+ inherits: false;
51
+ }
52
+ @property --ui-menu-item-radius {
53
+ syntax: "*";
54
+ inherits: false;
55
+ }
56
+
31
57
  [data-component~="ui-menu-item"] {
32
58
  display: block;
33
59
  box-sizing: border-box;
34
60
  width: 100%;
35
- padding: var(--ui-menu-item-padding-block, var(--ui-space-2))
36
- var(--ui-menu-item-padding-inline, var(--ui-space-3));
61
+ padding: var(
62
+ --ui-menu-item-padding-block,
63
+ var(--_ui-default-menu-item-padding-block, var(--ui-space-2))
64
+ )
65
+ var(
66
+ --ui-menu-item-padding-inline,
67
+ var(--_ui-default-menu-item-padding-inline, var(--ui-space-3))
68
+ );
37
69
  text-align: left;
38
- border-radius: var(--ui-menu-item-radius, var(--ui-radius-md));
70
+ border-radius: var(
71
+ --ui-menu-item-radius,
72
+ var(--_ui-default-menu-item-radius, var(--ui-radius-md))
73
+ );
39
74
  color: var(--ui-text-primary);
40
- font-size: var(--ui-menu-item-font-size, var(--ui-font-size-md));
75
+ font-size: var(
76
+ --ui-menu-item-font-size,
77
+ var(--_ui-default-menu-item-font-size, var(--ui-font-size-md))
78
+ );
41
79
  font-weight: var(--ui-font-medium);
42
80
  cursor: pointer;
43
81
  outline: none;
package/vue/UiNavItem.vue CHANGED
@@ -57,10 +57,24 @@ function attribute(value: unknown): any {
57
57
  </template>
58
58
 
59
59
  <style scoped>
60
+ /* This component's hooks style the element they are set on, and never a nested one. */
61
+ @property --ui-nav-item-current-surface {
62
+ syntax: "*";
63
+ inherits: false;
64
+ }
65
+ @property --ui-nav-item-indicator-color {
66
+ syntax: "*";
67
+ inherits: false;
68
+ }
69
+ @property --ui-nav-item-indicator-width {
70
+ syntax: "*";
71
+ inherits: false;
72
+ }
73
+
60
74
  /* One destination in a side or rail navigation: an icon to find it by (leading), its name (the
61
- default slot), and an optional line under it (description), such as the record a section
62
- belongs to. Label and description are one line each and end in an ellipsis, so every item in a
63
- navigation has the same height and the rail never grows sideways. */
75
+ default slot), and an optional line under it (description), such as the record a section
76
+ belongs to. Label and description are one line each and end in an ellipsis, so every item in a
77
+ navigation has the same height and the rail never grows sideways. */
64
78
  [data-component~="ui-nav-item"] {
65
79
  --_indicator-width: var(--ui-nav-item-indicator-width, 3px);
66
80
  --_indicator-color: var(--ui-nav-item-indicator-color, var(--ui-accent));