@threadlabs/looma 0.28.5 → 0.28.7

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 (453) hide show
  1. package/components/ui-editor-block-actions/ui-editor-block-actions.html +20 -0
  2. package/components/ui-editor-block-actions/ui-editor-block-actions.js +14 -0
  3. package/components/ui-editor-image-toolbar/ui-editor-image-toolbar.html +7 -6
  4. package/components/ui-editor-image-toolbar/ui-editor-image-toolbar.js +2 -1
  5. package/components/ui-editor-link-card/ui-editor-link-card.html +57 -0
  6. package/components/ui-editor-link-card/ui-editor-link-card.js +27 -0
  7. package/components/ui-editor-mention-menu-item/ui-editor-mention-menu-item.html +3 -2
  8. package/dist/index.js +36 -34
  9. package/package.json +3 -2
  10. package/styles/ui-action-bar.css +13 -6
  11. package/styles/ui-affordance-scope.css +12 -5
  12. package/styles/ui-avatar-group.css +17 -10
  13. package/styles/ui-avatar.css +23 -16
  14. package/styles/ui-badge.css +78 -71
  15. package/styles/ui-breadcrumb-item.css +12 -5
  16. package/styles/ui-breadcrumbs.css +10 -3
  17. package/styles/ui-button.css +79 -72
  18. package/styles/ui-callout.css +29 -22
  19. package/styles/ui-card.css +25 -18
  20. package/styles/ui-checkbox.css +45 -37
  21. package/styles/ui-cluster.css +34 -27
  22. package/styles/ui-combobox.css +46 -39
  23. package/styles/ui-container.css +20 -13
  24. package/styles/ui-context-menu.css +17 -10
  25. package/styles/ui-cover.css +12 -5
  26. package/styles/ui-description-item.css +10 -3
  27. package/styles/ui-description-list.css +20 -13
  28. package/styles/ui-dialog.css +44 -35
  29. package/styles/ui-disclosure.css +32 -25
  30. package/styles/ui-editable.css +15 -8
  31. package/styles/ui-editor-block-actions.css +1 -0
  32. package/styles/ui-editor-image-toolbar.css +1 -1
  33. package/styles/ui-editor-insert-table-grid.css +11 -4
  34. package/styles/ui-editor-link-card.css +1 -0
  35. package/styles/ui-editor-mention-menu-item.css +17 -8
  36. package/styles/ui-editor-mention-menu.css +14 -7
  37. package/styles/ui-editor-slash-menu-group.css +10 -3
  38. package/styles/ui-editor-slash-menu-item.css +15 -8
  39. package/styles/ui-editor-slash-menu.css +15 -8
  40. package/styles/ui-editor-surface.css +10 -3
  41. package/styles/ui-editor-table-context-menu.css +17 -10
  42. package/styles/ui-editor-table-overlay.css +17 -10
  43. package/styles/ui-editor-table-toolbar.css +22 -15
  44. package/styles/ui-editor-toolbar.css +18 -11
  45. package/styles/ui-floating-action-button.css +21 -14
  46. package/styles/ui-form-field.css +20 -13
  47. package/styles/ui-grid.css +21 -14
  48. package/styles/ui-icon-button.css +80 -73
  49. package/styles/ui-icon.css +14 -7
  50. package/styles/ui-image.css +25 -18
  51. package/styles/ui-input-group.css +34 -27
  52. package/styles/ui-input.css +42 -35
  53. package/styles/ui-list-item.css +33 -26
  54. package/styles/ui-list.css +22 -15
  55. package/styles/ui-listbox.css +22 -14
  56. package/styles/ui-menu-group.css +10 -3
  57. package/styles/ui-menu-item.css +29 -22
  58. package/styles/ui-menu.css +25 -18
  59. package/styles/ui-meter.css +36 -29
  60. package/styles/ui-nav-item.css +26 -19
  61. package/styles/ui-page-header.css +12 -5
  62. package/styles/ui-popover.css +27 -20
  63. package/styles/ui-radio-group.css +14 -6
  64. package/styles/ui-radio.css +24 -17
  65. package/styles/ui-reel.css +28 -21
  66. package/styles/ui-scroll-area.css +22 -15
  67. package/styles/ui-search-result-row.css +28 -21
  68. package/styles/ui-search-shell.css +24 -17
  69. package/styles/ui-section.css +14 -7
  70. package/styles/ui-select.css +33 -26
  71. package/styles/ui-separator.css +17 -10
  72. package/styles/ui-sidebar.css +35 -28
  73. package/styles/ui-spinner.css +32 -23
  74. package/styles/ui-stack.css +29 -21
  75. package/styles/ui-status-message.css +14 -7
  76. package/styles/ui-switch.css +29 -22
  77. package/styles/ui-switcher.css +27 -20
  78. package/styles/ui-table.css +14 -7
  79. package/styles/ui-tabs.css +24 -17
  80. package/styles/ui-text.css +35 -28
  81. package/styles/ui-textarea.css +37 -30
  82. package/styles/ui-toast-region.css +74 -63
  83. package/styles/ui-toast.css +21 -14
  84. package/styles/ui-tooltip.css +38 -31
  85. package/styles/ui-top-bar.css +19 -12
  86. package/styles/ui-tree-item.css +79 -71
  87. package/styles/ui-tree.css +18 -11
  88. package/vanilla/UiActionBar.d.ts +1 -1
  89. package/vanilla/UiActionBar.js +1 -1
  90. package/vanilla/UiAffordanceScope.d.ts +1 -1
  91. package/vanilla/UiAffordanceScope.js +1 -1
  92. package/vanilla/UiAvatar.d.ts +1 -1
  93. package/vanilla/UiAvatar.js +1 -1
  94. package/vanilla/UiAvatarGroup.d.ts +1 -1
  95. package/vanilla/UiAvatarGroup.js +1 -1
  96. package/vanilla/UiBadge.d.ts +1 -1
  97. package/vanilla/UiBadge.js +1 -1
  98. package/vanilla/UiBreadcrumbItem.d.ts +1 -1
  99. package/vanilla/UiBreadcrumbItem.js +1 -1
  100. package/vanilla/UiBreadcrumbs.d.ts +1 -1
  101. package/vanilla/UiBreadcrumbs.js +1 -1
  102. package/vanilla/UiButton.d.ts +1 -1
  103. package/vanilla/UiButton.js +19 -57
  104. package/vanilla/UiCallout.d.ts +1 -1
  105. package/vanilla/UiCallout.js +25 -73
  106. package/vanilla/UiCard.d.ts +1 -1
  107. package/vanilla/UiCard.js +1 -1
  108. package/vanilla/UiCheckbox.d.ts +1 -1
  109. package/vanilla/UiCheckbox.js +1 -1
  110. package/vanilla/UiCluster.d.ts +1 -1
  111. package/vanilla/UiCluster.js +1 -1
  112. package/vanilla/UiCombobox.d.ts +1 -1
  113. package/vanilla/UiCombobox.js +60 -166
  114. package/vanilla/UiContainer.d.ts +1 -1
  115. package/vanilla/UiContainer.js +1 -1
  116. package/vanilla/UiContextMenu.d.ts +1 -1
  117. package/vanilla/UiContextMenu.js +1 -1
  118. package/vanilla/UiCover.d.ts +1 -1
  119. package/vanilla/UiCover.js +1 -1
  120. package/vanilla/UiDescriptionItem.d.ts +1 -1
  121. package/vanilla/UiDescriptionItem.js +1 -1
  122. package/vanilla/UiDescriptionList.d.ts +1 -1
  123. package/vanilla/UiDescriptionList.js +1 -1
  124. package/vanilla/UiDialog.d.ts +1 -1
  125. package/vanilla/UiDialog.js +4 -10
  126. package/vanilla/UiDisclosure.d.ts +1 -1
  127. package/vanilla/UiDisclosure.js +1 -1
  128. package/vanilla/UiEditable.d.ts +1 -1
  129. package/vanilla/UiEditable.js +7 -19
  130. package/vanilla/UiEditorBlockActions.d.ts +16 -0
  131. package/vanilla/UiEditorBlockActions.js +41 -0
  132. package/vanilla/UiEditorImageToolbar.d.ts +1 -1
  133. package/vanilla/UiEditorImageToolbar.js +2 -2
  134. package/vanilla/UiEditorInsertTableGrid.d.ts +1 -1
  135. package/vanilla/UiEditorInsertTableGrid.js +1 -1
  136. package/vanilla/UiEditorLinkCard.d.ts +20 -0
  137. package/vanilla/UiEditorLinkCard.js +153 -0
  138. package/vanilla/UiEditorMentionMenu.d.ts +1 -1
  139. package/vanilla/UiEditorMentionMenu.js +17 -37
  140. package/vanilla/UiEditorMentionMenuItem.d.ts +1 -1
  141. package/vanilla/UiEditorMentionMenuItem.js +4 -10
  142. package/vanilla/UiEditorSlashMenu.d.ts +1 -1
  143. package/vanilla/UiEditorSlashMenu.js +5 -4
  144. package/vanilla/UiEditorSlashMenuGroup.d.ts +1 -1
  145. package/vanilla/UiEditorSlashMenuGroup.js +1 -1
  146. package/vanilla/UiEditorSlashMenuItem.d.ts +1 -1
  147. package/vanilla/UiEditorSlashMenuItem.js +7 -19
  148. package/vanilla/UiEditorSurface.d.ts +1 -1
  149. package/vanilla/UiEditorSurface.js +1 -1
  150. package/vanilla/UiEditorTableContextMenu.d.ts +1 -1
  151. package/vanilla/UiEditorTableContextMenu.js +6 -14
  152. package/vanilla/UiEditorTableOverlay.d.ts +1 -1
  153. package/vanilla/UiEditorTableOverlay.js +9 -25
  154. package/vanilla/UiEditorTableToolbar.d.ts +1 -1
  155. package/vanilla/UiEditorTableToolbar.js +25 -77
  156. package/vanilla/UiEditorToolbar.d.ts +1 -1
  157. package/vanilla/UiEditorToolbar.js +1 -1
  158. package/vanilla/UiFloatingActionButton.d.ts +1 -1
  159. package/vanilla/UiFloatingActionButton.js +1 -1
  160. package/vanilla/UiFormField.d.ts +1 -1
  161. package/vanilla/UiFormField.js +1 -1
  162. package/vanilla/UiGrid.d.ts +1 -1
  163. package/vanilla/UiGrid.js +1 -1
  164. package/vanilla/UiIcon.d.ts +1 -1
  165. package/vanilla/UiIcon.js +15 -47
  166. package/vanilla/UiIconButton.d.ts +1 -1
  167. package/vanilla/UiIconButton.js +4 -10
  168. package/vanilla/UiImage.d.ts +1 -1
  169. package/vanilla/UiImage.js +1 -1
  170. package/vanilla/UiInput.d.ts +1 -1
  171. package/vanilla/UiInput.js +1 -1
  172. package/vanilla/UiInputGroup.d.ts +1 -1
  173. package/vanilla/UiInputGroup.js +1 -1
  174. package/vanilla/UiList.d.ts +1 -1
  175. package/vanilla/UiList.js +1 -1
  176. package/vanilla/UiListItem.d.ts +1 -1
  177. package/vanilla/UiListItem.js +1 -1
  178. package/vanilla/UiListbox.d.ts +1 -1
  179. package/vanilla/UiListbox.js +4 -10
  180. package/vanilla/UiMenu.d.ts +1 -1
  181. package/vanilla/UiMenu.js +1 -1
  182. package/vanilla/UiMenuGroup.d.ts +1 -1
  183. package/vanilla/UiMenuGroup.js +4 -10
  184. package/vanilla/UiMenuItem.d.ts +1 -1
  185. package/vanilla/UiMenuItem.js +4 -10
  186. package/vanilla/UiMeter.d.ts +1 -1
  187. package/vanilla/UiMeter.js +13 -33
  188. package/vanilla/UiNavItem.d.ts +1 -1
  189. package/vanilla/UiNavItem.js +1 -1
  190. package/vanilla/UiPageHeader.d.ts +1 -1
  191. package/vanilla/UiPageHeader.js +1 -1
  192. package/vanilla/UiPopover.d.ts +1 -1
  193. package/vanilla/UiPopover.js +1 -1
  194. package/vanilla/UiRadio.d.ts +1 -1
  195. package/vanilla/UiRadio.js +1 -1
  196. package/vanilla/UiRadioGroup.d.ts +1 -1
  197. package/vanilla/UiRadioGroup.js +1 -1
  198. package/vanilla/UiReel.d.ts +1 -1
  199. package/vanilla/UiReel.js +1 -1
  200. package/vanilla/UiScrollArea.d.ts +1 -1
  201. package/vanilla/UiScrollArea.js +1 -1
  202. package/vanilla/UiSearchResultRow.d.ts +1 -1
  203. package/vanilla/UiSearchResultRow.js +1 -1
  204. package/vanilla/UiSearchShell.d.ts +1 -1
  205. package/vanilla/UiSearchShell.js +1 -1
  206. package/vanilla/UiSection.d.ts +1 -1
  207. package/vanilla/UiSection.js +1 -1
  208. package/vanilla/UiSelect.d.ts +1 -1
  209. package/vanilla/UiSelect.js +1 -1
  210. package/vanilla/UiSeparator.d.ts +1 -1
  211. package/vanilla/UiSeparator.js +1 -1
  212. package/vanilla/UiSidebar.d.ts +1 -1
  213. package/vanilla/UiSidebar.js +1 -1
  214. package/vanilla/UiSpinner.d.ts +1 -1
  215. package/vanilla/UiSpinner.js +1 -1
  216. package/vanilla/UiStack.d.ts +1 -1
  217. package/vanilla/UiStack.js +1 -1
  218. package/vanilla/UiStatusMessage.d.ts +1 -1
  219. package/vanilla/UiStatusMessage.js +1 -1
  220. package/vanilla/UiSwitch.d.ts +1 -1
  221. package/vanilla/UiSwitch.js +1 -1
  222. package/vanilla/UiSwitcher.d.ts +1 -1
  223. package/vanilla/UiSwitcher.js +1 -1
  224. package/vanilla/UiTable.d.ts +1 -1
  225. package/vanilla/UiTable.js +1 -1
  226. package/vanilla/UiTabs.d.ts +1 -1
  227. package/vanilla/UiTabs.js +1 -1
  228. package/vanilla/UiText.d.ts +1 -1
  229. package/vanilla/UiText.js +1 -1
  230. package/vanilla/UiTextarea.d.ts +1 -1
  231. package/vanilla/UiTextarea.js +1 -1
  232. package/vanilla/UiToast.d.ts +1 -1
  233. package/vanilla/UiToast.js +1 -1
  234. package/vanilla/UiToastRegion.d.ts +1 -1
  235. package/vanilla/UiToastRegion.js +1 -1
  236. package/vanilla/UiTooltip.d.ts +1 -1
  237. package/vanilla/UiTooltip.js +1 -1
  238. package/vanilla/UiTopBar.d.ts +1 -1
  239. package/vanilla/UiTopBar.js +1 -1
  240. package/vanilla/UiTree.d.ts +1 -1
  241. package/vanilla/UiTree.js +1 -1
  242. package/vanilla/UiTreeItem.d.ts +1 -1
  243. package/vanilla/UiTreeItem.js +7 -19
  244. package/vanilla/index.js +2 -0
  245. package/vue/UiActionBar.vue +46 -78
  246. package/vue/UiAffordanceScope.vue +27 -66
  247. package/vue/UiAvatar.d.ts +10 -7
  248. package/vue/UiAvatar.vue +100 -218
  249. package/vue/UiAvatarGroup.d.ts +10 -7
  250. package/vue/UiAvatarGroup.vue +78 -160
  251. package/vue/UiBadge.d.ts +1 -1
  252. package/vue/UiBadge.vue +483 -520
  253. package/vue/UiBreadcrumbItem.vue +52 -123
  254. package/vue/UiBreadcrumbs.vue +27 -70
  255. package/vue/UiButton.d.ts +2 -2
  256. package/vue/UiButton.vue +420 -471
  257. package/vue/UiCallout.vue +131 -175
  258. package/vue/UiCard.d.ts +1 -1
  259. package/vue/UiCard.vue +112 -151
  260. package/vue/UiCheckbox.d.ts +13 -10
  261. package/vue/UiCheckbox.vue +160 -221
  262. package/vue/UiCluster.d.ts +1 -1
  263. package/vue/UiCluster.vue +84 -128
  264. package/vue/UiCombobox.d.ts +71 -68
  265. package/vue/UiCombobox.vue +417 -743
  266. package/vue/UiContainer.vue +43 -87
  267. package/vue/UiContextMenu.d.ts +6 -6
  268. package/vue/UiContextMenu.vue +78 -117
  269. package/vue/UiCover.vue +29 -69
  270. package/vue/UiDescriptionItem.vue +39 -82
  271. package/vue/UiDescriptionList.vue +64 -107
  272. package/vue/UiDialog.d.ts +22 -19
  273. package/vue/UiDialog.vue +193 -246
  274. package/vue/UiDisclosure.d.ts +22 -19
  275. package/vue/UiDisclosure.vue +192 -283
  276. package/vue/UiEditable.d.ts +5 -5
  277. package/vue/UiEditable.vue +124 -207
  278. package/vue/UiEditorBlockActions.d.ts +33 -0
  279. package/vue/UiEditorBlockActions.js +2 -0
  280. package/vue/UiEditorBlockActions.vue +125 -0
  281. package/vue/UiEditorImageToolbar.d.ts +2 -2
  282. package/vue/UiEditorImageToolbar.vue +45 -256
  283. package/vue/UiEditorInsertTableGrid.d.ts +2 -2
  284. package/vue/UiEditorInsertTableGrid.vue +98 -266
  285. package/vue/UiEditorLinkCard.d.ts +58 -0
  286. package/vue/UiEditorLinkCard.js +2 -0
  287. package/vue/UiEditorLinkCard.vue +319 -0
  288. package/vue/UiEditorMentionMenu.d.ts +15 -12
  289. package/vue/UiEditorMentionMenu.vue +150 -239
  290. package/vue/UiEditorMentionMenuItem.vue +66 -110
  291. package/vue/UiEditorSlashMenu.d.ts +16 -13
  292. package/vue/UiEditorSlashMenu.vue +172 -253
  293. package/vue/UiEditorSlashMenuGroup.vue +25 -69
  294. package/vue/UiEditorSlashMenuItem.vue +67 -115
  295. package/vue/UiEditorSurface.vue +19 -63
  296. package/vue/UiEditorTableContextMenu.vue +135 -269
  297. package/vue/UiEditorTableOverlay.d.ts +2 -2
  298. package/vue/UiEditorTableOverlay.vue +310 -479
  299. package/vue/UiEditorTableToolbar.d.ts +2 -2
  300. package/vue/UiEditorTableToolbar.vue +182 -357
  301. package/vue/UiEditorToolbar.vue +143 -183
  302. package/vue/UiFloatingActionButton.vue +70 -114
  303. package/vue/UiFormField.d.ts +1 -1
  304. package/vue/UiFormField.vue +76 -117
  305. package/vue/UiGrid.d.ts +1 -1
  306. package/vue/UiGrid.vue +65 -103
  307. package/vue/UiIcon.vue +32 -106
  308. package/vue/UiIconButton.d.ts +2 -2
  309. package/vue/UiIconButton.vue +359 -411
  310. package/vue/UiImage.vue +145 -180
  311. package/vue/UiInput.vue +158 -190
  312. package/vue/UiInputGroup.vue +199 -239
  313. package/vue/UiList.vue +67 -109
  314. package/vue/UiListItem.vue +154 -201
  315. package/vue/UiListbox.d.ts +10 -7
  316. package/vue/UiListbox.vue +86 -260
  317. package/vue/UiMenu.d.ts +11 -11
  318. package/vue/UiMenu.vue +118 -152
  319. package/vue/UiMenuGroup.vue +21 -67
  320. package/vue/UiMenuItem.d.ts +19 -16
  321. package/vue/UiMenuItem.vue +169 -262
  322. package/vue/UiMeter.d.ts +4 -4
  323. package/vue/UiMeter.vue +166 -680
  324. package/vue/UiNavItem.vue +140 -213
  325. package/vue/UiPageHeader.vue +81 -127
  326. package/vue/UiPopover.d.ts +7 -7
  327. package/vue/UiPopover.vue +90 -129
  328. package/vue/UiRadio.d.ts +12 -9
  329. package/vue/UiRadio.vue +91 -149
  330. package/vue/UiRadioGroup.d.ts +2 -2
  331. package/vue/UiRadioGroup.vue +47 -85
  332. package/vue/UiReel.vue +89 -130
  333. package/vue/UiScrollArea.d.ts +1 -1
  334. package/vue/UiScrollArea.vue +78 -119
  335. package/vue/UiSearchResultRow.vue +96 -149
  336. package/vue/UiSearchShell.d.ts +2 -2
  337. package/vue/UiSearchShell.vue +159 -196
  338. package/vue/UiSection.vue +105 -149
  339. package/vue/UiSelect.d.ts +1 -1
  340. package/vue/UiSelect.vue +114 -146
  341. package/vue/UiSeparator.vue +42 -85
  342. package/vue/UiSidebar.d.ts +10 -7
  343. package/vue/UiSidebar.vue +193 -260
  344. package/vue/UiSpinner.vue +54 -130
  345. package/vue/UiStack.vue +66 -107
  346. package/vue/UiStatusMessage.d.ts +1 -1
  347. package/vue/UiStatusMessage.vue +61 -135
  348. package/vue/UiSwitch.d.ts +12 -9
  349. package/vue/UiSwitch.vue +136 -194
  350. package/vue/UiSwitcher.vue +69 -107
  351. package/vue/UiTable.vue +121 -156
  352. package/vue/UiTabs.d.ts +1 -1
  353. package/vue/UiTabs.vue +139 -267
  354. package/vue/UiText.d.ts +4 -4
  355. package/vue/UiText.vue +145 -184
  356. package/vue/UiTextarea.d.ts +2 -2
  357. package/vue/UiTextarea.vue +162 -194
  358. package/vue/UiToast.vue +70 -118
  359. package/vue/UiToastRegion.vue +157 -276
  360. package/vue/UiTooltip.d.ts +21 -18
  361. package/vue/UiTooltip.vue +174 -234
  362. package/vue/UiTopBar.vue +48 -76
  363. package/vue/UiTree.vue +46 -79
  364. package/vue/UiTreeItem.d.ts +18 -15
  365. package/vue/UiTreeItem.vue +526 -668
  366. package/vue/chunks/UiActionBar.js +5 -17
  367. package/vue/chunks/UiAffordanceScope.js +7 -26
  368. package/vue/chunks/UiAvatar.js +20 -74
  369. package/vue/chunks/UiAvatarGroup.js +14 -56
  370. package/vue/chunks/UiBadge.js +10 -28
  371. package/vue/chunks/UiBreadcrumbItem.js +11 -41
  372. package/vue/chunks/UiBreadcrumbs.js +7 -25
  373. package/vue/chunks/UiButton.js +80 -103
  374. package/vue/chunks/UiCallout.js +9 -27
  375. package/vue/chunks/UiCard.js +33 -53
  376. package/vue/chunks/UiCheckbox.js +14 -46
  377. package/vue/chunks/UiCluster.js +13 -31
  378. package/vue/chunks/UiCombobox.js +99 -237
  379. package/vue/chunks/UiContainer.js +9 -27
  380. package/vue/chunks/UiContextMenu.js +7 -26
  381. package/vue/chunks/UiCover.js +7 -25
  382. package/vue/chunks/UiDescriptionItem.js +6 -24
  383. package/vue/chunks/UiDescriptionList.js +9 -27
  384. package/vue/chunks/UiDialog.js +18 -47
  385. package/vue/chunks/UiDisclosure.js +19 -66
  386. package/vue/chunks/UiEditable.js +18 -60
  387. package/vue/chunks/UiEditorBlockActions.js +127 -0
  388. package/vue/chunks/UiEditorImageToolbar.js +40 -127
  389. package/vue/chunks/UiEditorInsertTableGrid.js +14 -112
  390. package/vue/chunks/UiEditorLinkCard.js +356 -0
  391. package/vue/chunks/UiEditorMentionMenu.js +16 -54
  392. package/vue/chunks/UiEditorMentionMenuItem.js +10 -28
  393. package/vue/chunks/UiEditorSlashMenu.js +17 -46
  394. package/vue/chunks/UiEditorSlashMenuGroup.js +7 -25
  395. package/vue/chunks/UiEditorSlashMenuItem.js +16 -31
  396. package/vue/chunks/UiEditorSurface.js +7 -25
  397. package/vue/chunks/UiEditorTableContextMenu.js +25 -102
  398. package/vue/chunks/UiEditorTableOverlay.js +41 -104
  399. package/vue/chunks/UiEditorTableToolbar.js +44 -122
  400. package/vue/chunks/UiEditorToolbar.js +7 -26
  401. package/vue/chunks/UiFloatingActionButton.js +10 -28
  402. package/vue/chunks/UiFormField.js +8 -27
  403. package/vue/chunks/UiGrid.js +10 -28
  404. package/vue/chunks/UiIcon.js +21 -74
  405. package/vue/chunks/UiIconButton.js +18 -50
  406. package/vue/chunks/UiImage.js +14 -33
  407. package/vue/chunks/UiInput.js +12 -31
  408. package/vue/chunks/UiInputGroup.js +10 -29
  409. package/vue/chunks/UiList.js +17 -37
  410. package/vue/chunks/UiListItem.js +12 -30
  411. package/vue/chunks/UiListbox.js +22 -124
  412. package/vue/chunks/UiMenu.js +13 -32
  413. package/vue/chunks/UiMenuGroup.js +8 -26
  414. package/vue/chunks/UiMenuItem.js +35 -80
  415. package/vue/chunks/UiMeter.js +17 -351
  416. package/vue/chunks/UiNavItem.js +23 -57
  417. package/vue/chunks/UiPageHeader.js +7 -25
  418. package/vue/chunks/UiPopover.js +9 -28
  419. package/vue/chunks/UiRadio.js +11 -43
  420. package/vue/chunks/UiRadioGroup.js +13 -32
  421. package/vue/chunks/UiReel.js +10 -28
  422. package/vue/chunks/UiScrollArea.js +10 -29
  423. package/vue/chunks/UiSearchResultRow.js +10 -28
  424. package/vue/chunks/UiSearchShell.js +9 -28
  425. package/vue/chunks/UiSection.js +9 -27
  426. package/vue/chunks/UiSelect.js +10 -29
  427. package/vue/chunks/UiSeparator.js +10 -28
  428. package/vue/chunks/UiSidebar.js +15 -47
  429. package/vue/chunks/UiSpinner.js +8 -44
  430. package/vue/chunks/UiStack.js +12 -30
  431. package/vue/chunks/UiStatusMessage.js +10 -42
  432. package/vue/chunks/UiSwitch.js +11 -43
  433. package/vue/chunks/UiSwitcher.js +9 -28
  434. package/vue/chunks/UiTable.js +7 -26
  435. package/vue/chunks/UiTabs.js +15 -91
  436. package/vue/chunks/UiText.js +148 -168
  437. package/vue/chunks/UiTextarea.js +16 -35
  438. package/vue/chunks/UiToast.js +13 -37
  439. package/vue/chunks/UiToastRegion.js +16 -88
  440. package/vue/chunks/UiTooltip.js +14 -46
  441. package/vue/chunks/UiTopBar.js +5 -17
  442. package/vue/chunks/UiTree.js +13 -32
  443. package/vue/chunks/UiTreeItem.js +34 -90
  444. package/vue/chunks/_plugin-vue_export-helper.js +904 -1
  445. package/vue/chunks/control.js +3 -0
  446. package/vue/chunks/props.js +1 -1
  447. package/vue/components.css +7689 -7617
  448. package/vue/editor/index.js +30 -95
  449. package/vue/editor/primitives.d.ts +8 -2
  450. package/vue/host.ts +999 -14
  451. package/vue/index.d.ts +2 -0
  452. package/vue/index.js +5 -3
  453. package/vue/chunks/host.js +0 -443
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>