@meistrari/tela-build 1.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 (295) hide show
  1. package/README.md +75 -0
  2. package/app.config.ts +73 -0
  3. package/components/tela/animated/animated-calculating-number.vue +16 -0
  4. package/components/tela/animated/animated-number.mdx +248 -0
  5. package/components/tela/animated/animated-number.stories.ts +52 -0
  6. package/components/tela/animated/animated-number.vue +23 -0
  7. package/components/tela/animated/animated-text.vue +124 -0
  8. package/components/tela/animated/animated-value.vue +68 -0
  9. package/components/tela/avatar/avatar.mdx +117 -0
  10. package/components/tela/avatar/avatar.stories.ts +62 -0
  11. package/components/tela/avatar/avatar.vue +71 -0
  12. package/components/tela/avatar/group/avatar-group.stories.ts +78 -0
  13. package/components/tela/avatar/group/avatar-group.vue +46 -0
  14. package/components/tela/badge/badge.mdx +154 -0
  15. package/components/tela/badge/badge.stories.ts +82 -0
  16. package/components/tela/badge/badge.vue +41 -0
  17. package/components/tela/button/button.mdx +155 -0
  18. package/components/tela/button/button.stories.ts +202 -0
  19. package/components/tela/button/button.vue +107 -0
  20. package/components/tela/card.vue +30 -0
  21. package/components/tela/chart/chart-bar.vue +58 -0
  22. package/components/tela/chat/chat.mdx +268 -0
  23. package/components/tela/chat/chat.stories.ts +253 -0
  24. package/components/tela/chat/command/index.vue +41 -0
  25. package/components/tela/chat/command/mention/index.vue +138 -0
  26. package/components/tela/chat/index.vue +112 -0
  27. package/components/tela/chat/pure-text-input/chat-text-input.vue +190 -0
  28. package/components/tela/chat/text-input/chat-text-input.stories.ts +128 -0
  29. package/components/tela/chat/text-input/index.vue +217 -0
  30. package/components/tela/chat/text-message/chat-text-message.stories.ts +138 -0
  31. package/components/tela/chat/text-message/index.vue +355 -0
  32. package/components/tela/chat/types.ts +19 -0
  33. package/components/tela/checkbox/checkbox-card.vue +30 -0
  34. package/components/tela/checkbox/checkbox.mdx +164 -0
  35. package/components/tela/checkbox/checkbox.stories.ts +104 -0
  36. package/components/tela/checkbox/checkbox.vue +43 -0
  37. package/components/tela/collapsible/Collapsible.vue +15 -0
  38. package/components/tela/collapsible/CollapsibleContent.vue +59 -0
  39. package/components/tela/collapsible/CollapsibleTrigger.vue +12 -0
  40. package/components/tela/collapsible/collapsible.mdx +157 -0
  41. package/components/tela/collapsible-section/collapsible-section.mdx +180 -0
  42. package/components/tela/collapsible-section/collapsible-section.stories.ts +53 -0
  43. package/components/tela/collapsible-section/collapsible-section.vue +51 -0
  44. package/components/tela/collapsible-section-with-actions.vue +98 -0
  45. package/components/tela/combobox/combobox-anchor.vue +24 -0
  46. package/components/tela/combobox/combobox-empty.vue +19 -0
  47. package/components/tela/combobox/combobox-group.vue +24 -0
  48. package/components/tela/combobox/combobox-indicator.vue +22 -0
  49. package/components/tela/combobox/combobox-input.vue +31 -0
  50. package/components/tela/combobox/combobox-item.vue +28 -0
  51. package/components/tela/combobox/combobox-label.vue +24 -0
  52. package/components/tela/combobox/combobox-list.vue +90 -0
  53. package/components/tela/combobox/combobox-module-selector.vue +366 -0
  54. package/components/tela/combobox/combobox-root.vue +15 -0
  55. package/components/tela/combobox/combobox-trigger.vue +12 -0
  56. package/components/tela/combobox/combobox.mdx +285 -0
  57. package/components/tela/combobox/combobox.stories.ts +232 -0
  58. package/components/tela/combobox/combobox.vue +497 -0
  59. package/components/tela/command/command-dialog.vue +22 -0
  60. package/components/tela/command/command-empty.vue +25 -0
  61. package/components/tela/command/command-group.vue +46 -0
  62. package/components/tela/command/command-input.vue +38 -0
  63. package/components/tela/command/command-item.vue +78 -0
  64. package/components/tela/command/command-list.vue +78 -0
  65. package/components/tela/command/command-separator.vue +23 -0
  66. package/components/tela/command/command-shortcut.vue +13 -0
  67. package/components/tela/command/command.vue +88 -0
  68. package/components/tela/command/dialog-base.vue +15 -0
  69. package/components/tela/command/dialog-content.vue +50 -0
  70. package/components/tela/command/utils.ts +15 -0
  71. package/components/tela/complex-table/complex-table-cell.stories.ts +145 -0
  72. package/components/tela/complex-table/complex-table-cell.vue +45 -0
  73. package/components/tela/complex-table/complex-table-header-cell.stories.ts +103 -0
  74. package/components/tela/complex-table/complex-table-header-cell.vue +48 -0
  75. package/components/tela/complex-table/complex-table-header.stories.ts +89 -0
  76. package/components/tela/complex-table/complex-table-header.vue +70 -0
  77. package/components/tela/complex-table/complex-table-row.vue +199 -0
  78. package/components/tela/complex-table/complex-table-virtualized.vue +326 -0
  79. package/components/tela/complex-table/complex-table.stories.ts +358 -0
  80. package/components/tela/complex-table/complex-table.vue +237 -0
  81. package/components/tela/complex-table/composables/table-common.ts +93 -0
  82. package/components/tela/complex-table/composables/table-selection.ts +87 -0
  83. package/components/tela/complex-table/composables/virtual-scroll.ts +252 -0
  84. package/components/tela/complex-table/styles/table-shared.css +170 -0
  85. package/components/tela/complex-table/types.ts +63 -0
  86. package/components/tela/complex-table/utils.ts +35 -0
  87. package/components/tela/confirm-button/confirm-button.vue +137 -0
  88. package/components/tela/confirmation-modal/confirmation-modal.vue +72 -0
  89. package/components/tela/copy-button.vue +86 -0
  90. package/components/tela/date-range-picker.vue +221 -0
  91. package/components/tela/dialog/dialog.mdx +170 -0
  92. package/components/tela/dialog/dialog.vue +182 -0
  93. package/components/tela/disabled-area.vue +16 -0
  94. package/components/tela/disclaimer/disclaimer.mdx +238 -0
  95. package/components/tela/disclaimer/disclaimer.stories.ts +196 -0
  96. package/components/tela/disclaimer/disclaimer.vue +125 -0
  97. package/components/tela/dropdown-menu/DropdownMenu.vue +121 -0
  98. package/components/tela/dropdown-menu/DropdownMenuCheckboxItem.vue +40 -0
  99. package/components/tela/dropdown-menu/DropdownMenuContent.vue +75 -0
  100. package/components/tela/dropdown-menu/DropdownMenuGroup.vue +12 -0
  101. package/components/tela/dropdown-menu/DropdownMenuItem.vue +137 -0
  102. package/components/tela/dropdown-menu/DropdownMenuLabel.vue +26 -0
  103. package/components/tela/dropdown-menu/DropdownMenuRadioGroup.vue +18 -0
  104. package/components/tela/dropdown-menu/DropdownMenuRadioItem.vue +40 -0
  105. package/components/tela/dropdown-menu/DropdownMenuRoot.vue +15 -0
  106. package/components/tela/dropdown-menu/DropdownMenuSeparator.vue +21 -0
  107. package/components/tela/dropdown-menu/DropdownMenuShortcut.vue +14 -0
  108. package/components/tela/dropdown-menu/DropdownMenuSub.vue +18 -0
  109. package/components/tela/dropdown-menu/DropdownMenuSubContent.vue +30 -0
  110. package/components/tela/dropdown-menu/DropdownMenuSubTrigger.vue +35 -0
  111. package/components/tela/dropdown-menu/DropdownMenuTrigger.vue +14 -0
  112. package/components/tela/dropdown-menu/dropdown-menu.mdx +265 -0
  113. package/components/tela/dropdown-menu/dropdown-menu.stories.ts +156 -0
  114. package/components/tela/expandable-input.vue +96 -0
  115. package/components/tela/file-drop.vue +37 -0
  116. package/components/tela/file-upload/file-upload.mdx +189 -0
  117. package/components/tela/file-upload/file-upload.stories.ts +48 -0
  118. package/components/tela/file-upload/file-upload.vue +205 -0
  119. package/components/tela/filters/checkbox-filter.stories.ts +218 -0
  120. package/components/tela/filters/checkbox-filter.vue +165 -0
  121. package/components/tela/filters/date-filter.stories.ts +258 -0
  122. package/components/tela/filters/date-filter.vue +200 -0
  123. package/components/tela/filters/user-filter.stories.ts +344 -0
  124. package/components/tela/filters/user-filter.vue +271 -0
  125. package/components/tela/hover-card/hover-card.mdx +221 -0
  126. package/components/tela/hover-card/hover-card.stories.ts +87 -0
  127. package/components/tela/hover-card/hover-card.vue +61 -0
  128. package/components/tela/icon/custom.vue +319 -0
  129. package/components/tela/icon/spinner.vue +12 -0
  130. package/components/tela/icon-button/icon-button.vue +114 -0
  131. package/components/tela/icon.vue +37 -0
  132. package/components/tela/initials.vue +28 -0
  133. package/components/tela/inline-input.vue +77 -0
  134. package/components/tela/input/input.mdx +182 -0
  135. package/components/tela/input/input.stories.ts +153 -0
  136. package/components/tela/input/tela-input.vue +240 -0
  137. package/components/tela/kbd/kbd-return.vue +6 -0
  138. package/components/tela/kbd/kbd.mdx +238 -0
  139. package/components/tela/kbd/kbd.vue +18 -0
  140. package/components/tela/label/label.mdx +121 -0
  141. package/components/tela/label/label.stories.ts +37 -0
  142. package/components/tela/label/label.vue +25 -0
  143. package/components/tela/link-decoration/link-decoration.vue +19 -0
  144. package/components/tela/live-label.vue +32 -0
  145. package/components/tela/long-press-button.vue +98 -0
  146. package/components/tela/menubar/menubar-content.vue +77 -0
  147. package/components/tela/menubar/menubar-item.vue +32 -0
  148. package/components/tela/menubar/menubar-label.vue +14 -0
  149. package/components/tela/menubar/menubar-menu.vue +12 -0
  150. package/components/tela/menubar/menubar-root.vue +30 -0
  151. package/components/tela/menubar/menubar-separator.vue +17 -0
  152. package/components/tela/menubar/menubar-shortcut.vue +14 -0
  153. package/components/tela/menubar/menubar-sub-content.vue +36 -0
  154. package/components/tela/menubar/menubar-sub-trigger.vue +28 -0
  155. package/components/tela/menubar/menubar-sub.vue +20 -0
  156. package/components/tela/menubar/menubar-trigger.vue +27 -0
  157. package/components/tela/menubar/menubar.vue +298 -0
  158. package/components/tela/modal/modal.mdx +145 -0
  159. package/components/tela/modal/modal.vue +242 -0
  160. package/components/tela/multiple-select/multiple-select.mdx +274 -0
  161. package/components/tela/multiple-select/multiple-select.stories.ts +325 -0
  162. package/components/tela/multiple-select/multiple-select.vue +666 -0
  163. package/components/tela/pane.vue +110 -0
  164. package/components/tela/popover/popover-content.vue +48 -0
  165. package/components/tela/popover/popover-trigger.vue +12 -0
  166. package/components/tela/popover/popover.mdx +239 -0
  167. package/components/tela/popover/popover.stories.ts +150 -0
  168. package/components/tela/popover/popover.vue +15 -0
  169. package/components/tela/popover-list/popover-list-nested.vue +104 -0
  170. package/components/tela/popover-list/popover-list.stories.ts +330 -0
  171. package/components/tela/popover-list/popover-list.vue +191 -0
  172. package/components/tela/radio-button.vue +66 -0
  173. package/components/tela/radio-group/radio-group-item.vue +40 -0
  174. package/components/tela/radio-group/radio-group-root.vue +26 -0
  175. package/components/tela/radio-group/radio-group.mdx +78 -0
  176. package/components/tela/radio-group/radio-group.stories.ts +106 -0
  177. package/components/tela/radio-group/radio-group.vue +23 -0
  178. package/components/tela/range-calendar.stories.ts +110 -0
  179. package/components/tela/range-calendar.vue +109 -0
  180. package/components/tela/scroll-area/scroll-area.mdx +183 -0
  181. package/components/tela/scroll-area/scroll-area.vue +30 -0
  182. package/components/tela/scroll-area/scroll-bar.vue +31 -0
  183. package/components/tela/segment-toggle.stories.ts +114 -0
  184. package/components/tela/segment-toggle.vue +66 -0
  185. package/components/tela/select-menu/select-menu-content.vue +106 -0
  186. package/components/tela/select-menu/select-menu-down-button.vue +20 -0
  187. package/components/tela/select-menu/select-menu-group.vue +16 -0
  188. package/components/tela/select-menu/select-menu-item.vue +40 -0
  189. package/components/tela/select-menu/select-menu-root.vue +15 -0
  190. package/components/tela/select-menu/select-menu-trigger.vue +34 -0
  191. package/components/tela/select-menu/select-menu-up-button.vue +20 -0
  192. package/components/tela/select-menu/select-menu-value.vue +12 -0
  193. package/components/tela/select-menu/select-menu.mdx +221 -0
  194. package/components/tela/select-menu/select-menu.stories.ts +91 -0
  195. package/components/tela/select-menu/select-menu.vue +165 -0
  196. package/components/tela/selector/selector.vue +47 -0
  197. package/components/tela/sheet/sheet-close.vue +12 -0
  198. package/components/tela/sheet/sheet-content.vue +57 -0
  199. package/components/tela/sheet/sheet-description.vue +23 -0
  200. package/components/tela/sheet/sheet-footer.vue +18 -0
  201. package/components/tela/sheet/sheet-header.vue +15 -0
  202. package/components/tela/sheet/sheet-root.vue +18 -0
  203. package/components/tela/sheet/sheet-title.vue +23 -0
  204. package/components/tela/sheet/sheet-trigger.vue +12 -0
  205. package/components/tela/sheet/sheet.client.vue +150 -0
  206. package/components/tela/sheet/sheet.mdx +176 -0
  207. package/components/tela/sheet/sheet.stories.ts +201 -0
  208. package/components/tela/sheet/variants.ts +22 -0
  209. package/components/tela/side-sheet/side-sheet.mdx +131 -0
  210. package/components/tela/side-sheet/side-sheet.stories.ts +134 -0
  211. package/components/tela/side-sheet/side-sheet.vue +106 -0
  212. package/components/tela/skeleton/skeleton.mdx +165 -0
  213. package/components/tela/skeleton/skeleton.stories.ts +35 -0
  214. package/components/tela/skeleton/skeleton.vue +45 -0
  215. package/components/tela/skeleton-icon.vue +24 -0
  216. package/components/tela/span.vue +24 -0
  217. package/components/tela/star-button.vue +70 -0
  218. package/components/tela/status/status-lean.vue +30 -0
  219. package/components/tela/status/status.mdx +187 -0
  220. package/components/tela/status/status.stories.ts +160 -0
  221. package/components/tela/status/status.vue +420 -0
  222. package/components/tela/status-bar/status-bar.mdx +178 -0
  223. package/components/tela/status-bar/status-bar.stories.ts +64 -0
  224. package/components/tela/status-bar/status-bar.vue +56 -0
  225. package/components/tela/status-bar/types.ts +5 -0
  226. package/components/tela/switch/switch.mdx +118 -0
  227. package/components/tela/switch/switch.stories.ts +80 -0
  228. package/components/tela/switch/switch.vue +56 -0
  229. package/components/tela/table/table-body.vue +13 -0
  230. package/components/tela/table/table-caption.vue +13 -0
  231. package/components/tela/table/table-cell.vue +20 -0
  232. package/components/tela/table/table-empty.vue +37 -0
  233. package/components/tela/table/table-footer.vue +13 -0
  234. package/components/tela/table/table-head.vue +13 -0
  235. package/components/tela/table/table-header.vue +13 -0
  236. package/components/tela/table/table-row.vue +13 -0
  237. package/components/tela/table/table.mdx +230 -0
  238. package/components/tela/table/table.stories.ts +384 -0
  239. package/components/tela/table/table.vue +15 -0
  240. package/components/tela/tabs/tabs-content.vue +20 -0
  241. package/components/tela/tabs/tabs-indicator.vue +22 -0
  242. package/components/tela/tabs/tabs-list.vue +23 -0
  243. package/components/tela/tabs/tabs-root.vue +15 -0
  244. package/components/tela/tabs/tabs-trigger.vue +27 -0
  245. package/components/tela/tabs/tabs.mdx +138 -0
  246. package/components/tela/tabs/tabs.stories.ts +72 -0
  247. package/components/tela/tabs/tabs.vue +61 -0
  248. package/components/tela/tags/tags-select.mdx +318 -0
  249. package/components/tela/tags/tags-select.stories.ts +47 -0
  250. package/components/tela/tags/tags-select.vue +637 -0
  251. package/components/tela/tags/tags.mdx +151 -0
  252. package/components/tela/tags/tags.stories.ts +118 -0
  253. package/components/tela/tags/tags.vue +112 -0
  254. package/components/tela/textarea/textarea.mdx +102 -0
  255. package/components/tela/textarea/textarea.stories.ts +50 -0
  256. package/components/tela/textarea/textarea.vue +34 -0
  257. package/components/tela/toggle-group.vue +91 -0
  258. package/components/tela/tooltip/tooltip-content.vue +45 -0
  259. package/components/tela/tooltip/tooltip-provider.vue +12 -0
  260. package/components/tela/tooltip/tooltip-root.vue +15 -0
  261. package/components/tela/tooltip/tooltip-trigger.vue +12 -0
  262. package/components/tela/tooltip/tooltip.mdx +196 -0
  263. package/components/tela/tooltip/tooltip.stories.ts +200 -0
  264. package/components/tela/tooltip/tooltip.vue +91 -0
  265. package/components/tela/tooltip-group/tooltip-group-trigger.vue +92 -0
  266. package/components/tela/tooltip-group/tooltip-group.mdx +236 -0
  267. package/components/tela/tooltip-group/tooltip-group.stories.ts +465 -0
  268. package/components/tela/tooltip-group/tooltip-group.vue +35 -0
  269. package/components/tela/transparent-input.vue +151 -0
  270. package/components/tela/variable-icon.vue +28 -0
  271. package/components/tela/variable-input.vue +77 -0
  272. package/components/tela/wide-button/wide-button.vue +40 -0
  273. package/components.json +18 -0
  274. package/composables/status-toast.ts +67 -0
  275. package/css/reset.css +386 -0
  276. package/css/text.css +22 -0
  277. package/lib/doc-generator.ts +903 -0
  278. package/lib/extractors/volar-extract.ts +186 -0
  279. package/lib/type-resolver.ts +402 -0
  280. package/lib/utils.ts +6 -0
  281. package/modules/tela-build-docs/index.ts +139 -0
  282. package/nuxt.config.ts +80 -0
  283. package/package.json +84 -0
  284. package/plugins/test-id.ts +7 -0
  285. package/tsconfig.json +7 -0
  286. package/types/custom-icon.ts +1 -0
  287. package/types/index.ts +2 -0
  288. package/types/status.ts +1 -0
  289. package/unocss.config.ts +89 -0
  290. package/utils/component-utils.ts +30 -0
  291. package/utils/design-tokens.ts +431 -0
  292. package/utils/fold.ts +8 -0
  293. package/utils/select-menu.ts +10 -0
  294. package/utils/status.ts +1 -0
  295. package/utils/without-keys.ts +34 -0
@@ -0,0 +1,265 @@
1
+ import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
2
+ import * as DropdownMenuStories from './dropdown-menu.stories.ts';
3
+
4
+ <Meta of={DropdownMenuStories} />
5
+
6
+ # TelaDropdownMenu
7
+
8
+ A dropdown menu component built on radix-vue. Provides a flexible menu system with support for grouping, icons, tooltips, checkboxes, and search functionality. Items can be organized into groups and can include click handlers, disabled states, and custom styling.
9
+
10
+ ## Examples
11
+
12
+ ### Basic Usage
13
+
14
+ <Canvas of={DropdownMenuStories.Simple} />
15
+
16
+ ### With Groups
17
+
18
+ <Canvas of={DropdownMenuStories.WithGroups} />
19
+
20
+ ### With Tooltips
21
+
22
+ <Canvas of={DropdownMenuStories.WithTooltips} />
23
+
24
+ ### Basic Usage Code
25
+
26
+ ```vue
27
+ <script setup>
28
+ const menuItems = [
29
+ {
30
+ label: 'New File',
31
+ icon: 'i-ph-file-plus',
32
+ click: () => console.log('New file')
33
+ },
34
+ {
35
+ label: 'Open',
36
+ icon: 'i-ph-folder-open',
37
+ click: () => console.log('Open')
38
+ },
39
+ {
40
+ label: 'Save',
41
+ icon: 'i-ph-floppy-disk',
42
+ click: () => console.log('Save')
43
+ }
44
+ ]
45
+ </script>
46
+
47
+ <template>
48
+ <TelaDropdownMenu :items="menuItems">
49
+ <TelaButton>Actions</TelaButton>
50
+ </TelaDropdownMenu>
51
+ </template>
52
+ ```
53
+
54
+ ### With Groups Code
55
+
56
+ ```vue
57
+ <TelaDropdownMenu
58
+ :items="[
59
+ {
60
+ label: 'Output File',
61
+ group: 'Files',
62
+ icon: 'i-ph-file-pdf',
63
+ click: () => {}
64
+ },
65
+ {
66
+ label: 'Database 1',
67
+ group: 'Databases',
68
+ icon: 'i-ph-database',
69
+ click: () => {}
70
+ },
71
+ {
72
+ label: 'Database 2',
73
+ group: 'Databases',
74
+ icon: 'i-ph-database',
75
+ click: () => {}
76
+ }
77
+ ]"
78
+ >
79
+ <TelaButton>Select Resource</TelaButton>
80
+ </TelaDropdownMenu>
81
+ ```
82
+
83
+ ### With Tooltips Code
84
+
85
+ ```vue
86
+ <TelaDropdownMenu
87
+ :items="[
88
+ {
89
+ label: 'Download',
90
+ icon: 'i-ph-download-simple',
91
+ tooltip: 'Download your files',
92
+ click: () => {}
93
+ },
94
+ {
95
+ label: 'Delete',
96
+ icon: 'i-ph-trash',
97
+ color: 'negative',
98
+ disabled: true,
99
+ tooltip: {
100
+ variant: 'multiline',
101
+ title: 'Cannot delete',
102
+ description: 'Some items are protected',
103
+ side: 'right'
104
+ },
105
+ click: () => {}
106
+ }
107
+ ]"
108
+ >
109
+ <TelaButton>Actions</TelaButton>
110
+ </TelaDropdownMenu>
111
+ ```
112
+
113
+ ### With Search
114
+
115
+ ```vue
116
+ <TelaDropdownMenu
117
+ :items="longItemList"
118
+ allow-search
119
+ search-placeholder="Search actions..."
120
+ >
121
+ <TelaButton>Many Actions</TelaButton>
122
+ </TelaDropdownMenu>
123
+ ```
124
+
125
+ ### With Checkboxes
126
+
127
+ ```vue
128
+ <script setup>
129
+ const items = ref([
130
+ {
131
+ label: 'Show Grid',
132
+ checkbox: true,
133
+ checked: true,
134
+ click: (item) => { item.checked = !item.checked }
135
+ },
136
+ {
137
+ label: 'Show Rulers',
138
+ checkbox: true,
139
+ checked: false,
140
+ click: (item) => { item.checked = !item.checked }
141
+ }
142
+ ])
143
+ </script>
144
+
145
+ <template>
146
+ <TelaDropdownMenu :items="items">
147
+ <TelaButton>View Options</TelaButton>
148
+ </TelaDropdownMenu>
149
+ </template>
150
+ ```
151
+
152
+ ### Destructive Actions
153
+
154
+ ```vue
155
+ <TelaDropdownMenu
156
+ :items="[
157
+ {
158
+ label: 'Edit',
159
+ icon: 'i-ph-pencil',
160
+ click: () => {}
161
+ },
162
+ {
163
+ label: 'Duplicate',
164
+ icon: 'i-ph-copy',
165
+ click: () => {}
166
+ },
167
+ {
168
+ label: 'Delete',
169
+ icon: 'i-ph-trash',
170
+ color: 'negative',
171
+ click: () => {}
172
+ }
173
+ ]"
174
+ >
175
+ <TelaButton variant="ghost">⋮</TelaButton>
176
+ </TelaDropdownMenu>
177
+ ```
178
+
179
+ ### With Custom Alignment
180
+
181
+ ```vue
182
+ <!-- Align to start -->
183
+ <TelaDropdownMenu :items="items" align="start">
184
+ <TelaButton>Align Start</TelaButton>
185
+ </TelaDropdownMenu>
186
+
187
+ <!-- Align to end (default) -->
188
+ <TelaDropdownMenu :items="items" align="end">
189
+ <TelaButton>Align End</TelaButton>
190
+ </TelaDropdownMenu>
191
+ ```
192
+
193
+ ## Props
194
+
195
+ <ArgTypes />
196
+
197
+ ```typescript
198
+ type DropdownMenuItem = {
199
+ label: string
200
+ icon?: string
201
+ click?: () => void
202
+ group?: string
203
+ color?: 'default' | 'negative'
204
+ disabled?: boolean
205
+ checkbox?: boolean
206
+ checked?: boolean
207
+ tooltip?: string | {
208
+ variant?: 'single' | 'multiline'
209
+ title?: string
210
+ description?: string
211
+ side?: 'top' | 'right' | 'bottom' | 'left'
212
+ align?: 'start' | 'center' | 'end'
213
+ alignOffset?: number
214
+ arrowOffset?: number
215
+ }
216
+ }
217
+
218
+ type DropdownMenuProps = {
219
+ items: DropdownMenuItem[]
220
+ sideOffset?: number
221
+ allowSearch?: boolean
222
+ searchPlaceholder?: string
223
+ shouldBeModal?: boolean
224
+ contentClass?: string
225
+ align?: 'start' | 'end' | 'center'
226
+ }
227
+ ```
228
+
229
+ ## Features
230
+
231
+ - **Flexible Items**: Support icons, groups, colors, and states
232
+ - **Search**: Optional search functionality for long lists
233
+ - **Grouping**: Organize items into labeled groups
234
+ - **Tooltips**: Add tooltips to menu items
235
+ - **Checkboxes**: Toggle options with checkbox items
236
+ - **Click Handlers**: Execute actions on item click
237
+ - **Disabled State**: Disable specific items
238
+ - **Color Options**: Default or negative (destructive) colors
239
+ - **Custom Styling**: Control content and item styling
240
+ - **Keyboard Navigation**: Arrow keys, Enter, Escape
241
+ - **Accessible**: Built on radix-vue primitives
242
+
243
+ ## Item Colors
244
+
245
+ - **default**: Standard menu item
246
+ - **negative**: Red/destructive action (e.g., Delete)
247
+
248
+ ## Best Practices
249
+
250
+ 1. **Group Related Items**: Use groups for better organization
251
+ 2. **Place Destructive Actions Last**: Put delete/remove at bottom
252
+ 3. **Use Icons**: Icons help with quick scanning
253
+ 4. **Enable Search**: For lists with 10+ items
254
+ 5. **Provide Tooltips**: Explain disabled items
255
+ 6. **Keep Labels Brief**: Short, action-oriented labels
256
+
257
+ ## Accessibility
258
+
259
+ - Built on radix-vue primitives
260
+ - Proper ARIA attributes (role="menu", role="menuitem")
261
+ - Keyboard navigation (Arrow keys, Home, End, Enter)
262
+ - Focus management
263
+ - Disabled items skip focus
264
+ - Screen reader support
265
+ - Escape key to close
@@ -0,0 +1,156 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3'
2
+
3
+ import DropdownMenu from './DropdownMenu.vue'
4
+ import Button from '../button/button.vue'
5
+
6
+ const meta: Meta<typeof DropdownMenu> = {
7
+ title: 'Core/DropdownMenu',
8
+ component: DropdownMenu,
9
+ parameters: {
10
+ layout: 'centered',
11
+ docs: {
12
+ description: {
13
+ component: 'A dropdown menu component built on radix-vue. Provides a flexible menu system with support for grouping, icons, tooltips, checkboxes, and search functionality. Items can be organized into groups and can include click handlers, disabled states, and custom styling.',
14
+ },
15
+ },
16
+ },
17
+ argTypes: {
18
+ items: {
19
+ control: false,
20
+ description: 'Array of menu items to display. Each item can have a label, icon, click handler, group, color, disabled state, checkbox, and tooltip. Items are automatically grouped by the `group` property.',
21
+ },
22
+ sideOffset: {
23
+ control: 'number',
24
+ description: 'Distance in pixels from the trigger element to the menu content.',
25
+ },
26
+ allowSearch: {
27
+ control: 'boolean',
28
+ description: 'Enable search functionality within the dropdown menu. Adds a search input at the top of the menu.',
29
+ },
30
+ searchPlaceholder: {
31
+ control: 'text',
32
+ description: 'Placeholder text for the search input. Only used when `allowSearch` is true.',
33
+ },
34
+ shouldBeModal: {
35
+ control: 'boolean',
36
+ description: 'Whether the dropdown menu should behave as a modal dialog.',
37
+ },
38
+ contentClass: {
39
+ control: 'text',
40
+ description: 'Custom CSS classes to apply to the dropdown menu content container.',
41
+ },
42
+ align: {
43
+ control: 'select',
44
+ options: ['start', 'end', 'center'],
45
+ description: 'Alignment of the dropdown menu relative to the trigger element.',
46
+ },
47
+ },
48
+ }
49
+
50
+ export default meta
51
+
52
+ type Story = StoryObj<typeof meta>
53
+
54
+ export const Simple: Story = {
55
+ args: {
56
+ items: [
57
+ {
58
+ label: 'Item 1',
59
+ icon: 'i-ph-plus',
60
+ click: () => {},
61
+ },
62
+ ],
63
+ },
64
+ render: args => ({
65
+ components: { DropdownMenu, Button },
66
+ setup() {
67
+ return { args }
68
+ },
69
+ template: '<DropdownMenu v-bind="args"><Button variant="secondary">Click me</Button></DropdownMenu>',
70
+ }),
71
+ }
72
+
73
+ export const WithGroups: Story = {
74
+ args: {
75
+ items: [
76
+ {
77
+ label: 'Informe-Laudo-Exame-284321312-2024-01-01.pdf',
78
+ group: 'Output File',
79
+ icon: 'i-ph-file-pdf',
80
+ click: () => {},
81
+ },
82
+ {
83
+ label: 'Brasíndice Completo',
84
+ group: 'Project Database',
85
+ icon: 'i-ph-file',
86
+ click: () => {},
87
+ },
88
+ {
89
+ label: 'Tabela SIMPRO 2024',
90
+ group: 'Project Database',
91
+ icon: 'i-ph-file',
92
+ click: () => {},
93
+ },
94
+ {
95
+ label: 'Acme Saúde Regras',
96
+ group: 'Project Database',
97
+ icon: 'i-ph-file',
98
+ click: () => {},
99
+ },
100
+ ],
101
+ },
102
+ render: args => ({
103
+ components: { DropdownMenu, Button },
104
+ setup() {
105
+ return { args }
106
+ },
107
+ template: '<DropdownMenu v-bind="args"><Button variant="secondary">Click me</Button></DropdownMenu>',
108
+ }),
109
+ }
110
+
111
+ export const WithTooltips: Story = {
112
+ args: {
113
+ items: [
114
+ {
115
+ label: 'Download',
116
+ icon: 'i-ph-download-simple-bold',
117
+ click: () => console.log('Download'),
118
+ tooltip: 'Download your files',
119
+ },
120
+ {
121
+ label: 'Share',
122
+ icon: 'i-ph-share-bold',
123
+ click: () => console.log('Share'),
124
+ tooltip: {
125
+ variant: 'multiline',
126
+ title: 'Share with team',
127
+ description: 'Share the selected items with your team members',
128
+ side: 'right',
129
+ },
130
+ },
131
+ {
132
+ label: 'Delete',
133
+ icon: 'i-ph-trash-bold',
134
+ color: 'negative',
135
+ click: () => console.log('Delete'),
136
+ disabled: true,
137
+ tooltip: {
138
+ variant: 'multiline',
139
+ side: 'top',
140
+ align: 'start',
141
+ title: 'Cannot delete',
142
+ description: 'Some items are protected and cannot be deleted',
143
+ alignOffset: -20,
144
+ arrowOffset: -25,
145
+ },
146
+ },
147
+ ],
148
+ },
149
+ render: args => ({
150
+ components: { DropdownMenu, Button },
151
+ setup() {
152
+ return { args }
153
+ },
154
+ template: '<DropdownMenu v-bind="args"><Button variant="secondary">Actions with Tooltips</Button></DropdownMenu>',
155
+ }),
156
+ }
@@ -0,0 +1,96 @@
1
+ <script setup lang="ts">
2
+ const props = defineProps<{
3
+ placeholder?: string
4
+ type?: 'text' | 'textarea'
5
+ readonly?: boolean
6
+ }>()
7
+
8
+ const internalValue = defineModel<string>()
9
+
10
+ const isEditing = ref(false)
11
+ const containerEl = ref<HTMLDivElement | null>()
12
+ const inputEl = ref<HTMLTextAreaElement | null>()
13
+
14
+ const { width: containerWidth } = useElementBounding(containerEl)
15
+
16
+ function onStartEditing() {
17
+ if (props.readonly)
18
+ return
19
+
20
+ isEditing.value = true
21
+ setTimeout(() => {
22
+ inputEl.value?.focus()
23
+ }, 50)
24
+ }
25
+
26
+ function onStopEditing() {
27
+ isEditing.value = false
28
+ }
29
+ </script>
30
+
31
+ <template>
32
+ <div
33
+ ref="containerEl"
34
+ font-inherit relative outline-none
35
+ :class="[
36
+ isEditing ? 'h-0px' : 'h-24px overflow-hidden truncate text-ellipsis',
37
+ ]"
38
+ :cursor="props.readonly ? 'default' : 'pointer'"
39
+ rounded-4px
40
+ px-8px
41
+ mr-24px
42
+ class="hover:bg-gray-200"
43
+ :tabindex="isEditing ? 1 : 0"
44
+ @click="onStartEditing"
45
+ @focus="onStartEditing"
46
+ >
47
+ <div
48
+ :cursor="props.readonly ? 'default' : 'pointer'"
49
+ flex="~" items-center
50
+ :class="[
51
+ isEditing && 'op-0',
52
+ ]"
53
+ h-24px
54
+ w-auto
55
+ truncate
56
+ >
57
+ <slot v-if="$slots.label" name="label" :internal-value="internalValue" :placeholder="placeholder" />
58
+ <span
59
+ v-else
60
+ font-inherit
61
+ whitespace-nowrap overflow-hidden text-ellipsis
62
+ z-1
63
+ >
64
+ {{ internalValue || placeholder }}
65
+ </span>
66
+ </div>
67
+
68
+ <textarea
69
+ v-if="isEditing"
70
+ ref="inputEl"
71
+ v-model="internalValue"
72
+ :placeholder="placeholder"
73
+ :style="{ width: `${containerWidth}px`, height: type === 'textarea' ? '100px' : 'auto', overflow: type === 'textarea' ? 'auto' : 'hidden' }"
74
+ absolute
75
+ z-3
76
+ rounded-4px
77
+ top--19.5px
78
+ left--2.5px
79
+ px-10px
80
+ py-10px
81
+ resize-none
82
+ autoresize
83
+ bg-gray-100
84
+ font-inherit
85
+ tabindex="0"
86
+ b=".5 gray-200"
87
+ shadow-flying
88
+ :spellcheck="false"
89
+ v-bind="$attrs"
90
+ @keydown.enter="onStopEditing"
91
+ @blur="onStopEditing"
92
+ @focusleave="onStopEditing"
93
+ @keydown.esc="onStopEditing"
94
+ />
95
+ </div>
96
+ </template>
@@ -0,0 +1,37 @@
1
+ <script setup lang="ts">
2
+ import { useDropZone } from '@vueuse/core'
3
+
4
+ const props = defineProps<{
5
+ accept?: string[]
6
+ }>()
7
+
8
+ const emit = defineEmits<{
9
+ fileDrop: [files: File[] | null]
10
+ }>()
11
+
12
+ const isOverDropZone = defineModel<boolean>()
13
+
14
+ const dropZoneRef = ref<HTMLElement>()
15
+
16
+ const { isOverDropZone: _isOverDropZone } = useDropZone(dropZoneRef, {
17
+ onDrop,
18
+ // specify the types of data to be received.
19
+ dataTypes: props.accept,
20
+ })
21
+
22
+ watch(_isOverDropZone, (isOver) => {
23
+ isOverDropZone.value = isOver
24
+ }, { immediate: true })
25
+
26
+ function onDrop(files: File[] | null) {
27
+ emit('fileDrop', files)
28
+ }
29
+ </script>
30
+
31
+ <template>
32
+ <div
33
+ ref="dropZoneRef"
34
+ >
35
+ <slot />
36
+ </div>
37
+ </template>