@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,155 @@
1
+ import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
2
+ import * as ButtonStories from './button.stories.ts';
3
+
4
+ <Meta of={ButtonStories} />
5
+
6
+ # TelaButton
7
+
8
+ A versatile button component with multiple variants, sizes, and states. Supports icons, loading states, and can function as a link when provided with a `to` prop. Built for consistent UI interactions across the application.
9
+
10
+ ## Examples
11
+
12
+ ### All Sizes
13
+
14
+ <Canvas of={ButtonStories.Sizes} />
15
+
16
+ ### With Icon
17
+
18
+ <Canvas of={ButtonStories.WithIcon} />
19
+
20
+ ### Loading State
21
+
22
+ <Canvas of={ButtonStories.Loading} />
23
+
24
+ ### As a Link
25
+
26
+ <Canvas of={ButtonStories.LinkButton} />
27
+
28
+ ### All Variants
29
+
30
+ <Canvas of={ButtonStories.Variants} />
31
+
32
+ ### Disabled State
33
+
34
+ <Canvas of={ButtonStories.Disabled} />
35
+
36
+ ### All Combinations
37
+
38
+ <Canvas of={ButtonStories.AllCombinations} />
39
+
40
+ ### Basic Usage
41
+
42
+ ```vue
43
+ <TelaButton variant="primary" size="md">
44
+ Click me
45
+ </TelaButton>
46
+ ```
47
+
48
+ ### With Icon Code
49
+
50
+ ```vue
51
+ <TelaButton icon="i-ph-plus" leading variant="primary">
52
+ Add Item
53
+ </TelaButton>
54
+
55
+ <TelaButton icon="i-ph-trash" variant="danger">
56
+ Delete
57
+ </TelaButton>
58
+ ```
59
+
60
+ ### Loading State Code
61
+
62
+ ```vue
63
+ <TelaButton loading variant="primary">
64
+ Saving...
65
+ </TelaButton>
66
+
67
+ <TelaButton loading leading variant="secondary">
68
+ Processing
69
+ </TelaButton>
70
+ ```
71
+
72
+ ### As a Link Code
73
+
74
+ ```vue
75
+ <TelaButton to="/home" variant="secondary">
76
+ Go to Home
77
+ </TelaButton>
78
+
79
+ <TelaButton to="https://example.com" target="_blank" variant="ghost">
80
+ External Link
81
+ </TelaButton>
82
+ ```
83
+
84
+ ### Using Slots
85
+
86
+ ```vue
87
+ <TelaButton variant="primary">
88
+ <template #leading>
89
+ <TelaIcon name="i-ph-check" />
90
+ </template>
91
+ Confirm
92
+ </TelaButton>
93
+
94
+ <TelaButton variant="secondary">
95
+ Save
96
+ <template #trailing>
97
+ <TelaIcon name="i-ph-arrow-right" />
98
+ </template>
99
+ </TelaButton>
100
+ ```
101
+
102
+ ## Props
103
+
104
+ <ArgTypes />
105
+
106
+ ```typescript
107
+ type ButtonSize = 'sm' | 'md' | 'lg'
108
+ type ButtonVariant = 'primary' | 'secondary' | 'ghost' | 'success' | 'danger'
109
+
110
+ type ButtonProps = {
111
+ size?: ButtonSize
112
+ variant?: ButtonVariant
113
+ icon?: string
114
+ loading?: boolean
115
+ leading?: boolean
116
+ disabled?: boolean
117
+ to?: string
118
+ target?: '_blank' | null
119
+ }
120
+ ```
121
+
122
+ ## Slots
123
+
124
+ The Button component supports three slots:
125
+
126
+ - `default` - Main button content/text
127
+ - `leading` - Content before the main text (e.g., icons)
128
+ - `trailing` - Content after the main text (e.g., icons, badges)
129
+
130
+ ## Features
131
+
132
+ - **Multiple Variants**: Primary, secondary, ghost, success, and danger styles
133
+ - **Flexible Sizing**: Small, medium, and large sizes
134
+ - **Icon Support**: Leading or trailing icons with automatic sizing
135
+ - **Loading State**: Built-in loading spinner with automatic disable
136
+ - **Link Functionality**: Renders as NuxtLink when `to` prop is provided
137
+ - **Disabled State**: Proper disabled styling and interaction prevention
138
+ - **Customizable**: Accepts custom classes for extended styling
139
+
140
+ ## Styling
141
+
142
+ The button uses dynamic computed styles based on size and variant:
143
+
144
+ - **Primary**: Dark background with white text, hover and focus states
145
+ - **Secondary**: White background with border, subtle hover effects
146
+ - **Ghost**: Transparent background, minimal styling
147
+ - **Danger**: Red-themed for destructive actions
148
+ - **Disabled**: Grayed out, cursor not-allowed
149
+
150
+ ## Accessibility
151
+
152
+ - Proper button semantics with `<button>` element
153
+ - Disabled state prevents interaction
154
+ - Focus visible styles for keyboard navigation
155
+ - Semantic link when using `to` prop
@@ -0,0 +1,202 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3'
2
+ import Button from './button.vue'
3
+
4
+ const meta: Meta<typeof Button> = {
5
+ title: 'Core/Button',
6
+ component: Button,
7
+ parameters: {
8
+ layout: 'centered',
9
+ docs: {
10
+ description: {
11
+ component: 'A versatile button component with multiple variants, sizes, and states. Supports icons, loading states, and can function as a link when provided with a `to` prop. Built for consistent UI interactions across the application.',
12
+ },
13
+ },
14
+ },
15
+ argTypes: {
16
+ size: {
17
+ control: 'select',
18
+ options: ['xs', 'sm', 'md', 'lg'],
19
+ description: 'Size of the button. Controls padding, font size, and icon size.',
20
+ },
21
+ variant: {
22
+ control: 'select',
23
+ options: ['primary', 'secondary', 'ghost', 'success', 'danger'],
24
+ description: 'Visual style variant of the button. Primary is the default emphasized style, secondary is outlined, ghost is minimal, success is for positive actions, and danger is for destructive actions.',
25
+ },
26
+ icon: {
27
+ control: 'text',
28
+ description: 'Icon class or name to display in the button. Use icon names like "i-ph-plus" or similar iconify classes.',
29
+ },
30
+ loading: {
31
+ control: 'boolean',
32
+ description: 'Show loading spinner and disable button interaction while loading.',
33
+ },
34
+ leading: {
35
+ control: 'boolean',
36
+ description: 'Place icon before the text content. If false, icon appears after text.',
37
+ },
38
+ disabled: {
39
+ control: 'boolean',
40
+ description: 'Disable the button, preventing user interaction and applying disabled styling.',
41
+ },
42
+ to: {
43
+ control: 'text',
44
+ description: 'URL or route path to navigate to when the button is clicked. When provided, the button renders as a NuxtLink instead of a button element.',
45
+ },
46
+ target: {
47
+ control: 'text',
48
+ description: 'Target attribute for links. Use "_blank" to open in a new tab. Only applicable when `to` prop is provided.',
49
+ },
50
+ },
51
+ }
52
+
53
+ export default meta
54
+
55
+ type Story = StoryObj<typeof Button>
56
+
57
+ export const Default: Story = {
58
+ render: args => ({
59
+ components: { Button },
60
+ setup() {
61
+ return { args }
62
+ },
63
+ template: `<Button v-bind="args">Button</Button>`,
64
+ }),
65
+ args: {
66
+ size: 'md',
67
+ variant: 'primary',
68
+ },
69
+ }
70
+
71
+ export const Loading: Story = {
72
+ render: args => ({
73
+ components: { Button },
74
+ setup() {
75
+ return { args }
76
+ },
77
+ template: `<Button v-bind="args">Loading</Button>`,
78
+ }),
79
+ args: {
80
+ loading: true,
81
+ size: 'md',
82
+ variant: 'primary',
83
+ },
84
+ }
85
+
86
+ export const Disabled: Story = {
87
+ render: args => ({
88
+ components: { Button },
89
+ setup() {
90
+ return { args }
91
+ },
92
+ template: `<Button v-bind="args">Disabled</Button>`,
93
+ }),
94
+ args: {
95
+ disabled: true,
96
+ size: 'md',
97
+ variant: 'primary',
98
+ },
99
+ }
100
+
101
+ export const WithIcon: Story = {
102
+ render: args => ({
103
+ components: { Button },
104
+ setup() {
105
+ return { args }
106
+ },
107
+ template: `<Button v-bind="args">With Icon</Button>`,
108
+ }),
109
+ args: {
110
+ icon: 'i-ph-plus',
111
+ leading: true,
112
+ size: 'md',
113
+ variant: 'primary',
114
+ },
115
+ }
116
+
117
+ export const LinkButton: Story = {
118
+ render: args => ({
119
+ components: { Button },
120
+ setup() {
121
+ return { args }
122
+ },
123
+ template: `<Button v-bind="args">Go to Home</Button>`,
124
+ }),
125
+ args: {
126
+ to: '/home',
127
+ size: 'md',
128
+ variant: 'secondary',
129
+ },
130
+ }
131
+
132
+ export const Sizes: Story = {
133
+ render: () => ({
134
+ components: { Button },
135
+ template: `
136
+ <div style="display: flex; gap: 10px; align-items: center;">
137
+ <Button size="sm" variant="primary">SM</Button>
138
+ <Button size="md" variant="primary">MD</Button>
139
+ <Button size="lg" variant="primary">LG</Button>
140
+ </div>
141
+ `,
142
+ }),
143
+ }
144
+
145
+ export const Variants: Story = {
146
+ render: () => ({
147
+ components: { Button },
148
+ template: `
149
+ <div style="display: flex; gap: 10px; flex-wrap: wrap; align-items: center;">
150
+ <Button variant="primary">Primary</Button>
151
+ <Button variant="secondary">Secondary</Button>
152
+ <Button variant="ghost">Ghost</Button>
153
+ <Button variant="danger">Danger</Button>
154
+ </div>
155
+ `,
156
+ }),
157
+ }
158
+
159
+ export const AllCombinations: Story = {
160
+ render: () => ({
161
+ components: { Button },
162
+ template: `
163
+ <div style="display: flex; flex-direction: column; gap: 20px;">
164
+ <div>
165
+ <h3>Sizes</h3>
166
+ <div style="display: flex; gap: 10px; align-items: center;">
167
+ <Button size="sm" variant="primary">SM</Button>
168
+ <Button size="md" variant="primary">MD</Button>
169
+ <Button size="lg" variant="primary">LG</Button>
170
+ </div>
171
+ </div>
172
+ <div>
173
+ <h3>Variants</h3>
174
+ <div style="display: flex; gap: 10px; flex-wrap: wrap; align-items: center;">
175
+ <Button variant="primary">Primary</Button>
176
+ <Button variant="secondary">Secondary</Button>
177
+ <Button variant="ghost">Ghost</Button>
178
+ <Button variant="danger">Danger</Button>
179
+ </div>
180
+ </div>
181
+ <div>
182
+ <h3>States</h3>
183
+ <div style="display: flex; gap: 10px; align-items: center;">
184
+ <Button disabled variant="primary">Disabled</Button>
185
+ <Button loading variant="primary">Loading</Button>
186
+ </div>
187
+ </div>
188
+ <div>
189
+ <h3>With Icons</h3>
190
+ <div style="display: flex; gap: 10px; align-items: center;">
191
+ <Button icon="i-ph-plus-bold" leading variant="primary">Add</Button>
192
+ <Button icon="i-ph-trash-bold" variant="danger">Delete</Button>
193
+ </div>
194
+ </div>
195
+ <div>
196
+ <h3>Link Button</h3>
197
+ <Button to="/home" variant="secondary">Go to Home</Button>
198
+ </div>
199
+ </div>
200
+ `,
201
+ }),
202
+ }
@@ -0,0 +1,107 @@
1
+ <script setup lang="ts">
2
+ import { NuxtLink } from '#components'
3
+
4
+ export type ButtonSize = 'sm' | 'md' | 'lg'
5
+ export type ButtonVariant = 'primary' | 'secondary' | 'ghost' | 'success' | 'danger'
6
+
7
+ export type ButtonProps = {
8
+ size?: ButtonSize
9
+ variant?: ButtonVariant
10
+ icon?: string
11
+ loading?: boolean
12
+ leading?: boolean
13
+ disabled?: boolean
14
+ to?: string
15
+ target?: '_blank' | null;
16
+ }
17
+
18
+ const props = defineProps<ButtonProps>()
19
+
20
+ const resolvedSize = computed(() => props.size || 'md')
21
+ const resolvedVariant = computed(() =>
22
+ (props.disabled && 'disabled')
23
+ || (props.loading && 'loading')
24
+ || props.variant
25
+ || 'primary',
26
+ )
27
+
28
+ const sizeStyle = computed(() => (({
29
+ sm: 'text-12px leading-16px font-580 tracking-normal px-10px py-4px rounded-9px',
30
+ md: 'text-14px leading-18px font-580 -tracking-0.01em px-12px py-7px rounded-11px [&>svg]:text-10px',
31
+ lg: 'text-16px leading-20px font-580 -tracking-0.01em px-16px py-10px rounded-13px [&>svg]:text-12px',
32
+ }) as Record<ButtonSize, string>)[resolvedSize.value] ?? '')
33
+
34
+ const variantStyle = computed(() => (({
35
+ primary: fold`
36
+ bg-gray-900 text-white
37
+ hover:bg-gray-800
38
+ active:bg-gray-700
39
+ focus-visible:ring-0.5px focus-visible:ring-cyan-600
40
+ `,
41
+ secondary: fold`
42
+ bg-white text-gray-900 border-gray-300 border-0.5px
43
+ hover:bg-gray-50 hover:border-gray-300 hover:shadow-subtle
44
+ active:bg-gray-100 active:border-gray-400/60
45
+ focus-visible:ring-0.5px focus-visible:ring-cyan-600
46
+ `,
47
+ ghost: fold`
48
+ bg-transparent text-gray-900
49
+ hover:bg-gray-100
50
+ focus-visible:ring-0.5px focus-visible:ring-cyan-600
51
+ `,
52
+ disabled: fold`
53
+ bg-gray-100 text-gray-400 !cursor-not-allowed
54
+ `,
55
+ loading: fold`
56
+ bg-gray-200 text-gray-600
57
+ `,
58
+ danger: fold`
59
+ bg-red-100 text-red-500
60
+ hover:bg-red-100/80
61
+ focus:outline-red-600
62
+ `,
63
+ }) as Record<ButtonVariant | 'disabled' | 'loading', string>)[resolvedVariant.value] ?? '')
64
+
65
+ const resolvedStyle = computed(() => [
66
+ sizeStyle.value,
67
+ variantStyle.value,
68
+ ].join(' '))
69
+
70
+ const tag = computed(() => props.to ? NuxtLink : 'button')
71
+
72
+ const iconSize = computed(() => {
73
+ switch (sizeStyle.value) {
74
+ case 'xs':
75
+ return '11px'
76
+ case 'sm':
77
+ return '11px'
78
+ case 'md':
79
+ return '13px'
80
+ case 'lg':
81
+ return '13px'
82
+ default:
83
+ return '13px'
84
+ }
85
+ })
86
+ </script>
87
+
88
+ <template>
89
+ <component
90
+ :is="tag"
91
+ :to="to"
92
+ :class="resolvedStyle" transition ease-in-out duration-80 flex items-center justify-center gap-6px
93
+ :disabled="disabled"
94
+ :cursor="disabled ? 'not-allowed' : 'pointer'"
95
+ :target="target"
96
+ border-box
97
+ select-none
98
+ >
99
+ <TelaIconSpinner v-if="loading && leading" animate-spin />
100
+ <slot v-else-if="$slots.leading" name="leading" />
101
+ <TelaIcon v-else-if="icon && leading" :name="icon" :size="iconSize" min-h-14px min-w-14px />
102
+ <slot />
103
+ <TelaIconSpinner v-if="loading && !leading" animate-spin ml-0.5 />
104
+ <slot v-else-if="$slots.trailing" name="trailing" />
105
+ <TelaIcon v-else-if="icon && !leading" :name="icon" :size="iconSize" />
106
+ </component>
107
+ </template>
@@ -0,0 +1,30 @@
1
+ <script setup lang="ts">
2
+ import { defineProps, ref } from 'vue'
3
+
4
+ defineProps<{
5
+ contentPadding?: string;
6
+ borderRadius?: string;
7
+ }>()
8
+
9
+ const rootEl = ref<HTMLElement | null>(null)
10
+
11
+ defineExpose({
12
+ el: rootEl,
13
+ })
14
+ </script>
15
+
16
+ <template>
17
+ <div
18
+ ref="rootEl"
19
+ bg-white
20
+ :class="borderRadius ? `rounded-${borderRadius}` : 'rounded-16px'"
21
+ b=".5 gray-200"
22
+ >
23
+ <div :class="contentPadding ?? 'p-32px'">
24
+ <slot />
25
+ </div>
26
+ <div v-if="$slots.footer" p-19px b="t-1 #EBEBEB">
27
+ <slot name="footer" />
28
+ </div>
29
+ </div>
30
+ </template>
@@ -0,0 +1,58 @@
1
+ <script setup lang="ts">
2
+ const props = withDefaults(defineProps<{
3
+ total: number
4
+ filled: number
5
+ height?: string
6
+ gap?: string
7
+ duration?: number
8
+ }>(), {
9
+ height: '12px',
10
+ gap: '2px',
11
+ duration: 1000,
12
+ })
13
+
14
+ const animatedFilled = ref(0)
15
+
16
+ const bars = computed(() => {
17
+ return Array.from({ length: props.total }, (_, index) => ({
18
+ index,
19
+ isFilled: index < animatedFilled.value,
20
+ }))
21
+ })
22
+
23
+ watch(() => props.filled, (newValue) => {
24
+ const startValue = animatedFilled.value
25
+ const startTime = Date.now()
26
+ const animate = () => {
27
+ const elapsed = Date.now() - startTime
28
+ const progress = Math.min(elapsed / props.duration, 1)
29
+
30
+ const easeOutQuad = (t: number) => t * (2 - t)
31
+ const easedProgress = easeOutQuad(progress)
32
+
33
+ animatedFilled.value = Math.floor(startValue + (newValue - startValue) * easedProgress)
34
+
35
+ if (progress < 1) {
36
+ requestAnimationFrame(animate)
37
+ }
38
+ else {
39
+ animatedFilled.value = newValue
40
+ }
41
+ }
42
+
43
+ animate()
44
+ }, { immediate: true })
45
+ </script>
46
+
47
+ <template>
48
+ <div flex="~" :style="{ gap }" items-center>
49
+ <div
50
+ v-for="bar in bars"
51
+ :key="bar.index"
52
+ :style="{ height }"
53
+ w-1px
54
+ rounded-1px
55
+ :bg="bar.isFilled ? '#5DC16B' : '#DFE3E7'"
56
+ />
57
+ </div>
58
+ </template>