@aleph-alpha/ui-library 1.9.0 → 1.11.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 (432) hide show
  1. package/README.md +14 -0
  2. package/dist/system/index-CkH7HQaa.js +7 -0
  3. package/dist/system/index-CuHwEAQ_.js +7 -0
  4. package/dist/system/index.d.ts +1322 -318
  5. package/dist/system/lib.js +8839 -6993
  6. package/package.json +2 -1
  7. package/src/@types/shims-vue.d.ts +5 -0
  8. package/src/__tests__/placeholder.test.ts +7 -0
  9. package/src/compositions/UiCompositionPlaceholder/UiCompositionPlaceholder.vue +9 -0
  10. package/src/compositions/UiCompositionPlaceholder/index.ts +1 -0
  11. package/src/compositions/UiCompositionPlaceholder/types.ts +8 -0
  12. package/src/compositions/UiDataTable/UiDataTable.mock.ts +104 -0
  13. package/src/compositions/UiDataTable/UiDataTable.stories.ts +1575 -0
  14. package/src/compositions/UiDataTable/UiDataTable.vue +129 -0
  15. package/src/compositions/UiDataTable/UiDataTableColumnHeader.vue +97 -0
  16. package/src/compositions/UiDataTable/UiDataTablePagination.vue +147 -0
  17. package/src/compositions/UiDataTable/UiDataTableToolbar.vue +85 -0
  18. package/src/compositions/UiDataTable/__tests__/UiDataTable.test.ts +372 -0
  19. package/src/compositions/UiDataTable/__tests__/UiDataTableColumnHeader.test.ts +217 -0
  20. package/src/compositions/UiDataTable/__tests__/UiDataTablePagination.test.ts +274 -0
  21. package/src/compositions/UiDataTable/__tests__/UiDataTableToolbar.test.ts +198 -0
  22. package/src/compositions/UiDataTable/constants.ts +77 -0
  23. package/src/compositions/UiDataTable/index.ts +6 -0
  24. package/src/compositions/UiDataTable/types.ts +39 -0
  25. package/src/compositions/UiDatePicker/UiDatePicker.stories.ts +976 -0
  26. package/src/compositions/UiDatePicker/UiDatePicker.vue +193 -0
  27. package/src/compositions/UiDatePicker/__tests__/UiDatePicker.test.ts +325 -0
  28. package/src/compositions/UiDatePicker/index.ts +14 -0
  29. package/src/compositions/UiDatePicker/types.ts +220 -0
  30. package/src/compositions/index.ts +8 -0
  31. package/src/foundations/UiPlaceholder/UiPlaceholder.vue +9 -0
  32. package/src/foundations/UiPlaceholder/index.ts +1 -0
  33. package/src/foundations/UiPlaceholder/types.ts +8 -0
  34. package/src/foundations/index.ts +6 -0
  35. package/src/index.ts +27 -0
  36. package/src/lib/utils.ts +6 -0
  37. package/src/primitives/UiAccordion/UiAccordion.stories.ts +476 -0
  38. package/src/primitives/UiAccordion/UiAccordion.vue +31 -0
  39. package/src/primitives/UiAccordion/UiAccordionContent.vue +16 -0
  40. package/src/primitives/UiAccordion/UiAccordionItem.vue +16 -0
  41. package/src/primitives/UiAccordion/UiAccordionTrigger.vue +23 -0
  42. package/src/primitives/UiAccordion/__tests__/UiAccordion.test.ts +198 -0
  43. package/src/primitives/UiAccordion/index.ts +6 -0
  44. package/src/primitives/UiAccordion/types.ts +95 -0
  45. package/src/primitives/UiAlert/UiAlert.stories.ts +199 -0
  46. package/src/primitives/UiAlert/UiAlert.vue +27 -0
  47. package/src/primitives/UiAlert/UiAlertDescription.vue +13 -0
  48. package/src/primitives/UiAlert/UiAlertTitle.vue +13 -0
  49. package/src/primitives/UiAlert/__tests__/UiAlert.test.ts +20 -0
  50. package/src/primitives/UiAlert/constants.ts +3 -0
  51. package/src/primitives/UiAlert/index.ts +5 -0
  52. package/src/primitives/UiAlert/types.ts +14 -0
  53. package/src/primitives/UiAlertDialog/UiAlertDialog.stories.ts +186 -0
  54. package/src/primitives/UiAlertDialog/UiAlertDialog.vue +18 -0
  55. package/src/primitives/UiAlertDialog/UiAlertDialogAction.vue +16 -0
  56. package/src/primitives/UiAlertDialog/UiAlertDialogCancel.vue +16 -0
  57. package/src/primitives/UiAlertDialog/UiAlertDialogContent.vue +26 -0
  58. package/src/primitives/UiAlertDialog/UiAlertDialogDescription.vue +16 -0
  59. package/src/primitives/UiAlertDialog/UiAlertDialogFooter.vue +13 -0
  60. package/src/primitives/UiAlertDialog/UiAlertDialogHeader.vue +16 -0
  61. package/src/primitives/UiAlertDialog/UiAlertDialogTitle.vue +16 -0
  62. package/src/primitives/UiAlertDialog/UiAlertDialogTrigger.vue +17 -0
  63. package/src/primitives/UiAlertDialog/__tests__/UiAlertDialog.test.ts +184 -0
  64. package/src/primitives/UiAlertDialog/index.ts +9 -0
  65. package/src/primitives/UiAlertDialog/types.ts +83 -0
  66. package/src/primitives/UiAvatar/UiAvatar.stories.ts +194 -0
  67. package/src/primitives/UiAvatar/UiAvatar.vue +13 -0
  68. package/src/primitives/UiAvatar/UiAvatarFallback.vue +13 -0
  69. package/src/primitives/UiAvatar/UiAvatarImage.vue +14 -0
  70. package/src/primitives/UiAvatar/__tests__/UiAvatar.test.ts +36 -0
  71. package/src/primitives/UiAvatar/index.ts +3 -0
  72. package/src/primitives/UiAvatar/types.ts +17 -0
  73. package/src/primitives/UiBadge/UiBadge.stories.ts +373 -0
  74. package/src/primitives/UiBadge/UiBadge.vue +21 -0
  75. package/src/primitives/UiBadge/__tests__/UiBadge.test.ts +44 -0
  76. package/src/primitives/UiBadge/constants.ts +3 -0
  77. package/src/primitives/UiBadge/index.ts +2 -0
  78. package/src/primitives/UiBadge/types.ts +48 -0
  79. package/src/primitives/UiButton/UiButton.stories.ts +537 -0
  80. package/src/primitives/UiButton/UiButton.vue +72 -0
  81. package/src/primitives/UiButton/__tests__/UiButton.test.ts +133 -0
  82. package/src/primitives/UiButton/index.ts +2 -0
  83. package/src/primitives/UiButton/types.ts +87 -0
  84. package/src/primitives/UiCalendar/UiCalendar.stories.ts +797 -0
  85. package/src/primitives/UiCalendar/UiCalendar.vue +67 -0
  86. package/src/primitives/UiCalendar/__tests__/UiCalendar.test.ts +45 -0
  87. package/src/primitives/UiCalendar/index.ts +15 -0
  88. package/src/primitives/UiCalendar/types.ts +236 -0
  89. package/src/primitives/UiCard/UiCard.stories.ts +197 -0
  90. package/src/primitives/UiCard/UiCard.vue +13 -0
  91. package/src/primitives/UiCard/UiCardAction.vue +13 -0
  92. package/src/primitives/UiCard/UiCardContent.vue +13 -0
  93. package/src/primitives/UiCard/UiCardDescription.vue +13 -0
  94. package/src/primitives/UiCard/UiCardFooter.vue +13 -0
  95. package/src/primitives/UiCard/UiCardHeader.vue +13 -0
  96. package/src/primitives/UiCard/UiCardTitle.vue +13 -0
  97. package/src/primitives/UiCard/__tests__/UiCard.test.ts +19 -0
  98. package/src/primitives/UiCard/__tests__/UiCardAction.test.ts +19 -0
  99. package/src/primitives/UiCard/__tests__/UiCardContent.test.ts +19 -0
  100. package/src/primitives/UiCard/__tests__/UiCardDescription.test.ts +19 -0
  101. package/src/primitives/UiCard/__tests__/UiCardFooter.test.ts +19 -0
  102. package/src/primitives/UiCard/__tests__/UiCardHeader.test.ts +19 -0
  103. package/src/primitives/UiCard/__tests__/UiCardTitle.test.ts +19 -0
  104. package/src/primitives/UiCard/index.ts +7 -0
  105. package/src/primitives/UiCard/types.ts +10 -0
  106. package/src/primitives/UiCheckbox/UiCheckbox.stories.ts +231 -0
  107. package/src/primitives/UiCheckbox/UiCheckbox.vue +19 -0
  108. package/src/primitives/UiCheckbox/__tests__/UiCheckbox.test.ts +29 -0
  109. package/src/primitives/UiCheckbox/index.ts +2 -0
  110. package/src/primitives/UiCheckbox/types.ts +30 -0
  111. package/src/primitives/UiDrawer/UiDrawer.stories.ts +602 -0
  112. package/src/primitives/UiDrawer/UiDrawer.vue +19 -0
  113. package/src/primitives/UiDrawer/UiDrawerClose.vue +16 -0
  114. package/src/primitives/UiDrawer/UiDrawerContent.vue +29 -0
  115. package/src/primitives/UiDrawer/UiDrawerDescription.vue +16 -0
  116. package/src/primitives/UiDrawer/UiDrawerFooter.vue +16 -0
  117. package/src/primitives/UiDrawer/UiDrawerHeader.vue +16 -0
  118. package/src/primitives/UiDrawer/UiDrawerTitle.vue +16 -0
  119. package/src/primitives/UiDrawer/UiDrawerTrigger.vue +16 -0
  120. package/src/primitives/UiDrawer/__tests__/UiDrawer.test.ts +229 -0
  121. package/src/primitives/UiDrawer/index.ts +8 -0
  122. package/src/primitives/UiDrawer/types.ts +96 -0
  123. package/src/primitives/UiDropdownMenu/UiDropdownMenu.stories.ts +760 -0
  124. package/src/primitives/UiDropdownMenu/UiDropdownMenu.vue +25 -0
  125. package/src/primitives/UiDropdownMenu/UiDropdownMenuCheckboxItem.vue +29 -0
  126. package/src/primitives/UiDropdownMenu/UiDropdownMenuContent.vue +27 -0
  127. package/src/primitives/UiDropdownMenu/UiDropdownMenuGroup.vue +13 -0
  128. package/src/primitives/UiDropdownMenu/UiDropdownMenuItem.vue +26 -0
  129. package/src/primitives/UiDropdownMenu/UiDropdownMenuLabel.vue +18 -0
  130. package/src/primitives/UiDropdownMenu/UiDropdownMenuRadioGroup.vue +20 -0
  131. package/src/primitives/UiDropdownMenu/UiDropdownMenuRadioItem.vue +26 -0
  132. package/src/primitives/UiDropdownMenu/UiDropdownMenuSeparator.vue +11 -0
  133. package/src/primitives/UiDropdownMenu/UiDropdownMenuShortcut.vue +13 -0
  134. package/src/primitives/UiDropdownMenu/UiDropdownMenuSub.vue +26 -0
  135. package/src/primitives/UiDropdownMenu/UiDropdownMenuSubContent.vue +23 -0
  136. package/src/primitives/UiDropdownMenu/UiDropdownMenuSubTrigger.vue +24 -0
  137. package/src/primitives/UiDropdownMenu/UiDropdownMenuTrigger.vue +24 -0
  138. package/src/primitives/UiDropdownMenu/__tests__/UiDropdownMenu.test.ts +557 -0
  139. package/src/primitives/UiDropdownMenu/index.ts +16 -0
  140. package/src/primitives/UiDropdownMenu/types.ts +219 -0
  141. package/src/primitives/UiField/UiField.stories.ts +1496 -0
  142. package/src/primitives/UiField/UiField.vue +18 -0
  143. package/src/primitives/UiField/UiFieldContent.vue +13 -0
  144. package/src/primitives/UiField/UiFieldDescription.vue +13 -0
  145. package/src/primitives/UiField/UiFieldError.vue +20 -0
  146. package/src/primitives/UiField/UiFieldGroup.vue +13 -0
  147. package/src/primitives/UiField/UiFieldLabel.vue +16 -0
  148. package/src/primitives/UiField/UiFieldLegend.vue +13 -0
  149. package/src/primitives/UiField/UiFieldSeparator.vue +13 -0
  150. package/src/primitives/UiField/UiFieldSet.vue +13 -0
  151. package/src/primitives/UiField/UiFieldTitle.vue +13 -0
  152. package/src/primitives/UiField/__tests__/UiFieldError.test.ts +35 -0
  153. package/src/primitives/UiField/index.ts +10 -0
  154. package/src/primitives/UiField/types.ts +47 -0
  155. package/src/primitives/UiIcon/UiIcon.stories.ts +95 -0
  156. package/src/primitives/UiIcon/UiIcon.vue +14 -0
  157. package/src/primitives/UiIcon/__tests__/UiIcon.test.ts +24 -0
  158. package/src/primitives/UiIcon/index.ts +1 -0
  159. package/src/primitives/UiIcon/types.ts +23 -0
  160. package/src/primitives/UiIconButton/UiIconButton.stories.ts +446 -0
  161. package/src/primitives/UiIconButton/UiIconButton.vue +63 -0
  162. package/src/primitives/UiIconButton/__tests__/UiIconButton.test.ts +102 -0
  163. package/src/primitives/UiIconButton/index.ts +2 -0
  164. package/src/primitives/UiIconButton/types.ts +67 -0
  165. package/src/primitives/UiInput/UiInput.stories.ts +193 -0
  166. package/src/primitives/UiInput/UiInput.vue +19 -0
  167. package/src/primitives/UiInput/__tests__/UiInput.test.ts +38 -0
  168. package/src/primitives/UiInput/index.ts +2 -0
  169. package/src/primitives/UiInput/types.ts +31 -0
  170. package/src/primitives/UiPopover/UiPopover.stories.ts +394 -0
  171. package/src/primitives/UiPopover/UiPopover.vue +17 -0
  172. package/src/primitives/UiPopover/UiPopoverContent.vue +27 -0
  173. package/src/primitives/UiPopover/UiPopoverTrigger.vue +16 -0
  174. package/src/primitives/UiPopover/__tests__/UiPopover.test.ts +87 -0
  175. package/src/primitives/UiPopover/index.ts +5 -0
  176. package/src/primitives/UiPopover/types.ts +86 -0
  177. package/src/primitives/UiProgress/UiProgress.stories.ts +92 -0
  178. package/src/primitives/UiProgress/UiProgress.vue +25 -0
  179. package/src/primitives/UiProgress/__tests__/UiProgress.test.ts +46 -0
  180. package/src/primitives/UiProgress/index.ts +2 -0
  181. package/src/primitives/UiProgress/types.ts +16 -0
  182. package/src/primitives/UiRadioGroup/UiRadioGroup.stories.ts +291 -0
  183. package/src/primitives/UiRadioGroup/UiRadioGroup.vue +43 -0
  184. package/src/primitives/UiRadioGroup/UiRadioGroupItem.vue +18 -0
  185. package/src/primitives/UiRadioGroup/__tests__/UiRadioGroup.test.ts +404 -0
  186. package/src/primitives/UiRadioGroup/index.ts +4 -0
  187. package/src/primitives/UiRadioGroup/types.ts +66 -0
  188. package/src/primitives/UiRangeCalendar/UiRangeCalendar.stories.ts +609 -0
  189. package/src/primitives/UiRangeCalendar/UiRangeCalendar.vue +50 -0
  190. package/src/primitives/UiRangeCalendar/__tests__/UiRangeCalendar.test.ts +35 -0
  191. package/src/primitives/UiRangeCalendar/index.ts +13 -0
  192. package/src/primitives/UiRangeCalendar/types.ts +184 -0
  193. package/src/primitives/UiSelect/UiSelect.stories.ts +425 -0
  194. package/src/primitives/UiSelect/UiSelect.vue +47 -0
  195. package/src/primitives/UiSelect/UiSelectContent.vue +30 -0
  196. package/src/primitives/UiSelect/UiSelectGroup.vue +13 -0
  197. package/src/primitives/UiSelect/UiSelectItem.vue +19 -0
  198. package/src/primitives/UiSelect/UiSelectLabel.vue +13 -0
  199. package/src/primitives/UiSelect/UiSelectSeparator.vue +11 -0
  200. package/src/primitives/UiSelect/UiSelectTrigger.vue +30 -0
  201. package/src/primitives/UiSelect/UiSelectValue.vue +18 -0
  202. package/src/primitives/UiSelect/__tests__/UiSelect.test.ts +211 -0
  203. package/src/primitives/UiSelect/__tests__/UiSelectContent.test.ts +30 -0
  204. package/src/primitives/UiSelect/__tests__/UiSelectGroup.test.ts +85 -0
  205. package/src/primitives/UiSelect/__tests__/UiSelectItem.test.ts +79 -0
  206. package/src/primitives/UiSelect/__tests__/UiSelectLabel.test.ts +83 -0
  207. package/src/primitives/UiSelect/__tests__/UiSelectSeparator.test.ts +82 -0
  208. package/src/primitives/UiSelect/__tests__/UiSelectTrigger.test.ts +54 -0
  209. package/src/primitives/UiSelect/__tests__/UiSelectValue.test.ts +39 -0
  210. package/src/primitives/UiSelect/index.ts +10 -0
  211. package/src/primitives/UiSelect/types.ts +93 -0
  212. package/src/primitives/UiSlider/UiSlider.stories.ts +226 -0
  213. package/src/primitives/UiSlider/UiSlider.vue +44 -0
  214. package/src/primitives/UiSlider/__tests__/UiSlider.test.ts +76 -0
  215. package/src/primitives/UiSlider/index.ts +1 -0
  216. package/src/primitives/UiSlider/types.ts +101 -0
  217. package/src/primitives/UiSpinner/UiSpinner.stories.ts +143 -0
  218. package/src/primitives/UiSpinner/UiSpinner.vue +16 -0
  219. package/src/primitives/UiSpinner/__tests__/UiSpinner.test.ts +19 -0
  220. package/src/primitives/UiSpinner/index.ts +2 -0
  221. package/src/primitives/UiSpinner/types.ts +16 -0
  222. package/src/primitives/UiSwitch/UiSwitch.stories.ts +120 -0
  223. package/src/primitives/UiSwitch/UiSwitch.vue +21 -0
  224. package/src/primitives/UiSwitch/__tests__/UiSwitch.test.ts +47 -0
  225. package/src/primitives/UiSwitch/index.ts +2 -0
  226. package/src/primitives/UiSwitch/types.ts +25 -0
  227. package/src/primitives/UiTable/UiTable.stories.ts +505 -0
  228. package/src/primitives/UiTable/UiTable.vue +13 -0
  229. package/src/primitives/UiTable/UiTableBody.vue +13 -0
  230. package/src/primitives/UiTable/UiTableCaption.vue +13 -0
  231. package/src/primitives/UiTable/UiTableCell.vue +16 -0
  232. package/src/primitives/UiTable/UiTableEmpty.vue +18 -0
  233. package/src/primitives/UiTable/UiTableFooter.vue +13 -0
  234. package/src/primitives/UiTable/UiTableHead.vue +18 -0
  235. package/src/primitives/UiTable/UiTableHeader.vue +13 -0
  236. package/src/primitives/UiTable/UiTableRow.vue +18 -0
  237. package/src/primitives/UiTable/__tests__/UiTable.test.ts +19 -0
  238. package/src/primitives/UiTable/__tests__/UiTableBody.test.ts +19 -0
  239. package/src/primitives/UiTable/__tests__/UiTableCaption.test.ts +19 -0
  240. package/src/primitives/UiTable/__tests__/UiTableCell.test.ts +26 -0
  241. package/src/primitives/UiTable/__tests__/UiTableEmpty.test.ts +32 -0
  242. package/src/primitives/UiTable/__tests__/UiTableFooter.test.ts +19 -0
  243. package/src/primitives/UiTable/__tests__/UiTableHead.test.ts +43 -0
  244. package/src/primitives/UiTable/__tests__/UiTableHeader.test.ts +19 -0
  245. package/src/primitives/UiTable/__tests__/UiTableRow.test.ts +32 -0
  246. package/src/primitives/UiTable/index.ts +16 -0
  247. package/src/primitives/UiTable/types.ts +68 -0
  248. package/src/primitives/UiTabs/UiTabs.stories.ts +456 -0
  249. package/src/primitives/UiTabs/UiTabs.vue +31 -0
  250. package/src/primitives/UiTabs/UiTabsContent.vue +16 -0
  251. package/src/primitives/UiTabs/UiTabsList.vue +16 -0
  252. package/src/primitives/UiTabs/UiTabsTrigger.vue +16 -0
  253. package/src/primitives/UiTabs/__tests__/UiTabs.test.ts +122 -0
  254. package/src/primitives/UiTabs/index.ts +6 -0
  255. package/src/primitives/UiTabs/types.ts +68 -0
  256. package/src/primitives/UiTextarea/UiTextarea.stories.ts +107 -0
  257. package/src/primitives/UiTextarea/UiTextarea.vue +19 -0
  258. package/src/primitives/UiTextarea/__tests__/UiTextarea.test.ts +40 -0
  259. package/src/primitives/UiTextarea/index.ts +2 -0
  260. package/src/primitives/UiTextarea/types.ts +30 -0
  261. package/src/primitives/UiTooltip/UiTooltip.stories.ts +550 -0
  262. package/src/primitives/UiTooltip/UiTooltip.vue +42 -0
  263. package/src/primitives/UiTooltip/__tests__/UiTooltip.test.ts +78 -0
  264. package/src/primitives/UiTooltip/index.ts +2 -0
  265. package/src/primitives/UiTooltip/types.ts +53 -0
  266. package/src/primitives/index.ts +33 -0
  267. package/src/primitives/shadcn/accordion/Accordion.vue +15 -0
  268. package/src/primitives/shadcn/accordion/AccordionContent.vue +23 -0
  269. package/src/primitives/shadcn/accordion/AccordionItem.vue +24 -0
  270. package/src/primitives/shadcn/accordion/AccordionTrigger.vue +35 -0
  271. package/src/primitives/shadcn/accordion/index.ts +4 -0
  272. package/src/primitives/shadcn/alert/Alert.vue +17 -0
  273. package/src/primitives/shadcn/alert/AlertDescription.vue +22 -0
  274. package/src/primitives/shadcn/alert/AlertTitle.vue +17 -0
  275. package/src/primitives/shadcn/alert/index.ts +24 -0
  276. package/src/primitives/shadcn/alert-dialog/AlertDialog.vue +15 -0
  277. package/src/primitives/shadcn/alert-dialog/AlertDialogAction.vue +18 -0
  278. package/src/primitives/shadcn/alert-dialog/AlertDialogCancel.vue +21 -0
  279. package/src/primitives/shadcn/alert-dialog/AlertDialogContent.vue +44 -0
  280. package/src/primitives/shadcn/alert-dialog/AlertDialogDescription.vue +21 -0
  281. package/src/primitives/shadcn/alert-dialog/AlertDialogFooter.vue +17 -0
  282. package/src/primitives/shadcn/alert-dialog/AlertDialogHeader.vue +17 -0
  283. package/src/primitives/shadcn/alert-dialog/AlertDialogTitle.vue +21 -0
  284. package/src/primitives/shadcn/alert-dialog/AlertDialogTrigger.vue +12 -0
  285. package/src/primitives/shadcn/alert-dialog/index.ts +9 -0
  286. package/src/primitives/shadcn/avatar/Avatar.vue +18 -0
  287. package/src/primitives/shadcn/avatar/AvatarFallback.vue +21 -0
  288. package/src/primitives/shadcn/avatar/AvatarImage.vue +12 -0
  289. package/src/primitives/shadcn/avatar/index.ts +3 -0
  290. package/src/primitives/shadcn/badge/Badge.vue +28 -0
  291. package/src/primitives/shadcn/badge/index.ts +24 -0
  292. package/src/primitives/shadcn/button/Button.vue +29 -0
  293. package/src/primitives/shadcn/button/index.ts +36 -0
  294. package/src/primitives/shadcn/calendar/Calendar.vue +206 -0
  295. package/src/primitives/shadcn/calendar/CalendarCell.vue +28 -0
  296. package/src/primitives/shadcn/calendar/CalendarCellTrigger.vue +44 -0
  297. package/src/primitives/shadcn/calendar/CalendarGrid.vue +23 -0
  298. package/src/primitives/shadcn/calendar/CalendarGridBody.vue +12 -0
  299. package/src/primitives/shadcn/calendar/CalendarGridHead.vue +13 -0
  300. package/src/primitives/shadcn/calendar/CalendarGridRow.vue +23 -0
  301. package/src/primitives/shadcn/calendar/CalendarHeadCell.vue +23 -0
  302. package/src/primitives/shadcn/calendar/CalendarHeader.vue +23 -0
  303. package/src/primitives/shadcn/calendar/CalendarHeading.vue +30 -0
  304. package/src/primitives/shadcn/calendar/CalendarNextButton.vue +33 -0
  305. package/src/primitives/shadcn/calendar/CalendarPrevButton.vue +33 -0
  306. package/src/primitives/shadcn/calendar/index.ts +14 -0
  307. package/src/primitives/shadcn/card/Card.vue +22 -0
  308. package/src/primitives/shadcn/card/CardAction.vue +17 -0
  309. package/src/primitives/shadcn/card/CardContent.vue +14 -0
  310. package/src/primitives/shadcn/card/CardDescription.vue +14 -0
  311. package/src/primitives/shadcn/card/CardFooter.vue +14 -0
  312. package/src/primitives/shadcn/card/CardHeader.vue +22 -0
  313. package/src/primitives/shadcn/card/CardTitle.vue +14 -0
  314. package/src/primitives/shadcn/card/index.ts +7 -0
  315. package/src/primitives/shadcn/checkbox/Checkbox.vue +38 -0
  316. package/src/primitives/shadcn/checkbox/index.ts +1 -0
  317. package/src/primitives/shadcn/drawer/Drawer.vue +15 -0
  318. package/src/primitives/shadcn/drawer/DrawerClose.vue +12 -0
  319. package/src/primitives/shadcn/drawer/DrawerContent.vue +52 -0
  320. package/src/primitives/shadcn/drawer/DrawerDescription.vue +20 -0
  321. package/src/primitives/shadcn/drawer/DrawerFooter.vue +17 -0
  322. package/src/primitives/shadcn/drawer/DrawerHeader.vue +17 -0
  323. package/src/primitives/shadcn/drawer/DrawerTitle.vue +20 -0
  324. package/src/primitives/shadcn/drawer/DrawerTrigger.vue +12 -0
  325. package/src/primitives/shadcn/drawer/index.ts +8 -0
  326. package/src/primitives/shadcn/dropdown-menu/DropdownMenu.vue +15 -0
  327. package/src/primitives/shadcn/dropdown-menu/DropdownMenuCheckboxItem.vue +41 -0
  328. package/src/primitives/shadcn/dropdown-menu/DropdownMenuContent.vue +40 -0
  329. package/src/primitives/shadcn/dropdown-menu/DropdownMenuGroup.vue +12 -0
  330. package/src/primitives/shadcn/dropdown-menu/DropdownMenuItem.vue +41 -0
  331. package/src/primitives/shadcn/dropdown-menu/DropdownMenuLabel.vue +25 -0
  332. package/src/primitives/shadcn/dropdown-menu/DropdownMenuRadioGroup.vue +15 -0
  333. package/src/primitives/shadcn/dropdown-menu/DropdownMenuRadioItem.vue +38 -0
  334. package/src/primitives/shadcn/dropdown-menu/DropdownMenuSeparator.vue +23 -0
  335. package/src/primitives/shadcn/dropdown-menu/DropdownMenuShortcut.vue +17 -0
  336. package/src/primitives/shadcn/dropdown-menu/DropdownMenuSub.vue +15 -0
  337. package/src/primitives/shadcn/dropdown-menu/DropdownMenuSubContent.vue +29 -0
  338. package/src/primitives/shadcn/dropdown-menu/DropdownMenuSubTrigger.vue +31 -0
  339. package/src/primitives/shadcn/dropdown-menu/DropdownMenuTrigger.vue +14 -0
  340. package/src/primitives/shadcn/dropdown-menu/index.ts +16 -0
  341. package/src/primitives/shadcn/field/Field.vue +22 -0
  342. package/src/primitives/shadcn/field/FieldContent.vue +17 -0
  343. package/src/primitives/shadcn/field/FieldDescription.vue +24 -0
  344. package/src/primitives/shadcn/field/FieldError.vue +69 -0
  345. package/src/primitives/shadcn/field/FieldGroup.vue +22 -0
  346. package/src/primitives/shadcn/field/FieldLabel.vue +28 -0
  347. package/src/primitives/shadcn/field/FieldLegend.vue +26 -0
  348. package/src/primitives/shadcn/field/FieldSeparator.vue +28 -0
  349. package/src/primitives/shadcn/field/FieldSet.vue +23 -0
  350. package/src/primitives/shadcn/field/FieldTitle.vue +22 -0
  351. package/src/primitives/shadcn/field/index.ts +39 -0
  352. package/src/primitives/shadcn/icon/Icon.vue +38 -0
  353. package/src/primitives/shadcn/icon/index.ts +1 -0
  354. package/src/primitives/shadcn/index.ts +3 -0
  355. package/src/primitives/shadcn/input/Input.vue +35 -0
  356. package/src/primitives/shadcn/input/index.ts +1 -0
  357. package/src/primitives/shadcn/label/Label.vue +28 -0
  358. package/src/primitives/shadcn/label/index.ts +1 -0
  359. package/src/primitives/shadcn/native-select/NativeSelect.vue +56 -0
  360. package/src/primitives/shadcn/native-select/NativeSelectOptGroup.vue +18 -0
  361. package/src/primitives/shadcn/native-select/NativeSelectOption.vue +18 -0
  362. package/src/primitives/shadcn/native-select/index.ts +3 -0
  363. package/src/primitives/shadcn/popover/Popover.vue +19 -0
  364. package/src/primitives/shadcn/popover/PopoverContent.vue +41 -0
  365. package/src/primitives/shadcn/popover/PopoverTrigger.vue +11 -0
  366. package/src/primitives/shadcn/popover/index.ts +4 -0
  367. package/src/primitives/shadcn/progress/Progress.vue +30 -0
  368. package/src/primitives/shadcn/progress/index.ts +1 -0
  369. package/src/primitives/shadcn/radio-group/RadioGroup.vue +25 -0
  370. package/src/primitives/shadcn/radio-group/RadioGroupItem.vue +38 -0
  371. package/src/primitives/shadcn/radio-group/index.ts +2 -0
  372. package/src/primitives/shadcn/range-calendar/RangeCalendar.vue +73 -0
  373. package/src/primitives/shadcn/range-calendar/RangeCalendarCell.vue +28 -0
  374. package/src/primitives/shadcn/range-calendar/RangeCalendarCellTrigger.vue +46 -0
  375. package/src/primitives/shadcn/range-calendar/RangeCalendarGrid.vue +23 -0
  376. package/src/primitives/shadcn/range-calendar/RangeCalendarGridBody.vue +12 -0
  377. package/src/primitives/shadcn/range-calendar/RangeCalendarGridHead.vue +12 -0
  378. package/src/primitives/shadcn/range-calendar/RangeCalendarGridRow.vue +23 -0
  379. package/src/primitives/shadcn/range-calendar/RangeCalendarHeadCell.vue +23 -0
  380. package/src/primitives/shadcn/range-calendar/RangeCalendarHeader.vue +23 -0
  381. package/src/primitives/shadcn/range-calendar/RangeCalendarHeading.vue +30 -0
  382. package/src/primitives/shadcn/range-calendar/RangeCalendarNextButton.vue +34 -0
  383. package/src/primitives/shadcn/range-calendar/RangeCalendarPrevButton.vue +34 -0
  384. package/src/primitives/shadcn/range-calendar/index.ts +12 -0
  385. package/src/primitives/shadcn/select/Select.vue +15 -0
  386. package/src/primitives/shadcn/select/SelectContent.vue +55 -0
  387. package/src/primitives/shadcn/select/SelectGroup.vue +12 -0
  388. package/src/primitives/shadcn/select/SelectItem.vue +39 -0
  389. package/src/primitives/shadcn/select/SelectItemText.vue +12 -0
  390. package/src/primitives/shadcn/select/SelectLabel.vue +17 -0
  391. package/src/primitives/shadcn/select/SelectScrollDownButton.vue +26 -0
  392. package/src/primitives/shadcn/select/SelectScrollUpButton.vue +26 -0
  393. package/src/primitives/shadcn/select/SelectSeparator.vue +19 -0
  394. package/src/primitives/shadcn/select/SelectTrigger.vue +37 -0
  395. package/src/primitives/shadcn/select/SelectValue.vue +12 -0
  396. package/src/primitives/shadcn/select/index.ts +11 -0
  397. package/src/primitives/shadcn/separator/Separator.vue +27 -0
  398. package/src/primitives/shadcn/separator/index.ts +1 -0
  399. package/src/primitives/shadcn/slider/Slider.vue +45 -0
  400. package/src/primitives/shadcn/slider/index.ts +1 -0
  401. package/src/primitives/shadcn/spinner/Spinner.vue +18 -0
  402. package/src/primitives/shadcn/spinner/index.ts +1 -0
  403. package/src/primitives/shadcn/switch/Switch.vue +40 -0
  404. package/src/primitives/shadcn/switch/index.ts +1 -0
  405. package/src/primitives/shadcn/table/Table.vue +16 -0
  406. package/src/primitives/shadcn/table/TableBody.vue +14 -0
  407. package/src/primitives/shadcn/table/TableCaption.vue +14 -0
  408. package/src/primitives/shadcn/table/TableCell.vue +26 -0
  409. package/src/primitives/shadcn/table/TableEmpty.vue +29 -0
  410. package/src/primitives/shadcn/table/TableFooter.vue +17 -0
  411. package/src/primitives/shadcn/table/TableHead.vue +28 -0
  412. package/src/primitives/shadcn/table/TableHeader.vue +14 -0
  413. package/src/primitives/shadcn/table/TableRow.vue +21 -0
  414. package/src/primitives/shadcn/table/index.ts +9 -0
  415. package/src/primitives/shadcn/table/utils.ts +8 -0
  416. package/src/primitives/shadcn/tabs/Tabs.vue +24 -0
  417. package/src/primitives/shadcn/tabs/TabsContent.vue +21 -0
  418. package/src/primitives/shadcn/tabs/TabsList.vue +26 -0
  419. package/src/primitives/shadcn/tabs/TabsTrigger.vue +28 -0
  420. package/src/primitives/shadcn/tabs/index.ts +4 -0
  421. package/src/primitives/shadcn/textarea/Textarea.vue +33 -0
  422. package/src/primitives/shadcn/textarea/index.ts +1 -0
  423. package/src/primitives/shadcn/tooltip/Tooltip.vue +15 -0
  424. package/src/primitives/shadcn/tooltip/TooltipContent.vue +40 -0
  425. package/src/primitives/shadcn/tooltip/TooltipProvider.vue +12 -0
  426. package/src/primitives/shadcn/tooltip/TooltipTrigger.vue +12 -0
  427. package/src/primitives/shadcn/tooltip/index.ts +4 -0
  428. package/src/styles/global.css +1 -0
  429. package/src/templates/UiTemplatePlaceholder/UiTemplatePlaceholder.vue +9 -0
  430. package/src/templates/UiTemplatePlaceholder/index.ts +1 -0
  431. package/src/templates/UiTemplatePlaceholder/types.ts +8 -0
  432. package/src/templates/index.ts +6 -0
@@ -0,0 +1,446 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3-vite';
2
+ import UiIconButton from './UiIconButton.vue';
3
+ import { UiIcon } from '../UiIcon';
4
+
5
+ const meta: Meta<typeof UiIconButton> = {
6
+ title: 'Primitives/UiIconButton',
7
+ component: UiIconButton,
8
+ tags: ['autodocs'],
9
+ argTypes: {
10
+ variant: {
11
+ control: 'select',
12
+ options: ['default', 'destructive', 'outline', 'secondary', 'ghost', 'link'],
13
+ description: 'The visual style of the button',
14
+ },
15
+ size: {
16
+ control: 'select',
17
+ options: ['icon', 'icon-sm', 'icon-lg'],
18
+ description: 'The size of the icon button',
19
+ },
20
+ asChild: {
21
+ control: 'boolean',
22
+ description: 'Whether to render as a child (Slot) instead of a wrapper element',
23
+ },
24
+ ariaLabel: {
25
+ control: 'text',
26
+ description: 'Accessible label (required for icon buttons)',
27
+ },
28
+ disabled: {
29
+ control: 'boolean',
30
+ description: 'Disables the button',
31
+ },
32
+ loading: {
33
+ control: 'boolean',
34
+ description: 'Shows a loading state and prevents interaction',
35
+ },
36
+ },
37
+ args: {
38
+ variant: 'default',
39
+ size: 'icon',
40
+ asChild: false,
41
+ ariaLabel: 'Icon button',
42
+ disabled: false,
43
+ loading: false,
44
+ },
45
+ };
46
+
47
+ export default meta;
48
+
49
+ type Story = StoryObj<typeof UiIconButton>;
50
+
51
+ const defaultTemplateSource = `<script setup lang="ts">
52
+ import { UiIconButton, UiIcon } from '@aleph-alpha/ui-library'
53
+ </script>
54
+
55
+ <template>
56
+ <UiIconButton aria-label="Next">
57
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
58
+ </UiIconButton>
59
+ </template>`;
60
+
61
+ /**
62
+ * Default icon button.
63
+ */
64
+ export const Default: Story = {
65
+ render: (args) => ({
66
+ components: { UiIconButton, UiIcon },
67
+ setup() {
68
+ return { args };
69
+ },
70
+ template: `<UiIconButton :variant="args.variant" :size="args.size" :disabled="args.disabled" :loading="args.loading" :aria-label="args.ariaLabel">
71
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
72
+ </UiIconButton>`,
73
+ }),
74
+ parameters: {
75
+ docs: {
76
+ source: {
77
+ code: defaultTemplateSource,
78
+ },
79
+ },
80
+ },
81
+ };
82
+
83
+ const secondaryTemplateSource = `<script setup lang="ts">
84
+ import { UiIconButton, UiIcon } from '@aleph-alpha/ui-library'
85
+ </script>
86
+
87
+ <template>
88
+ <UiIconButton variant="secondary" aria-label="Next">
89
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
90
+ </UiIconButton>
91
+ </template>`;
92
+
93
+ /**
94
+ * Secondary icon button variant.
95
+ */
96
+ export const Secondary: Story = {
97
+ render: () => ({
98
+ components: { UiIconButton, UiIcon },
99
+ template: `<UiIconButton variant="secondary" aria-label="Next">
100
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
101
+ </UiIconButton>`,
102
+ }),
103
+ parameters: {
104
+ docs: {
105
+ source: {
106
+ code: secondaryTemplateSource,
107
+ },
108
+ },
109
+ },
110
+ };
111
+
112
+ const destructiveTemplateSource = `<script setup lang="ts">
113
+ import { UiIconButton, UiIcon } from '@aleph-alpha/ui-library'
114
+ </script>
115
+
116
+ <template>
117
+ <UiIconButton variant="destructive" aria-label="Delete">
118
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
119
+ </UiIconButton>
120
+ </template>`;
121
+
122
+ /**
123
+ * Destructive icon button variant.
124
+ */
125
+ export const Destructive: Story = {
126
+ render: () => ({
127
+ components: { UiIconButton, UiIcon },
128
+ template: `<UiIconButton variant="destructive" aria-label="Delete">
129
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
130
+ </UiIconButton>`,
131
+ }),
132
+ parameters: {
133
+ docs: {
134
+ source: {
135
+ code: destructiveTemplateSource,
136
+ },
137
+ },
138
+ },
139
+ };
140
+
141
+ const outlineTemplateSource = `<script setup lang="ts">
142
+ import { UiIconButton, UiIcon } from '@aleph-alpha/ui-library'
143
+ </script>
144
+
145
+ <template>
146
+ <UiIconButton variant="outline" aria-label="Next">
147
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
148
+ </UiIconButton>
149
+ </template>`;
150
+
151
+ /**
152
+ * Outline icon button variant.
153
+ */
154
+ export const Outline: Story = {
155
+ render: () => ({
156
+ components: { UiIconButton, UiIcon },
157
+ template: `<UiIconButton variant="outline" aria-label="Next">
158
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
159
+ </UiIconButton>`,
160
+ }),
161
+ parameters: {
162
+ docs: {
163
+ source: {
164
+ code: outlineTemplateSource,
165
+ },
166
+ },
167
+ },
168
+ };
169
+
170
+ const ghostTemplateSource = `<script setup lang="ts">
171
+ import { UiIconButton, UiIcon } from '@aleph-alpha/ui-library'
172
+ </script>
173
+
174
+ <template>
175
+ <UiIconButton variant="ghost" aria-label="Next">
176
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
177
+ </UiIconButton>
178
+ </template>`;
179
+
180
+ /**
181
+ * Ghost icon button variant.
182
+ */
183
+ export const Ghost: Story = {
184
+ render: () => ({
185
+ components: { UiIconButton, UiIcon },
186
+ template: `<UiIconButton variant="ghost" aria-label="Next">
187
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
188
+ </UiIconButton>`,
189
+ }),
190
+ parameters: {
191
+ docs: {
192
+ source: {
193
+ code: ghostTemplateSource,
194
+ },
195
+ },
196
+ },
197
+ };
198
+
199
+ const linkTemplateSource = `<script setup lang="ts">
200
+ import { UiIconButton, UiIcon } from '@aleph-alpha/ui-library'
201
+ </script>
202
+
203
+ <template>
204
+ <UiIconButton variant="link" aria-label="Next">
205
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
206
+ </UiIconButton>
207
+ </template>`;
208
+
209
+ /**
210
+ * Link icon button variant.
211
+ */
212
+ export const Link: Story = {
213
+ render: () => ({
214
+ components: { UiIconButton, UiIcon },
215
+ template: `<UiIconButton variant="link" aria-label="Next">
216
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
217
+ </UiIconButton>`,
218
+ }),
219
+ parameters: {
220
+ docs: {
221
+ source: {
222
+ code: linkTemplateSource,
223
+ },
224
+ },
225
+ },
226
+ };
227
+
228
+ const loadingTemplateSource = `<script setup lang="ts">
229
+ import { UiIconButton, UiIcon } from '@aleph-alpha/ui-library'
230
+ </script>
231
+
232
+ <template>
233
+ <UiIconButton :loading="true" aria-label="Loading">
234
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
235
+ </UiIconButton>
236
+ </template>`;
237
+
238
+ /**
239
+ * Loading state shows a spinner.
240
+ */
241
+ export const Loading: Story = {
242
+ render: () => ({
243
+ components: { UiIconButton, UiIcon },
244
+ template: `<UiIconButton :loading="true" aria-label="Loading">
245
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
246
+ </UiIconButton>`,
247
+ }),
248
+ parameters: {
249
+ docs: {
250
+ source: {
251
+ code: loadingTemplateSource,
252
+ },
253
+ },
254
+ },
255
+ };
256
+
257
+ const disabledTemplateSource = `<script setup lang="ts">
258
+ import { UiIconButton, UiIcon } from '@aleph-alpha/ui-library'
259
+ </script>
260
+
261
+ <template>
262
+ <UiIconButton :disabled="true" aria-label="Disabled">
263
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
264
+ </UiIconButton>
265
+ </template>`;
266
+
267
+ /**
268
+ * Disabled state.
269
+ */
270
+ export const Disabled: Story = {
271
+ render: () => ({
272
+ components: { UiIconButton, UiIcon },
273
+ template: `<UiIconButton :disabled="true" aria-label="Disabled">
274
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
275
+ </UiIconButton>`,
276
+ }),
277
+ parameters: {
278
+ docs: {
279
+ source: {
280
+ code: disabledTemplateSource,
281
+ },
282
+ },
283
+ },
284
+ };
285
+
286
+ const allVariantsTemplateSource = `<script setup lang="ts">
287
+ import { UiIconButton, UiIcon } from '@aleph-alpha/ui-library'
288
+ </script>
289
+
290
+ <template>
291
+ <div class="flex flex-wrap items-center gap-4">
292
+ <UiIconButton variant="default" aria-label="Default">
293
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
294
+ </UiIconButton>
295
+ <UiIconButton variant="secondary" aria-label="Secondary">
296
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
297
+ </UiIconButton>
298
+ <UiIconButton variant="destructive" aria-label="Destructive">
299
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
300
+ </UiIconButton>
301
+ <UiIconButton variant="outline" aria-label="Outline">
302
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
303
+ </UiIconButton>
304
+ <UiIconButton variant="ghost" aria-label="Ghost">
305
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
306
+ </UiIconButton>
307
+ <UiIconButton variant="link" aria-label="Link">
308
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
309
+ </UiIconButton>
310
+ </div>
311
+ </template>`;
312
+
313
+ /**
314
+ * All icon button variants side by side.
315
+ */
316
+ export const AllVariants: Story = {
317
+ render: () => ({
318
+ components: { UiIconButton, UiIcon },
319
+ template: `<div class="flex flex-wrap items-center gap-4">
320
+ <UiIconButton variant="default" aria-label="Default">
321
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
322
+ </UiIconButton>
323
+ <UiIconButton variant="secondary" aria-label="Secondary">
324
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
325
+ </UiIconButton>
326
+ <UiIconButton variant="destructive" aria-label="Destructive">
327
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
328
+ </UiIconButton>
329
+ <UiIconButton variant="outline" aria-label="Outline">
330
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
331
+ </UiIconButton>
332
+ <UiIconButton variant="ghost" aria-label="Ghost">
333
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
334
+ </UiIconButton>
335
+ <UiIconButton variant="link" aria-label="Link">
336
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
337
+ </UiIconButton>
338
+ </div>`,
339
+ }),
340
+ parameters: {
341
+ docs: {
342
+ source: {
343
+ code: allVariantsTemplateSource,
344
+ },
345
+ },
346
+ },
347
+ };
348
+
349
+ const allSizesTemplateSource = `<script setup lang="ts">
350
+ import { UiIconButton, UiIcon } from '@aleph-alpha/ui-library'
351
+ </script>
352
+
353
+ <template>
354
+ <div class="flex flex-wrap items-end gap-4">
355
+ <div class="flex flex-col items-center gap-2">
356
+ <span class="text-muted-foreground text-xs">icon-sm</span>
357
+ <UiIconButton size="icon-sm" variant="outline" aria-label="Small Icon">
358
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
359
+ </UiIconButton>
360
+ </div>
361
+ <div class="flex flex-col items-center gap-2">
362
+ <span class="text-muted-foreground text-xs">icon</span>
363
+ <UiIconButton size="icon" variant="outline" aria-label="Default Icon">
364
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
365
+ </UiIconButton>
366
+ </div>
367
+ <div class="flex flex-col items-center gap-2">
368
+ <span class="text-muted-foreground text-xs">icon-lg</span>
369
+ <UiIconButton size="icon-lg" variant="outline" aria-label="Large Icon">
370
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-5" />
371
+ </UiIconButton>
372
+ </div>
373
+ </div>
374
+ </template>`;
375
+
376
+ /**
377
+ * All icon button sizes.
378
+ */
379
+ export const AllSizes: Story = {
380
+ render: () => ({
381
+ components: { UiIconButton, UiIcon },
382
+ template: `<div class="flex flex-wrap items-end gap-4">
383
+ <div class="flex flex-col items-center gap-2">
384
+ <span class="text-muted-foreground text-xs">icon-sm</span>
385
+ <UiIconButton size="icon-sm" variant="outline" aria-label="Small Icon">
386
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
387
+ </UiIconButton>
388
+ </div>
389
+ <div class="flex flex-col items-center gap-2">
390
+ <span class="text-muted-foreground text-xs">icon</span>
391
+ <UiIconButton size="icon" variant="outline" aria-label="Default Icon">
392
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
393
+ </UiIconButton>
394
+ </div>
395
+ <div class="flex flex-col items-center gap-2">
396
+ <span class="text-muted-foreground text-xs">icon-lg</span>
397
+ <UiIconButton size="icon-lg" variant="outline" aria-label="Large Icon">
398
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-5" />
399
+ </UiIconButton>
400
+ </div>
401
+ </div>`,
402
+ }),
403
+ parameters: {
404
+ docs: {
405
+ source: {
406
+ code: allSizesTemplateSource,
407
+ },
408
+ },
409
+ },
410
+ };
411
+
412
+ const asChildTemplateSource = `<script setup lang="ts">
413
+ import { UiIconButton, UiIcon } from '@aleph-alpha/ui-library'
414
+ </script>
415
+
416
+ <template>
417
+ <UiIconButton :as-child="true" aria-label="Navigate">
418
+ <a href="#">
419
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
420
+ </a>
421
+ </UiIconButton>
422
+ </template>`;
423
+
424
+ /**
425
+ * Use `as-child` to render icon button styling on a link or custom element.
426
+ * Perfect for navigation arrows, external link icons, or router integration.
427
+ *
428
+ * **Note:** The `aria-label` is still required for accessibility even when using `as-child`.
429
+ */
430
+ export const AsChild: Story = {
431
+ render: () => ({
432
+ components: { UiIconButton, UiIcon },
433
+ template: `<UiIconButton :as-child="true" aria-label="Navigate">
434
+ <a href="#">
435
+ <UiIcon icon="i-material-symbols-chevron-right" class="size-4" />
436
+ </a>
437
+ </UiIconButton>`,
438
+ }),
439
+ parameters: {
440
+ docs: {
441
+ source: {
442
+ code: asChildTemplateSource,
443
+ },
444
+ },
445
+ },
446
+ };
@@ -0,0 +1,63 @@
1
+ <script setup lang="ts">
2
+ import { Button as ShadcnButton } from '@/primitives/shadcn/button';
3
+ import { UiSpinner } from '@/primitives/UiSpinner';
4
+ import { computed } from 'vue';
5
+ import type { UiIconButtonProps, UiIconButtonVariant } from './types';
6
+
7
+ defineOptions({
8
+ name: 'UiIconButton',
9
+ });
10
+
11
+ const props = withDefaults(defineProps<UiIconButtonProps>(), {
12
+ variant: 'default',
13
+ size: 'icon',
14
+ asChild: false,
15
+ type: 'button',
16
+ disabled: false,
17
+ loading: false,
18
+ });
19
+
20
+ const variantMap: Record<
21
+ UiIconButtonVariant,
22
+ 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link'
23
+ > = {
24
+ default: 'default',
25
+ destructive: 'destructive',
26
+ outline: 'outline',
27
+ secondary: 'secondary',
28
+ ghost: 'ghost',
29
+ link: 'link',
30
+ };
31
+
32
+ const sizeMap: Record<'icon' | 'icon-sm' | 'icon-lg', 'icon' | 'icon-sm' | 'icon-lg'> = {
33
+ icon: 'icon',
34
+ 'icon-sm': 'icon-sm',
35
+ 'icon-lg': 'icon-lg',
36
+ };
37
+
38
+ const isDisabled = computed(() => props.disabled || props.loading);
39
+
40
+ function handleClick(e: MouseEvent) {
41
+ if (isDisabled.value) {
42
+ e.preventDefault();
43
+ e.stopPropagation();
44
+ }
45
+ }
46
+ </script>
47
+
48
+ <template>
49
+ <ShadcnButton
50
+ :variant="variantMap[props.variant]"
51
+ :size="sizeMap[props.size]"
52
+ :aria-label="props.ariaLabel"
53
+ :as-child="props.asChild"
54
+ :type="props.type"
55
+ :disabled="isDisabled"
56
+ :aria-busy="props.loading ? 'true' : undefined"
57
+ @click="handleClick"
58
+ >
59
+ <!-- Spinner when loading and not using asChild -->
60
+ <UiSpinner v-if="props.loading && !props.asChild" aria-label="Loading" />
61
+ <slot v-else />
62
+ </ShadcnButton>
63
+ </template>
@@ -0,0 +1,102 @@
1
+ import { render } from '@testing-library/vue';
2
+ import userEvent from '@testing-library/user-event';
3
+ import { describe, expect, test } from 'vitest';
4
+ import { defineComponent, h, markRaw } from 'vue';
5
+ import UiIconButton from '../UiIconButton.vue';
6
+
7
+ // Mock icon component for testing slot content
8
+ const MockIcon = markRaw(
9
+ defineComponent({
10
+ name: 'MockIcon',
11
+ template: '<svg data-testid="mock-icon" aria-hidden="true" />',
12
+ }),
13
+ );
14
+
15
+ describe('UiIconButton', () => {
16
+ test('renders with icon, type="button", and required aria-label', () => {
17
+ const { getByRole, getByTestId } = render(UiIconButton, {
18
+ props: { ariaLabel: 'Delete item' },
19
+ slots: { default: () => h(MockIcon) },
20
+ });
21
+ const button = getByRole('button');
22
+ expect(button).toHaveAttribute('type', 'button');
23
+ expect(button).toHaveAttribute('aria-label', 'Delete item');
24
+ expect(getByTestId('mock-icon')).toBeInTheDocument();
25
+ });
26
+
27
+ describe('Variants (contract test)', () => {
28
+ const variants = ['default', 'destructive', 'outline', 'secondary', 'ghost', 'link'] as const;
29
+
30
+ test.each(variants)('accepts variant="%s"', (variant) => {
31
+ const { getByRole } = render(UiIconButton, {
32
+ props: { ariaLabel: 'Icon', variant },
33
+ slots: { default: '🔍' },
34
+ });
35
+ expect(getByRole('button')).toBeInTheDocument();
36
+ });
37
+ });
38
+
39
+ describe('Sizes (contract test)', () => {
40
+ const sizes = ['icon', 'icon-sm', 'icon-lg'] as const;
41
+
42
+ test.each(sizes)('accepts size="%s"', (size) => {
43
+ const { getByRole } = render(UiIconButton, {
44
+ props: { ariaLabel: 'Icon', size },
45
+ slots: { default: '🔍' },
46
+ });
47
+ expect(getByRole('button')).toBeInTheDocument();
48
+ });
49
+ });
50
+
51
+ test('emits click event when clicked', async () => {
52
+ const user = userEvent.setup();
53
+ const { getByRole, emitted } = render(UiIconButton, {
54
+ props: { ariaLabel: 'Click me' },
55
+ slots: { default: '🔍' },
56
+ });
57
+
58
+ await user.click(getByRole('button'));
59
+
60
+ expect(emitted('click')).toHaveLength(1);
61
+ });
62
+
63
+ test('is disabled when disabled prop is true', () => {
64
+ const { getByRole } = render(UiIconButton, {
65
+ props: { ariaLabel: 'Test', disabled: true },
66
+ slots: { default: '🔍' },
67
+ });
68
+ expect(getByRole('button')).toBeDisabled();
69
+ });
70
+
71
+ describe('Loading State', () => {
72
+ test('is disabled with aria-busy and shows spinner when loading', () => {
73
+ const { getByRole, getByLabelText, queryByTestId } = render(UiIconButton, {
74
+ props: { ariaLabel: 'Test', loading: true },
75
+ slots: { default: () => h(MockIcon) },
76
+ });
77
+ const button = getByRole('button');
78
+ expect(button).toBeDisabled();
79
+ expect(button).toHaveAttribute('aria-busy', 'true');
80
+ expect(getByLabelText('Loading')).toBeInTheDocument();
81
+ expect(queryByTestId('mock-icon')).not.toBeInTheDocument();
82
+ });
83
+
84
+ test('does not show spinner in asChild mode when loading', () => {
85
+ const { queryByLabelText } = render(UiIconButton, {
86
+ props: { ariaLabel: 'Test', loading: true, asChild: true },
87
+ slots: { default: '🔍' },
88
+ });
89
+ expect(queryByLabelText('Loading')).not.toBeInTheDocument();
90
+ });
91
+ });
92
+
93
+ describe('asChild Mode', () => {
94
+ test('shows slot content even when loading in asChild mode', () => {
95
+ const { getByTestId } = render(UiIconButton, {
96
+ props: { ariaLabel: 'Test', asChild: true, loading: true },
97
+ slots: { default: () => h(MockIcon) },
98
+ });
99
+ expect(getByTestId('mock-icon')).toBeInTheDocument();
100
+ });
101
+ });
102
+ });
@@ -0,0 +1,2 @@
1
+ export { default as UiIconButton } from './UiIconButton.vue';
2
+ export type { UiIconButtonProps, UiIconButtonVariant, UiIconButtonSize } from './types';
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Visual style variants for UiIconButton.
3
+ */
4
+ export type UiIconButtonVariant =
5
+ | 'default'
6
+ | 'destructive'
7
+ | 'outline'
8
+ | 'secondary'
9
+ | 'ghost'
10
+ | 'link';
11
+
12
+ /**
13
+ * Size variants for UiIconButton.
14
+ */
15
+ export type UiIconButtonSize = 'icon' | 'icon-sm' | 'icon-lg';
16
+
17
+ /**
18
+ * A button that displays only an icon without text. Use for compact
19
+ * actions like close, edit, delete, or toolbar buttons.
20
+ *
21
+ * @category Actions
22
+ * @useCases close button, edit action, toolbar button, compact action
23
+ * @keywords iconbutton, icon, button, action, close, edit, delete
24
+ * @related UiButton, UiIcon
25
+ */
26
+ export interface UiIconButtonProps {
27
+ /**
28
+ * The visual style of the button.
29
+ * @default 'default'
30
+ */
31
+ variant?: UiIconButtonVariant;
32
+
33
+ /**
34
+ * The size of the icon button.
35
+ * @default 'icon'
36
+ */
37
+ size?: UiIconButtonSize;
38
+
39
+ /**
40
+ * Whether to render as a child (Slot) instead of a wrapper element.
41
+ * Useful for tooltips or wrapping other components.
42
+ * @default false
43
+ */
44
+ asChild?: boolean;
45
+
46
+ /**
47
+ * The native button type.
48
+ * @default 'button'
49
+ */
50
+ type?: 'button' | 'submit' | 'reset';
51
+
52
+ /**
53
+ * Disables the button.
54
+ */
55
+ disabled?: boolean;
56
+
57
+ /**
58
+ * Shows a loading state and prevents interaction.
59
+ */
60
+ loading?: boolean;
61
+
62
+ /**
63
+ * Accessible label for the button.
64
+ * **REQUIRED** because the button renders only an icon (no visible text).
65
+ */
66
+ ariaLabel: string;
67
+ }