@threadlabs/looma 0.16.5 → 0.17.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 (230) hide show
  1. package/components/ui-avatar-group/ui-avatar-group.html +8 -5
  2. package/components/ui-avatar-group/ui-avatar-group.js +3 -3
  3. package/components/ui-badge/ui-badge.html +10 -5
  4. package/components/ui-breadcrumb-item/ui-breadcrumb-item.html +2 -1
  5. package/components/ui-button/ui-button.html +33 -26
  6. package/components/ui-button/ui-button.js +2 -2
  7. package/components/ui-callout/ui-callout.html +3 -1
  8. package/components/ui-card/ui-card.html +5 -3
  9. package/components/ui-checkbox/ui-checkbox.html +36 -8
  10. package/components/ui-combobox/ui-combobox.html +72 -45
  11. package/components/ui-combobox/ui-combobox.js +7 -2
  12. package/components/ui-context-menu/ui-context-menu.html +2 -2
  13. package/components/ui-description-item/ui-description-item.html +1 -1
  14. package/components/ui-description-list/ui-description-list.html +2 -0
  15. package/components/ui-dialog/ui-dialog.html +3 -23
  16. package/components/ui-disclosure/ui-disclosure.html +2 -2
  17. package/components/ui-editor-insert-table-grid/ui-editor-insert-table-grid.html +2 -2
  18. package/components/ui-editor-mention-menu/ui-editor-mention-menu.html +3 -3
  19. package/components/ui-editor-slash-menu/ui-editor-slash-menu.html +4 -4
  20. package/components/ui-editor-slash-menu-item/ui-editor-slash-menu-item.html +6 -1
  21. package/components/ui-editor-table-context-menu/ui-editor-table-context-menu.html +2 -2
  22. package/components/ui-editor-table-toolbar/ui-editor-table-toolbar.html +4 -4
  23. package/components/ui-editor-toolbar/ui-editor-toolbar.html +5 -5
  24. package/components/ui-floating-action-button/ui-floating-action-button.html +4 -2
  25. package/components/ui-icon-button/ui-icon-button.html +57 -17
  26. package/components/ui-icon-button/ui-icon-button.js +1 -1
  27. package/components/ui-list/ui-list.html +46 -6
  28. package/components/ui-list-item/ui-list-item.html +1 -1
  29. package/components/ui-menu/ui-menu.html +4 -3
  30. package/components/ui-menu/ui-menu.js +9 -3
  31. package/components/ui-menu-item/ui-menu-item.html +43 -6
  32. package/components/ui-meter/ui-meter.html +4 -1
  33. package/components/ui-nav-item/ui-nav-item.html +0 -1
  34. package/components/ui-page-header/ui-page-header.html +1 -0
  35. package/components/ui-popover/ui-popover.html +1 -1
  36. package/components/ui-radio/ui-radio.html +5 -2
  37. package/components/ui-scroll-area/ui-scroll-area.html +9 -14
  38. package/components/ui-scroll-area/ui-scroll-area.js +32 -0
  39. package/components/ui-search-result-row/ui-search-result-row.html +5 -3
  40. package/components/ui-search-shell/ui-search-shell.html +8 -8
  41. package/components/ui-section/ui-section.html +5 -3
  42. package/components/ui-separator/ui-separator.html +2 -2
  43. package/components/ui-sidebar/ui-sidebar.html +2 -2
  44. package/components/ui-spinner/ui-spinner.html +28 -8
  45. package/components/ui-status-message/ui-status-message.html +1 -1
  46. package/components/ui-switch/ui-switch.html +17 -8
  47. package/components/ui-table/ui-table.html +1 -1
  48. package/components/ui-tabs/ui-tabs.html +21 -12
  49. package/components/ui-toast/ui-toast.html +1 -1
  50. package/components/ui-toast-region/ui-toast-region.html +1 -1
  51. package/components/ui-tooltip/ui-tooltip.html +12 -12
  52. package/components/ui-tooltip/ui-tooltip.js +1 -1
  53. package/components/ui-top-bar/ui-top-bar.html +1 -1
  54. package/components/ui-tree/ui-tree.js +4 -1
  55. package/components/ui-tree-item/ui-tree-item.html +2 -1
  56. package/dist/index.js +15 -14
  57. package/editor/chunks/extensions.js +3 -4
  58. package/editor/extensions/index.d.ts +1 -1
  59. package/editor/extensions/preset.d.ts +5 -0
  60. package/package.json +1 -1
  61. package/styles/ui-avatar-group.css +8 -5
  62. package/styles/ui-badge.css +10 -5
  63. package/styles/ui-breadcrumb-item.css +2 -1
  64. package/styles/ui-button.css +19 -25
  65. package/styles/ui-callout.css +3 -1
  66. package/styles/ui-card.css +4 -2
  67. package/styles/ui-checkbox.css +38 -8
  68. package/styles/ui-combobox.css +27 -8
  69. package/styles/ui-context-menu.css +2 -2
  70. package/styles/ui-description-item.css +1 -1
  71. package/styles/ui-description-list.css +2 -0
  72. package/styles/ui-dialog.css +1 -22
  73. package/styles/ui-disclosure.css +2 -2
  74. package/styles/ui-editor-insert-table-grid.css +2 -2
  75. package/styles/ui-editor-mention-menu.css +3 -3
  76. package/styles/ui-editor-slash-menu-item.css +6 -1
  77. package/styles/ui-editor-slash-menu.css +4 -4
  78. package/styles/ui-editor-table-context-menu.css +2 -2
  79. package/styles/ui-editor-table-toolbar.css +4 -4
  80. package/styles/ui-editor-toolbar.css +5 -5
  81. package/styles/ui-floating-action-button.css +3 -1
  82. package/styles/ui-icon-button.css +53 -18
  83. package/styles/ui-list-item.css +1 -1
  84. package/styles/ui-list.css +41 -6
  85. package/styles/ui-menu-item.css +43 -5
  86. package/styles/ui-menu.css +3 -3
  87. package/styles/ui-meter.css +4 -1
  88. package/styles/ui-nav-item.css +0 -1
  89. package/styles/ui-page-header.css +1 -0
  90. package/styles/ui-popover.css +1 -1
  91. package/styles/ui-radio.css +5 -2
  92. package/styles/ui-scroll-area.css +10 -16
  93. package/styles/ui-search-result-row.css +3 -2
  94. package/styles/ui-search-shell.css +7 -7
  95. package/styles/ui-section.css +5 -3
  96. package/styles/ui-separator.css +2 -2
  97. package/styles/ui-sidebar.css +2 -2
  98. package/styles/ui-spinner.css +27 -6
  99. package/styles/ui-status-message.css +1 -1
  100. package/styles/ui-switch.css +17 -8
  101. package/styles/ui-table.css +1 -1
  102. package/styles/ui-tabs.css +60 -51
  103. package/styles/ui-toast-region.css +1 -1
  104. package/styles/ui-toast.css +1 -1
  105. package/styles/ui-tooltip.css +12 -12
  106. package/styles/ui-top-bar.css +1 -1
  107. package/styles/ui-tree-item.css +2 -1
  108. package/theme-dark.css +4 -4
  109. package/theme-light.css +3 -3
  110. package/tokens.css +9 -6
  111. package/vanilla/UiButton.d.ts +1 -0
  112. package/vanilla/UiButton.js +17 -19
  113. package/vanilla/UiCombobox.js +162 -159
  114. package/vanilla/UiDialog.js +2 -2
  115. package/vanilla/UiIconButton.d.ts +1 -0
  116. package/vanilla/UiIconButton.js +1 -4
  117. package/vanilla/UiList.d.ts +3 -1
  118. package/vanilla/UiList.js +36 -19
  119. package/vanilla/UiMenu.d.ts +1 -0
  120. package/vanilla/UiMenu.js +1 -1
  121. package/vanilla/UiMenuItem.js +10 -13
  122. package/vanilla/UiScrollArea.js +11 -6
  123. package/vanilla/UiSearchShell.js +2 -2
  124. package/vanilla/UiSpinner.js +2 -4
  125. package/vue/UiAvatarGroup.vue +8 -5
  126. package/vue/UiBadge.vue +10 -5
  127. package/vue/UiBreadcrumbItem.vue +2 -1
  128. package/vue/UiButton.d.ts +2 -0
  129. package/vue/UiButton.vue +31 -28
  130. package/vue/UiCallout.vue +3 -2
  131. package/vue/UiCard.vue +4 -2
  132. package/vue/UiCheckbox.vue +36 -8
  133. package/vue/UiCombobox.d.ts +1 -1
  134. package/vue/UiCombobox.vue +55 -35
  135. package/vue/UiContextMenu.vue +2 -2
  136. package/vue/UiDescriptionItem.vue +1 -1
  137. package/vue/UiDescriptionList.vue +2 -0
  138. package/vue/UiDialog.d.ts +3 -3
  139. package/vue/UiDialog.vue +3 -27
  140. package/vue/UiDisclosure.vue +2 -2
  141. package/vue/UiEditorInsertTableGrid.vue +2 -2
  142. package/vue/UiEditorMentionMenu.d.ts +1 -1
  143. package/vue/UiEditorMentionMenu.vue +4 -3
  144. package/vue/UiEditorSlashMenu.vue +6 -4
  145. package/vue/UiEditorSlashMenuItem.vue +6 -1
  146. package/vue/UiEditorTableContextMenu.vue +2 -2
  147. package/vue/UiEditorTableToolbar.vue +4 -4
  148. package/vue/UiEditorToolbar.vue +5 -5
  149. package/vue/UiFloatingActionButton.vue +3 -1
  150. package/vue/UiIconButton.d.ts +2 -0
  151. package/vue/UiIconButton.vue +61 -19
  152. package/vue/UiList.d.ts +7 -1
  153. package/vue/UiList.vue +57 -6
  154. package/vue/UiListItem.vue +1 -1
  155. package/vue/UiMenu.d.ts +2 -0
  156. package/vue/UiMenu.vue +6 -3
  157. package/vue/UiMenuItem.d.ts +3 -3
  158. package/vue/UiMenuItem.vue +47 -7
  159. package/vue/UiMeter.vue +4 -1
  160. package/vue/UiNavItem.vue +0 -1
  161. package/vue/UiPageHeader.vue +1 -0
  162. package/vue/UiPopover.vue +1 -1
  163. package/vue/UiRadio.vue +5 -2
  164. package/vue/UiScrollArea.vue +24 -18
  165. package/vue/UiSearchResultRow.vue +3 -2
  166. package/vue/UiSearchShell.vue +8 -8
  167. package/vue/UiSection.vue +5 -3
  168. package/vue/UiSeparator.vue +2 -2
  169. package/vue/UiSidebar.vue +2 -2
  170. package/vue/UiSpinner.vue +28 -7
  171. package/vue/UiStatusMessage.vue +1 -1
  172. package/vue/UiSwitch.vue +20 -9
  173. package/vue/UiTable.vue +1 -1
  174. package/vue/UiTabs.vue +25 -12
  175. package/vue/UiToast.vue +1 -1
  176. package/vue/UiToastRegion.vue +1 -1
  177. package/vue/UiTooltip.vue +12 -12
  178. package/vue/UiTopBar.vue +1 -1
  179. package/vue/UiTreeItem.vue +2 -1
  180. package/vue/chunks/UiAvatarGroup.js +1 -1
  181. package/vue/chunks/UiBadge.js +1 -1
  182. package/vue/chunks/UiBreadcrumbItem.js +1 -1
  183. package/vue/chunks/UiButton.js +28 -23
  184. package/vue/chunks/UiCallout.js +1 -1
  185. package/vue/chunks/UiCard.js +1 -1
  186. package/vue/chunks/UiCheckbox.js +1 -1
  187. package/vue/chunks/UiCombobox.js +80 -77
  188. package/vue/chunks/UiContextMenu.js +1 -1
  189. package/vue/chunks/UiDescriptionItem.js +1 -1
  190. package/vue/chunks/UiDescriptionList.js +1 -1
  191. package/vue/chunks/UiDialog.js +7 -4
  192. package/vue/chunks/UiDisclosure.js +1 -1
  193. package/vue/chunks/UiEditorInsertTableGrid.js +1 -1
  194. package/vue/chunks/UiEditorMentionMenu.js +1 -1
  195. package/vue/chunks/UiEditorSlashMenu.js +1 -1
  196. package/vue/chunks/UiEditorSlashMenuItem.js +1 -1
  197. package/vue/chunks/UiEditorTableContextMenu.js +1 -1
  198. package/vue/chunks/UiEditorTableToolbar.js +1 -1
  199. package/vue/chunks/UiEditorToolbar.js +1 -1
  200. package/vue/chunks/UiFloatingActionButton.js +1 -1
  201. package/vue/chunks/UiIconButton.js +13 -8
  202. package/vue/chunks/UiList.js +17 -5
  203. package/vue/chunks/UiListItem.js +1 -1
  204. package/vue/chunks/UiMenu.js +10 -2
  205. package/vue/chunks/UiMenuItem.js +1 -4
  206. package/vue/chunks/UiMeter.js +1 -1
  207. package/vue/chunks/UiNavItem.js +1 -1
  208. package/vue/chunks/UiPageHeader.js +1 -1
  209. package/vue/chunks/UiPopover.js +1 -1
  210. package/vue/chunks/UiRadio.js +1 -1
  211. package/vue/chunks/UiScrollArea.js +22 -3
  212. package/vue/chunks/UiSearchResultRow.js +1 -1
  213. package/vue/chunks/UiSearchShell.js +2 -2
  214. package/vue/chunks/UiSection.js +1 -1
  215. package/vue/chunks/UiSeparator.js +1 -1
  216. package/vue/chunks/UiSidebar.js +1 -1
  217. package/vue/chunks/UiSpinner.js +7 -5
  218. package/vue/chunks/UiStatusMessage.js +1 -1
  219. package/vue/chunks/UiSwitch.js +1 -1
  220. package/vue/chunks/UiTable.js +1 -1
  221. package/vue/chunks/UiTabs.js +1 -1
  222. package/vue/chunks/UiToast.js +1 -1
  223. package/vue/chunks/UiToastRegion.js +1 -1
  224. package/vue/chunks/UiTooltip.js +1 -1
  225. package/vue/chunks/UiTopBar.js +1 -1
  226. package/vue/chunks/UiTreeItem.js +1 -1
  227. package/vue/components.css +1238 -1032
  228. package/vue/editor/LoomaEditor.d.ts +12 -1
  229. package/vue/editor/index.js +7 -1
  230. package/vue/index.js +1 -1
@@ -118,8 +118,7 @@ function attribute(value: unknown): any {
118
118
  <span class="indicator" aria-hidden="true"><UiIcon
119
119
  v-if="type === 'checkbox' && internalChecked"
120
120
  name="check"
121
- />
122
- <UiIcon v-if="type === 'radio' && internalChecked" name="circle-dot" /></span>
121
+ /></span>
123
122
  <span class="label"><slot /></span>
124
123
  <span class="shortcut" aria-hidden="true"><slot name="shortcut" /></span>
125
124
  </div>
@@ -155,7 +154,7 @@ function attribute(value: unknown): any {
155
154
  [data-component~="ui-menu-item"] {
156
155
  display: flex;
157
156
  align-items: center;
158
- gap: var(--ui-space-5);
157
+ gap: var(--ui-space-2);
159
158
  box-sizing: border-box;
160
159
  width: 100%;
161
160
  padding: var(
@@ -192,16 +191,46 @@ function attribute(value: unknown): any {
192
191
 
193
192
  .indicator {
194
193
  display: inline-flex;
195
- place-items: center;
194
+ align-items: center;
195
+ justify-content: center;
196
196
  flex: none;
197
- inline-size: var(--ui-icon-size-md);
198
- color: var(--ui-accent-solid);
197
+ box-sizing: border-box;
198
+ inline-size: var(--ui-icon-size-sm);
199
+ block-size: var(--ui-icon-size-sm);
200
+ border: 1.5px solid var(--ui-control-border);
201
+ border-radius: var(--ui-radius-sm);
202
+ color: var(--ui-surface);
203
+ --_ui-default-icon-size: 0.75rem;
199
204
  }
200
205
 
201
206
  [data-component~="ui-menu-item"][data-ui-menu-item-state~="type=action"] .indicator {
202
207
  display: none;
203
208
  }
204
209
 
210
+ [data-component~="ui-menu-item"][data-ui-menu-item-state~="type=checkbox"][aria-checked="true"]
211
+ .indicator {
212
+ border-color: var(--ui-accent);
213
+ background: var(--ui-accent);
214
+ }
215
+
216
+ [data-component~="ui-menu-item"][data-ui-menu-item-state~="type=radio"] .indicator {
217
+ border-radius: var(--ui-radius-round);
218
+ }
219
+
220
+ [data-component~="ui-menu-item"][data-ui-menu-item-state~="type=radio"][aria-checked="true"]
221
+ .indicator {
222
+ border-color: var(--ui-accent);
223
+ }
224
+
225
+ [data-component~="ui-menu-item"][data-ui-menu-item-state~="type=radio"][aria-checked="true"]
226
+ .indicator::after {
227
+ content: "";
228
+ inline-size: 0.375rem;
229
+ block-size: 0.375rem;
230
+ border-radius: var(--ui-radius-round);
231
+ background: var(--ui-accent);
232
+ }
233
+
205
234
  .shortcut {
206
235
  margin-inline-start: auto;
207
236
  color: var(--ui-text-secondary);
@@ -232,10 +261,21 @@ function attribute(value: unknown): any {
232
261
  }
233
262
 
234
263
  [data-component~="ui-menu-item"][aria-disabled="true"] {
235
- opacity: 0.6;
264
+ background: var(--ui-disabled-surface);
265
+ color: var(--ui-disabled-text);
236
266
  cursor: not-allowed;
237
267
  }
238
268
 
269
+ [data-component~="ui-menu-item"][aria-disabled="true"] .indicator {
270
+ border-color: var(--ui-disabled-border);
271
+ background: transparent;
272
+ color: var(--ui-disabled-text);
273
+ }
274
+
275
+ [data-component~="ui-menu-item"][aria-disabled="true"] .indicator::after {
276
+ background: var(--ui-disabled-text);
277
+ }
278
+
239
279
  @media (forced-colors: active) {
240
280
  [data-component~="ui-menu-item"]:focus-visible {
241
281
  outline-color: Highlight;
package/vue/UiMeter.vue CHANGED
@@ -147,6 +147,7 @@ function number(value: unknown): number | undefined {
147
147
  overflow: hidden;
148
148
  border-radius: var(--ui-radius-round);
149
149
  background: var(--ui-border);
150
+ box-shadow: inset 0 1px 2px rgb(0 0 0 / 0.1), inset 0 -1px rgb(255 255 255 / 0.22);
150
151
  /* Unseen until forced colours draw it, where the track's own colour is gone. */
151
152
  outline: 1px solid transparent;
152
153
  }
@@ -159,7 +160,9 @@ function number(value: unknown): number | undefined {
159
160
  .fill {
160
161
  display: block;
161
162
  block-size: 100%;
162
- background: var(--_meter-fill);
163
+ background-color: var(--_meter-fill);
164
+ background-image: linear-gradient(to bottom, rgb(255 255 255 / 0.26), transparent 70%);
165
+ box-shadow: inset 0 1px rgb(255 255 255 / 0.26), inset 0 -1px rgb(0 0 0 / 0.1);
163
166
  }
164
167
 
165
168
  [data-component~="ui-meter"][data-ui-meter-state~="tone=accent"] {
package/vue/UiNavItem.vue CHANGED
@@ -152,7 +152,6 @@ function attribute(value: unknown): any {
152
152
  inset-inline-start: 0;
153
153
  display: none;
154
154
  border-inline-start: var(--_indicator-width) solid var(--_indicator-color);
155
- border-radius: var(--ui-radius-round);
156
155
  }
157
156
 
158
157
  [data-component~="ui-nav-item"][aria-current] .indicator {
@@ -42,6 +42,7 @@ const hostState = computed(() =>
42
42
  [data-component~="ui-page-header"] {
43
43
  display: flex;
44
44
  flex-wrap: wrap;
45
+ inline-size: 100%;
45
46
  align-items: center;
46
47
  gap: var(--ui-space-3) var(--ui-space-4);
47
48
  min-inline-size: 0;
package/vue/UiPopover.vue CHANGED
@@ -148,7 +148,7 @@ useComponentHost(controllerModule.default, {
148
148
  overflow: auto;
149
149
  padding: var(--ui-space-3);
150
150
  background: var(--_ui-popover-surface, var(--ui-overlay-surface, var(--ui-surface-elevated)));
151
- border: 1px solid var(--_ui-popover-border, var(--ui-overlay-border, var(--ui-border-default)));
151
+ border: 1px solid var(--_ui-popover-border, var(--ui-overlay-border, var(--ui-border-strong)));
152
152
  border-radius: var(--_ui-popover-radius, var(--ui-overlay-radius, var(--ui-radius-lg)));
153
153
  box-shadow: var(
154
154
  --_ui-popover-shadow,
package/vue/UiRadio.vue CHANGED
@@ -144,7 +144,7 @@ input {
144
144
  flex: 0 0 auto;
145
145
  inline-size: var(--_ui-radio-size, 1.125rem);
146
146
  block-size: var(--_ui-radio-size, 1.125rem);
147
- margin: 0.125em 0 0;
147
+ margin: calc(0.125em + 1px) 0 0;
148
148
  accent-color: var(--ui-accent-solid);
149
149
  cursor: pointer;
150
150
  }
@@ -158,6 +158,9 @@ input:focus-visible {
158
158
  color: var(--ui-disabled-text);
159
159
  cursor: not-allowed;
160
160
  }
161
+ [data-component~="ui-radio"][data-ui-radio-state~="disabled"] .description {
162
+ color: var(--ui-disabled-text);
163
+ }
161
164
  [data-component~="ui-radio"][data-ui-radio-state~="disabled"] input {
162
165
  cursor: not-allowed;
163
166
  }
@@ -184,7 +187,7 @@ input:focus-visible {
184
187
 
185
188
  [data-component~="ui-radio"][data-ui-radio-state~="size=sm"] input,
186
189
  [data-component~="ui-radio"][data-ui-radio-state~="size=lg"] input {
187
- margin-top: calc((var(--_line) - var(--_ui-radio-size, 1.125rem)) / 2);
190
+ margin-top: calc((var(--_line) - var(--_ui-radio-size, 1.125rem)) / 2 + 1px);
188
191
  }
189
192
 
190
193
  @media (pointer: coarse) {
@@ -1,6 +1,8 @@
1
1
  <!-- Generated by HTML Next 1.0.0-alpha.7 for Vue 3.5. Do not edit. -->
2
2
  <script setup lang="ts">
3
- import { computed } from 'vue'
3
+ import { computed, ref, useTemplateRef } from 'vue'
4
+ import * as controllerModule from '../components/ui-scroll-area/ui-scroll-area.js'
5
+ import { createDispatch, useComponentHost } from './host'
4
6
 
5
7
  defineOptions({ inheritAttrs: false })
6
8
 
@@ -13,12 +15,24 @@ const props = withDefaults(
13
15
  },
14
16
  )
15
17
 
18
+ const root = ref<HTMLElement | null>(null)
19
+ const contentElement = useTemplateRef<HTMLElement>('content')
20
+
16
21
  /** The values the styles' :host-state() rules test. */
17
22
  const hostState = computed(() =>
18
23
  [
19
24
  props.orientation && `orientation orientation=${props.orientation}`,
20
25
  ].filter(Boolean).join(' ')
21
26
  )
27
+
28
+ const dispatch = createDispatch(root)
29
+
30
+ useComponentHost(controllerModule.default, {
31
+ root,
32
+ dispatch,
33
+ props,
34
+ refs: { content: contentElement },
35
+ })
22
36
  </script>
23
37
 
24
38
  <template>
@@ -26,16 +40,16 @@ const hostState = computed(() =>
26
40
  data-component="ui-scroll-area"
27
41
  v-bind="$attrs"
28
42
  :data-ui-scroll-area-state="hostState || undefined"
43
+ ref="root"
29
44
  >
30
- <slot />
45
+ <div class="content" ref="content"><slot /></div>
31
46
  </div>
32
47
  </template>
33
48
 
34
49
  <style scoped>
35
- /* A region that scrolls when its content outgrows it. Each edge that hides content fades, growing
36
- in as the content leaves that edge (the scroll fade in tokens.css), so the reader can tell there
37
- is more; an edge with nothing past it stays crisp, and content that fits shows no fade. The
38
- fade is a mask, so it blends into whatever is behind the area without knowing its colour. */
50
+ /* The controller sets each fade length from overflow and scroll position. The mask blends
51
+ into whatever is behind the area without needing to know its colour. Before upgrade, its
52
+ zero-length defaults leave the authored scroll area fully visible. */
39
53
  [data-component~="ui-scroll-area"] {
40
54
  display: block;
41
55
  box-sizing: border-box;
@@ -54,24 +68,16 @@ const hostState = computed(() =>
54
68
  #000 calc(100% - var(--_ui-scroll-fade-end)),
55
69
  transparent
56
70
  );
57
- animation:
58
- ui-scroll-fade-start linear,
59
- ui-scroll-fade-start-hold linear,
60
- ui-scroll-fade-end-hold linear,
61
- ui-scroll-fade-end linear;
62
- animation-timeline: scroll(self block);
63
- animation-range:
64
- 0 var(--_ui-scroll-fade-size),
65
- var(--_ui-scroll-fade-size) calc(100% + 1px),
66
- -1px calc(100% - var(--_ui-scroll-fade-size)),
67
- calc(100% - var(--_ui-scroll-fade-size)) 100%;
71
+ }
72
+
73
+ .content {
74
+ display: flow-root;
68
75
  }
69
76
 
70
77
  [data-component~="ui-scroll-area"][data-ui-scroll-area-state~="orientation=horizontal"] {
71
78
  overflow-x: auto;
72
79
  overflow-y: hidden;
73
80
  --_ui-scroll-fade-direction: var(--_ui-scroll-fade-inline);
74
- animation-timeline: scroll(self inline);
75
81
  }
76
82
 
77
83
  [data-component~="ui-scroll-area"]:dir(rtl) {
@@ -87,7 +87,7 @@ const hostState = computed(() =>
87
87
  gap: var(--ui-search-result-row-gap, var(--ui-space-3));
88
88
  background: var(--ui-search-result-row-surface, transparent);
89
89
  border: none;
90
- border-block-end: 1px solid var(--ui-search-result-row-border, var(--ui-border));
90
+ border-block-end: 1px solid var(--ui-search-result-row-border, var(--ui-border-divider));
91
91
  color: inherit;
92
92
  cursor: pointer;
93
93
  text-align: left;
@@ -118,7 +118,8 @@ const hostState = computed(() =>
118
118
  }
119
119
 
120
120
  [data-component~="ui-search-result-row"]:disabled {
121
- opacity: 0.6;
121
+ background: var(--ui-disabled-surface);
122
+ color: var(--ui-disabled-text);
122
123
  cursor: not-allowed;
123
124
  }
124
125
 
@@ -69,7 +69,7 @@ useComponentHost(controllerModule.default, {
69
69
  <div class="search"><slot name="search" /></div>
70
70
  <div class="status"><slot name="status" /></div>
71
71
  <div class="body"><slot name="body" /></div>
72
- <div class="footer"><slot name="footer" /></div>
72
+ <div class="actions"><slot name="footer" /></div>
73
73
  </div>
74
74
  </dialog>
75
75
  </div>
@@ -170,7 +170,7 @@ dialog::backdrop {
170
170
  var(--ui-overlay-surface, var(--ui-surface-elevated))
171
171
  );
172
172
  border: 1px solid
173
- var(--_ui-search-shell-border, var(--ui-overlay-border, var(--ui-border-default)));
173
+ var(--_ui-search-shell-border, var(--ui-overlay-border, var(--ui-border-strong)));
174
174
  border-radius: var(--_ui-search-shell-radius, var(--ui-overlay-radius, var(--ui-radius-dialog)));
175
175
  box-shadow: var(
176
176
  --_ui-search-shell-shadow,
@@ -180,7 +180,7 @@ dialog::backdrop {
180
180
 
181
181
  .search {
182
182
  padding: var(--ui-space-3);
183
- border-block-end: 1px solid var(--ui-border-default);
183
+ border-block-end: 1px solid var(--ui-border-divider);
184
184
  transition:
185
185
  border-color var(--ui-motion-fast) var(--ui-motion-ease),
186
186
  box-shadow var(--ui-motion-fast) var(--ui-motion-ease);
@@ -212,7 +212,7 @@ dialog::backdrop {
212
212
  }
213
213
 
214
214
  .status,
215
- .footer {
215
+ .actions {
216
216
  flex-shrink: 0;
217
217
  padding: var(--ui-space-2) var(--ui-space-4);
218
218
  color: var(--ui-text-secondary);
@@ -220,22 +220,22 @@ dialog::backdrop {
220
220
  }
221
221
 
222
222
  .status {
223
- border-block-end: 1px solid var(--ui-border-default);
223
+ border-block-end: 1px solid var(--ui-border-divider);
224
224
  }
225
225
 
226
226
  /* Laid out like the dialog's action row: actions right-aligned, spaced as buttons, no fill. */
227
- .footer {
227
+ .actions {
228
228
  display: flex;
229
229
  flex-wrap: wrap;
230
230
  align-items: center;
231
231
  justify-content: flex-end;
232
232
  gap: var(--ui-space-2);
233
233
  padding: var(--ui-space-3) var(--ui-space-4);
234
- border-block-start: 1px solid var(--ui-border-default);
234
+ border-block-start: 1px solid var(--ui-border-divider);
235
235
  }
236
236
 
237
237
  .status:empty,
238
- .footer:empty {
238
+ .actions:empty {
239
239
  display: none;
240
240
  }
241
241
 
package/vue/UiSection.vue CHANGED
@@ -51,18 +51,20 @@ const hostState = computed(() =>
51
51
 
52
52
  [data-component~="ui-section"][data-ui-section-state~="variant=card"] {
53
53
  padding: var(--ui-space-5);
54
- border: 1px solid var(--ui-border-default);
54
+ border: 1px solid var(--ui-border-strong);
55
55
  border-radius: var(--ui-radius-lg);
56
56
  background: var(--ui-surface-raised);
57
57
  }
58
58
 
59
59
  [data-component~="ui-section"][data-ui-section-state~="variant=divided"] {
60
60
  padding-block-start: var(--ui-space-6);
61
- border-block-start: 1px solid var(--ui-border-default);
61
+ border-block-start: 1px solid var(--ui-border-divider);
62
62
  }
63
63
 
64
64
  [data-component~="ui-section"][data-ui-section-state~="variant=card"][data-ui-section-state~="tone=danger"] {
65
- border-color: var(--ui-danger);
65
+ border-color: color-mix(in srgb, var(--ui-danger) 45%, var(--ui-border-default));
66
+ border-inline-start: 4px solid var(--ui-danger);
67
+ background: var(--ui-danger-soft);
66
68
  }
67
69
 
68
70
  .head {
@@ -29,12 +29,12 @@ withDefaults(
29
29
  align-self: stretch;
30
30
  margin: 0;
31
31
  border: 0;
32
- border-block-start: 1px solid var(--ui-separator-color, var(--ui-border-default));
32
+ border-block-start: 1px solid var(--ui-separator-color, var(--ui-border-divider));
33
33
  }
34
34
 
35
35
  [data-component~="ui-separator"][aria-orientation="vertical"] {
36
36
  block-size: auto;
37
37
  border-block-start: 0;
38
- border-inline-start: 1px solid var(--ui-separator-color, var(--ui-border-default));
38
+ border-inline-start: 1px solid var(--ui-separator-color, var(--ui-border-divider));
39
39
  }
40
40
  </style>
package/vue/UiSidebar.vue CHANGED
@@ -146,12 +146,12 @@ useComponentHost(controllerModule.default, {
146
146
  max-inline-size: 100%;
147
147
  min-block-size: 0;
148
148
  background: var(--ui-sidebar-surface, var(--ui-surface-default));
149
- border-inline-end: 1px solid var(--ui-sidebar-border, var(--ui-border-default));
149
+ border-inline-end: 1px solid var(--ui-sidebar-border, var(--ui-border-divider));
150
150
  }
151
151
 
152
152
  [data-component~="ui-sidebar"][data-ui-sidebar-state~="side=end"] {
153
153
  border-inline-end: 0;
154
- border-inline-start: 1px solid var(--ui-sidebar-border, var(--ui-border-default));
154
+ border-inline-start: 1px solid var(--ui-sidebar-border, var(--ui-border-divider));
155
155
  }
156
156
 
157
157
  /* The panel's content scrolls, and each edge that hides content fades: the scroll fade every
package/vue/UiSpinner.vue CHANGED
@@ -1,7 +1,6 @@
1
1
  <!-- Generated by HTML Next 1.0.0-alpha.7 for Vue 3.5. Do not edit. -->
2
2
  <script setup lang="ts">
3
3
  import { computed } from 'vue'
4
- import UiIcon from './UiIcon.vue'
5
4
 
6
5
  defineOptions({ inheritAttrs: false })
7
6
 
@@ -40,6 +39,7 @@ function attribute(value: unknown): any {
40
39
  <template>
41
40
  <span
42
41
  data-component="ui-spinner"
42
+ class="ring"
43
43
  v-bind="$attrs"
44
44
  :role="attribute(({ true: 'status', false: null })[`${label !== ''}`])"
45
45
  :aria-label="typeof (({ true: label, false: null })[`${label !== ''}`]) === 'boolean'
@@ -49,33 +49,54 @@ function attribute(value: unknown): any {
49
49
  ? String(({ true: null, false: 'true' })[`${label !== ''}`])
50
50
  : attribute(({ true: null, false: 'true' })[`${label !== ''}`])"
51
51
  :data-ui-spinner-state="hostState || undefined"
52
- ><UiIcon name="loader" /></span>
52
+ ></span>
53
53
  </template>
54
54
 
55
55
  <style scoped>
56
- /* Something is on its way. It turns in the current text colour; with reduced motion it holds still,
56
+ /* Something is on its way. The ring chases in the current text colour; with reduced motion it holds still,
57
57
  and the label (or the text beside it) still says what is happening. */
58
58
  [data-component~="ui-spinner"] {
59
59
  display: inline-flex;
60
60
  flex: none;
61
+ align-items: center;
62
+ justify-content: center;
63
+ inline-size: 1em;
64
+ block-size: 1em;
61
65
  color: currentColor;
62
66
  font-size: var(--ui-font-size-lg);
63
67
  line-height: 1;
64
- animation: ui-spinner-turn 0.8s linear infinite;
68
+ }
69
+
70
+ .ring {
71
+ display: block;
72
+ box-sizing: border-box;
73
+ inline-size: 100%;
74
+ block-size: 100%;
75
+ border: 2px solid transparent;
76
+ border-block-start-color: currentColor;
77
+ border-inline-end-color: color-mix(in srgb, currentColor 52%, transparent);
78
+ border-radius: 50%;
79
+ animation: ui-spinner-chase 1s linear infinite;
65
80
  }
66
81
 
67
82
  [data-component~="ui-spinner"][data-ui-spinner-state~="size=sm"] {
68
83
  font-size: var(--ui-font-size-md);
69
84
  }
70
85
 
71
- @keyframes ui-spinner-turn {
72
- to {
86
+ @keyframes ui-spinner-chase {
87
+ 0% {
88
+ transform: rotate(0);
89
+ }
90
+ 70% {
91
+ transform: rotate(160deg);
92
+ }
93
+ 100% {
73
94
  transform: rotate(1turn);
74
95
  }
75
96
  }
76
97
 
77
98
  @media (prefers-reduced-motion: reduce) {
78
- [data-component~="ui-spinner"] {
99
+ .ring {
79
100
  animation: none;
80
101
  }
81
102
  }
@@ -74,7 +74,7 @@ function attribute(value: unknown): any {
74
74
 
75
75
  [data-component~="ui-status-message"][data-ui-status-message-state~="layout=panel"] {
76
76
  padding: var(--ui-space-6);
77
- border: 1px dashed var(--ui-border-default);
77
+ border: 1px dashed var(--ui-border-strong);
78
78
  border-radius: var(--ui-radius-lg);
79
79
  }
80
80
 
package/vue/UiSwitch.vue CHANGED
@@ -154,14 +154,14 @@ input {
154
154
  width: var(--_ui-switch-track-width, 2.5rem);
155
155
  height: var(--_ui-switch-track-height, 1.5rem);
156
156
  padding: 0;
157
- border: 1px solid var(--ui-control-border-hover, var(--ui-border-strong));
157
+ border: 1px solid var(--ui-control-border, var(--ui-border-strong));
158
158
  border-radius: var(--ui-radius-round);
159
- background: var(--ui-control-surface, var(--ui-surface-default));
160
- box-shadow: inset 0 1px 2px color-mix(in srgb, var(--ui-text-primary) 10%, transparent);
159
+ background-color: var(--ui-control-surface, var(--ui-surface-default));
160
+ box-shadow: var(--ui-control-inset);
161
161
  cursor: pointer;
162
162
  transition:
163
- background-color var(--ui-motion-fast) var(--ui-motion-ease),
164
- border-color var(--ui-motion-fast) var(--ui-motion-ease);
163
+ background-color var(--ui-motion-base) var(--ui-motion-ease),
164
+ border-color var(--ui-motion-base) var(--ui-motion-ease);
165
165
  margin: 0;
166
166
  }
167
167
 
@@ -175,11 +175,13 @@ input::after {
175
175
  border-radius: var(--ui-radius-round);
176
176
  background: var(--ui-text-secondary);
177
177
  box-shadow: var(--ui-shadow-xs);
178
- transition: transform var(--ui-motion-fast) var(--ui-motion-ease);
178
+ transition:
179
+ transform var(--ui-motion-base) var(--ui-motion-ease),
180
+ background-color var(--ui-motion-base) var(--ui-motion-ease);
179
181
  }
180
182
 
181
183
  input:checked {
182
- background: var(--ui-accent-solid);
184
+ background-color: var(--ui-accent-solid);
183
185
  border-color: var(--ui-accent-solid);
184
186
  }
185
187
 
@@ -197,12 +199,21 @@ input:focus-visible {
197
199
  color: var(--ui-disabled-text);
198
200
  cursor: not-allowed;
199
201
  }
202
+ [data-component~="ui-switch"][data-ui-switch-state~="disabled"] .description {
203
+ color: var(--ui-disabled-text);
204
+ }
200
205
  [data-component~="ui-switch"][data-ui-switch-state~="disabled"] input {
201
- border-color: var(--ui-border-default);
202
- background: var(--ui-control-surface-disabled, var(--ui-surface-muted));
206
+ border-color: var(--ui-disabled-border);
207
+ background-color: var(--ui-disabled-surface);
208
+ box-shadow: none;
203
209
  cursor: not-allowed;
204
210
  }
205
211
 
212
+ [data-component~="ui-switch"][data-ui-switch-state~="disabled"] input::after {
213
+ background-color: var(--ui-disabled-text);
214
+ box-shadow: none;
215
+ }
216
+
206
217
  @media (prefers-reduced-motion: reduce) {
207
218
  input, input::after {
208
219
  transition: none;
package/vue/UiTable.vue CHANGED
@@ -135,7 +135,7 @@ useComponentHost(controllerModule.default, {
135
135
  :slotted(thead th) {
136
136
  block-size: auto;
137
137
  padding-block: var(--ui-space-2);
138
- border-block-end-color: var(--ui-border-default);
138
+ border-block-end-color: var(--ui-border-divider);
139
139
  background: var(--ui-surface);
140
140
  color: var(--ui-text-muted);
141
141
  font-weight: var(--ui-font-medium);
package/vue/UiTabs.vue CHANGED
@@ -154,10 +154,11 @@ useComponentHost(controllerModule.default, {
154
154
  overflow-y: hidden;
155
155
  overscroll-behavior: contain;
156
156
  scrollbar-width: thin;
157
- border-block-end: 1px solid var(--ui-border-default);
157
+ border-block-end: 1px solid var(--ui-border-divider);
158
158
  }
159
159
 
160
- .list button {
160
+ .list button,
161
+ .list > :slotted(button[slot="tab"]) {
161
162
  min-block-size: var(--_ui-tabs-tab-min-block-size, var(--_tab-min-block-size));
162
163
  margin: 0 0 -1px;
163
164
  padding: var(--_ui-tabs-tab-padding-block, var(--_tab-padding-block))
@@ -180,7 +181,8 @@ useComponentHost(controllerModule.default, {
180
181
  /* Centre the glyphs, not the line box: a label without descenders otherwise reads high.
181
182
  * Trimming applies to block containers, so the box is a block with centred content. */
182
183
  @supports (text-box-trim: trim-both) {
183
- .list button {
184
+ .list button,
185
+ .list > :slotted(button[slot="tab"]) {
184
186
  display: block;
185
187
  text-align: center;
186
188
  align-content: center;
@@ -193,19 +195,23 @@ useComponentHost(controllerModule.default, {
193
195
  grid-auto-columns: minmax(max-content, 1fr);
194
196
  }
195
197
 
196
- .list button {
198
+ .list button,
199
+ .list > :slotted(button[slot="tab"]) {
197
200
  white-space: nowrap;
198
201
  }
199
202
 
200
- .list button:hover {
203
+ .list button:hover,
204
+ .list > :slotted(button[slot="tab"]:hover) {
201
205
  color: var(--ui-text-primary);
202
206
  background: var(--ui-surface-muted);
203
207
  }
204
- .list button[aria-selected="true"] {
208
+ .list button[aria-selected="true"],
209
+ .list > :slotted(button[slot="tab"][aria-selected="true"]) {
205
210
  color: var(--ui-accent-solid);
206
211
  border-block-end-color: var(--ui-accent-solid);
207
212
  }
208
- .list button:focus-visible {
213
+ .list button:focus-visible,
214
+ .list > :slotted(button[slot="tab"]:focus-visible) {
209
215
  position: relative;
210
216
  outline: none;
211
217
  box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--ui-focus-ring) 45%, transparent);
@@ -215,7 +221,7 @@ useComponentHost(controllerModule.default, {
215
221
  .panels {
216
222
  min-inline-size: 0;
217
223
  }
218
- :slotted(*) {
224
+ .panels > :slotted(*) {
219
225
  padding: var(--ui-space-4);
220
226
  }
221
227
 
@@ -228,10 +234,13 @@ useComponentHost(controllerModule.default, {
228
234
  grid-auto-flow: row;
229
235
  grid-auto-columns: auto;
230
236
  border-block-end: 0;
231
- border-inline-end: 1px solid var(--ui-border-default);
237
+ border-inline-end: 1px solid var(--ui-border-divider);
232
238
  }
233
239
 
234
- [data-component~="ui-tabs"][data-ui-tabs-state~="orientation=vertical"] .list button {
240
+ [data-component~="ui-tabs"][data-ui-tabs-state~="orientation=vertical"] .list button,
241
+ [data-component~="ui-tabs"][data-ui-tabs-state~="orientation=vertical"]
242
+ .list
243
+ > :slotted(button[slot="tab"]) {
235
244
  margin: 0 -1px 0 0;
236
245
  border-block-end: 0;
237
246
  border-inline-end: 2px solid transparent;
@@ -240,12 +249,16 @@ useComponentHost(controllerModule.default, {
240
249
 
241
250
  [data-component~="ui-tabs"][data-ui-tabs-state~="orientation=vertical"]
242
251
  .list
243
- button[aria-selected="true"] {
252
+ button[aria-selected="true"],
253
+ [data-component~="ui-tabs"][data-ui-tabs-state~="orientation=vertical"]
254
+ .list
255
+ > :slotted(button[slot="tab"][aria-selected="true"]) {
244
256
  border-inline-end-color: var(--ui-accent-solid);
245
257
  }
246
258
 
247
259
  @media (prefers-reduced-motion: reduce) {
248
- .list button {
260
+ .list button,
261
+ .list > :slotted(button[slot="tab"]) {
249
262
  transition: none;
250
263
  }
251
264
  }
package/vue/UiToast.vue CHANGED
@@ -131,7 +131,7 @@ function attribute(value: unknown): any {
131
131
  inline-size: 100%;
132
132
  margin: 0;
133
133
  padding: var(--ui-space-3) var(--ui-space-4);
134
- border: 1px solid var(--ui-toast-border, var(--ui-overlay-border, var(--ui-border-default)));
134
+ border: 1px solid var(--ui-toast-border, var(--ui-overlay-border, var(--ui-border-strong)));
135
135
  border-inline-start: 3px solid var(--ui-toast-accent, var(--_ui-toast-accent));
136
136
  border-radius: var(--ui-toast-radius, var(--ui-overlay-radius, var(--ui-radius-lg)));
137
137
  background: var(--ui-toast-surface, var(--ui-overlay-surface, var(--ui-surface-elevated)));
@@ -207,7 +207,7 @@ defineExpose({
207
207
  gap: var(--ui-space-2);
208
208
  align-items: start;
209
209
  border: 1px solid
210
- var(--_ui-toast-region-border, var(--ui-overlay-border, var(--ui-border-default)));
210
+ var(--_ui-toast-region-border, var(--ui-overlay-border, var(--ui-border-strong)));
211
211
  border-radius: var(--_ui-toast-region-radius, var(--ui-overlay-radius, var(--ui-radius-lg)));
212
212
  padding: var(--ui-space-3) var(--ui-space-4);
213
213
  background: var(