@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
@@ -1,24 +1,114 @@
1
1
  <script setup lang="ts">
2
2
  import { provide, toRef } from 'vue'
3
+ import { UI_TABLE_SIZE_KEY, type UiTableSize } from './context'
3
4
 
4
5
  export interface UiTableProps {
5
- variant?: 'condensed' | 'large'
6
- hoverEffect?: boolean
6
+ /**
7
+ * Row heights: `md` = 40px header / 48px rows, `lg` = 48px header / 64px rows.
8
+ * @default 'md'
9
+ */
10
+ size?: UiTableSize
11
+ /**
12
+ * Alternating row backgrounds. Preferred over row dividers for readability.
13
+ * @default true
14
+ */
15
+ zebra?: boolean
7
16
  }
8
17
 
9
18
  const props = withDefaults(defineProps<UiTableProps>(), {
10
- variant: 'condensed',
11
- hoverEffect: false,
19
+ size: 'md',
20
+ zebra: true,
12
21
  })
13
22
 
14
- provide('tableVariant', toRef(props, 'variant'))
15
- provide('hoverEffect', toRef(props, 'hoverEffect'))
23
+ provide(UI_TABLE_SIZE_KEY, toRef(props, 'size'))
16
24
  </script>
17
25
 
18
26
  <template>
19
- <div class="w-full">
20
- <table class="w-full border-separate border-spacing-0">
27
+ <div
28
+ class="ui-table relative flow-root w-fit min-w-full overflow-y-clip"
29
+ :class="{ 'ui-table--zebra': zebra }"
30
+ >
31
+ <table class="-my-0.5 w-full border-separate border-spacing-x-0 border-spacing-y-0.5">
21
32
  <slot />
22
33
  </table>
23
34
  </div>
24
35
  </template>
36
+
37
+ <style scoped>
38
+ /*
39
+ * Row backgrounds live here rather than on the cells so the zebra stripe,
40
+ * hover and selected overlays stack the way the Figma spec layers them:
41
+ * zebra is a background-color, state overlays are background-image
42
+ * gradients painted on top of it.
43
+ */
44
+ .ui-table--zebra :deep(tbody:not([data-zebra-offset]) > tr:nth-child(even of :not([data-zebra-skip])) > td),
45
+ .ui-table--zebra :deep(tbody[data-zebra-offset] > tr:nth-child(odd of :not([data-zebra-skip])) > td) {
46
+ background-color: var(--color-surface-neutral-alpha-100);
47
+ }
48
+
49
+ .ui-table :deep(tbody > tr[data-clickable]:hover > td),
50
+ .ui-table :deep(tbody > tr[data-clickable]:focus-visible > td),
51
+ .ui-table :deep(tbody > tr[data-linked]:hover > td),
52
+ .ui-table :deep(tbody > tr[data-linked]:focus-within > td),
53
+ .ui-table :deep(tbody > tr:has(> .ui-table__actions-cell):hover > td) {
54
+ background-image: linear-gradient(var(--color-actions-primary-hover-overlay), var(--color-actions-primary-hover-overlay));
55
+ }
56
+
57
+ .ui-table :deep(tbody > tr[data-selected] > td),
58
+ .ui-table :deep(tbody > tr[data-selected]:hover > td) {
59
+ background-image: linear-gradient(var(--color-actions-primary-active-overlay), var(--color-actions-primary-active-overlay));
60
+ }
61
+
62
+ .ui-table :deep(tbody > tr > td:first-child) {
63
+ border-top-left-radius: var(--radius-table-row);
64
+ border-bottom-left-radius: var(--radius-table-row);
65
+ }
66
+
67
+ /*
68
+ * A zero-width trailing cell cannot show the row end, so the cell before it
69
+ * rounds it. A menu column is zero-width when no row has a menu.
70
+ */
71
+ .ui-table :deep(tbody > tr > td:last-child),
72
+ .ui-table :deep(tbody > tr > td:has(+ .ui-table__zero-width-cell)),
73
+ .ui-table :deep(table:not(:has(.ui-table__menu-cell)) > tbody > tr > td:has(+ .ui-table__empty-menu-cell)) {
74
+ border-top-right-radius: var(--radius-table-row);
75
+ border-bottom-right-radius: var(--radius-table-row);
76
+ }
77
+
78
+ /*
79
+ * The trailing actions backdrop (default variant only) masks the cells it
80
+ * overlays, so it mirrors the effective row background: opaque base plus
81
+ * the same stacked overlays. The floating variant carries no backdrop —
82
+ * its content (e.g. a UiActionBar) brings its own surface.
83
+ */
84
+ .ui-table :deep(.ui-table__actions--backdrop) {
85
+ background-color: var(--color-surface-neutral-bg-main);
86
+ }
87
+
88
+ .ui-table--zebra :deep(tbody:not([data-zebra-offset]) > tr:nth-child(even of :not([data-zebra-skip])) .ui-table__actions--backdrop),
89
+ .ui-table--zebra :deep(tbody[data-zebra-offset] > tr:nth-child(odd of :not([data-zebra-skip])) .ui-table__actions--backdrop) {
90
+ background-image: linear-gradient(var(--color-surface-neutral-alpha-100), var(--color-surface-neutral-alpha-100));
91
+ }
92
+
93
+ .ui-table :deep(tbody > tr:hover .ui-table__actions--backdrop) {
94
+ background-image: linear-gradient(var(--color-actions-primary-hover-overlay), var(--color-actions-primary-hover-overlay));
95
+ }
96
+
97
+ .ui-table--zebra :deep(tbody:not([data-zebra-offset]) > tr:nth-child(even of :not([data-zebra-skip])):hover .ui-table__actions--backdrop),
98
+ .ui-table--zebra :deep(tbody[data-zebra-offset] > tr:nth-child(odd of :not([data-zebra-skip])):hover .ui-table__actions--backdrop) {
99
+ background-image:
100
+ linear-gradient(var(--color-actions-primary-hover-overlay), var(--color-actions-primary-hover-overlay)),
101
+ linear-gradient(var(--color-surface-neutral-alpha-100), var(--color-surface-neutral-alpha-100));
102
+ }
103
+
104
+ .ui-table :deep(tbody > tr[data-selected]:hover .ui-table__actions--backdrop) {
105
+ background-image: linear-gradient(var(--color-actions-primary-active-overlay), var(--color-actions-primary-active-overlay));
106
+ }
107
+
108
+ .ui-table--zebra :deep(tbody:not([data-zebra-offset]) > tr[data-selected]:nth-child(even of :not([data-zebra-skip])):hover .ui-table__actions--backdrop),
109
+ .ui-table--zebra :deep(tbody[data-zebra-offset] > tr[data-selected]:nth-child(odd of :not([data-zebra-skip])):hover .ui-table__actions--backdrop) {
110
+ background-image:
111
+ linear-gradient(var(--color-actions-primary-active-overlay), var(--color-actions-primary-active-overlay)),
112
+ linear-gradient(var(--color-surface-neutral-alpha-100), var(--color-surface-neutral-alpha-100));
113
+ }
114
+ </style>
@@ -0,0 +1,135 @@
1
+ <script setup lang="ts">
2
+ import { computed, inject, ref, unref, useSlots } from 'vue'
3
+ import { PopoverContent, PopoverPortal, PopoverRoot, PopoverTrigger } from 'reka-ui'
4
+ import { useTranslate } from '../../utils/i18n'
5
+ import { UI_TABLE_SIZE_KEY, type UiTableSize } from './context'
6
+
7
+ /**
8
+ * Host for trailing row actions. Place it as the last cell of a row, under a
9
+ * UiTableActionsHeaderCell. The overlay variants reveal the actions over the
10
+ * preceding cells on row hover or keyboard focus; the menu variant renders a
11
+ * persistent trigger instead. Without content it renders an empty cell, for
12
+ * rows that have no actions.
13
+ */
14
+ export interface UiTableActionsCellProps {
15
+ /**
16
+ * `default` masks the cells behind the actions with a row-state backdrop,
17
+ * for bare buttons per the Figma spec. `floating` drops the backdrop for
18
+ * self-contained content that brings its own surface, like a UiActionBar.
19
+ * `menu` tucks the actions behind an always-visible trigger button that
20
+ * opens them in a popover on click — no hover needed, so it also works
21
+ * on touch devices.
22
+ * @default 'default'
23
+ */
24
+ variant?: 'default' | 'floating' | 'menu'
25
+ /**
26
+ * Accessible label of the menu trigger. Defaults to the built-in
27
+ * "More actions" label.
28
+ */
29
+ menuLabel?: string
30
+ /**
31
+ * Keeps the overlay actions shown without row hover or focus, e.g. while
32
+ * a menu they opened is open.
33
+ * @default false
34
+ */
35
+ revealed?: boolean
36
+ }
37
+
38
+ const props = withDefaults(defineProps<UiTableActionsCellProps>(), {
39
+ variant: 'default',
40
+ menuLabel: undefined,
41
+ revealed: false,
42
+ })
43
+
44
+ const slots = useSlots()
45
+
46
+ const translate = useTranslate()
47
+
48
+ const size = inject(UI_TABLE_SIZE_KEY, ref<UiTableSize>('md'))
49
+
50
+ const heightClass = computed(() => (unref(size) === 'lg' ? 'h-16' : 'h-12'))
51
+
52
+ const overlayVisibilityClass = computed(() => (
53
+ props.revealed
54
+ ? 'pointer-events-auto opacity-100'
55
+ : 'pointer-events-none opacity-0 group-hover:pointer-events-auto group-hover:opacity-100 group-focus-within:pointer-events-auto group-focus-within:opacity-100'
56
+ ))
57
+
58
+ const overlayVariantClass = computed(() => (
59
+ props.variant === 'floating'
60
+ ? 'pr-3'
61
+ : 'ui-table__actions--backdrop gap-2 rounded-r-table-row py-1 pl-2 pr-3'
62
+ ))
63
+
64
+ const emptyCellClasses = computed(() => [heightClass.value, props.variant === 'menu' ? 'ui-table__empty-menu-cell' : 'ui-table__zero-width-cell'])
65
+
66
+ const menuOpen = ref(false)
67
+ const menuContent = ref<HTMLElement | null>(null)
68
+
69
+ const menuTriggerLabel = computed(() => props.menuLabel ?? translate('general_table_more-actions'))
70
+
71
+ // Land the opening focus on the container, not the first action: focusing
72
+ // an action would immediately pop its tooltip.
73
+ function onMenuOpenAutoFocus (event: Event) {
74
+ event.preventDefault()
75
+ menuContent.value?.focus()
76
+ }
77
+ </script>
78
+
79
+ <template>
80
+ <td
81
+ v-if="!slots.default"
82
+ class="p-0"
83
+ :class="emptyCellClasses"
84
+ />
85
+ <td
86
+ v-else-if="variant === 'menu'"
87
+ class="ui-table__menu-cell relative px-3 text-right"
88
+ :class="heightClass"
89
+ @click.stop
90
+ @keydown.stop
91
+ >
92
+ <PopoverRoot v-model:open="menuOpen">
93
+ <PopoverTrigger
94
+ :aria-label="menuTriggerLabel"
95
+ class="inline-flex size-button-sm cursor-pointer items-center justify-center rounded-button-sm align-middle text-actions-neutral-idle transition-colors hover:bg-actions-neutral-hover-overlay"
96
+ >
97
+ <span class="i-ph-dots-three size-4 shrink-0" />
98
+ </PopoverTrigger>
99
+ <PopoverPortal>
100
+ <PopoverContent
101
+ side="bottom"
102
+ align="end"
103
+ :side-offset="4"
104
+ class="z-overlay"
105
+ @open-auto-focus="onMenuOpenAutoFocus"
106
+ >
107
+ <!-- Row action menus are one-shot: picking an action closes them. -->
108
+ <div
109
+ ref="menuContent"
110
+ tabindex="-1"
111
+ class="focus-indicator-none outline-none"
112
+ @click="menuOpen = false"
113
+ >
114
+ <slot />
115
+ </div>
116
+ </PopoverContent>
117
+ </PopoverPortal>
118
+ </PopoverRoot>
119
+ </td>
120
+ <td
121
+ v-else
122
+ class="ui-table__actions-cell ui-table__zero-width-cell sticky right-0 w-0 p-0"
123
+ :class="heightClass"
124
+ >
125
+ <div
126
+ class="ui-table__actions absolute inset-y-0 right-0 flex items-center transition-opacity"
127
+ :class="[overlayVisibilityClass, overlayVariantClass]"
128
+ data-testid="ui-table-actions"
129
+ @click.stop
130
+ @keydown.stop
131
+ >
132
+ <slot />
133
+ </div>
134
+ </td>
135
+ </template>
@@ -0,0 +1,19 @@
1
+ <script setup lang="ts">
2
+ import { useTranslate } from '../../utils/i18n'
3
+
4
+ /**
5
+ * Header of the trailing actions column, paired with UiTableActionsCell. The
6
+ * column takes no width of its own: overlay actions sit over the row end and
7
+ * menu triggers size it. It names the column for assistive tech.
8
+ */
9
+ const translate = useTranslate()
10
+ </script>
11
+
12
+ <template>
13
+ <th
14
+ scope="col"
15
+ class="w-0 p-0"
16
+ >
17
+ <span class="sr-only">{{ translate('general_table_more-actions') }}</span>
18
+ </th>
19
+ </template>
@@ -1,5 +1,20 @@
1
+ <script setup lang="ts">
2
+ export interface UiTableBodyProps {
3
+ /**
4
+ * Starts the zebra on the first row, so a body that follows another body
5
+ * with an odd number of rows keeps the stripes alternating.
6
+ * @default false
7
+ */
8
+ zebraOffset?: boolean
9
+ }
10
+
11
+ withDefaults(defineProps<UiTableBodyProps>(), {
12
+ zebraOffset: false,
13
+ })
14
+ </script>
15
+
1
16
  <template>
2
- <tbody>
17
+ <tbody :data-zebra-offset="zebraOffset ? '' : undefined">
3
18
  <slot />
4
19
  </tbody>
5
20
  </template>
@@ -1,26 +1,43 @@
1
1
  <script setup lang="ts">
2
- import { inject, computed, unref, type Ref } from 'vue'
2
+ import { computed, inject, ref, unref } from 'vue'
3
+ import { UI_TABLE_SIZE_KEY, type UiTableSize } from './context'
3
4
 
4
- const variant = inject<Ref<'condensed' | 'large'>>('tableVariant')
5
- const isEven = inject<boolean>('rowIsEven', false)
6
- const hoverEffect = inject<Ref<boolean>>('hoverEffect')
5
+ export interface UiTableCellProps {
6
+ /**
7
+ * Renders an en dash (–), the convention for missing values.
8
+ * @default false
9
+ */
10
+ empty?: boolean
11
+ /**
12
+ * Content alignment. Textual data stays left-aligned; reserve `right` for numeric data.
13
+ * @default 'left'
14
+ */
15
+ align?: 'left' | 'right'
16
+ }
7
17
 
8
- const cellClasses = computed(() => ({
9
- 'h-10': unref(variant) === 'condensed',
10
- 'h-20': unref(variant) === 'large',
11
- 'bg-surface-neutral-alpha-100': isEven,
12
- 'group-hover:bg-surface-neutral-alpha-200': unref(hoverEffect) && isEven,
13
- 'group-hover:bg-surface-neutral-alpha-100': unref(hoverEffect) && !isEven,
14
- 'first:rounded-l-md': true,
15
- 'last:rounded-r-md': true,
16
- }))
18
+ withDefaults(defineProps<UiTableCellProps>(), {
19
+ empty: false,
20
+ align: 'left',
21
+ })
22
+
23
+ const size = inject(UI_TABLE_SIZE_KEY, ref<UiTableSize>('md'))
24
+
25
+ const sizeClasses = computed(() => (
26
+ unref(size) === 'lg'
27
+ ? 'h-16 text-content-text-md-medium'
28
+ : 'h-12 text-content-legends-medium-md'
29
+ ))
17
30
  </script>
18
31
 
19
32
  <template>
20
33
  <td
21
- :class="cellClasses"
22
- class="px-3 overflow-hidden text-ellipsis transition-colors"
34
+ :class="[sizeClasses, align === 'right' ? 'text-right' : 'text-left']"
35
+ class="overflow-hidden px-3 text-ellipsis text-text-neutral-base transition-colors"
23
36
  >
24
- <slot />
37
+ <span
38
+ v-if="empty"
39
+ class="text-text-neutral-secondary"
40
+ >–</span>
41
+ <slot v-else />
25
42
  </td>
26
43
  </template>
@@ -1,12 +1,13 @@
1
1
  <script setup lang="ts">
2
- import { inject, computed, unref, type Ref } from 'vue'
2
+ import { computed, inject, ref, unref } from 'vue'
3
+ import { UI_TABLE_SIZE_KEY, type UiTableSize } from './context'
3
4
 
4
- const variant = inject<Ref<'condensed' | 'large'>>('tableVariant')
5
+ const size = inject(UI_TABLE_SIZE_KEY, ref<UiTableSize>('md'))
5
6
 
6
7
  const headerClasses = computed(() => ({
7
- 'h-10': unref(variant) === 'condensed',
8
- 'h-12': unref(variant) === 'large',
9
- 'sticky top-0 z-20': true,
8
+ 'h-10': unref(size) === 'md',
9
+ 'h-12': unref(size) === 'lg',
10
+ 'sticky top-0 z-20 bg-surface-neutral-bg-main': true,
10
11
  }))
11
12
  </script>
12
13
 
@@ -1,19 +1,71 @@
1
1
  <script setup lang="ts">
2
- import { inject, computed, unref, type Ref } from 'vue'
2
+ import { computed, inject, ref, unref } from 'vue'
3
+ import { UI_TABLE_SIZE_KEY, type UiTableSize } from './context'
3
4
 
4
- const variant = inject<Ref<'condensed' | 'large'>>('tableVariant')
5
+ export type UiTableSortDirection = 'asc' | 'desc' | 'none'
5
6
 
6
- const cellClasses = computed(() => ({
7
- 'h-10': unref(variant) === 'condensed',
8
- 'h-12': unref(variant) === 'large',
9
- }))
7
+ export interface UiTableHeaderCellProps {
8
+ /**
9
+ * Renders the sort affordance and makes the header interactive.
10
+ * Sorting itself stays in the consumer: listen to `sort` and update `sort-direction`.
11
+ * @default false
12
+ */
13
+ sortable?: boolean
14
+ /**
15
+ * Current sort direction, controlled by the consumer.
16
+ * @default 'none'
17
+ */
18
+ sortDirection?: UiTableSortDirection
19
+ /**
20
+ * Content alignment. Textual data stays left-aligned; reserve `right` for numeric data.
21
+ * @default 'left'
22
+ */
23
+ align?: 'left' | 'right'
24
+ }
25
+
26
+ const props = withDefaults(defineProps<UiTableHeaderCellProps>(), {
27
+ sortable: false,
28
+ sortDirection: 'none',
29
+ align: 'left',
30
+ })
31
+
32
+ const emit = defineEmits<{
33
+ sort: []
34
+ }>()
35
+
36
+ const size = inject(UI_TABLE_SIZE_KEY, ref<UiTableSize>('md'))
37
+
38
+ const heightClass = computed(() => (unref(size) === 'lg' ? 'h-12' : 'h-10'))
39
+
40
+ const ariaSort = computed(() => {
41
+ if (!props.sortable) return undefined
42
+ return ({ asc: 'ascending', desc: 'descending', none: 'none' } as const)[props.sortDirection]
43
+ })
10
44
  </script>
11
45
 
12
46
  <template>
13
47
  <th
14
- :class="cellClasses"
15
- class="px-3 py-1 text-left text-content-legends-bold-md text-text-neutral-tertiary"
48
+ scope="col"
49
+ :aria-sort="ariaSort"
50
+ :class="[heightClass, align === 'right' ? 'text-right' : 'text-left', sortable ? 'p-0' : 'px-3 pt-1 pb-2.5']"
51
+ class="align-bottom text-content-legends-bold-md text-text-neutral-tertiary"
16
52
  >
17
- <slot />
53
+ <button
54
+ v-if="sortable"
55
+ type="button"
56
+ class="group/sort flex size-full items-end justify-start gap-2 rounded-row px-3 pt-1 pb-2.5 transition-colors hover:text-text-neutral-base focus-visible:text-text-neutral-base"
57
+ :class="align === 'right' ? 'flex-row-reverse text-right' : 'text-left'"
58
+ @click="emit('sort')"
59
+ >
60
+ <slot />
61
+ <span
62
+ class="size-3 shrink-0 transition-opacity"
63
+ :class="[
64
+ sortDirection === 'asc' ? 'i-ph-caret-up' : 'i-ph-caret-down',
65
+ sortDirection === 'none' ? 'opacity-0 group-hover/sort:opacity-100 group-focus-visible/sort:opacity-100' : 'opacity-100',
66
+ ]"
67
+ />
68
+ </button>
69
+ <slot v-else />
18
70
  </th>
19
71
  </template>
@@ -1,26 +1,62 @@
1
1
  <script setup lang="ts">
2
- import { inject, computed, provide, unref, type Ref } from 'vue'
2
+ import { computed } from 'vue'
3
3
 
4
4
  export interface UiTableRowProps {
5
- isEven?: boolean
5
+ /**
6
+ * Marks the row as selected.
7
+ * @default false
8
+ */
9
+ selected?: boolean
10
+ /**
11
+ * Makes the row interactive: hover feedback, pointer cursor and keyboard focus.
12
+ * @default false
13
+ */
14
+ clickable?: boolean
15
+ /**
16
+ * The row hosts a link stretched over it: positions the row for the link
17
+ * and gives it the hover and focus tone.
18
+ * @default false
19
+ */
20
+ linked?: boolean
21
+ /**
22
+ * Takes part in the table zebra. Turn it off for a row that is not a data
23
+ * row, such as an overlay over the rows: it is neither striped nor counted.
24
+ * @default true
25
+ */
26
+ zebra?: boolean
6
27
  }
7
28
 
8
- const props = defineProps<UiTableRowProps>()
29
+ const props = withDefaults(defineProps<UiTableRowProps>(), {
30
+ selected: false,
31
+ clickable: false,
32
+ linked: false,
33
+ zebra: true,
34
+ })
9
35
 
10
- const variant = inject<Ref<'condensed' | 'large'>>('tableVariant')
36
+ const rowClasses = computed(() => ({ 'cursor-pointer': props.clickable, relative: props.linked }))
11
37
 
12
- provide('rowIsEven', props.isEven)
38
+ const emit = defineEmits<{
39
+ click: [event: MouseEvent | KeyboardEvent]
40
+ }>()
13
41
 
14
- const rowClasses = computed(() => ({
15
- 'h-12': unref(variant) === 'condensed',
16
- 'h-20': unref(variant) === 'large',
17
- }))
42
+ function onActivate (event: MouseEvent | KeyboardEvent) {
43
+ if (!props.clickable) return
44
+ emit('click', event)
45
+ }
18
46
  </script>
19
47
 
20
48
  <template>
21
49
  <tr
22
- :class="rowClasses"
23
50
  class="group"
51
+ :class="rowClasses"
52
+ :data-clickable="clickable ? '' : undefined"
53
+ :data-linked="linked ? '' : undefined"
54
+ :data-selected="selected ? '' : undefined"
55
+ :data-zebra-skip="zebra ? undefined : ''"
56
+ :tabindex="clickable ? 0 : undefined"
57
+ @click="onActivate"
58
+ @keydown.enter.self="onActivate"
59
+ @keydown.space.self.prevent="onActivate"
24
60
  >
25
61
  <slot />
26
62
  </tr>
@@ -0,0 +1,5 @@
1
+ import type { InjectionKey, Ref } from 'vue'
2
+
3
+ export type UiTableSize = 'md' | 'lg'
4
+
5
+ export const UI_TABLE_SIZE_KEY: InjectionKey<Ref<UiTableSize>> = Symbol('ui-table-size')
@@ -1,6 +1,10 @@
1
1
  export { default as UiTable } from './UiTable.vue'
2
2
  export { default as UiTableHeader } from './UiTableHeader.vue'
3
3
  export { default as UiTableHeaderCell } from './UiTableHeaderCell.vue'
4
+ export { default as UiTableActionsHeaderCell } from './UiTableActionsHeaderCell.vue'
4
5
  export { default as UiTableBody } from './UiTableBody.vue'
5
6
  export { default as UiTableRow } from './UiTableRow.vue'
6
7
  export { default as UiTableCell } from './UiTableCell.vue'
8
+ export { default as UiTableActionsCell } from './UiTableActionsCell.vue'
9
+ export type { UiTableSize } from './context'
10
+ export type { UiTableSortDirection } from './UiTableHeaderCell.vue'