@livestorm/ui-vue 2.0.5 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (302) hide show
  1. package/README.md +9 -6
  2. package/components-vite.js +2 -2
  3. package/dist/UiButton-uyW8EHRJ.mjs +602 -0
  4. package/dist/UiTimelineItem-EiOEi1yF.mjs +7293 -0
  5. package/dist/UiTooltip-DZcPD6_N.mjs +158 -0
  6. package/dist/a11y-CaZxRWzo.mjs +6 -0
  7. package/dist/breakpoints.mjs +4 -9
  8. package/dist/bus.mjs +5 -5
  9. package/dist/components.mjs +236 -222
  10. package/dist/i18n-B8QOMuFD.mjs +46 -0
  11. package/dist/index.mjs +4 -87
  12. package/dist/integrations.mjs +3 -14
  13. package/dist/layouts.mjs +228 -236
  14. package/dist/responsive.mjs +31 -36
  15. package/dist/slot.mjs +11 -17
  16. package/dist/toastDSV2-D3xDZPe5.mjs +105 -0
  17. package/dist/types/index.d.ts +23 -1
  18. package/dist/types/src/components/Toast/ToastMessage.vue.d.ts +17 -7
  19. package/dist/types/src/components/Toast/toastDSV2.d.ts +89 -64
  20. package/dist/types/src/components/UiActionBar/UiActionBar.vue.d.ts +3 -1
  21. package/dist/types/src/components/UiActionBar/UiActionBarItem.vue.d.ts +18 -3
  22. package/dist/types/src/components/UiActionBar/types.d.ts +5 -1
  23. package/dist/types/src/components/UiAvatar/UiAvatar.vue.d.ts +4 -2
  24. package/dist/types/src/components/UiAvatarList/UiAvatarList.vue.d.ts +3 -2
  25. package/dist/types/src/components/UiBanner/UiBanner.vue.d.ts +13 -1
  26. package/dist/types/src/components/UiButton/UiButton.vue.d.ts +102 -38
  27. package/dist/types/src/components/UiButtonGroup/UiButtonGroup.vue.d.ts +8 -2
  28. package/dist/types/src/components/UiButtonGroup/UiButtonGroupItem.vue.d.ts +3 -0
  29. package/dist/types/src/components/UiButtonGroup/types.d.ts +5 -1
  30. package/dist/types/src/components/UiChoice/UiChoice.vue.d.ts +71 -0
  31. package/dist/types/src/components/UiChoice/index.d.ts +2 -0
  32. package/dist/types/src/components/UiChoice/types.d.ts +7 -0
  33. package/dist/types/src/components/UiColorField/UiColorField.vue.d.ts +1 -1
  34. package/dist/types/src/components/UiColorPicker/UiColorPicker.vue.d.ts +2 -2
  35. package/dist/types/src/components/UiCombobox/UiCombobox.types.d.ts +47 -0
  36. package/dist/types/src/components/UiCombobox/UiCombobox.vue.d.ts +40 -0
  37. package/dist/types/src/components/UiCombobox/index.d.ts +2 -0
  38. package/dist/types/src/components/UiDataTable/UiDataTable.types.d.ts +46 -0
  39. package/dist/types/src/components/UiDataTable/UiDataTable.vue.d.ts +136 -0
  40. package/dist/types/src/components/UiDataTable/index.d.ts +5 -0
  41. package/dist/types/src/components/UiDrawer/UiDrawer.vue.d.ts +28 -0
  42. package/dist/types/src/components/UiDrawer/UiDrawerContent.vue.d.ts +18 -0
  43. package/dist/types/src/components/UiDrawer/UiDrawerTrigger.vue.d.ts +14 -0
  44. package/dist/types/src/components/UiDropdown/DropdownItemCheckbox.vue.d.ts +3 -0
  45. package/dist/types/src/components/UiDropdown/UiDropdownContent.vue.d.ts +10 -0
  46. package/dist/types/src/components/UiDropdown/UiDropdownGroup.vue.d.ts +17 -0
  47. package/dist/types/src/components/UiDropdown/UiDropdownItem.vue.d.ts +9 -4
  48. package/dist/types/src/components/UiDropdown/UiDropdownTrigger.vue.d.ts +21 -5
  49. package/dist/types/src/components/UiDropdown/index.d.ts +1 -0
  50. package/dist/types/src/components/UiEmojiPickerList/UiEmojiPickerList.vue.d.ts +22 -0
  51. package/dist/types/src/components/UiEmptyState/UiEmptyState.vue.d.ts +8 -3
  52. package/dist/types/src/components/UiFieldWrapper/UiFieldWrapper.vue.d.ts +2 -2
  53. package/dist/types/src/components/UiInputCheckbox/CheckboxGlyph.vue.d.ts +17 -0
  54. package/dist/types/src/components/UiInputCheckbox/UiInputCheckbox.vue.d.ts +35 -4
  55. package/dist/types/src/components/UiInputEmoji/UiInputEmoji.vue.d.ts +45 -0
  56. package/dist/types/src/components/UiInputRadio/RadioGlyph.vue.d.ts +19 -0
  57. package/dist/types/src/components/UiInputRadio/UiInputRadio.vue.d.ts +80 -0
  58. package/dist/types/src/components/UiInputRadio/UiInputRadioGroup.vue.d.ts +86 -0
  59. package/dist/types/src/components/UiInputRadio/types.d.ts +19 -0
  60. package/dist/types/src/components/UiInputSelect/UiInputSelect.vue.d.ts +5 -5
  61. package/dist/types/src/components/UiInputTextarea/UiInputTextarea.vue.d.ts +5 -5
  62. package/dist/types/src/components/UiListItem/UiListItem.vue.d.ts +18 -4
  63. package/dist/types/src/components/UiLoader/UiLoader.vue.d.ts +6 -5
  64. package/dist/types/src/components/UiLoader/UiSpinnerIcon.vue.d.ts +3 -0
  65. package/dist/types/src/components/UiLogo/UiLogo.vue.d.ts +9 -3
  66. package/dist/types/src/components/UiMenu/UiMenuContent.vue.d.ts +15 -2
  67. package/dist/types/src/components/UiMenu/UiMenuItem.vue.d.ts +9 -3
  68. package/dist/types/src/components/UiNestedOptions/UiNestedOptions.vue.d.ts +13 -0
  69. package/dist/types/src/components/UiPage/UiPage.vue.d.ts +106 -8
  70. package/dist/types/src/components/UiPagination/UiPagination.vue.d.ts +36 -0
  71. package/dist/types/src/components/UiPagination/index.d.ts +2 -0
  72. package/dist/types/src/components/UiPagination/types.d.ts +4 -0
  73. package/dist/types/src/components/UiPane/UiPane.vue.d.ts +22 -0
  74. package/dist/types/src/components/UiPane/UiPaneContent.vue.d.ts +75 -0
  75. package/dist/types/src/components/UiPane/UiPaneTrigger.vue.d.ts +14 -0
  76. package/dist/types/src/components/UiPane/index.d.ts +5 -0
  77. package/dist/types/src/components/UiProgress/UiProgress.vue.d.ts +1 -1
  78. package/dist/types/src/components/UiRating/UiRating.vue.d.ts +62 -0
  79. package/dist/types/src/components/UiRating/types.d.ts +1 -0
  80. package/dist/types/src/components/UiRoomButton/UiRoomButton.vue.d.ts +5 -3
  81. package/dist/types/src/components/UiRoomCountdown/UiRoomCountdown.vue.d.ts +32 -0
  82. package/dist/types/src/components/UiShell/UiShell.vue.d.ts +3 -0
  83. package/dist/types/src/components/UiSideMenu/UiSideMenu.vue.d.ts +22 -1
  84. package/dist/types/src/components/UiSideMenu/UiSideMenuItemContent.vue.d.ts +2 -2
  85. package/dist/types/src/components/UiSwitch/UiSwitch.vue.d.ts +114 -0
  86. package/dist/types/src/components/UiSwitch/types.d.ts +3 -0
  87. package/dist/types/src/components/UiTable/UiTable.vue.d.ts +13 -4
  88. package/dist/types/src/components/UiTable/UiTableActionsCell.vue.d.ts +49 -0
  89. package/dist/types/src/components/UiTable/UiTableActionsHeaderCell.vue.d.ts +3 -0
  90. package/dist/types/src/components/UiTable/UiTableBody.vue.d.ts +11 -1
  91. package/dist/types/src/components/UiTable/UiTableCell.vue.d.ts +16 -1
  92. package/dist/types/src/components/UiTable/UiTableHeaderCell.vue.d.ts +31 -2
  93. package/dist/types/src/components/UiTable/UiTableRow.vue.d.ts +32 -2
  94. package/dist/types/src/components/UiTable/context.d.ts +3 -0
  95. package/dist/types/src/components/UiTable/index.d.ts +4 -0
  96. package/dist/types/src/components/UiTabs/UiTabs.vue.d.ts +8 -2
  97. package/dist/types/src/components/UiTag/UiTag.types.d.ts +25 -0
  98. package/dist/types/src/components/UiTag/UiTag.vue.d.ts +5 -26
  99. package/dist/types/src/components/UiTag/index.d.ts +2 -1
  100. package/dist/types/src/components/UiTextField/UiTextField.vue.d.ts +10 -5
  101. package/dist/types/src/components/UiTooltip/UiTooltipProvider.vue.d.ts +1 -0
  102. package/dist/types/src/components/UiTooltip/UiTooltipTrigger.vue.d.ts +2 -2
  103. package/dist/types/src/composables/storedThemingApplies.d.ts +17 -0
  104. package/dist/types/src/composables/useButtonStyles.d.ts +1 -0
  105. package/dist/types/src/composables/useChoiceboxSurface.d.ts +11 -0
  106. package/dist/types/src/composables/useContentMode.d.ts +23 -0
  107. package/dist/types/src/composables/useControlModes.d.ts +7 -0
  108. package/dist/types/src/composables/useControlShape.d.ts +24 -0
  109. package/dist/types/src/composables/useFieldFocusEvents.d.ts +12 -0
  110. package/dist/types/src/composables/useIconSize.d.ts +13 -0
  111. package/dist/types/src/composables/usePullGesture.d.ts +42 -0
  112. package/dist/types/src/composables/useThemeAndModes.d.ts +4 -0
  113. package/dist/types/src/constants/sizes.d.ts +1 -1
  114. package/dist/types/src/theming/colorScale.d.ts +165 -0
  115. package/dist/types/src/theming/legacyColorScale.d.ts +27 -0
  116. package/dist/types/src/theming/presetColors.d.ts +11 -0
  117. package/dist/types/src/theming/primitiveTokens.d.ts +2 -0
  118. package/dist/types/src/utils/effectiveOpacity.d.ts +2 -0
  119. package/dist/types/src/utils/numbers.d.ts +1 -2
  120. package/dist/types/src/utils/tokenColor.d.ts +2 -0
  121. package/dist/ui-vue.css +2 -1
  122. package/dist/utils.mjs +165 -194
  123. package/index.d.ts +22 -0
  124. package/index.js +44 -0
  125. package/package.json +28 -20
  126. package/src/components/Toast/LayoutToasts.vue +19 -11
  127. package/src/components/Toast/ToastMessage.vue +130 -73
  128. package/src/components/Toast/toastDSV2.ts +238 -67
  129. package/src/components/UiActionBar/UiActionBar.vue +15 -5
  130. package/src/components/UiActionBar/UiActionBarItem.vue +65 -38
  131. package/src/components/UiActionBar/types.ts +16 -1
  132. package/src/components/UiAvatar/UiAvatar.vue +9 -3
  133. package/src/components/UiAvatarList/UiAvatarList.vue +51 -20
  134. package/src/components/UiBadge/UiBadge.vue +1 -1
  135. package/src/components/UiBanner/UiBanner.vue +77 -27
  136. package/src/components/UiBreadcrumb/UiBreadcrumb.vue +1 -1
  137. package/src/components/UiButton/UiButton.vue +96 -29
  138. package/src/components/UiButtonGroup/UiButtonGroup.vue +22 -16
  139. package/src/components/UiButtonGroup/UiButtonGroupItem.vue +44 -14
  140. package/src/components/UiButtonGroup/types.ts +20 -1
  141. package/src/components/UiCard/UiCard.vue +20 -23
  142. package/src/components/UiCarousel/UiCarousel.vue +2 -2
  143. package/src/components/UiChoice/UiChoice.vue +187 -0
  144. package/src/components/UiChoice/index.ts +2 -0
  145. package/src/components/UiChoice/types.ts +11 -0
  146. package/src/components/UiColorField/UiColorField.vue +2 -2
  147. package/src/components/UiColorPicker/UiColorPicker.vue +16 -13
  148. package/src/components/UiCombobox/UiCombobox.types.ts +52 -0
  149. package/src/components/UiCombobox/UiCombobox.vue +296 -0
  150. package/src/components/UiCombobox/index.ts +2 -0
  151. package/src/components/UiDataTable/UiDataTable.types.ts +47 -0
  152. package/src/components/UiDataTable/UiDataTable.vue +422 -0
  153. package/src/components/UiDataTable/index.ts +12 -0
  154. package/src/components/UiDialog/UiDialogClose.vue +1 -1
  155. package/src/components/UiDialog/UiDialogContent.vue +22 -7
  156. package/src/components/UiDrawer/UiDrawer.vue +16 -0
  157. package/src/components/UiDrawer/UiDrawerContent.vue +42 -0
  158. package/src/components/UiDrawer/UiDrawerTrigger.vue +17 -0
  159. package/src/components/UiDropdown/DropdownItemCheckbox.vue +10 -0
  160. package/src/components/UiDropdown/UiDropdownContent.vue +32 -21
  161. package/src/components/UiDropdown/UiDropdownGroup.vue +23 -0
  162. package/src/components/UiDropdown/UiDropdownItem.vue +45 -18
  163. package/src/components/UiDropdown/UiDropdownSeparator.vue +1 -1
  164. package/src/components/UiDropdown/UiDropdownTrigger.vue +139 -45
  165. package/src/components/UiDropdown/index.ts +1 -0
  166. package/src/components/UiEmojiPickerList/UiEmojiPickerList.vue +122 -0
  167. package/src/components/UiEmptyState/UiEmptyState.vue +16 -4
  168. package/src/components/UiFieldWrapper/UiFieldWrapper.vue +10 -4
  169. package/src/components/UiHorizontalSeparator/UiHorizontalSeparator.vue +2 -2
  170. package/src/components/UiInputCheckbox/CheckboxGlyph.vue +78 -0
  171. package/src/components/UiInputCheckbox/UiInputCheckbox.vue +213 -177
  172. package/src/components/UiInputEmoji/UiInputEmoji.vue +96 -0
  173. package/src/components/UiInputRadio/RadioGlyph.vue +45 -0
  174. package/src/components/UiInputRadio/UiInputRadio.vue +382 -0
  175. package/src/components/UiInputRadio/UiInputRadioGroup.vue +166 -0
  176. package/src/components/UiInputRadio/types.ts +24 -0
  177. package/src/components/UiInputSelect/UiInputSelect.vue +9 -7
  178. package/src/components/UiInputTextarea/UiInputTextarea.vue +20 -35
  179. package/src/components/UiLabel/UiLabel.vue +1 -1
  180. package/src/components/UiListItem/UiListItem.vue +55 -9
  181. package/src/components/UiLoader/UiLoader.vue +11 -29
  182. package/src/components/UiLoader/UiSpinnerIcon.vue +21 -0
  183. package/src/components/UiLogo/UiLogo.vue +41 -7
  184. package/src/components/UiMenu/UiMenuContent.vue +24 -3
  185. package/src/components/UiMenu/UiMenuGroup.vue +1 -1
  186. package/src/components/UiMenu/UiMenuItem.vue +14 -3
  187. package/src/components/UiMenu/UiMenuSubContent.vue +1 -1
  188. package/src/components/UiMenu/UiMenuSubTrigger.vue +2 -2
  189. package/src/components/UiNestedOptions/UiNestedOptions.vue +6 -0
  190. package/src/components/UiPage/UiPage.vue +273 -47
  191. package/src/components/UiPageHeader/UiPageHeader.vue +29 -9
  192. package/src/components/UiPagination/UiPagination.vue +99 -0
  193. package/src/components/UiPagination/index.ts +2 -0
  194. package/src/components/UiPagination/types.ts +28 -0
  195. package/src/components/UiPane/UiPane.vue +20 -0
  196. package/src/components/UiPane/UiPaneContent.vue +232 -0
  197. package/src/components/UiPane/UiPaneTrigger.vue +14 -0
  198. package/src/components/UiPane/index.ts +12 -0
  199. package/src/components/UiPopover/UiPopoverContent.vue +21 -1
  200. package/src/components/UiProgress/UiProgress.vue +2 -2
  201. package/src/components/UiRating/UiRating.vue +258 -0
  202. package/src/components/UiRating/types.ts +1 -0
  203. package/src/components/UiRoomButton/UiRoomButton.vue +14 -45
  204. package/src/components/UiRoomCountdown/UiRoomCountdown.vue +376 -0
  205. package/src/components/UiShell/UiShell.vue +10 -4
  206. package/src/components/UiSideMenu/UiSideMenu.vue +158 -18
  207. package/src/components/UiSideMenu/UiSideMenuItemContent.vue +22 -18
  208. package/src/components/UiStepper/UiStepper.vue +3 -16
  209. package/src/components/UiStepper/UiStepperDescription.vue +1 -13
  210. package/src/components/UiStepper/UiStepperIndicator.vue +17 -57
  211. package/src/components/UiStepper/UiStepperItem.vue +1 -8
  212. package/src/components/UiStepper/UiStepperSeparator.vue +5 -16
  213. package/src/components/UiStepper/UiStepperTitle.vue +1 -10
  214. package/src/components/UiSwitch/UiSwitch.vue +375 -0
  215. package/src/components/UiSwitch/types.ts +5 -0
  216. package/src/components/UiTable/UiTable.vue +98 -8
  217. package/src/components/UiTable/UiTableActionsCell.vue +135 -0
  218. package/src/components/UiTable/UiTableActionsHeaderCell.vue +19 -0
  219. package/src/components/UiTable/UiTableBody.vue +16 -1
  220. package/src/components/UiTable/UiTableCell.vue +33 -16
  221. package/src/components/UiTable/UiTableHeader.vue +6 -5
  222. package/src/components/UiTable/UiTableHeaderCell.vue +61 -9
  223. package/src/components/UiTable/UiTableRow.vue +46 -10
  224. package/src/components/UiTable/context.ts +5 -0
  225. package/src/components/UiTable/index.ts +4 -0
  226. package/src/components/UiTabs/UiTabs.vue +61 -63
  227. package/src/components/UiTag/UiTag.types.ts +28 -0
  228. package/src/components/UiTag/UiTag.vue +24 -42
  229. package/src/components/UiTag/index.ts +2 -0
  230. package/src/components/UiTextField/UiTextField.vue +27 -47
  231. package/src/components/UiTimeline/README.md +6 -6
  232. package/src/components/UiTimeline/UiTimelineItem.vue +3 -3
  233. package/src/components/UiTooltip/UiTooltipContent.vue +1 -1
  234. package/src/components/UiTooltip/UiTooltipProvider.vue +3 -0
  235. package/src/components/UiTooltip/UiTooltipTrigger.vue +16 -1
  236. package/src/composables/storedThemingApplies.ts +19 -0
  237. package/src/composables/useButtonStyles.ts +9 -13
  238. package/src/composables/useChoiceboxSurface.ts +36 -0
  239. package/src/composables/useContentMode.ts +66 -0
  240. package/src/composables/useControlModes.ts +11 -0
  241. package/src/composables/useControlShape.ts +34 -0
  242. package/src/composables/useFieldFocusEvents.ts +30 -0
  243. package/src/composables/useIconSize.ts +43 -0
  244. package/src/composables/usePullGesture.ts +142 -0
  245. package/src/composables/useThemeAndModes.ts +28 -1
  246. package/src/constants/sizes.ts +1 -1
  247. package/src/css/body.css +16 -1
  248. package/src/css/fonts.css +39 -5
  249. package/src/global.d.ts +44 -0
  250. package/src/theming/colorScale.ts +173 -0
  251. package/src/theming/legacyColorScale.ts +58 -0
  252. package/src/theming/presetColors.ts +33 -0
  253. package/src/theming/primitiveTokens.ts +71 -0
  254. package/src/utils/effectiveOpacity.ts +8 -0
  255. package/src/utils/i18n.ts +6 -0
  256. package/src/utils/numbers.ts +1 -1
  257. package/src/utils/responsive.d.ts +14 -0
  258. package/src/utils/tokenColor.ts +9 -0
  259. package/dist/UiTimelineItem.vue_vue_type_style_index_0_lang-DJFdCn2R.mjs +0 -5456
  260. package/dist/a11y-BhF_nl7L.mjs +0 -159
  261. package/dist/i18n-Cktw9hIu.mjs +0 -49
  262. package/dist/toastDSV2-wMh-UMzW.mjs +0 -74
  263. package/dist/types/src/components/UiAvatar/index.d.ts +0 -1
  264. package/dist/types/src/components/UiAvatarList/index.d.ts +0 -1
  265. package/dist/types/src/components/UiBadge/index.d.ts +0 -1
  266. package/dist/types/src/components/UiBanner/index.d.ts +0 -2
  267. package/dist/types/src/components/UiButtonGroup/index.d.ts +0 -3
  268. package/dist/types/src/components/UiCarousel/index.d.ts +0 -2
  269. package/dist/types/src/components/UiColorField/index.d.ts +0 -2
  270. package/dist/types/src/components/UiDialog/MarketplaceHeaderExample.vue.d.ts +0 -28
  271. package/dist/types/src/components/UiDialog/index.d.ts +0 -7
  272. package/dist/types/src/components/UiFieldWrapper/index.d.ts +0 -1
  273. package/dist/types/src/components/UiInputCheckbox/index.d.ts +0 -2
  274. package/dist/types/src/components/UiInputSelect/index.d.ts +0 -2
  275. package/dist/types/src/components/UiInputTextarea/index.d.ts +0 -2
  276. package/dist/types/src/components/UiMenu/index.d.ts +0 -10
  277. package/dist/types/src/components/UiProgress/index.d.ts +0 -2
  278. package/dist/types/src/components/UiTabs/index.d.ts +0 -2
  279. package/dist/types/src/components/UiTimeline/index.d.ts +0 -2
  280. package/dist/types/src/components/UiTooltip/index.d.ts +0 -4
  281. package/dist/types/src/mixins/DynamicAction.d.ts +0 -30
  282. package/dist/useThemeAndModes-BzYwSOEv.mjs +0 -108
  283. package/src/components/UiAvatar/index.js +0 -1
  284. package/src/components/UiAvatarList/index.js +0 -1
  285. package/src/components/UiBadge/index.ts +0 -2
  286. package/src/components/UiBanner/index.ts +0 -2
  287. package/src/components/UiButtonGroup/index.ts +0 -3
  288. package/src/components/UiCarousel/index.ts +0 -2
  289. package/src/components/UiColorField/index.ts +0 -2
  290. package/src/components/UiDialog/MarketplaceHeaderExample.vue +0 -217
  291. package/src/components/UiDialog/index.ts +0 -18
  292. package/src/components/UiFieldWrapper/index.ts +0 -1
  293. package/src/components/UiInputCheckbox/index.ts +0 -2
  294. package/src/components/UiInputSelect/index.ts +0 -2
  295. package/src/components/UiInputTextarea/index.ts +0 -2
  296. package/src/components/UiMenu/index.ts +0 -10
  297. package/src/components/UiProgress/index.ts +0 -2
  298. package/src/components/UiTabs/index.ts +0 -5
  299. package/src/components/UiTag/index.js +0 -1
  300. package/src/components/UiTimeline/index.ts +0 -2
  301. package/src/components/UiTooltip/index.js +0 -4
  302. package/src/mixins/DynamicAction.js +0 -61
@@ -0,0 +1,232 @@
1
+ <script setup lang="ts">
2
+ import { reactiveOmit, useMutationObserver, useScroll } from '@vueuse/core'
3
+ import type { DialogContentEmits, DialogContentProps } from 'reka-ui'
4
+ import {
5
+ DialogClose,
6
+ DialogContent,
7
+ DialogPortal,
8
+ DialogTitle,
9
+ useForwardPropsEmits,
10
+ VisuallyHidden,
11
+ } from 'reka-ui'
12
+ import { computed, onMounted, ref, useAttrs, useSlots } from 'vue'
13
+ import { useTranslate } from '../../utils/i18n'
14
+ import UiButton from '../UiButton/UiButton.vue'
15
+
16
+ export type UiPaneSize = 'sm' | 'lg'
17
+ export type UiPaneOrientation = 'horizontal' | 'vertical'
18
+
19
+ export interface UiPaneContentProps extends DialogContentProps {
20
+ /**
21
+ * Header title, also used as the pane's accessible name
22
+ */
23
+ title?: string
24
+ /**
25
+ * Density of the header, padding and title
26
+ * @values sm, lg
27
+ */
28
+ size?: UiPaneSize
29
+ /**
30
+ * Layout of the footer actions: in a row, or stacked full width
31
+ * @values horizontal, vertical
32
+ */
33
+ orientation?: UiPaneOrientation
34
+ hideClose?: boolean
35
+ closeButtonAriaLabel?: string
36
+ /**
37
+ * Removes the body padding, for full-bleed content
38
+ */
39
+ noPadding?: boolean
40
+ /**
41
+ * When false, a click outside or Escape no longer closes the pane:
42
+ * only the close button or the consumer's own actions do
43
+ */
44
+ dismissible?: boolean
45
+ /**
46
+ * Any CSS width, for content with a fixed width of its own (an email's 600px column).
47
+ * Still capped to the viewport.
48
+ */
49
+ width?: string
50
+ }
51
+
52
+ // Attributes belong on the pane itself, not on the portal root.
53
+ defineOptions({ inheritAttrs: false })
54
+
55
+ const props = withDefaults(defineProps<UiPaneContentProps>(), {
56
+ title: undefined,
57
+ size: 'lg',
58
+ orientation: 'horizontal',
59
+ hideClose: false,
60
+ closeButtonAriaLabel: undefined,
61
+ noPadding: false,
62
+ dismissible: true,
63
+ width: undefined,
64
+ })
65
+
66
+ const emits = defineEmits<DialogContentEmits>()
67
+
68
+ // Our own props must not reach DialogContent, where `title` would become a native tooltip.
69
+ const contentProps = reactiveOmit(props, 'title', 'size', 'orientation', 'hideClose', 'closeButtonAriaLabel', 'noPadding', 'dismissible', 'width')
70
+ const forwarded = useForwardPropsEmits(contentProps, emits)
71
+
72
+ const slots = useSlots()
73
+ const attrs = useAttrs()
74
+ const translate = useTranslate()
75
+
76
+ const closeAriaLabel = computed(() => props.closeButtonAriaLabel ?? translate('general_close'))
77
+ const accessibleTitle = computed(() => (attrs['aria-label'] as string) || translate('general_dialog_title'))
78
+
79
+ // Non-modal, the page stays usable: only a click outside or Escape dismisses the pane.
80
+ // Focus leaving it (tabbing back to the page, a menu restoring focus to its trigger) must not.
81
+ function keepOpenOnFocusOutside (event: Event) {
82
+ event.preventDefault()
83
+ }
84
+
85
+ function preventUnlessDismissible (event: Event) {
86
+ if (!props.dismissible) event.preventDefault()
87
+ }
88
+
89
+ // Portaled to the body so no stacking context of the page can cover it, the pane takes the
90
+ // color mode of the place it is declared, as if it rendered there.
91
+ const anchor = ref<HTMLElement | null>(null)
92
+ const colorModeHost = ref<HTMLElement | null>(null)
93
+ const colorMode = ref<string>()
94
+
95
+ function syncColorMode () {
96
+ colorMode.value = colorModeHost.value?.getAttribute('data-colors-semantic') ?? undefined
97
+ }
98
+
99
+ onMounted(() => {
100
+ colorModeHost.value = anchor.value?.closest<HTMLElement>('[data-colors-semantic]') ?? null
101
+ syncColorMode()
102
+ })
103
+
104
+ useMutationObserver(colorModeHost, syncColorMode, { attributeFilter: ['data-colors-semantic'] })
105
+
106
+ const hasHeader = computed(() => !!props.title || !!slots.header || !props.hideClose)
107
+
108
+ const body = ref<HTMLElement | null>(null)
109
+ const { y: bodyScrollTop } = useScroll(body)
110
+
111
+ const isLarge = computed(() => props.size === 'lg')
112
+ const spacing = computed(() => isLarge.value ? 'p-6' : 'p-4')
113
+
114
+ const bodyClasses = computed(() => {
115
+ if (props.noPadding) return ''
116
+
117
+ return [
118
+ isLarge.value ? 'px-6 pb-6' : 'px-4 pb-4',
119
+ !hasHeader.value && (isLarge.value ? 'pt-6' : 'pt-4'),
120
+ ]
121
+ })
122
+
123
+ const footerClasses = computed(() => props.orientation === 'vertical'
124
+ ? 'flex flex-col gap-2 *:w-full'
125
+ : 'flex items-center justify-end gap-2')
126
+ </script>
127
+
128
+ <template>
129
+ <span
130
+ ref="anchor"
131
+ hidden
132
+ />
133
+ <DialogPortal>
134
+ <!-- The pane has no description slot; opt out of reka's one unless the consumer points to its own. -->
135
+ <DialogContent
136
+ data-testid="ui-pane-content"
137
+ v-bind="{ 'aria-describedby': undefined, ...forwarded, ...$attrs }"
138
+ :class="[
139
+ 'ui-pane-content fixed top-3 right-3 bottom-3 z-pane flex flex-col overflow-hidden',
140
+ !width && 'w-[560px]',
141
+ 'max-w-[calc(100vw-1.5rem)]',
142
+ 'bg-surface-neutral-300 shadow-shadows-drop-shadow-2xl rounded-container',
143
+ 'focus:outline-hidden focus-indicator-none',
144
+ ]"
145
+ :style="width ? { width } : undefined"
146
+ :data-colors-semantic="colorMode"
147
+ @focus-outside="keepOpenOnFocusOutside"
148
+ @pointer-down-outside="preventUnlessDismissible"
149
+ @escape-key-down="preventUnlessDismissible"
150
+ >
151
+ <VisuallyHidden
152
+ v-if="!title"
153
+ as-child
154
+ >
155
+ <DialogTitle>{{ accessibleTitle }}</DialogTitle>
156
+ </VisuallyHidden>
157
+
158
+ <div
159
+ v-if="hasHeader"
160
+ data-testid="ui-pane-header"
161
+ :class="['relative z-1 flex min-h-10 shrink-0 items-center box-content', spacing, isLarge ? 'gap-6' : 'gap-4', bodyScrollTop > 0 && 'shadow-elevation-level-1']"
162
+ >
163
+ <DialogTitle
164
+ v-if="title"
165
+ :class="['min-w-0 break-words text-text-neutral-base', isLarge ? 'text-title-md-bold' : 'text-title-sm-bold']"
166
+ >
167
+ {{ title }}
168
+ </DialogTitle>
169
+
170
+ <div
171
+ v-if="$slots.header"
172
+ class="flex min-w-0 flex-1 items-center"
173
+ >
174
+ <slot name="header" />
175
+ </div>
176
+
177
+ <!-- Not UiDialogClose: it pins itself to light, and the pane follows the mode around it -->
178
+ <DialogClose
179
+ v-if="!hideClose"
180
+ as-child
181
+ >
182
+ <UiButton
183
+ variant="tertiary"
184
+ color="neutral"
185
+ size="md"
186
+ icon="i-ph-x"
187
+ data-testid="ui-pane-close"
188
+ class="ml-auto shrink-0"
189
+ :aria-label="closeAriaLabel"
190
+ />
191
+ </DialogClose>
192
+ </div>
193
+
194
+ <div
195
+ ref="body"
196
+ data-testid="ui-pane-body"
197
+ :class="['min-h-0 flex-1 overflow-y-auto', bodyClasses]"
198
+ >
199
+ <slot />
200
+ </div>
201
+
202
+ <div
203
+ v-if="$slots.footer"
204
+ data-testid="ui-pane-footer"
205
+ :class="['shrink-0 border-t border-divider', spacing, footerClasses]"
206
+ >
207
+ <slot name="footer" />
208
+ </div>
209
+ </DialogContent>
210
+ </DialogPortal>
211
+ </template>
212
+
213
+ <style scoped>
214
+ /* Own keyframes, like UiDialogContent: reka waits for `animationend` before unmounting. */
215
+ @keyframes ui-pane-in {
216
+ from { opacity: 0; transform: translateX(1rem); }
217
+ to { opacity: 1; transform: translateX(0); }
218
+ }
219
+
220
+ @keyframes ui-pane-out {
221
+ from { opacity: 1; transform: translateX(0); }
222
+ to { opacity: 0; transform: translateX(1rem); }
223
+ }
224
+
225
+ .ui-pane-content[data-state='open'] {
226
+ animation: ui-pane-in 200ms ease-out both;
227
+ }
228
+
229
+ .ui-pane-content[data-state='closed'] {
230
+ animation: ui-pane-out 150ms ease-in both;
231
+ }
232
+ </style>
@@ -0,0 +1,14 @@
1
+ <script setup lang="ts">
2
+ import type { DialogTriggerProps } from 'reka-ui'
3
+ import { DialogTrigger, useForwardProps } from 'reka-ui'
4
+
5
+ const props = defineProps<DialogTriggerProps>()
6
+
7
+ const forwarded = useForwardProps(props)
8
+ </script>
9
+
10
+ <template>
11
+ <DialogTrigger v-bind="{ ...forwarded, ...$attrs }">
12
+ <slot />
13
+ </DialogTrigger>
14
+ </template>
@@ -0,0 +1,12 @@
1
+ export { default as UiPane } from './UiPane.vue'
2
+ export { default as UiPaneTrigger } from './UiPaneTrigger.vue'
3
+ export { default as UiPaneContent } from './UiPaneContent.vue'
4
+ export type { UiPaneContentProps, UiPaneOrientation, UiPaneSize } from './UiPaneContent.vue'
5
+
6
+ export {
7
+ DialogClose,
8
+ type DialogRootProps,
9
+ type DialogRootEmits,
10
+ type DialogContentProps,
11
+ type DialogContentEmits,
12
+ } from 'reka-ui'
@@ -12,7 +12,7 @@ const forwarded = useForwardPropsEmits(props, emits)
12
12
  <PopoverPortal>
13
13
  <PopoverContent
14
14
  v-bind="{ ...forwarded, ...$attrs }"
15
- class="rounded-lg shadow-shadows-drop-shadow-lg border ui-popover-content animate-scale-in z-50"
15
+ class="rounded-container shadow-shadows-drop-shadow-lg border border-container-border ui-popover-content z-overlay"
16
16
  >
17
17
  <slot />
18
18
  </PopoverContent>
@@ -20,7 +20,27 @@ const forwarded = useForwardPropsEmits(props, emits)
20
20
  </template>
21
21
 
22
22
  <style>
23
+ /* Unscoped: reka gives the scope id to its popper wrapper, not this content. */
23
24
  .ui-popover-content {
24
25
  transform-origin: var(--reka-popover-content-transform-origin, center);
25
26
  }
27
+
28
+ /* Local keyframes: reka waits for the closing animation before unmounting. */
29
+ @keyframes ui-popover-scale-in {
30
+ from { opacity: 0; transform: scale(0.6); }
31
+ to { opacity: 1; transform: scale(1); }
32
+ }
33
+
34
+ @keyframes ui-popover-scale-out {
35
+ from { opacity: 1; transform: scale(1); }
36
+ to { opacity: 0; transform: scale(0.6); }
37
+ }
38
+
39
+ :where(.ui-popover-content[data-state='open']) {
40
+ animation: ui-popover-scale-in 150ms ease-out both;
41
+ }
42
+
43
+ .ui-popover-content[data-state='closed'] {
44
+ animation: ui-popover-scale-out 100ms ease-in both;
45
+ }
26
46
  </style>
@@ -66,11 +66,11 @@ const sizeClass = computed(() => {
66
66
  @reference '@livestorm/ui-tokens/output/supernova/index.css';
67
67
 
68
68
  .ui-progress-root {
69
- @apply relative w-full bg-actions-neutral-active-overlay overflow-hidden rounded-lg;
69
+ @apply relative w-full bg-actions-neutral-active-overlay overflow-hidden rounded-full;
70
70
  }
71
71
 
72
72
  .ui-progress-indicator {
73
- @apply h-full w-full rounded-lg transition-transform duration-[660ms];
73
+ @apply h-full w-full rounded-full transition-transform duration-[660ms];
74
74
  transition-timing-function: cubic-bezier(0.65, 0, 0.35, 1);
75
75
  }
76
76
 
@@ -0,0 +1,258 @@
1
+ <script setup lang="ts">
2
+ import { computed, ref, watch } from 'vue'
3
+ import type { ComponentPublicInstance } from 'vue'
4
+ import { RadioGroupItem, RadioGroupRoot } from 'reka-ui'
5
+ import type { AcceptableValue, RadioGroupItemEmits } from 'reka-ui'
6
+ import type { RatingSize } from './types'
7
+
8
+ interface UiRatingProps {
9
+ /**
10
+ * The selected star, from 1 to `max`. `null` means no selection.
11
+ * @default null
12
+ */
13
+ modelValue?: number | null
14
+ /**
15
+ * Number of stars
16
+ * @default 5
17
+ */
18
+ max?: number
19
+ /**
20
+ * Caption under each star, in star order. The caption is also the star's
21
+ * accessible name; a star without one is named by its number.
22
+ */
23
+ labels?: string[]
24
+ /**
25
+ * Size of the stars
26
+ * @default 'md'
27
+ */
28
+ size?: RatingSize
29
+ /**
30
+ * Whether the rating only displays its value. The stars stay focusable so
31
+ * the value can be read, but cannot be changed.
32
+ * @default false
33
+ */
34
+ readonly?: boolean
35
+ /**
36
+ * Whether the rating is disabled
37
+ * @default false
38
+ */
39
+ disabled?: boolean
40
+ /**
41
+ * Whether a rating is required
42
+ * @default false
43
+ */
44
+ required?: boolean
45
+ /**
46
+ * Name attribute, submitted with the form via a hidden input
47
+ */
48
+ name?: string
49
+ }
50
+
51
+ const props = withDefaults(defineProps<UiRatingProps>(), {
52
+ modelValue: null,
53
+ max: 5,
54
+ labels: undefined,
55
+ size: 'md',
56
+ readonly: false,
57
+ disabled: false,
58
+ required: false,
59
+ name: undefined,
60
+ })
61
+
62
+ const emit = defineEmits<{
63
+ 'update:modelValue': [value: number]
64
+ }>()
65
+
66
+ const STAR_SIZE_CLASSES: Record<RatingSize, string> = {
67
+ sm: 'size-4',
68
+ md: 'size-6',
69
+ lg: 'size-8',
70
+ }
71
+
72
+ type StarState = 'empty' | 'preview' | 'selected'
73
+ type StarFill = 'empty' | 'selected'
74
+
75
+ const STAR_FILL_CLASSES: Record<StarFill, string> = {
76
+ empty: 'i-ph-star text-text-neutral-tertiary',
77
+ selected: 'i-ph-star-fill text-actions-primary-idle',
78
+ }
79
+
80
+ // The pressed overlay stands in for the hover one, too faint on a glyph. It darkens
81
+ // the empty outline and lightens the primary fill, as it does on a primary button.
82
+ const STAR_OVERLAY_CLASSES: Record<StarFill, string> = {
83
+ empty: 'i-ph-star-fill text-actions-neutral-pressed-overlay',
84
+ selected: 'i-ph-star-fill text-actions-neutral-invert-pressed-overlay',
85
+ }
86
+
87
+ // Vertical padding keeps every star inside a hit area of at least 32px high
88
+ const ITEM_PADDING_CLASSES: Record<RatingSize, string> = {
89
+ sm: 'py-2',
90
+ md: 'py-1',
91
+ lg: 'py-1',
92
+ }
93
+
94
+ // Every star gets the same fixed column, wider with captions so their length
95
+ // never changes the star spacing. Only sm trades the 32px hit width for density.
96
+ const ITEM_WIDTH_CLASSES: Record<RatingSize, { plain: string, captioned: string }> = {
97
+ sm: { plain: 'w-6', captioned: 'w-12' },
98
+ md: { plain: 'w-8', captioned: 'w-12' },
99
+ lg: { plain: 'w-10', captioned: 'w-15' },
100
+ }
101
+
102
+ // Mirror the value locally so the stars follow a selection even when the
103
+ // consumer does not bind v-model (uncontrolled usage)
104
+ const currentValue = ref<number | null>(props.modelValue)
105
+
106
+ watch(() => props.modelValue, (value) => {
107
+ currentValue.value = value
108
+ })
109
+
110
+ const hoveredValue = ref<number | null>(null)
111
+
112
+ const isInteractive = computed(() => !props.readonly && !props.disabled)
113
+
114
+ // A rating locked under the pointer drops the preview straight away
115
+ const previewValue = computed(() => isInteractive.value ? hoveredValue.value : null)
116
+
117
+ const hasCaptions = computed(() => (props.labels?.length ?? 0) > 0)
118
+
119
+ const rootClasses = computed(() => [
120
+ 'flex w-fit gap-1',
121
+ { 'opacity-50': props.disabled },
122
+ ])
123
+
124
+ const cursorClass = computed(() => {
125
+ if (props.disabled) {
126
+ return 'cursor-not-allowed'
127
+ }
128
+ if (props.readonly) {
129
+ return 'cursor-default'
130
+ }
131
+ return 'cursor-pointer'
132
+ })
133
+
134
+ const itemClasses = computed(() => [
135
+ 'group/star flex flex-col items-center gap-2 rounded-md',
136
+ ITEM_PADDING_CLASSES[props.size],
137
+ ITEM_WIDTH_CLASSES[props.size][hasCaptions.value ? 'captioned' : 'plain'],
138
+ cursorClass.value,
139
+ ])
140
+
141
+ function starFill(value: number): StarFill {
142
+ return value <= (currentValue.value ?? 0) ? 'selected' : 'empty'
143
+ }
144
+
145
+ // Past the selection only the added stars preview; within it, the stars up to
146
+ // the pointer do. The rest of the selection stays as it is.
147
+ function starState(value: number): StarState {
148
+ const selected = currentValue.value ?? 0
149
+ const preview = previewValue.value
150
+
151
+ if (preview !== null) {
152
+ const previewFrom = preview > selected ? selected + 1 : 1
153
+ if (value >= previewFrom && value <= preview) {
154
+ return 'preview'
155
+ }
156
+ }
157
+ return starFill(value)
158
+ }
159
+
160
+ function starClasses(value: number): string[] {
161
+ return [STAR_SIZE_CLASSES[props.size], STAR_FILL_CLASSES[starFill(value)]]
162
+ }
163
+
164
+ function overlayClasses(value: number): string[] {
165
+ return [STAR_SIZE_CLASSES[props.size], STAR_OVERLAY_CLASSES[starFill(value)]]
166
+ }
167
+
168
+ // An empty caption counts as a missing one, so the star keeps its number as a name
169
+ function labelFor(value: number): string | undefined {
170
+ return props.labels?.[value - 1] || undefined
171
+ }
172
+
173
+ // A star without a caption keeps its number as a visually hidden name
174
+ function captionClasses(value: number): string {
175
+ if (!labelFor(value)) {
176
+ return 'sr-only'
177
+ }
178
+ return 'text-content-legends-medium-md text-center wrap-break-word text-text-neutral-secondary group-data-[state=checked]/star:text-text-primary-base'
179
+ }
180
+
181
+ function onUpdateModelValue(value: AcceptableValue) {
182
+ currentValue.value = value as number
183
+ emit('update:modelValue', value as number)
184
+ }
185
+
186
+ function onSelect(event: RadioGroupItemEmits['select'][0]) {
187
+ if (props.readonly) {
188
+ event.preventDefault()
189
+ }
190
+ }
191
+
192
+ function onMouseEnter(value: number) {
193
+ if (isInteractive.value) {
194
+ hoveredValue.value = value
195
+ }
196
+ }
197
+
198
+ function onMouseLeave() {
199
+ hoveredValue.value = null
200
+ }
201
+
202
+ // RadioGroupRoot is a generic component, so InstanceType<typeof RadioGroupRoot> can't be used
203
+ const rootRef = ref<ComponentPublicInstance | null>(null)
204
+
205
+ // Focuses the selected star, or the first one when nothing is selected
206
+ function focus() {
207
+ const root = rootRef.value?.$el as HTMLElement | undefined
208
+ const star = root?.querySelector<HTMLElement>('[role="radio"][aria-checked="true"]') ??
209
+ root?.querySelector<HTMLElement>('[role="radio"]')
210
+ star?.focus()
211
+ }
212
+
213
+ defineExpose({ focus })
214
+ </script>
215
+
216
+ <template>
217
+ <RadioGroupRoot
218
+ ref="rootRef"
219
+ :model-value="currentValue"
220
+ :disabled="disabled"
221
+ :required="required"
222
+ :name="name"
223
+ :loop="false"
224
+ :aria-readonly="readonly || undefined"
225
+ :class="rootClasses"
226
+ @update:model-value="onUpdateModelValue"
227
+ @mouseleave="onMouseLeave"
228
+ >
229
+ <RadioGroupItem
230
+ v-for="value in max"
231
+ :key="value"
232
+ :value="value"
233
+ :class="itemClasses"
234
+ @select="onSelect"
235
+ @mouseenter="onMouseEnter(value)"
236
+ >
237
+ <!-- The star under the pointer grows a little so the hovered one stands out of the preview -->
238
+ <span
239
+ aria-hidden="true"
240
+ class="relative motion-safe:transition-transform"
241
+ :class="[STAR_SIZE_CLASSES[size], { 'scale-110': previewValue === value }]"
242
+ >
243
+ <span
244
+ data-testid="ui-rating-star"
245
+ :data-state="starState(value)"
246
+ :class="starClasses(value)"
247
+ />
248
+ <span
249
+ v-if="starState(value) === 'preview'"
250
+ data-testid="ui-rating-star-overlay"
251
+ class="absolute inset-0"
252
+ :class="overlayClasses(value)"
253
+ />
254
+ </span>
255
+ <span :class="captionClasses(value)">{{ labelFor(value) ?? value }}</span>
256
+ </RadioGroupItem>
257
+ </RadioGroupRoot>
258
+ </template>
@@ -0,0 +1 @@
1
+ export type RatingSize = 'sm' | 'md' | 'lg'
@@ -4,6 +4,7 @@ import UiTooltipProvider from "../UiTooltip/UiTooltipProvider.vue";
4
4
  import UiTooltip from "../UiTooltip/UiTooltip.vue";
5
5
  import UiTooltipTrigger from "../UiTooltip/UiTooltipTrigger.vue";
6
6
  import UiTooltipContent from "../UiTooltip/UiTooltipContent.vue";
7
+ import UiSpinnerIcon from "../UiLoader/UiSpinnerIcon.vue";
7
8
 
8
9
  defineOptions({ inheritAttrs: false });
9
10
 
@@ -14,6 +15,7 @@ withDefaults(
14
15
  icon?: string;
15
16
  tooltip?: string;
16
17
  tooltipSide?: "top" | "bottom" | "left" | "right";
18
+ tooltipDisabled?: boolean;
17
19
  disabled?: boolean;
18
20
  active?: boolean;
19
21
  loading?: boolean;
@@ -22,6 +24,7 @@ withDefaults(
22
24
  variant: "ghost",
23
25
  color: "neutral",
24
26
  tooltipSide: "top",
27
+ tooltipDisabled: false,
25
28
  },
26
29
  );
27
30
 
@@ -31,7 +34,7 @@ const isIconOnly = computed(() => !slots.default);
31
34
 
32
35
  <template>
33
36
  <UiTooltipProvider v-if="tooltip">
34
- <UiTooltip>
37
+ <UiTooltip :disabled="tooltipDisabled">
35
38
  <UiTooltipTrigger as-child>
36
39
  <button
37
40
  v-bind="$attrs"
@@ -55,30 +58,13 @@ const isIconOnly = computed(() => !slots.default);
55
58
  ]"
56
59
  :disabled="disabled || loading"
57
60
  >
58
- <svg
61
+ <UiSpinnerIcon
59
62
  v-if="loading"
60
- class="h-4 w-4 shrink-0 animate-spin"
61
- xmlns="http://www.w3.org/2000/svg"
62
- fill="none"
63
- viewBox="0 0 24 24"
64
- >
65
- <circle
66
- class="opacity-20"
67
- cx="12"
68
- cy="12"
69
- r="10"
70
- stroke="currentColor"
71
- stroke-width="4"
72
- />
73
- <path
74
- class="opacity-100"
75
- fill="currentColor"
76
- d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
77
- />
78
- </svg>
63
+ class="size-5 shrink-0 animate-spin"
64
+ />
79
65
  <div
80
66
  v-else-if="icon"
81
- class="h-4 w-4 shrink-0"
67
+ class="size-5 shrink-0"
82
68
  :class="icon"
83
69
  />
84
70
  <slot />
@@ -115,30 +101,13 @@ const isIconOnly = computed(() => !slots.default);
115
101
  ]"
116
102
  :disabled="disabled || loading"
117
103
  >
118
- <svg
104
+ <UiSpinnerIcon
119
105
  v-if="loading"
120
- class="h-4 w-4 shrink-0 animate-spin"
121
- xmlns="http://www.w3.org/2000/svg"
122
- fill="none"
123
- viewBox="0 0 24 24"
124
- >
125
- <circle
126
- class="opacity-20"
127
- cx="12"
128
- cy="12"
129
- r="10"
130
- stroke="currentColor"
131
- stroke-width="4"
132
- />
133
- <path
134
- class="opacity-100"
135
- fill="currentColor"
136
- d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
137
- />
138
- </svg>
106
+ class="size-5 shrink-0 animate-spin"
107
+ />
139
108
  <div
140
109
  v-else-if="icon"
141
- class="h-4 w-4 shrink-0"
110
+ class="size-5 shrink-0"
142
111
  :class="icon"
143
112
  />
144
113
  <slot />
@@ -156,7 +125,7 @@ const isIconOnly = computed(() => !slots.default);
156
125
  }
157
126
 
158
127
  .ui-room-button--ghost.ui-room-button--neutral:not(:disabled):hover {
159
- background: rgba(245, 247, 252, 0.1);
128
+ background: var(--color-actions-neutral-hover-overlay, rgba(245, 247, 252, 0.1));
160
129
  }
161
130
 
162
131
  .ui-room-button--ghost.ui-room-button--danger {
@@ -182,7 +151,7 @@ const isIconOnly = computed(() => !slots.default);
182
151
  }
183
152
 
184
153
  .ui-room-button--glass.ui-room-button--neutral:not(:disabled):hover {
185
- background: rgba(245, 247, 252, 0.1);
154
+ background: var(--color-actions-neutral-hover-overlay, rgba(245, 247, 252, 0.1));
186
155
  }
187
156
 
188
157
  .ui-room-button--ghost.ui-room-button--primary {