@threadlabs/looma 0.28.4 → 0.28.6

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 (437) hide show
  1. package/components/ui-editor-image-toolbar/ui-editor-image-toolbar.html +96 -0
  2. package/components/ui-editor-image-toolbar/ui-editor-image-toolbar.js +56 -0
  3. package/components/ui-editor-mention-menu-item/ui-editor-mention-menu-item.html +3 -2
  4. package/dist/index.js +34 -33
  5. package/package.json +3 -2
  6. package/styles/ui-action-bar.css +13 -6
  7. package/styles/ui-affordance-scope.css +12 -5
  8. package/styles/ui-avatar-group.css +17 -10
  9. package/styles/ui-avatar.css +23 -16
  10. package/styles/ui-badge.css +78 -71
  11. package/styles/ui-breadcrumb-item.css +12 -5
  12. package/styles/ui-breadcrumbs.css +10 -3
  13. package/styles/ui-button.css +79 -72
  14. package/styles/ui-callout.css +29 -22
  15. package/styles/ui-card.css +25 -18
  16. package/styles/ui-checkbox.css +45 -37
  17. package/styles/ui-cluster.css +34 -27
  18. package/styles/ui-combobox.css +46 -39
  19. package/styles/ui-container.css +20 -13
  20. package/styles/ui-context-menu.css +17 -10
  21. package/styles/ui-cover.css +12 -5
  22. package/styles/ui-description-item.css +10 -3
  23. package/styles/ui-description-list.css +20 -13
  24. package/styles/ui-dialog.css +44 -35
  25. package/styles/ui-disclosure.css +32 -25
  26. package/styles/ui-editable.css +15 -8
  27. package/styles/ui-editor-image-toolbar.css +1 -0
  28. package/styles/ui-editor-insert-table-grid.css +11 -4
  29. package/styles/ui-editor-mention-menu-item.css +17 -8
  30. package/styles/ui-editor-mention-menu.css +14 -7
  31. package/styles/ui-editor-slash-menu-group.css +10 -3
  32. package/styles/ui-editor-slash-menu-item.css +15 -8
  33. package/styles/ui-editor-slash-menu.css +15 -8
  34. package/styles/ui-editor-surface.css +10 -3
  35. package/styles/ui-editor-table-context-menu.css +17 -10
  36. package/styles/ui-editor-table-overlay.css +17 -10
  37. package/styles/ui-editor-table-toolbar.css +22 -15
  38. package/styles/ui-editor-toolbar.css +18 -11
  39. package/styles/ui-floating-action-button.css +21 -14
  40. package/styles/ui-form-field.css +20 -13
  41. package/styles/ui-grid.css +21 -14
  42. package/styles/ui-icon-button.css +80 -73
  43. package/styles/ui-icon.css +14 -7
  44. package/styles/ui-image.css +25 -18
  45. package/styles/ui-input-group.css +34 -27
  46. package/styles/ui-input.css +42 -35
  47. package/styles/ui-list-item.css +33 -26
  48. package/styles/ui-list.css +22 -15
  49. package/styles/ui-listbox.css +22 -14
  50. package/styles/ui-menu-group.css +10 -3
  51. package/styles/ui-menu-item.css +29 -22
  52. package/styles/ui-menu.css +25 -18
  53. package/styles/ui-meter.css +36 -29
  54. package/styles/ui-nav-item.css +26 -19
  55. package/styles/ui-page-header.css +12 -5
  56. package/styles/ui-popover.css +27 -20
  57. package/styles/ui-radio-group.css +14 -6
  58. package/styles/ui-radio.css +24 -17
  59. package/styles/ui-reel.css +28 -21
  60. package/styles/ui-scroll-area.css +22 -15
  61. package/styles/ui-search-result-row.css +28 -21
  62. package/styles/ui-search-shell.css +24 -17
  63. package/styles/ui-section.css +14 -7
  64. package/styles/ui-select.css +33 -26
  65. package/styles/ui-separator.css +17 -10
  66. package/styles/ui-sidebar.css +35 -28
  67. package/styles/ui-spinner.css +32 -23
  68. package/styles/ui-stack.css +29 -21
  69. package/styles/ui-status-message.css +14 -7
  70. package/styles/ui-switch.css +29 -22
  71. package/styles/ui-switcher.css +27 -20
  72. package/styles/ui-table.css +14 -7
  73. package/styles/ui-tabs.css +24 -17
  74. package/styles/ui-text.css +35 -28
  75. package/styles/ui-textarea.css +37 -30
  76. package/styles/ui-toast-region.css +74 -63
  77. package/styles/ui-toast.css +21 -14
  78. package/styles/ui-tooltip.css +38 -31
  79. package/styles/ui-top-bar.css +19 -12
  80. package/styles/ui-tree-item.css +79 -71
  81. package/styles/ui-tree.css +18 -11
  82. package/vanilla/UiActionBar.d.ts +1 -1
  83. package/vanilla/UiActionBar.js +1 -1
  84. package/vanilla/UiAffordanceScope.d.ts +1 -1
  85. package/vanilla/UiAffordanceScope.js +1 -1
  86. package/vanilla/UiAvatar.d.ts +1 -1
  87. package/vanilla/UiAvatar.js +1 -1
  88. package/vanilla/UiAvatarGroup.d.ts +1 -1
  89. package/vanilla/UiAvatarGroup.js +1 -1
  90. package/vanilla/UiBadge.d.ts +1 -1
  91. package/vanilla/UiBadge.js +1 -1
  92. package/vanilla/UiBreadcrumbItem.d.ts +1 -1
  93. package/vanilla/UiBreadcrumbItem.js +1 -1
  94. package/vanilla/UiBreadcrumbs.d.ts +1 -1
  95. package/vanilla/UiBreadcrumbs.js +1 -1
  96. package/vanilla/UiButton.d.ts +1 -1
  97. package/vanilla/UiButton.js +19 -57
  98. package/vanilla/UiCallout.d.ts +1 -1
  99. package/vanilla/UiCallout.js +25 -73
  100. package/vanilla/UiCard.d.ts +1 -1
  101. package/vanilla/UiCard.js +1 -1
  102. package/vanilla/UiCheckbox.d.ts +1 -1
  103. package/vanilla/UiCheckbox.js +1 -1
  104. package/vanilla/UiCluster.d.ts +1 -1
  105. package/vanilla/UiCluster.js +1 -1
  106. package/vanilla/UiCombobox.d.ts +1 -1
  107. package/vanilla/UiCombobox.js +60 -166
  108. package/vanilla/UiContainer.d.ts +1 -1
  109. package/vanilla/UiContainer.js +1 -1
  110. package/vanilla/UiContextMenu.d.ts +1 -1
  111. package/vanilla/UiContextMenu.js +1 -1
  112. package/vanilla/UiCover.d.ts +1 -1
  113. package/vanilla/UiCover.js +1 -1
  114. package/vanilla/UiDescriptionItem.d.ts +1 -1
  115. package/vanilla/UiDescriptionItem.js +1 -1
  116. package/vanilla/UiDescriptionList.d.ts +1 -1
  117. package/vanilla/UiDescriptionList.js +1 -1
  118. package/vanilla/UiDialog.d.ts +1 -1
  119. package/vanilla/UiDialog.js +4 -10
  120. package/vanilla/UiDisclosure.d.ts +1 -1
  121. package/vanilla/UiDisclosure.js +1 -1
  122. package/vanilla/UiEditable.d.ts +1 -1
  123. package/vanilla/UiEditable.js +7 -19
  124. package/vanilla/UiEditorImageToolbar.d.ts +19 -0
  125. package/vanilla/UiEditorImageToolbar.js +171 -0
  126. package/vanilla/UiEditorInsertTableGrid.d.ts +1 -1
  127. package/vanilla/UiEditorInsertTableGrid.js +1 -1
  128. package/vanilla/UiEditorMentionMenu.d.ts +1 -1
  129. package/vanilla/UiEditorMentionMenu.js +17 -37
  130. package/vanilla/UiEditorMentionMenuItem.d.ts +1 -1
  131. package/vanilla/UiEditorMentionMenuItem.js +4 -10
  132. package/vanilla/UiEditorSlashMenu.d.ts +1 -1
  133. package/vanilla/UiEditorSlashMenu.js +5 -4
  134. package/vanilla/UiEditorSlashMenuGroup.d.ts +1 -1
  135. package/vanilla/UiEditorSlashMenuGroup.js +1 -1
  136. package/vanilla/UiEditorSlashMenuItem.d.ts +1 -1
  137. package/vanilla/UiEditorSlashMenuItem.js +7 -19
  138. package/vanilla/UiEditorSurface.d.ts +1 -1
  139. package/vanilla/UiEditorSurface.js +1 -1
  140. package/vanilla/UiEditorTableContextMenu.d.ts +1 -1
  141. package/vanilla/UiEditorTableContextMenu.js +6 -14
  142. package/vanilla/UiEditorTableOverlay.d.ts +1 -1
  143. package/vanilla/UiEditorTableOverlay.js +9 -25
  144. package/vanilla/UiEditorTableToolbar.d.ts +1 -1
  145. package/vanilla/UiEditorTableToolbar.js +25 -77
  146. package/vanilla/UiEditorToolbar.d.ts +1 -1
  147. package/vanilla/UiEditorToolbar.js +1 -1
  148. package/vanilla/UiFloatingActionButton.d.ts +1 -1
  149. package/vanilla/UiFloatingActionButton.js +1 -1
  150. package/vanilla/UiFormField.d.ts +1 -1
  151. package/vanilla/UiFormField.js +1 -1
  152. package/vanilla/UiGrid.d.ts +1 -1
  153. package/vanilla/UiGrid.js +1 -1
  154. package/vanilla/UiIcon.d.ts +1 -1
  155. package/vanilla/UiIcon.js +15 -47
  156. package/vanilla/UiIconButton.d.ts +1 -1
  157. package/vanilla/UiIconButton.js +4 -10
  158. package/vanilla/UiImage.d.ts +1 -1
  159. package/vanilla/UiImage.js +1 -1
  160. package/vanilla/UiInput.d.ts +1 -1
  161. package/vanilla/UiInput.js +1 -1
  162. package/vanilla/UiInputGroup.d.ts +1 -1
  163. package/vanilla/UiInputGroup.js +1 -1
  164. package/vanilla/UiList.d.ts +1 -1
  165. package/vanilla/UiList.js +1 -1
  166. package/vanilla/UiListItem.d.ts +1 -1
  167. package/vanilla/UiListItem.js +1 -1
  168. package/vanilla/UiListbox.d.ts +1 -1
  169. package/vanilla/UiListbox.js +4 -10
  170. package/vanilla/UiMenu.d.ts +1 -1
  171. package/vanilla/UiMenu.js +1 -1
  172. package/vanilla/UiMenuGroup.d.ts +1 -1
  173. package/vanilla/UiMenuGroup.js +4 -10
  174. package/vanilla/UiMenuItem.d.ts +1 -1
  175. package/vanilla/UiMenuItem.js +4 -10
  176. package/vanilla/UiMeter.d.ts +1 -1
  177. package/vanilla/UiMeter.js +13 -33
  178. package/vanilla/UiNavItem.d.ts +1 -1
  179. package/vanilla/UiNavItem.js +1 -1
  180. package/vanilla/UiPageHeader.d.ts +1 -1
  181. package/vanilla/UiPageHeader.js +1 -1
  182. package/vanilla/UiPopover.d.ts +1 -1
  183. package/vanilla/UiPopover.js +1 -1
  184. package/vanilla/UiRadio.d.ts +1 -1
  185. package/vanilla/UiRadio.js +1 -1
  186. package/vanilla/UiRadioGroup.d.ts +1 -1
  187. package/vanilla/UiRadioGroup.js +1 -1
  188. package/vanilla/UiReel.d.ts +1 -1
  189. package/vanilla/UiReel.js +1 -1
  190. package/vanilla/UiScrollArea.d.ts +1 -1
  191. package/vanilla/UiScrollArea.js +1 -1
  192. package/vanilla/UiSearchResultRow.d.ts +1 -1
  193. package/vanilla/UiSearchResultRow.js +1 -1
  194. package/vanilla/UiSearchShell.d.ts +1 -1
  195. package/vanilla/UiSearchShell.js +1 -1
  196. package/vanilla/UiSection.d.ts +1 -1
  197. package/vanilla/UiSection.js +1 -1
  198. package/vanilla/UiSelect.d.ts +1 -1
  199. package/vanilla/UiSelect.js +1 -1
  200. package/vanilla/UiSeparator.d.ts +1 -1
  201. package/vanilla/UiSeparator.js +1 -1
  202. package/vanilla/UiSidebar.d.ts +1 -1
  203. package/vanilla/UiSidebar.js +1 -1
  204. package/vanilla/UiSpinner.d.ts +1 -1
  205. package/vanilla/UiSpinner.js +1 -1
  206. package/vanilla/UiStack.d.ts +1 -1
  207. package/vanilla/UiStack.js +1 -1
  208. package/vanilla/UiStatusMessage.d.ts +1 -1
  209. package/vanilla/UiStatusMessage.js +1 -1
  210. package/vanilla/UiSwitch.d.ts +1 -1
  211. package/vanilla/UiSwitch.js +1 -1
  212. package/vanilla/UiSwitcher.d.ts +1 -1
  213. package/vanilla/UiSwitcher.js +1 -1
  214. package/vanilla/UiTable.d.ts +1 -1
  215. package/vanilla/UiTable.js +1 -1
  216. package/vanilla/UiTabs.d.ts +1 -1
  217. package/vanilla/UiTabs.js +1 -1
  218. package/vanilla/UiText.d.ts +1 -1
  219. package/vanilla/UiText.js +1 -1
  220. package/vanilla/UiTextarea.d.ts +1 -1
  221. package/vanilla/UiTextarea.js +1 -1
  222. package/vanilla/UiToast.d.ts +1 -1
  223. package/vanilla/UiToast.js +1 -1
  224. package/vanilla/UiToastRegion.d.ts +1 -1
  225. package/vanilla/UiToastRegion.js +1 -1
  226. package/vanilla/UiTooltip.d.ts +1 -1
  227. package/vanilla/UiTooltip.js +1 -1
  228. package/vanilla/UiTopBar.d.ts +1 -1
  229. package/vanilla/UiTopBar.js +1 -1
  230. package/vanilla/UiTree.d.ts +1 -1
  231. package/vanilla/UiTree.js +1 -1
  232. package/vanilla/UiTreeItem.d.ts +1 -1
  233. package/vanilla/UiTreeItem.js +7 -19
  234. package/vanilla/index.js +1 -0
  235. package/vue/UiActionBar.vue +46 -78
  236. package/vue/UiAffordanceScope.vue +27 -66
  237. package/vue/UiAvatar.d.ts +10 -7
  238. package/vue/UiAvatar.vue +100 -218
  239. package/vue/UiAvatarGroup.d.ts +10 -7
  240. package/vue/UiAvatarGroup.vue +78 -160
  241. package/vue/UiBadge.d.ts +1 -1
  242. package/vue/UiBadge.vue +483 -520
  243. package/vue/UiBreadcrumbItem.vue +52 -123
  244. package/vue/UiBreadcrumbs.vue +27 -70
  245. package/vue/UiButton.d.ts +2 -2
  246. package/vue/UiButton.vue +420 -471
  247. package/vue/UiCallout.vue +131 -175
  248. package/vue/UiCard.d.ts +1 -1
  249. package/vue/UiCard.vue +112 -151
  250. package/vue/UiCheckbox.d.ts +13 -10
  251. package/vue/UiCheckbox.vue +160 -221
  252. package/vue/UiCluster.d.ts +1 -1
  253. package/vue/UiCluster.vue +84 -128
  254. package/vue/UiCombobox.d.ts +71 -68
  255. package/vue/UiCombobox.vue +417 -743
  256. package/vue/UiContainer.vue +43 -87
  257. package/vue/UiContextMenu.d.ts +6 -6
  258. package/vue/UiContextMenu.vue +78 -117
  259. package/vue/UiCover.vue +29 -69
  260. package/vue/UiDescriptionItem.vue +39 -82
  261. package/vue/UiDescriptionList.vue +64 -107
  262. package/vue/UiDialog.d.ts +22 -19
  263. package/vue/UiDialog.vue +193 -246
  264. package/vue/UiDisclosure.d.ts +22 -19
  265. package/vue/UiDisclosure.vue +192 -283
  266. package/vue/UiEditable.d.ts +5 -5
  267. package/vue/UiEditable.vue +124 -207
  268. package/vue/UiEditorImageToolbar.d.ts +54 -0
  269. package/vue/UiEditorImageToolbar.js +2 -0
  270. package/vue/UiEditorImageToolbar.vue +415 -0
  271. package/vue/UiEditorInsertTableGrid.d.ts +2 -2
  272. package/vue/UiEditorInsertTableGrid.vue +98 -266
  273. package/vue/UiEditorMentionMenu.d.ts +15 -12
  274. package/vue/UiEditorMentionMenu.vue +150 -239
  275. package/vue/UiEditorMentionMenuItem.vue +66 -110
  276. package/vue/UiEditorSlashMenu.d.ts +16 -13
  277. package/vue/UiEditorSlashMenu.vue +172 -253
  278. package/vue/UiEditorSlashMenuGroup.vue +25 -69
  279. package/vue/UiEditorSlashMenuItem.vue +67 -115
  280. package/vue/UiEditorSurface.vue +19 -63
  281. package/vue/UiEditorTableContextMenu.vue +135 -269
  282. package/vue/UiEditorTableOverlay.d.ts +2 -2
  283. package/vue/UiEditorTableOverlay.vue +310 -479
  284. package/vue/UiEditorTableToolbar.d.ts +2 -2
  285. package/vue/UiEditorTableToolbar.vue +182 -357
  286. package/vue/UiEditorToolbar.vue +143 -183
  287. package/vue/UiFloatingActionButton.vue +70 -114
  288. package/vue/UiFormField.d.ts +1 -1
  289. package/vue/UiFormField.vue +76 -117
  290. package/vue/UiGrid.d.ts +1 -1
  291. package/vue/UiGrid.vue +65 -103
  292. package/vue/UiIcon.vue +32 -106
  293. package/vue/UiIconButton.d.ts +2 -2
  294. package/vue/UiIconButton.vue +359 -411
  295. package/vue/UiImage.vue +145 -180
  296. package/vue/UiInput.vue +158 -190
  297. package/vue/UiInputGroup.vue +199 -239
  298. package/vue/UiList.vue +67 -109
  299. package/vue/UiListItem.vue +154 -201
  300. package/vue/UiListbox.d.ts +10 -7
  301. package/vue/UiListbox.vue +86 -260
  302. package/vue/UiMenu.d.ts +11 -11
  303. package/vue/UiMenu.vue +118 -152
  304. package/vue/UiMenuGroup.vue +21 -67
  305. package/vue/UiMenuItem.d.ts +19 -16
  306. package/vue/UiMenuItem.vue +169 -262
  307. package/vue/UiMeter.d.ts +4 -4
  308. package/vue/UiMeter.vue +166 -680
  309. package/vue/UiNavItem.vue +140 -213
  310. package/vue/UiPageHeader.vue +81 -127
  311. package/vue/UiPopover.d.ts +7 -7
  312. package/vue/UiPopover.vue +90 -129
  313. package/vue/UiRadio.d.ts +12 -9
  314. package/vue/UiRadio.vue +91 -149
  315. package/vue/UiRadioGroup.d.ts +2 -2
  316. package/vue/UiRadioGroup.vue +47 -85
  317. package/vue/UiReel.vue +89 -130
  318. package/vue/UiScrollArea.d.ts +1 -1
  319. package/vue/UiScrollArea.vue +78 -119
  320. package/vue/UiSearchResultRow.vue +96 -149
  321. package/vue/UiSearchShell.d.ts +2 -2
  322. package/vue/UiSearchShell.vue +159 -196
  323. package/vue/UiSection.vue +105 -149
  324. package/vue/UiSelect.d.ts +1 -1
  325. package/vue/UiSelect.vue +114 -146
  326. package/vue/UiSeparator.vue +42 -85
  327. package/vue/UiSidebar.d.ts +10 -7
  328. package/vue/UiSidebar.vue +193 -260
  329. package/vue/UiSpinner.vue +54 -130
  330. package/vue/UiStack.vue +66 -107
  331. package/vue/UiStatusMessage.d.ts +1 -1
  332. package/vue/UiStatusMessage.vue +61 -135
  333. package/vue/UiSwitch.d.ts +12 -9
  334. package/vue/UiSwitch.vue +136 -194
  335. package/vue/UiSwitcher.vue +69 -107
  336. package/vue/UiTable.vue +121 -156
  337. package/vue/UiTabs.d.ts +1 -1
  338. package/vue/UiTabs.vue +139 -267
  339. package/vue/UiText.d.ts +4 -4
  340. package/vue/UiText.vue +145 -184
  341. package/vue/UiTextarea.d.ts +2 -2
  342. package/vue/UiTextarea.vue +162 -194
  343. package/vue/UiToast.vue +70 -118
  344. package/vue/UiToastRegion.vue +157 -276
  345. package/vue/UiTooltip.d.ts +21 -18
  346. package/vue/UiTooltip.vue +174 -234
  347. package/vue/UiTopBar.vue +48 -76
  348. package/vue/UiTree.vue +46 -79
  349. package/vue/UiTreeItem.d.ts +18 -15
  350. package/vue/UiTreeItem.vue +526 -668
  351. package/vue/chunks/UiActionBar.js +5 -17
  352. package/vue/chunks/UiAffordanceScope.js +7 -26
  353. package/vue/chunks/UiAvatar.js +20 -74
  354. package/vue/chunks/UiAvatarGroup.js +14 -56
  355. package/vue/chunks/UiBadge.js +10 -28
  356. package/vue/chunks/UiBreadcrumbItem.js +11 -41
  357. package/vue/chunks/UiBreadcrumbs.js +7 -25
  358. package/vue/chunks/UiButton.js +80 -103
  359. package/vue/chunks/UiCallout.js +9 -27
  360. package/vue/chunks/UiCard.js +33 -53
  361. package/vue/chunks/UiCheckbox.js +14 -46
  362. package/vue/chunks/UiCluster.js +13 -31
  363. package/vue/chunks/UiCombobox.js +99 -237
  364. package/vue/chunks/UiContainer.js +9 -27
  365. package/vue/chunks/UiContextMenu.js +7 -26
  366. package/vue/chunks/UiCover.js +7 -25
  367. package/vue/chunks/UiDescriptionItem.js +6 -24
  368. package/vue/chunks/UiDescriptionList.js +9 -27
  369. package/vue/chunks/UiDialog.js +18 -47
  370. package/vue/chunks/UiDisclosure.js +19 -66
  371. package/vue/chunks/UiEditable.js +18 -60
  372. package/vue/chunks/UiEditorImageToolbar.js +515 -0
  373. package/vue/chunks/UiEditorInsertTableGrid.js +14 -112
  374. package/vue/chunks/UiEditorMentionMenu.js +16 -54
  375. package/vue/chunks/UiEditorMentionMenuItem.js +10 -28
  376. package/vue/chunks/UiEditorSlashMenu.js +17 -46
  377. package/vue/chunks/UiEditorSlashMenuGroup.js +7 -25
  378. package/vue/chunks/UiEditorSlashMenuItem.js +16 -31
  379. package/vue/chunks/UiEditorSurface.js +7 -25
  380. package/vue/chunks/UiEditorTableContextMenu.js +25 -102
  381. package/vue/chunks/UiEditorTableOverlay.js +41 -104
  382. package/vue/chunks/UiEditorTableToolbar.js +44 -122
  383. package/vue/chunks/UiEditorToolbar.js +7 -26
  384. package/vue/chunks/UiFloatingActionButton.js +10 -28
  385. package/vue/chunks/UiFormField.js +8 -27
  386. package/vue/chunks/UiGrid.js +10 -28
  387. package/vue/chunks/UiIcon.js +21 -74
  388. package/vue/chunks/UiIconButton.js +18 -50
  389. package/vue/chunks/UiImage.js +14 -33
  390. package/vue/chunks/UiInput.js +12 -31
  391. package/vue/chunks/UiInputGroup.js +10 -29
  392. package/vue/chunks/UiList.js +17 -37
  393. package/vue/chunks/UiListItem.js +12 -30
  394. package/vue/chunks/UiListbox.js +22 -124
  395. package/vue/chunks/UiMenu.js +13 -32
  396. package/vue/chunks/UiMenuGroup.js +8 -26
  397. package/vue/chunks/UiMenuItem.js +35 -80
  398. package/vue/chunks/UiMeter.js +17 -351
  399. package/vue/chunks/UiNavItem.js +23 -57
  400. package/vue/chunks/UiPageHeader.js +7 -25
  401. package/vue/chunks/UiPopover.js +9 -28
  402. package/vue/chunks/UiRadio.js +11 -43
  403. package/vue/chunks/UiRadioGroup.js +13 -32
  404. package/vue/chunks/UiReel.js +10 -28
  405. package/vue/chunks/UiScrollArea.js +10 -29
  406. package/vue/chunks/UiSearchResultRow.js +10 -28
  407. package/vue/chunks/UiSearchShell.js +9 -28
  408. package/vue/chunks/UiSection.js +9 -27
  409. package/vue/chunks/UiSelect.js +10 -29
  410. package/vue/chunks/UiSeparator.js +10 -28
  411. package/vue/chunks/UiSidebar.js +15 -47
  412. package/vue/chunks/UiSpinner.js +8 -44
  413. package/vue/chunks/UiStack.js +12 -30
  414. package/vue/chunks/UiStatusMessage.js +10 -42
  415. package/vue/chunks/UiSwitch.js +11 -43
  416. package/vue/chunks/UiSwitcher.js +9 -28
  417. package/vue/chunks/UiTable.js +7 -26
  418. package/vue/chunks/UiTabs.js +15 -91
  419. package/vue/chunks/UiText.js +148 -168
  420. package/vue/chunks/UiTextarea.js +16 -35
  421. package/vue/chunks/UiToast.js +13 -37
  422. package/vue/chunks/UiToastRegion.js +16 -88
  423. package/vue/chunks/UiTooltip.js +14 -46
  424. package/vue/chunks/UiTopBar.js +5 -17
  425. package/vue/chunks/UiTree.js +13 -32
  426. package/vue/chunks/UiTreeItem.js +34 -90
  427. package/vue/chunks/_plugin-vue_export-helper.js +904 -1
  428. package/vue/chunks/control.js +3 -0
  429. package/vue/chunks/props.js +1 -1
  430. package/vue/components.css +7902 -7830
  431. package/vue/editor/index.js +42 -171
  432. package/vue/editor/primitives.d.ts +9 -1
  433. package/vue/host.ts +999 -14
  434. package/vue/index.d.ts +1 -0
  435. package/vue/index.js +9 -8
  436. package/vue/chunks/host.js +0 -443
  437. package/vue/editor/image-controls.d.ts +0 -19
package/vue/UiButton.vue CHANGED
@@ -1,8 +1,17 @@
1
- <!-- Generated by HTML Next 1.0.0-alpha.35 for Vue 3.5. Do not edit. -->
1
+ <!-- Generated by HTML Next 1.0.0-alpha.51 for Vue 3.5. Do not edit. -->
2
2
  <script setup lang="ts">
3
3
  import { computed, getCurrentInstance, useTemplateRef, watchSyncEffect } from 'vue'
4
4
  import type { PropType } from 'vue'
5
- import { createDispatch, preserveRootFocus, useComponentHost } from './host'
5
+ import {
6
+ attribute,
7
+ checkHydratedRoot,
8
+ concat,
9
+ createDispatch,
10
+ nativeAttrs,
11
+ preserveRootFocus,
12
+ useComponentHost,
13
+ useReflectedProp,
14
+ } from './host'
6
15
  import { checkedProp, propValidityState, vPropValidity } from './props'
7
16
  import UiIcon from './UiIcon.vue'
8
17
  import UiSpinner from './UiSpinner.vue'
@@ -275,38 +284,7 @@ void checkedProps.value
275
284
  watchSyncEffect(() => {
276
285
  void checkedProps.value
277
286
  })
278
- function nativeAttrs(attrs: Record<string, unknown>): Record<string, unknown> {
279
- const names = Object.keys(attrs)
280
- if (!names.some((name) => Object.hasOwn(Object.prototype, name))) return attrs
281
- return Object.fromEntries(names.map((name) => [
282
- Object.hasOwn(Object.prototype, name)
283
- ? name === '__proto__' ? '__Proto__' : name[0]!.toUpperCase() + name.slice(1)
284
- : name,
285
- attrs[name],
286
- ]))
287
- }
288
- const componentInstance = getCurrentInstance()
289
- function reflectedProp(
290
- name: string,
291
- kebab: string,
292
- value: unknown,
293
- fallback: string | undefined,
294
- bound: boolean,
295
- separator?: string,
296
- ): string | undefined {
297
- const incoming = componentInstance?.vnode.props
298
- if (
299
- !bound
300
- && (incoming === null || incoming === undefined
301
- || (!Object.hasOwn(incoming, name) && !Object.hasOwn(incoming, kebab)))
302
- ) return fallback
303
- if (value === null || value === undefined) return undefined
304
- return Array.isArray(value) && separator !== undefined
305
- ? value.join(separator)
306
- : typeof value === 'object'
307
- ? JSON.stringify(value)
308
- : String(value)
309
- }
287
+ const reflectedProp = useReflectedProp()
310
288
  const hydrationInstance = getCurrentInstance()
311
289
 
312
290
  const rootArmElement = useTemplateRef<HTMLElement>('@html-next/root')
@@ -590,25 +568,14 @@ const guardedBinding7 = computed(() => {
590
568
  concat(checkedProps.value.loading || checkedProps.value.pending),
591
569
  ))
592
570
  })
593
- const hydrationNode = hydrationInstance?.vnode.el
594
- if (
595
- typeof window !== 'undefined' && hydrationNode != null
596
- && (!(hydrationNode instanceof Element)
597
- || hydrationNode.localName
598
- !== ((checkedProps.value.variant === 'card' && checkedProps.value.as === 'a')
599
- ? 'a'
600
- : ((checkedProps.value.variant === 'card')
601
- ? 'button'
602
- : ((checkedProps.value.as === 'a') ? 'a' : ('button')))))
603
- ) {
604
- throw Object.assign(new Error('HR005: Server markup for <ui-button> has an incompatible root.'), {
605
- name: 'HtmlDiagnosticError',
606
- diagnostic: Object.freeze({
607
- code: 'HR005',
608
- message: 'Server markup for <ui-button> has an incompatible root.',
609
- }),
610
- })
611
- }
571
+ checkHydratedRoot(
572
+ (checkedProps.value.variant === 'card' && checkedProps.value.as === 'a')
573
+ ? 'a'
574
+ : ((checkedProps.value.variant === 'card')
575
+ ? 'button'
576
+ : ((checkedProps.value.as === 'a') ? 'a' : ('button'))),
577
+ 'ui-button',
578
+ )
612
579
 
613
580
  /** The values the styles' :host-state() rules test. */
614
581
  const hostState = computed(() =>
@@ -666,43 +633,12 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
666
633
  propValidity: (name: string) =>
667
634
  propValidityState({ contract: propValidityContract, values: { ...props } }, name),
668
635
  })
669
-
670
- function text(value: unknown): string {
671
- if (Array.isArray(value)) return value.map(text).join(' ')
672
- return value === null || value === undefined || typeof value === 'object' ? '' : String(value)
673
- }
674
-
675
- function attribute(value: unknown): any {
676
- if (
677
- value === null || value === undefined || value === false
678
- || (typeof value === 'object' && !Array.isArray(value))
679
- ) return undefined
680
- return value === true ? '' : text(value)
681
- }
682
-
683
- // A nonempty scalar call cannot produce the invalid-result sentinel.
684
- type ConcatResult<T extends unknown[]> = T extends
685
- [
686
- string | number | boolean | null | undefined,
687
- ...(string | number | boolean | null | undefined)[],
688
- ] ? string | undefined
689
- : string | symbol | undefined
690
- function concat<T extends unknown[]>(...values: T): ConcatResult<T> {
691
- if (values.some(value => value === Symbol.for('html-next.invalid-result'))) {
692
- return Symbol.for('html-next.invalid-result') as ConcatResult<T>
693
- }
694
- if (values.some(value => value === undefined)) return undefined as ConcatResult<T>
695
- if (values.length === 0 || values.some(value => typeof value === 'object' && value !== null)) {
696
- return Symbol.for('html-next.invalid-result') as ConcatResult<T>
697
- }
698
- return values.map(value => value === null ? '' : String(value)).join('') as ConcatResult<T>
699
- }
700
636
  </script>
701
637
 
702
638
  <template>
703
639
  <a
704
640
  v-if="checkedProps.variant === 'card' && checkedProps.as === 'a'"
705
- data-component="ui-button"
641
+ class="ui-button"
706
642
  v-bind="nativeAttrs($attrs)"
707
643
  :href="guarded"
708
644
  :target="checkedProps.target ?? undefined"
@@ -729,6 +665,7 @@ function concat<T extends unknown[]>(...values: T): ConcatResult<T> {
729
665
  ref="@html-next/root"
730
666
  ><span class="card-icon"><UiSpinner
731
667
  v-if="checkedProps.loading || checkedProps.pending"
668
+ class="ui-spinner"
732
669
  size="sm"
733
670
  />
734
671
  <template v-if="!(checkedProps.loading || checkedProps.pending)"><slot
@@ -736,12 +673,13 @@ function concat<T extends unknown[]>(...values: T): ConcatResult<T> {
736
673
  /></template></span>
737
674
  <span class="card-content"><slot /></span>
738
675
  <span class="card-action"><slot name="action"><UiIcon
676
+ class="ui-icon"
739
677
  name="chevron-right"
740
678
  aria-hidden="true"
741
679
  /></slot></span></a>
742
680
  <button
743
681
  v-else-if="checkedProps.variant === 'card'"
744
- data-component="ui-button"
682
+ class="ui-button"
745
683
  v-bind="nativeAttrs($attrs)"
746
684
  :type="checkedProps.type ?? undefined"
747
685
  :disabled="checkedProps.disabled ?? undefined"
@@ -767,6 +705,7 @@ function concat<T extends unknown[]>(...values: T): ConcatResult<T> {
767
705
  >
768
706
  <span class="card-icon"><UiSpinner
769
707
  v-if="checkedProps.loading || checkedProps.pending"
708
+ class="ui-spinner"
770
709
  size="sm"
771
710
  />
772
711
  <template v-if="!(checkedProps.loading || checkedProps.pending)"><slot
@@ -774,13 +713,14 @@ function concat<T extends unknown[]>(...values: T): ConcatResult<T> {
774
713
  /></template></span>
775
714
  <span class="card-content"><slot /></span>
776
715
  <span class="card-action"><slot name="action"><UiIcon
716
+ class="ui-icon"
777
717
  name="chevron-right"
778
718
  aria-hidden="true"
779
719
  /></slot></span>
780
720
  </button>
781
721
  <a
782
722
  v-else-if="checkedProps.as === 'a'"
783
- data-component="ui-button"
723
+ class="ui-button"
784
724
  v-bind="nativeAttrs($attrs)"
785
725
  :href="guardedBinding4"
786
726
  :target="checkedProps.target ?? undefined"
@@ -806,13 +746,14 @@ function concat<T extends unknown[]>(...values: T): ConcatResult<T> {
806
746
  :data-ui-button-state="hostState || undefined"
807
747
  ref="@html-next/root"
808
748
  ><span v-if="checkedProps.loading || checkedProps.pending" class="spinner-wrap"><UiSpinner
749
+ class="ui-spinner"
809
750
  size="sm"
810
751
  /></span>
811
752
  <slot />
812
753
  <span class="badge"><slot name="badge" /></span></a>
813
754
  <button
814
755
  v-else
815
- data-component="ui-button"
756
+ class="ui-button"
816
757
  v-bind="nativeAttrs($attrs)"
817
758
  :type="checkedProps.type ?? undefined"
818
759
  :disabled="checkedProps.disabled ?? undefined"
@@ -837,6 +778,7 @@ function concat<T extends unknown[]>(...values: T): ConcatResult<T> {
837
778
  ref="@html-next/root"
838
779
  >
839
780
  <span v-if="checkedProps.loading || checkedProps.pending" class="spinner-wrap"><UiSpinner
781
+ class="ui-spinner"
840
782
  size="sm"
841
783
  /></span>
842
784
  <slot />
@@ -919,440 +861,447 @@ function concat<T extends unknown[]>(...values: T): ConcatResult<T> {
919
861
  inherits: false;
920
862
  }
921
863
 
922
- [data-component~="ui-button"] {
923
- /* Optional inherited action-group values keep text and icon actions under the same light.
924
- One fine top/start highlight follows the bottom/end lowlight at a joined action seam.
925
- A single ambient lift avoids stacking a face gradient or another inset bevel. */
926
- --_ui-action-start: 1px;
927
- --_ui-action-edge: var(
928
- --ui-action-edge,
929
- inset var(--_ui-action-start) 1px 0 light-dark(
930
- rgb(255 255 255 / 0.08),
931
- rgb(255 255 255 / 0.06)
932
- ),
933
- inset calc(-1 * var(--_ui-action-start)) -1px 0 light-dark(rgb(0 0 0 / 0.08), rgb(0 0 0 / 0.08))
934
- );
935
- --_ui-action-shadow:
936
- var(--_ui-action-edge),
937
- 0 1px 2px light-dark(rgb(0 0 0 / 0.10), rgb(0 0 0 / 0.20));
938
- --_hue: var(--ui-accent);
939
- --_hue-hover: var(--ui-accent-hover);
940
- --_hue-active: var(--ui-accent-active);
941
- --_hue-text: var(--ui-accent-active);
942
- --_on-hue: var(--ui-on-accent);
864
+ /* An anchor keeps the boxed button look even when an app styles ordinary links. */
943
865
 
944
- --_tone: var(--_hue);
945
- --_tone-hover: var(--_hue-hover);
946
- --_tone-active: var(--_hue-active);
947
- --_tone-text: var(--_hue-text);
948
- --_on-tone: var(--_on-hue);
866
+ /* A count is an adornment, not another line of label text. Keep the standard control height
867
+ with enough inset for a 24px mark; large content can still grow the button naturally. */
949
868
 
950
- display: inline-flex;
951
- align-items: center;
952
- justify-content: center;
953
- column-gap: var(--ui-space-2);
954
- vertical-align: middle;
955
- color: var(--_tone-text);
956
- }
869
+ /* Card actions inherit Button's palette and behavior; only their shared layout changes.
870
+ The icon may contain any decorative composition. Empty icons remove their column. */
957
871
 
958
- [data-component~="ui-button"]:dir(rtl) {
959
- --_ui-action-start: -1px;
960
- }
872
+ /* A link is never :enabled, so interactive states test "not unavailable" instead: for a button that
873
+ is exactly :enabled, at the same specificity, and it also matches a link that can be followed. */
961
874
 
962
- [data-component~="ui-button"][data-ui-button-state~="align=start"] {
963
- justify-content: flex-start;
964
- text-align: start;
965
- }
875
+ /* A neutral card encloses content quietly; ordinary outlines keep their action-tone edge. */
966
876
 
967
- [data-component~="ui-button"][data-ui-button-state~="stretch"] {
968
- display: flex;
969
- inline-size: 100%;
970
- }
877
+ /* Pressed reads as pressed in: the highlight goes, and the shadow moves inside. */
971
878
 
972
- [data-component~="ui-button"] {
973
- appearance: none;
974
- min-block-size: var(--ui-button-min-block-size, var(--ui-control-size-md));
975
- border-style: solid;
976
- border-width: var(--ui-border-width);
977
- border-color: var(--ui-button-border, var(--_tone));
978
- border-radius: var(--ui-button-radius, var(--ui-action-radius, var(--ui-radius-md)));
979
- background-color: var(--ui-button-surface, oklch(from var(--_tone) l c h / 5%));
980
- color: var(--ui-button-text, var(--_tone-text));
981
- font: inherit;
982
- font-weight: var(--ui-font-medium);
983
- text-decoration: none;
984
- /* Unset, a button wraps as its container does. */
985
- white-space: var(--ui-button-white-space, inherit);
986
- line-height: var(--ui-line-height-tight);
987
- padding: var(--ui-space-2) var(--ui-space-3);
988
- background-image: none;
989
- box-shadow: var(--ui-button-shadow, var(--ui-action-shadow, var(--_ui-action-shadow)));
990
- cursor: pointer;
991
- transition:
992
- background-color var(--ui-motion-fast) var(--ui-motion-ease),
993
- border-color var(--ui-motion-fast) var(--ui-motion-ease),
994
- color var(--ui-motion-fast) var(--ui-motion-ease),
995
- box-shadow var(--ui-motion-base) var(--ui-motion-ease);
996
- margin: 0;
997
- }
879
+ /* Tone is the colour, variant is the volume. Every pairing works: a danger outline is a
880
+ destructive secondary action, not a special case. */
998
881
 
999
- /* An anchor keeps the boxed button look even when an app styles ordinary links. */
1000
- [data-component~="ui-button"]:is(a) {
1001
- text-decoration: none;
1002
- }
882
+ /* A value picker is a field, with Select's quiet edge and resting lift. */
1003
883
 
1004
- .spinner-wrap {
1005
- display: inline-flex;
1006
- flex: none;
1007
- vertical-align: middle;
1008
- }
884
+ /* Tints derive from the text colour, not a surface token, so hover and press show on any background. */
1009
885
 
1010
- /* A count is an adornment, not another line of label text. Keep the standard control height
1011
- with enough inset for a 24px mark; large content can still grow the button naturally. */
1012
- [data-component~="ui-button"]:not([variant="link"]):has(.badge:not(:empty)) {
1013
- padding-block: var(--ui-space-0-5);
1014
- }
886
+ /* Pressed, or holding its menu open, a ghost button sinks slightly: a light surface with a faint
887
+ edge and a soft inner shadow. Lighter than hover, so an open menu's trigger never reads as heavy. */
1015
888
 
1016
- .badge {
1017
- display: inline-flex;
1018
- align-items: center;
1019
- flex: none;
1020
- }
889
+ /* A soft halo that transitions in with the other box-shadow changes, layered on the raised shadow. */
1021
890
 
1022
- .badge:empty {
1023
- display: none;
1024
- }
891
+ /* A loading action stays visually active; only an explicitly disabled action takes the
892
+ neutral disabled palette. Its flat surface and muted ink make the state unambiguous. */
1025
893
 
1026
- @supports (text-box-trim: trim-both) {
1027
- [data-component~="ui-button"] {
1028
- text-box-trim: trim-both;
1029
- text-box-edge: cap alphabetic;
1030
- }
1031
- }
894
+ /* Ghost keeps no border, but gains the same neutral surface as other disabled buttons. */
1032
895
 
1033
- [data-component~="ui-button"][data-ui-button-state~="size=xs"] {
1034
- min-block-size: 1.5rem;
1035
- padding: calc(var(--ui-space-0-5) * 1.5) calc(var(--ui-space-1) * 1.25);
1036
- font-size: var(--ui-font-size-xs);
1037
- }
896
+ /* The size states outrank :host, so sm is named too, or a small button would stay small. */
1038
897
 
1039
- [data-component~="ui-button"][data-ui-button-state~="shape=pill"] {
1040
- border-radius: var(--ui-button-radius, var(--ui-radius-round));
1041
- }
898
+ /* Under touch, a link-style button's press lands within the control minimum: an invisible hit
899
+ area, centred on it, like IconButton's. A boxed button grows to the minimum itself (below);
900
+ a link-style one keeps its text size, so a standalone one ("See all" under a list) needs the
901
+ area. xs sits inside a line of text the same way, so it keeps its size and gains the area too.
902
+ Only these need it: a hit area on every button would reach over its neighbours. */
1042
903
 
1043
- [data-component~="ui-button"][data-ui-button-state~="size=sm"] {
1044
- min-block-size: var(--ui-control-size-sm);
1045
- padding: var(--ui-space-1) var(--ui-space-2);
1046
- font-size: var(--ui-font-size-sm);
1047
- }
904
+ /* Link: an inline text action. No box, padding, or minimum height (inline targets are exempt under
905
+ WCAG 2.5.8); the inherited font; an underline that strengthens on hover; a visible focus ring. */
1048
906
 
1049
- [data-component~="ui-button"][data-ui-button-state~="size=lg"] {
1050
- min-block-size: var(--ui-control-size-lg);
1051
- padding: var(--ui-space-3) var(--ui-space-4);
1052
- font-size: var(--ui-font-size-md);
1053
- }
907
+ /* A component that sets its display still honours the hidden attribute on its root. */
1054
908
 
1055
- /* Card actions inherit Button's palette and behavior; only their shared layout changes.
1056
- The icon may contain any decorative composition. Empty icons remove their column. */
1057
- [data-component~="ui-button"][data-ui-button-state~="variant=card"] {
1058
- display: grid;
1059
- grid-template-columns: auto minmax(0, 1fr) auto;
1060
- align-content: center;
1061
- align-items: start;
1062
- gap: var(--ui-space-3);
1063
- inline-size: 100%;
1064
- min-block-size: max(var(--ui-control-min-block-size), var(--ui-control-size-md));
1065
- text-align: start;
1066
- white-space: normal;
1067
- box-shadow: none;
1068
- background-image: none;
1069
- }
1070
- [data-component~="ui-button"][data-ui-button-state~="variant=card"][data-ui-button-state~="size=lg"] {
1071
- min-block-size: max(var(--ui-control-min-block-size), var(--ui-control-size-lg));
1072
- }
1073
- [data-component~="ui-button"][data-ui-button-state~="variant=card"]:has(.card-icon:empty) {
1074
- grid-template-columns: minmax(0, 1fr) auto;
1075
- }
1076
- .card-icon {
1077
- display: flex;
1078
- align-items: flex-start;
1079
- }
1080
- .card-icon:empty {
1081
- display: none;
1082
- }
1083
- .card-content {
1084
- min-inline-size: 0;
1085
- }
1086
- .card-action {
1087
- display: flex;
1088
- align-items: center;
1089
- align-self: center;
1090
- }
909
+ @scope (.ui-button) to (.ui-spinner, .ui-icon) {
910
+ :scope:where(:scope) {
911
+ /* Optional inherited action-group values keep text and icon actions under the same light.
912
+ One fine top/start highlight follows the bottom/end lowlight at a joined action seam.
913
+ A single ambient lift avoids stacking a face gradient or another inset bevel. */
914
+ --_ui-action-start: 1px;
915
+ --_ui-action-edge: var(
916
+ --ui-action-edge,
917
+ inset var(--_ui-action-start) 1px 0 light-dark(
918
+ rgb(255 255 255 / 0.08),
919
+ rgb(255 255 255 / 0.06)
920
+ ),
921
+ inset calc(-1 * var(--_ui-action-start)) -1px 0 light-dark(
922
+ rgb(0 0 0 / 0.08),
923
+ rgb(0 0 0 / 0.08)
924
+ )
925
+ );
926
+ --_ui-action-shadow:
927
+ var(--_ui-action-edge),
928
+ 0 1px 2px light-dark(rgb(0 0 0 / 0.10), rgb(0 0 0 / 0.20));
929
+ --_hue: var(--ui-accent);
930
+ --_hue-hover: var(--ui-accent-hover);
931
+ --_hue-active: var(--ui-accent-active);
932
+ --_hue-text: var(--ui-accent-active);
933
+ --_on-hue: var(--ui-on-accent);
1091
934
 
1092
- /* A link is never :enabled, so interactive states test "not unavailable" instead: for a button that
1093
- is exactly :enabled, at the same specificity, and it also matches a link that can be followed. */
1094
- [data-component~="ui-button"]:hover:not(:disabled, [aria-disabled="true"]) {
1095
- border-color: var(--ui-button-hover-border, var(--_tone-hover));
1096
- background-color: var(--ui-button-hover-surface, oklch(from var(--_tone) l c h / 12%));
1097
- }
935
+ --_tone: var(--_hue);
936
+ --_tone-hover: var(--_hue-hover);
937
+ --_tone-active: var(--_hue-active);
938
+ --_tone-text: var(--_hue-text);
939
+ --_on-tone: var(--_on-hue);
1098
940
 
1099
- /* A neutral card encloses content quietly; ordinary outlines keep their action-tone edge. */
1100
- [data-component~="ui-button"][data-ui-button-state~="variant=card"][data-ui-button-state~="tone=neutral"] {
1101
- border-color: var(--ui-button-border, var(--ui-border));
1102
- }
941
+ display: inline-flex;
942
+ align-items: center;
943
+ justify-content: center;
944
+ column-gap: var(--ui-space-2);
945
+ vertical-align: middle;
946
+ color: var(--_tone-text);
947
+ }
1103
948
 
1104
- [data-component~="ui-button"][data-ui-button-state~="variant=card"][data-ui-button-state~="tone=neutral"]:hover:not(:disabled, [aria-disabled="true"]) {
1105
- border-color: var(--ui-button-hover-border, var(--ui-border-strong));
1106
- }
949
+ :scope:where(:scope):is(:dir(rtl)) {
950
+ --_ui-action-start: -1px;
951
+ }
1107
952
 
1108
- /* Pressed reads as pressed in: the highlight goes, and the shadow moves inside. */
1109
- [data-component~="ui-button"]:active:not(:disabled, [aria-disabled="true"]) {
1110
- background-color: var(--ui-button-active-surface, oklch(from var(--_tone) l c h / 18%));
1111
- background-image: none;
1112
- box-shadow: var(--ui-pressed);
1113
- }
953
+ :scope:where(:scope):is([data-ui-button-state~="align=start"]) {
954
+ justify-content: flex-start;
955
+ text-align: start;
956
+ }
1114
957
 
1115
- [data-component~="ui-button"][data-ui-button-state~="variant=solid"],
1116
- [data-component~="ui-button"][data-ui-button-state~="variant=danger"] {
1117
- border-color: var(--_tone);
1118
- background-color: var(--_tone);
1119
- color: var(--_on-tone);
1120
- box-shadow: var(--ui-button-solid-shadow, var(--ui-action-shadow, var(--_ui-action-shadow)));
1121
- }
958
+ :scope:where(:scope):is([data-ui-button-state~="stretch"]) {
959
+ display: flex;
960
+ inline-size: 100%;
961
+ }
1122
962
 
1123
- :is([data-component~="ui-button"][data-ui-button-state~="variant=solid"], [data-component~="ui-button"][data-ui-button-state~="variant=danger"]):hover:not(:disabled, [aria-disabled="true"]) {
1124
- background-color: var(--_tone-hover);
1125
- border-color: var(--_tone-hover);
1126
- }
963
+ :scope:where(:scope) {
964
+ appearance: none;
965
+ min-block-size: var(--ui-button-min-block-size, var(--ui-control-size-md));
966
+ border-style: solid;
967
+ border-width: var(--ui-border-width);
968
+ border-color: var(--ui-button-border, var(--_tone));
969
+ border-radius: var(--ui-button-radius, var(--ui-action-radius, var(--ui-radius-md)));
970
+ background-color: var(--ui-button-surface, oklch(from var(--_tone) l c h / 5%));
971
+ color: var(--ui-button-text, var(--_tone-text));
972
+ font: inherit;
973
+ font-weight: var(--ui-font-medium);
974
+ text-decoration: none;
975
+ /* Unset, a button wraps as its container does. */
976
+ white-space: var(--ui-button-white-space, inherit);
977
+ line-height: var(--ui-line-height-tight);
978
+ padding: var(--ui-space-2) var(--ui-space-3);
979
+ background-image: none;
980
+ box-shadow: var(--ui-button-shadow, var(--ui-action-shadow, var(--_ui-action-shadow)));
981
+ cursor: pointer;
982
+ transition:
983
+ background-color var(--ui-motion-fast) var(--ui-motion-ease),
984
+ border-color var(--ui-motion-fast) var(--ui-motion-ease),
985
+ color var(--ui-motion-fast) var(--ui-motion-ease),
986
+ box-shadow var(--ui-motion-base) var(--ui-motion-ease);
987
+ margin: 0;
988
+ }
989
+ :scope:where(:scope):is(:is(a)) {
990
+ text-decoration: none;
991
+ }
1127
992
 
1128
- :is([data-component~="ui-button"][data-ui-button-state~="variant=solid"], [data-component~="ui-button"][data-ui-button-state~="variant=danger"]):active:not(:disabled, [aria-disabled="true"]) {
1129
- background-color: var(--_tone-active);
1130
- border-color: var(--_tone-active);
1131
- background-image: none;
1132
- box-shadow: var(--ui-pressed);
1133
- }
993
+ .spinner-wrap {
994
+ display: inline-flex;
995
+ flex: none;
996
+ vertical-align: middle;
997
+ }
998
+ :scope:where(:scope):is(:not([variant="link"]):has(.badge:not(:empty))) {
999
+ padding-block: var(--ui-space-0-5);
1000
+ }
1134
1001
 
1135
- /* Tone is the colour, variant is the volume. Every pairing works: a danger outline is a
1136
- destructive secondary action, not a special case. */
1137
- [data-component~="ui-button"][data-ui-button-state~="tone=neutral"] {
1138
- --_hue: var(--ui-text);
1139
- --_hue-hover: var(--ui-text);
1140
- --_hue-active: var(--ui-text);
1141
- --_hue-text: var(--ui-text);
1142
- --_on-hue: var(--ui-surface);
1143
- }
1002
+ .badge {
1003
+ display: inline-flex;
1004
+ align-items: center;
1005
+ flex: none;
1006
+ }
1144
1007
 
1145
- [data-component~="ui-button"][data-ui-button-state~="tone=danger"],
1146
- [data-component~="ui-button"][data-ui-button-state~="variant=danger"] {
1147
- --_hue: var(--ui-danger);
1148
- --_hue-hover: var(--ui-danger-hover);
1149
- --_hue-active: var(--ui-danger-hover);
1150
- --_hue-text: var(--ui-danger-hover);
1151
- --_on-hue: var(--ui-on-danger);
1152
- }
1008
+ .badge:empty {
1009
+ display: none;
1010
+ }
1153
1011
 
1154
- [data-component~="ui-button"][data-ui-button-state~="tone=success"] {
1155
- --_hue: var(--ui-success);
1156
- --_hue-hover: color-mix(in srgb, var(--ui-success) 85%, #000);
1157
- --_hue-active: color-mix(in srgb, var(--ui-success) 75%, #000);
1158
- --_hue-text: color-mix(in srgb, var(--ui-success) 85%, #000);
1159
- --_on-hue: var(--ui-surface);
1160
- }
1012
+ @supports (text-box-trim: trim-both) {
1013
+ :scope:where(:scope) {
1014
+ text-box-trim: trim-both;
1015
+ text-box-edge: cap alphabetic;
1016
+ }
1017
+ }
1161
1018
 
1162
- [data-component~="ui-button"][data-ui-button-state~="tone=warning"] {
1163
- --_hue: var(--ui-warning);
1164
- --_hue-hover: color-mix(in srgb, var(--ui-warning) 85%, #000);
1165
- --_hue-active: color-mix(in srgb, var(--ui-warning) 75%, #000);
1166
- --_hue-text: color-mix(in srgb, var(--ui-warning) 85%, #000);
1167
- --_on-hue: var(--ui-surface);
1168
- }
1019
+ :scope:where(:scope):is([data-ui-button-state~="size=xs"]) {
1020
+ min-block-size: 1.5rem;
1021
+ padding: calc(var(--ui-space-0-5) * 1.5) calc(var(--ui-space-1) * 1.25);
1022
+ font-size: var(--ui-font-size-xs);
1023
+ }
1169
1024
 
1170
- [data-component~="ui-button"][data-ui-button-state~="tone=info"] {
1171
- --_hue: var(--ui-info);
1172
- --_hue-hover: color-mix(in srgb, var(--ui-info) 85%, #000);
1173
- --_hue-active: color-mix(in srgb, var(--ui-info) 75%, #000);
1174
- --_hue-text: color-mix(in srgb, var(--ui-info) 85%, #000);
1175
- --_on-hue: var(--ui-surface);
1176
- }
1025
+ :scope:where(:scope):is([data-ui-button-state~="shape=pill"]) {
1026
+ border-radius: var(--ui-button-radius, var(--ui-radius-round));
1027
+ }
1177
1028
 
1178
- /* A value picker is a field, with Select's quiet edge and resting lift. */
1179
- [data-component~="ui-button"][data-ui-button-state~="variant=field"] {
1180
- --_ui-field-shadow: var(--ui-shadow-sm);
1181
- border-color: var(--ui-button-border, var(--ui-control-border, var(--ui-border-strong)));
1182
- border-radius: var(--ui-button-radius, var(--ui-field-radius, var(--ui-radius-md)));
1183
- background-color: var(--ui-button-surface, var(--ui-control-surface, var(--ui-surface-elevated)));
1184
- color: var(--ui-button-text, var(--ui-text-primary));
1185
- font-weight: var(--ui-font-normal);
1186
- box-shadow: var(--ui-button-shadow, var(--_ui-field-shadow));
1187
- }
1029
+ :scope:where(:scope):is([data-ui-button-state~="size=sm"]) {
1030
+ min-block-size: var(--ui-control-size-sm);
1031
+ padding: var(--ui-space-1) var(--ui-space-2);
1032
+ font-size: var(--ui-font-size-sm);
1033
+ }
1188
1034
 
1189
- [data-component~="ui-button"][data-ui-button-state~="variant=field"]:hover:not(:disabled, [aria-disabled="true"]) {
1190
- border-color: var(
1191
- --ui-button-hover-border,
1192
- var(--ui-control-border-hover, var(--ui-text-secondary))
1193
- );
1194
- background-color: var(
1195
- --ui-button-hover-surface,
1196
- var(--ui-control-surface, var(--ui-surface-elevated))
1197
- );
1198
- }
1035
+ :scope:where(:scope):is([data-ui-button-state~="size=lg"]) {
1036
+ min-block-size: var(--ui-control-size-lg);
1037
+ padding: var(--ui-space-3) var(--ui-space-4);
1038
+ font-size: var(--ui-font-size-md);
1039
+ }
1040
+ :scope:where(:scope):is([data-ui-button-state~="variant=card"]) {
1041
+ display: grid;
1042
+ grid-template-columns: auto minmax(0, 1fr) auto;
1043
+ align-content: center;
1044
+ align-items: start;
1045
+ gap: var(--ui-space-3);
1046
+ inline-size: 100%;
1047
+ min-block-size: max(var(--ui-control-min-block-size), var(--ui-control-size-md));
1048
+ text-align: start;
1049
+ white-space: normal;
1050
+ box-shadow: none;
1051
+ background-image: none;
1052
+ }
1053
+ :scope:where(:scope):is([data-ui-button-state~="variant=card"][data-ui-button-state~="size=lg"]) {
1054
+ min-block-size: max(var(--ui-control-min-block-size), var(--ui-control-size-lg));
1055
+ }
1056
+ :scope:where(:scope):is([data-ui-button-state~="variant=card"]:has(.card-icon:empty)) {
1057
+ grid-template-columns: minmax(0, 1fr) auto;
1058
+ }
1059
+ .card-icon {
1060
+ display: flex;
1061
+ align-items: flex-start;
1062
+ }
1063
+ .card-icon:empty {
1064
+ display: none;
1065
+ }
1066
+ .card-content {
1067
+ min-inline-size: 0;
1068
+ }
1069
+ .card-action {
1070
+ display: flex;
1071
+ align-items: center;
1072
+ align-self: center;
1073
+ }
1074
+ :scope:where(:scope):is(:hover:not(:disabled, [aria-disabled="true"])) {
1075
+ border-color: var(--ui-button-hover-border, var(--_tone-hover));
1076
+ background-color: var(--ui-button-hover-surface, oklch(from var(--_tone) l c h / 12%));
1077
+ }
1078
+ :scope:where(:scope):is([data-ui-button-state~="variant=card"][data-ui-button-state~="tone=neutral"]) {
1079
+ border-color: var(--ui-button-border, var(--ui-border));
1080
+ }
1199
1081
 
1200
- [data-component~="ui-button"][data-ui-button-state~="variant=field"]:is(:active, [aria-expanded="true"]):not(:disabled, [aria-disabled="true"]) {
1201
- --_ui-field-shadow: var(--ui-pressed);
1202
- }
1082
+ :scope:where(:scope):is([data-ui-button-state~="variant=card"][data-ui-button-state~="tone=neutral"]:hover:not(:disabled, [aria-disabled="true"])) {
1083
+ border-color: var(--ui-button-hover-border, var(--ui-border-strong));
1084
+ }
1085
+ :scope:where(:scope):is(:active:not(:disabled, [aria-disabled="true"])) {
1086
+ background-color: var(--ui-button-active-surface, oklch(from var(--_tone) l c h / 18%));
1087
+ background-image: none;
1088
+ box-shadow: var(--ui-pressed);
1089
+ }
1203
1090
 
1204
- [data-component~="ui-button"][data-ui-button-state~="variant=field"]:focus-visible {
1205
- border-color: var(--ui-control-focus, var(--ui-accent-solid));
1206
- box-shadow:
1207
- var(--ui-button-shadow, var(--_ui-field-shadow)),
1208
- var(--ui-control-focus-halo-shadow);
1209
- }
1091
+ :scope:where(:scope):is([data-ui-button-state~="variant=solid"]),
1092
+ :scope:where(:scope):is([data-ui-button-state~="variant=danger"]) {
1093
+ border-color: var(--_tone);
1094
+ background-color: var(--_tone);
1095
+ color: var(--_on-tone);
1096
+ box-shadow: var(--ui-button-solid-shadow, var(--ui-action-shadow, var(--_ui-action-shadow)));
1097
+ }
1210
1098
 
1211
- [data-component~="ui-button"][data-ui-button-state~="variant=ghost"] {
1212
- border-color: transparent;
1213
- background: transparent;
1214
- box-shadow: none;
1215
- color: var(--ui-button-ghost-text, var(--_tone-text));
1216
- }
1099
+ :is(:scope[data-ui-button-state~="variant=solid"], :scope[data-ui-button-state~="variant=danger"]):hover:not(:disabled, [aria-disabled="true"]) {
1100
+ background-color: var(--_tone-hover);
1101
+ border-color: var(--_tone-hover);
1102
+ }
1217
1103
 
1218
- /* Tints derive from the text colour, not a surface token, so hover and press show on any background. */
1219
- [data-component~="ui-button"][data-ui-button-state~="variant=ghost"]:hover:not(:disabled, [aria-disabled="true"]) {
1220
- background-color: var(--ui-button-ghost-hover-surface, oklch(from var(--_tone) l c h / 10%));
1221
- border-color: transparent;
1222
- }
1104
+ :is(:scope[data-ui-button-state~="variant=solid"], :scope[data-ui-button-state~="variant=danger"]):active:not(:disabled, [aria-disabled="true"]) {
1105
+ background-color: var(--_tone-active);
1106
+ border-color: var(--_tone-active);
1107
+ background-image: none;
1108
+ box-shadow: var(--ui-pressed);
1109
+ }
1110
+ :scope:where(:scope):is([data-ui-button-state~="tone=neutral"]) {
1111
+ --_hue: var(--ui-text);
1112
+ --_hue-hover: var(--ui-text);
1113
+ --_hue-active: var(--ui-text);
1114
+ --_hue-text: var(--ui-text);
1115
+ --_on-hue: var(--ui-surface);
1116
+ }
1223
1117
 
1224
- /* Pressed, or holding its menu open, a ghost button sinks slightly: a light surface with a faint
1225
- edge and a soft inner shadow. Lighter than hover, so an open menu's trigger never reads as heavy. */
1226
- [data-component~="ui-button"][data-ui-button-state~="variant=ghost"]:is(:active, [aria-expanded="true"]):not(:disabled, [aria-disabled="true"]) {
1227
- background-color: var(
1228
- --ui-button-ghost-active-surface,
1229
- color-mix(in oklch, var(--ui-surface), var(--_tone) 3%)
1230
- );
1231
- border-color: transparent;
1232
- box-shadow:
1233
- inset 0 0 0 1px oklch(from var(--_tone) l c h / 10%),
1234
- inset 0 1px 2px oklch(from var(--_tone) l c h / 8%);
1235
- }
1118
+ :scope:where(:scope):is([data-ui-button-state~="tone=danger"]),
1119
+ :scope:where(:scope):is([data-ui-button-state~="variant=danger"]) {
1120
+ --_hue: var(--ui-danger);
1121
+ --_hue-hover: var(--ui-danger-hover);
1122
+ --_hue-active: var(--ui-danger-hover);
1123
+ --_hue-text: var(--ui-danger-hover);
1124
+ --_on-hue: var(--ui-on-danger);
1125
+ }
1236
1126
 
1237
- /* A soft halo that transitions in with the other box-shadow changes, layered on the raised shadow. */
1238
- [data-component~="ui-button"]:focus-visible {
1239
- outline: none;
1240
- box-shadow:
1241
- var(--ui-button-shadow, var(--ui-action-shadow, var(--_ui-action-shadow))),
1242
- var(--ui-focus-halo);
1243
- }
1127
+ :scope:where(:scope):is([data-ui-button-state~="tone=success"]) {
1128
+ --_hue: var(--ui-success);
1129
+ --_hue-hover: color-mix(in srgb, var(--ui-success) 85%, #000);
1130
+ --_hue-active: color-mix(in srgb, var(--ui-success) 75%, #000);
1131
+ --_hue-text: color-mix(in srgb, var(--ui-success) 85%, #000);
1132
+ --_on-hue: var(--ui-surface);
1133
+ }
1244
1134
 
1245
- [data-component~="ui-button"][data-ui-button-state~="variant=solid"]:focus-visible {
1246
- box-shadow:
1247
- var(--ui-button-solid-shadow, var(--ui-action-shadow, var(--_ui-action-shadow))),
1248
- var(--ui-focus-halo);
1249
- }
1135
+ :scope:where(:scope):is([data-ui-button-state~="tone=warning"]) {
1136
+ --_hue: var(--ui-warning);
1137
+ --_hue-hover: color-mix(in srgb, var(--ui-warning) 85%, #000);
1138
+ --_hue-active: color-mix(in srgb, var(--ui-warning) 75%, #000);
1139
+ --_hue-text: color-mix(in srgb, var(--ui-warning) 85%, #000);
1140
+ --_on-hue: var(--ui-surface);
1141
+ }
1250
1142
 
1251
- :is([data-component~="ui-button"][data-ui-button-state~="variant=ghost"], [data-component~="ui-button"][data-ui-button-state~="variant=link"], [data-component~="ui-button"][data-ui-button-state~="variant=card"]):focus-visible {
1252
- box-shadow: var(--ui-focus-halo);
1253
- }
1143
+ :scope:where(:scope):is([data-ui-button-state~="tone=info"]) {
1144
+ --_hue: var(--ui-info);
1145
+ --_hue-hover: color-mix(in srgb, var(--ui-info) 85%, #000);
1146
+ --_hue-active: color-mix(in srgb, var(--ui-info) 75%, #000);
1147
+ --_hue-text: color-mix(in srgb, var(--ui-info) 85%, #000);
1148
+ --_on-hue: var(--ui-surface);
1149
+ }
1150
+ :scope:where(:scope):is([data-ui-button-state~="variant=field"]) {
1151
+ --_ui-field-shadow: var(--ui-shadow-sm);
1152
+ border-color: var(--ui-button-border, var(--ui-control-border, var(--ui-border-strong)));
1153
+ border-radius: var(--ui-button-radius, var(--ui-field-radius, var(--ui-radius-md)));
1154
+ background-color: var(
1155
+ --ui-button-surface,
1156
+ var(--ui-control-surface, var(--ui-surface-elevated))
1157
+ );
1158
+ color: var(--ui-button-text, var(--ui-text-primary));
1159
+ font-weight: var(--ui-font-normal);
1160
+ box-shadow: var(--ui-button-shadow, var(--_ui-field-shadow));
1161
+ }
1254
1162
 
1255
- /* A loading action stays visually active; only an explicitly disabled action takes the
1256
- neutral disabled palette. Its flat surface and muted ink make the state unambiguous. */
1257
- [data-component~="ui-button"]:is(:disabled, [aria-disabled="true"]:not([aria-busy="true"])) {
1258
- border-color: var(--ui-disabled-border);
1259
- background-color: var(--ui-disabled-surface);
1260
- color: var(--ui-disabled-text);
1261
- filter: var(--ui-button-disabled-filter, var(--ui-disabled-filter));
1262
- opacity: var(--ui-button-disabled-opacity, 1);
1263
- cursor: not-allowed;
1264
- background-image: none;
1265
- box-shadow: none;
1266
- }
1163
+ :scope:where(:scope):is([data-ui-button-state~="variant=field"]:hover:not(:disabled, [aria-disabled="true"])) {
1164
+ border-color: var(
1165
+ --ui-button-hover-border,
1166
+ var(--ui-control-border-hover, var(--ui-text-secondary))
1167
+ );
1168
+ background-color: var(
1169
+ --ui-button-hover-surface,
1170
+ var(--ui-control-surface, var(--ui-surface-elevated))
1171
+ );
1172
+ }
1267
1173
 
1268
- :is([data-component~="ui-button"][data-ui-button-state~="loading"], [data-component~="ui-button"][data-ui-button-state~="pending"]):focus-visible {
1269
- box-shadow: var(--ui-focus-halo);
1270
- }
1174
+ :scope:where(:scope):is([data-ui-button-state~="variant=field"]:is(:active, [aria-expanded="true"]):not(:disabled, [aria-disabled="true"])) {
1175
+ --_ui-field-shadow: var(--ui-pressed);
1176
+ }
1271
1177
 
1272
- /* Ghost keeps no border, but gains the same neutral surface as other disabled buttons. */
1273
- [data-component~="ui-button"][data-ui-button-state~="variant=ghost"]:is(:disabled, [aria-disabled="true"]:not([aria-busy="true"])) {
1274
- background-color: var(--ui-disabled-surface);
1275
- border-color: transparent;
1276
- }
1178
+ :scope:where(:scope):is([data-ui-button-state~="variant=field"]:focus-visible) {
1179
+ border-color: var(--ui-control-focus, var(--ui-accent-solid));
1180
+ box-shadow:
1181
+ var(--ui-button-shadow, var(--_ui-field-shadow)),
1182
+ var(--ui-control-focus-halo-shadow);
1183
+ }
1277
1184
 
1278
- /* The size states outrank :host, so sm is named too, or a small button would stay small. */
1279
- @media (pointer: coarse) {
1280
- [data-component~="ui-button"], [data-component~="ui-button"][data-ui-button-state~="size=sm"] {
1281
- min-block-size: var(--ui-control-min-block-size);
1185
+ :scope:where(:scope):is([data-ui-button-state~="variant=ghost"]) {
1186
+ border-color: transparent;
1187
+ background: transparent;
1188
+ box-shadow: none;
1189
+ color: var(--ui-button-ghost-text, var(--_tone-text));
1190
+ }
1191
+ :scope:where(:scope):is([data-ui-button-state~="variant=ghost"]:hover:not(:disabled, [aria-disabled="true"])) {
1192
+ background-color: var(--ui-button-ghost-hover-surface, oklch(from var(--_tone) l c h / 10%));
1193
+ border-color: transparent;
1194
+ }
1195
+ :scope:where(:scope):is([data-ui-button-state~="variant=ghost"]:is(:active, [aria-expanded="true"]):not(:disabled, [aria-disabled="true"])) {
1196
+ background-color: var(
1197
+ --ui-button-ghost-active-surface,
1198
+ color-mix(in oklch, var(--ui-surface), var(--_tone) 3%)
1199
+ );
1200
+ border-color: transparent;
1201
+ box-shadow:
1202
+ inset 0 0 0 1px oklch(from var(--_tone) l c h / 10%),
1203
+ inset 0 1px 2px oklch(from var(--_tone) l c h / 8%);
1204
+ }
1205
+ :scope:where(:scope):is(:focus-visible) {
1206
+ outline: none;
1207
+ box-shadow:
1208
+ var(--ui-button-shadow, var(--ui-action-shadow, var(--_ui-action-shadow))),
1209
+ var(--ui-focus-halo);
1282
1210
  }
1283
- }
1284
1211
 
1285
- /* Under touch, a link-style button's press lands within the control minimum: an invisible hit
1286
- area, centred on it, like IconButton's. A boxed button grows to the minimum itself (below);
1287
- a link-style one keeps its text size, so a standalone one ("See all" under a list) needs the
1288
- area. xs sits inside a line of text the same way, so it keeps its size and gains the area too.
1289
- Only these need it: a hit area on every button would reach over its neighbours. */
1290
- html[data-ui-input-modality="touch"]
1291
- [data-component~="ui-button"][data-ui-button-state~="variant=link"],
1292
- html[data-ui-input-modality="touch"]
1293
- [data-component~="ui-button"][data-ui-button-state~="size=xs"] {
1294
- position: relative;
1295
- }
1212
+ :scope:where(:scope):is([data-ui-button-state~="variant=solid"]:focus-visible) {
1213
+ box-shadow:
1214
+ var(--ui-button-solid-shadow, var(--ui-action-shadow, var(--_ui-action-shadow))),
1215
+ var(--ui-focus-halo);
1216
+ }
1296
1217
 
1297
- html[data-ui-input-modality="touch"]
1298
- [data-component~="ui-button"][data-ui-button-state~="variant=link"]::after,
1299
- html[data-ui-input-modality="touch"]
1300
- [data-component~="ui-button"][data-ui-button-state~="size=xs"]::after {
1301
- position: absolute;
1302
- inset: 50% auto auto 50%;
1303
- inline-size: max(100%, var(--ui-control-min-block-size));
1304
- block-size: max(100%, var(--ui-control-min-block-size));
1305
- transform: translate(-50%, -50%);
1306
- content: "";
1307
- }
1218
+ :is(:scope[data-ui-button-state~="variant=ghost"], :scope[data-ui-button-state~="variant=link"], :scope[data-ui-button-state~="variant=card"]):focus-visible {
1219
+ box-shadow: var(--ui-focus-halo);
1220
+ }
1221
+ :scope:where(:scope):is(:is(:disabled, [aria-disabled="true"]:not([aria-busy="true"]))) {
1222
+ border-color: var(--ui-disabled-border);
1223
+ background-color: var(--ui-disabled-surface);
1224
+ color: var(--ui-disabled-text);
1225
+ filter: var(--ui-button-disabled-filter, var(--ui-disabled-filter));
1226
+ opacity: var(--ui-button-disabled-opacity, 1);
1227
+ cursor: not-allowed;
1228
+ background-image: none;
1229
+ box-shadow: none;
1230
+ }
1308
1231
 
1309
- /* Link: an inline text action. No box, padding, or minimum height (inline targets are exempt under
1310
- WCAG 2.5.8); the inherited font; an underline that strengthens on hover; a visible focus ring. */
1311
- [data-component~="ui-button"][data-ui-button-state~="variant=link"] {
1312
- display: inline;
1313
- min-block-size: 0;
1314
- padding: 0;
1315
- border: 0;
1316
- border-radius: var(--ui-radius-sm);
1317
- background: none;
1318
- box-shadow: none;
1319
- font: inherit;
1320
- color: var(--ui-button-link-text, var(--ui-text-secondary));
1321
- text-decoration-line: underline;
1322
- text-decoration-thickness: 1px;
1323
- text-decoration-color: color-mix(in srgb, currentColor 40%, transparent);
1324
- text-underline-offset: 0.2em;
1325
- transition:
1326
- color var(--ui-motion-fast) var(--ui-motion-ease),
1327
- text-decoration-color var(--ui-motion-fast) var(--ui-motion-ease);
1328
- }
1232
+ :is(:scope[data-ui-button-state~="loading"], :scope[data-ui-button-state~="pending"]):focus-visible {
1233
+ box-shadow: var(--ui-focus-halo);
1234
+ }
1235
+ :scope:where(:scope):is([data-ui-button-state~="variant=ghost"]:is(:disabled, [aria-disabled="true"]:not([aria-busy="true"]))) {
1236
+ background-color: var(--ui-disabled-surface);
1237
+ border-color: transparent;
1238
+ }
1239
+ @media (pointer: coarse) {
1240
+ :scope:where(:scope), :scope:where(:scope):is([data-ui-button-state~="size=sm"]) {
1241
+ min-block-size: var(--ui-control-min-block-size);
1242
+ }
1243
+ }
1244
+ :scope:where(:scope):is(html[data-ui-input-modality="touch"]
1245
+ [data-ui-button-state~="variant=link"]),
1246
+ :scope:where(:scope):is(html[data-ui-input-modality="touch"] [data-ui-button-state~="size=xs"]) {
1247
+ position: relative;
1248
+ }
1329
1249
 
1330
- [data-component~="ui-button"][data-ui-button-state~="variant=link"]:hover:not(:disabled, [aria-disabled="true"]) {
1331
- color: var(--ui-button-link-hover-text, var(--ui-text-primary));
1332
- text-decoration-color: currentColor;
1333
- background: none;
1334
- transform: none;
1335
- }
1250
+ :scope:where(:scope):is(html[data-ui-input-modality="touch"]
1251
+ [data-ui-button-state~="variant=link"])::after,
1252
+ :scope:where(:scope):is(html[data-ui-input-modality="touch"]
1253
+ [data-ui-button-state~="size=xs"])::after {
1254
+ position: absolute;
1255
+ inset: 50% auto auto 50%;
1256
+ inline-size: max(100%, var(--ui-control-min-block-size));
1257
+ block-size: max(100%, var(--ui-control-min-block-size));
1258
+ transform: translate(-50%, -50%);
1259
+ content: "";
1260
+ }
1261
+ :scope:where(:scope):is([data-ui-button-state~="variant=link"]) {
1262
+ display: inline;
1263
+ min-block-size: 0;
1264
+ padding: 0;
1265
+ border: 0;
1266
+ border-radius: var(--ui-radius-sm);
1267
+ background: none;
1268
+ box-shadow: none;
1269
+ font: inherit;
1270
+ color: var(--ui-button-link-text, var(--ui-text-secondary));
1271
+ text-decoration-line: underline;
1272
+ text-decoration-thickness: 1px;
1273
+ text-decoration-color: color-mix(in srgb, currentColor 40%, transparent);
1274
+ text-underline-offset: 0.2em;
1275
+ transition:
1276
+ color var(--ui-motion-fast) var(--ui-motion-ease),
1277
+ text-decoration-color var(--ui-motion-fast) var(--ui-motion-ease);
1278
+ }
1336
1279
 
1337
- [data-component~="ui-button"][data-ui-button-state~="variant=link"]:active:not(:disabled, [aria-disabled="true"]) {
1338
- background: none;
1339
- transform: none;
1340
- }
1280
+ :scope:where(:scope):is([data-ui-button-state~="variant=link"]:hover:not(:disabled, [aria-disabled="true"])) {
1281
+ color: var(--ui-button-link-hover-text, var(--ui-text-primary));
1282
+ text-decoration-color: currentColor;
1283
+ background: none;
1284
+ transform: none;
1285
+ }
1341
1286
 
1342
- [data-component~="ui-button"][data-ui-button-state~="variant=link"]:is(:disabled, [aria-disabled="true"]:not([aria-busy="true"])) {
1343
- background: none;
1344
- border-color: transparent;
1345
- }
1287
+ :scope:where(:scope):is([data-ui-button-state~="variant=link"]:active:not(:disabled, [aria-disabled="true"])) {
1288
+ background: none;
1289
+ transform: none;
1290
+ }
1346
1291
 
1347
- [data-component~="ui-button"][data-ui-button-state~="variant=link"]:focus-visible {
1348
- box-shadow: none;
1349
- /* Fallback keeps the ring if the token is missing: an unresolved var() would void the outline. */
1350
- outline: var(--ui-focus-width) solid var(--ui-focus-ring);
1351
- outline-offset: var(--ui-focus-width);
1352
- }
1292
+ :scope:where(:scope):is([data-ui-button-state~="variant=link"]:is(:disabled, [aria-disabled="true"]:not([aria-busy="true"]))) {
1293
+ background: none;
1294
+ border-color: transparent;
1295
+ }
1353
1296
 
1354
- /* A component that sets its display still honours the hidden attribute on its root. */
1355
- [data-component~="ui-button"][hidden] {
1356
- display: none;
1297
+ :scope:where(:scope):is([data-ui-button-state~="variant=link"]:focus-visible) {
1298
+ box-shadow: none;
1299
+ /* Fallback keeps the ring if the token is missing: an unresolved var() would void the outline. */
1300
+ outline: var(--ui-focus-width) solid var(--ui-focus-ring);
1301
+ outline-offset: var(--ui-focus-width);
1302
+ }
1303
+ :scope:where(:scope):is([hidden]) {
1304
+ display: none;
1305
+ }
1357
1306
  }
1358
1307
  </style>