@threadlabs/looma 0.12.7 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) 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 +16 -2
  4. package/components/ui-badge/ui-badge.html +42 -0
  5. package/components/ui-button/ui-button.html +70 -0
  6. package/components/ui-callout/ui-callout.html +55 -4
  7. package/components/ui-checkbox/ui-checkbox.html +15 -2
  8. package/components/ui-cluster/ui-cluster.html +7 -1
  9. package/components/ui-combobox/ui-combobox.html +64 -10
  10. package/components/ui-container/ui-container.html +12 -1
  11. package/components/ui-context-menu/ui-context-menu.html +10 -1
  12. package/components/ui-dialog/ui-dialog.html +21 -4
  13. package/components/ui-disclosure/ui-disclosure.html +22 -3
  14. package/components/ui-editor-slash-menu/ui-editor-slash-menu.html +2 -2
  15. package/components/ui-editor-table-context-menu/ui-editor-table-context-menu.html +2 -2
  16. package/components/ui-editor-table-overlay/ui-editor-table-overlay.html +8 -8
  17. package/components/ui-editor-table-toolbar/ui-editor-table-toolbar.html +3 -3
  18. package/components/ui-floating-action-button/ui-floating-action-button.html +14 -0
  19. package/components/ui-form-field/ui-form-field.html +10 -1
  20. package/components/ui-grid/ui-grid.html +11 -1
  21. package/components/ui-icon/ui-icon.html +17 -3
  22. package/components/ui-icon-button/ui-icon-button.html +81 -3
  23. package/components/ui-input/ui-input.html +67 -12
  24. package/components/ui-input-group/ui-input-group.html +14 -13
  25. package/components/ui-list/ui-list.html +10 -0
  26. package/components/ui-list-item/ui-list-item.html +22 -1
  27. package/components/ui-menu/ui-menu.html +17 -5
  28. package/components/ui-menu-item/ui-menu-item.html +30 -3
  29. package/components/ui-nav-item/ui-nav-item.html +14 -0
  30. package/components/ui-popover/ui-popover.html +6 -0
  31. package/components/ui-radio/ui-radio.html +15 -2
  32. package/components/ui-reel/ui-reel.html +15 -2
  33. package/components/ui-search-result-row/ui-search-result-row.html +34 -0
  34. package/components/ui-search-shell/ui-search-shell.html +65 -11
  35. package/components/ui-select/ui-select.html +14 -0
  36. package/components/ui-separator/ui-separator.html +9 -2
  37. package/components/ui-sidebar/ui-sidebar.html +22 -1
  38. package/components/ui-stack/ui-stack.html +7 -1
  39. package/components/ui-switch/ui-switch.html +20 -2
  40. package/components/ui-switcher/ui-switcher.html +18 -5
  41. package/components/ui-tabs/ui-tabs.html +21 -2
  42. package/components/ui-textarea/ui-textarea.html +14 -0
  43. package/components/ui-toast-region/ui-toast-region.html +16 -2
  44. package/components/ui-tooltip/ui-tooltip.html +62 -13
  45. package/components/ui-top-bar/ui-top-bar.html +34 -1
  46. package/components/ui-tree/ui-tree.html +27 -4
  47. package/components/ui-tree-item/ui-tree-item.html +39 -10
  48. package/components/ui-tree-item/ui-tree-item.js +1 -1
  49. package/dist/index.js +1 -1
  50. package/package.json +1 -1
  51. package/styles/ui-action-bar.css +14 -3
  52. package/styles/ui-avatar-group.css +20 -4
  53. package/styles/ui-avatar.css +22 -2
  54. package/styles/ui-badge.css +46 -2
  55. package/styles/ui-button.css +74 -2
  56. package/styles/ui-callout.css +59 -6
  57. package/styles/ui-checkbox.css +19 -4
  58. package/styles/ui-cluster.css +10 -2
  59. package/styles/ui-combobox.css +67 -12
  60. package/styles/ui-container.css +14 -2
  61. package/styles/ui-context-menu.css +14 -3
  62. package/styles/ui-dialog.css +25 -6
  63. package/styles/ui-disclosure.css +26 -5
  64. package/styles/ui-editor-slash-menu.css +2 -2
  65. package/styles/ui-editor-table-context-menu.css +2 -2
  66. package/styles/ui-editor-table-overlay.css +8 -8
  67. package/styles/ui-editor-table-toolbar.css +3 -3
  68. package/styles/ui-floating-action-button.css +18 -2
  69. package/styles/ui-form-field.css +14 -3
  70. package/styles/ui-grid.css +14 -2
  71. package/styles/ui-icon-button.css +85 -5
  72. package/styles/ui-icon.css +21 -5
  73. package/styles/ui-input-group.css +14 -13
  74. package/styles/ui-input.css +72 -14
  75. package/styles/ui-list-item.css +26 -3
  76. package/styles/ui-list.css +14 -2
  77. package/styles/ui-menu-item.css +34 -5
  78. package/styles/ui-menu.css +21 -6
  79. package/styles/ui-nav-item.css +18 -2
  80. package/styles/ui-popover.css +10 -2
  81. package/styles/ui-radio.css +19 -4
  82. package/styles/ui-reel.css +18 -3
  83. package/styles/ui-search-result-row.css +38 -2
  84. package/styles/ui-search-shell.css +69 -13
  85. package/styles/ui-select.css +18 -2
  86. package/styles/ui-separator.css +14 -2
  87. package/styles/ui-sidebar.css +26 -3
  88. package/styles/ui-stack.css +10 -2
  89. package/styles/ui-switch.css +24 -4
  90. package/styles/ui-switcher.css +21 -6
  91. package/styles/ui-tabs.css +25 -4
  92. package/styles/ui-textarea.css +18 -2
  93. package/styles/ui-toast-region.css +20 -4
  94. package/styles/ui-tooltip.css +66 -15
  95. package/styles/ui-top-bar.css +38 -3
  96. package/styles/ui-tree-item.css +43 -12
  97. package/styles/ui-tree.css +33 -6
  98. package/vue/UiActionBar.vue +12 -3
  99. package/vue/UiAvatar.vue +18 -0
  100. package/vue/UiAvatarGroup.vue +16 -2
  101. package/vue/UiBadge.vue +42 -0
  102. package/vue/UiButton.vue +70 -0
  103. package/vue/UiCallout.vue +55 -4
  104. package/vue/UiCheckbox.vue +15 -2
  105. package/vue/UiCluster.vue +6 -0
  106. package/vue/UiCombobox.vue +64 -10
  107. package/vue/UiContainer.vue +10 -0
  108. package/vue/UiContextMenu.vue +10 -1
  109. package/vue/UiDialog.vue +21 -4
  110. package/vue/UiDisclosure.vue +22 -3
  111. package/vue/UiEditorSlashMenu.vue +2 -2
  112. package/vue/UiEditorTableContextMenu.vue +2 -2
  113. package/vue/UiEditorTableOverlay.vue +8 -8
  114. package/vue/UiEditorTableToolbar.vue +3 -3
  115. package/vue/UiFloatingActionButton.vue +14 -0
  116. package/vue/UiFormField.vue +10 -1
  117. package/vue/UiGrid.vue +10 -0
  118. package/vue/UiIcon.vue +17 -3
  119. package/vue/UiIconButton.vue +81 -3
  120. package/vue/UiInput.vue +89 -14
  121. package/vue/UiInputGroup.vue +14 -13
  122. package/vue/UiList.vue +12 -2
  123. package/vue/UiListItem.vue +30 -9
  124. package/vue/UiMenu.vue +17 -5
  125. package/vue/UiMenuItem.vue +42 -4
  126. package/vue/UiNavItem.vue +17 -3
  127. package/vue/UiPopover.vue +6 -0
  128. package/vue/UiRadio.vue +15 -2
  129. package/vue/UiReel.vue +14 -1
  130. package/vue/UiSearchResultRow.vue +34 -0
  131. package/vue/UiSearchShell.vue +66 -12
  132. package/vue/UiSelect.vue +14 -0
  133. package/vue/UiSeparator.vue +9 -2
  134. package/vue/UiSidebar.vue +22 -1
  135. package/vue/UiStack.vue +6 -0
  136. package/vue/UiSwitch.vue +20 -2
  137. package/vue/UiSwitcher.vue +17 -4
  138. package/vue/UiTabs.vue +22 -3
  139. package/vue/UiTextarea.vue +14 -0
  140. package/vue/UiToastRegion.vue +16 -2
  141. package/vue/UiTooltip.vue +62 -13
  142. package/vue/UiTopBar.vue +34 -1
  143. package/vue/UiTree.vue +28 -5
  144. package/vue/UiTreeItem.vue +46 -11
  145. package/vue/chunks/UiActionBar.js +1 -1
  146. package/vue/chunks/UiAvatar.js +1 -1
  147. package/vue/chunks/UiAvatarGroup.js +1 -1
  148. package/vue/chunks/UiBadge.js +1 -1
  149. package/vue/chunks/UiButton.js +1 -1
  150. package/vue/chunks/UiCallout.js +1 -1
  151. package/vue/chunks/UiCheckbox.js +1 -1
  152. package/vue/chunks/UiCluster.js +1 -1
  153. package/vue/chunks/UiCombobox.js +1 -1
  154. package/vue/chunks/UiContainer.js +1 -1
  155. package/vue/chunks/UiContextMenu.js +1 -1
  156. package/vue/chunks/UiDialog.js +1 -1
  157. package/vue/chunks/UiDisclosure.js +1 -1
  158. package/vue/chunks/UiEditorSlashMenu.js +1 -1
  159. package/vue/chunks/UiEditorTableContextMenu.js +1 -1
  160. package/vue/chunks/UiEditorTableOverlay.js +1 -1
  161. package/vue/chunks/UiEditorTableToolbar.js +1 -1
  162. package/vue/chunks/UiFloatingActionButton.js +1 -1
  163. package/vue/chunks/UiFormField.js +1 -1
  164. package/vue/chunks/UiGrid.js +1 -1
  165. package/vue/chunks/UiIcon.js +1 -1
  166. package/vue/chunks/UiIconButton.js +1 -1
  167. package/vue/chunks/UiInput.js +1 -1
  168. package/vue/chunks/UiInputGroup.js +1 -1
  169. package/vue/chunks/UiList.js +1 -1
  170. package/vue/chunks/UiListItem.js +1 -1
  171. package/vue/chunks/UiMenu.js +1 -1
  172. package/vue/chunks/UiMenuItem.js +1 -1
  173. package/vue/chunks/UiNavItem.js +1 -1
  174. package/vue/chunks/UiPopover.js +1 -1
  175. package/vue/chunks/UiRadio.js +1 -1
  176. package/vue/chunks/UiReel.js +1 -1
  177. package/vue/chunks/UiSearchResultRow.js +1 -1
  178. package/vue/chunks/UiSearchShell.js +1 -1
  179. package/vue/chunks/UiSelect.js +1 -1
  180. package/vue/chunks/UiSeparator.js +1 -1
  181. package/vue/chunks/UiSidebar.js +1 -1
  182. package/vue/chunks/UiStack.js +1 -1
  183. package/vue/chunks/UiSwitch.js +1 -1
  184. package/vue/chunks/UiSwitcher.js +1 -1
  185. package/vue/chunks/UiTabs.js +1 -1
  186. package/vue/chunks/UiTextarea.js +1 -1
  187. package/vue/chunks/UiToastRegion.js +1 -1
  188. package/vue/chunks/UiTooltip.js +1 -1
  189. package/vue/chunks/UiTopBar.js +1 -1
  190. package/vue/chunks/UiTree.js +1 -1
  191. package/vue/chunks/UiTreeItem.js +1 -1
  192. package/vue/components.css +1929 -897
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));
package/vue/UiPopover.vue CHANGED
@@ -83,6 +83,12 @@ useComponentHost(controllerModule.default, {
83
83
  </template>
84
84
 
85
85
  <style scoped>
86
+ /* This component's hooks style the element they are set on, and never a nested one. */
87
+ @property --ui-popover-viewport-gap {
88
+ syntax: "*";
89
+ inherits: false;
90
+ }
91
+
86
92
  [data-component~="ui-popover"] {
87
93
  box-sizing: border-box;
88
94
  max-inline-size: min(
package/vue/UiRadio.vue CHANGED
@@ -92,7 +92,20 @@ useComponentHost(controllerModule.default, {
92
92
  </template>
93
93
 
94
94
  <style scoped>
95
+ /* This component's hooks style the element they are set on, and never a nested one. */
96
+ @property --ui-radio-gap {
97
+ syntax: "*";
98
+ inherits: false;
99
+ }
100
+ @property --ui-radio-size {
101
+ syntax: "*";
102
+ inherits: false;
103
+ }
104
+
95
105
  [data-component~="ui-radio"] {
106
+ /* Hooks do not inherit, so the parts below read them from the root. */
107
+ --_ui-radio-size: var(--ui-radio-size);
108
+
96
109
  display: inline-flex;
97
110
  align-items: flex-start;
98
111
  gap: var(--ui-radio-gap, var(--ui-space-2));
@@ -126,8 +139,8 @@ useComponentHost(controllerModule.default, {
126
139
 
127
140
  input {
128
141
  flex: 0 0 auto;
129
- inline-size: var(--ui-radio-size, 1.125rem);
130
- block-size: var(--ui-radio-size, 1.125rem);
142
+ inline-size: var(--_ui-radio-size, 1.125rem);
143
+ block-size: var(--_ui-radio-size, 1.125rem);
131
144
  margin: 0.125em 0 0;
132
145
  accent-color: var(--ui-accent-solid);
133
146
  cursor: pointer;
package/vue/UiReel.vue CHANGED
@@ -33,7 +33,20 @@ const hostState = computed(() =>
33
33
  </template>
34
34
 
35
35
  <style scoped>
36
+ /* This component's hooks style the element they are set on, and never a nested one. */
37
+ @property --ui-reel-gap {
38
+ syntax: "*";
39
+ inherits: false;
40
+ }
41
+ @property --ui-reel-item-width {
42
+ syntax: "*";
43
+ inherits: false;
44
+ }
45
+
36
46
  [data-component~="ui-reel"] {
47
+ /* Hooks do not inherit, so the parts below read them from the root. */
48
+ --_ui-reel-item-width: var(--ui-reel-item-width);
49
+
37
50
  --_reel-gap: var(--ui-space-4);
38
51
  --_reel-item-width: auto;
39
52
  display: flex;
@@ -77,7 +90,7 @@ const hostState = computed(() =>
77
90
 
78
91
  [data-component~="ui-reel"] > :slotted(*) {
79
92
  min-inline-size: 0;
80
- flex: 0 0 var(--ui-reel-item-width, var(--_reel-item-width));
93
+ flex: 0 0 var(--_ui-reel-item-width, var(--_reel-item-width));
81
94
  }
82
95
 
83
96
  [data-component~="ui-reel"][data-ui-reel-state~="gap=xs"] {
@@ -41,6 +41,40 @@ const hostState = computed(() =>
41
41
  </template>
42
42
 
43
43
  <style scoped>
44
+ /* This component's hooks style the element they are set on, and never a nested one. */
45
+ @property --ui-search-result-row-border {
46
+ syntax: "*";
47
+ inherits: false;
48
+ }
49
+ @property --ui-search-result-row-gap {
50
+ syntax: "*";
51
+ inherits: false;
52
+ }
53
+ @property --ui-search-result-row-hover-surface {
54
+ syntax: "*";
55
+ inherits: false;
56
+ }
57
+ @property --ui-search-result-row-min-height {
58
+ syntax: "*";
59
+ inherits: false;
60
+ }
61
+ @property --ui-search-result-row-padding-block {
62
+ syntax: "*";
63
+ inherits: false;
64
+ }
65
+ @property --ui-search-result-row-padding-inline {
66
+ syntax: "*";
67
+ inherits: false;
68
+ }
69
+ @property --ui-search-result-row-selected-bg {
70
+ syntax: "*";
71
+ inherits: false;
72
+ }
73
+ @property --ui-search-result-row-surface {
74
+ syntax: "*";
75
+ inherits: false;
76
+ }
77
+
44
78
  [data-component~="ui-search-result-row"] {
45
79
  appearance: none;
46
80
  inline-size: 100%;