@health-samurai/react-components 0.0.0-alpha.4 → 0.0.0-alpha.6

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 (304) hide show
  1. package/dist/bundle.css +1375 -484
  2. package/dist/src/components/code-editor/http/grammar/http.d.ts +3 -0
  3. package/dist/src/components/code-editor/http/grammar/http.d.ts.map +1 -0
  4. package/dist/src/components/code-editor/http/grammar/http.grammar +74 -0
  5. package/dist/src/components/code-editor/http/grammar/http.js +38 -0
  6. package/dist/src/components/code-editor/http/grammar/http.js.map +1 -0
  7. package/dist/src/components/code-editor/http/grammar/http.terms.d.ts +2 -0
  8. package/dist/src/components/code-editor/http/grammar/http.terms.d.ts.map +1 -0
  9. package/dist/src/components/code-editor/http/grammar/http.terms.js +4 -0
  10. package/dist/src/components/code-editor/http/grammar/http.terms.js.map +1 -0
  11. package/dist/src/components/code-editor/http/grammar/http.test.d.ts +2 -0
  12. package/dist/src/components/code-editor/http/grammar/http.test.d.ts.map +1 -0
  13. package/dist/src/components/code-editor/http/grammar/http.test.js +80 -0
  14. package/dist/src/components/code-editor/http/grammar/http.test.js.map +1 -0
  15. package/dist/src/components/code-editor/http/index.d.ts +4 -0
  16. package/dist/src/components/code-editor/http/index.d.ts.map +1 -0
  17. package/dist/src/components/code-editor/http/index.js +66 -0
  18. package/dist/src/components/code-editor/http/index.js.map +1 -0
  19. package/dist/src/components/code-editor/index.d.ts +14 -2
  20. package/dist/src/components/code-editor/index.d.ts.map +1 -1
  21. package/dist/src/components/code-editor/index.js +309 -20
  22. package/dist/src/components/code-editor/index.js.map +1 -1
  23. package/dist/src/components/code-editor.stories.d.ts +1 -0
  24. package/dist/src/components/code-editor.stories.d.ts.map +1 -1
  25. package/dist/src/components/code-editor.stories.js +255 -2
  26. package/dist/src/components/code-editor.stories.js.map +1 -1
  27. package/dist/src/components/copy-icon.d.ts +5 -1
  28. package/dist/src/components/copy-icon.d.ts.map +1 -1
  29. package/dist/src/components/copy-icon.js +41 -3
  30. package/dist/src/components/copy-icon.js.map +1 -1
  31. package/dist/src/components/data-table.d.ts +8 -0
  32. package/dist/src/components/data-table.d.ts.map +1 -0
  33. package/dist/src/components/data-table.js +65 -0
  34. package/dist/src/components/data-table.js.map +1 -0
  35. package/dist/src/components/data-table.stories.d.ts +7 -0
  36. package/dist/src/components/data-table.stories.d.ts.map +1 -0
  37. package/dist/src/components/data-table.stories.js +44 -0
  38. package/dist/src/components/data-table.stories.js.map +1 -0
  39. package/dist/src/components/fhir-structure-view.d.ts +34 -0
  40. package/dist/src/components/fhir-structure-view.d.ts.map +1 -0
  41. package/dist/src/components/fhir-structure-view.js +229 -0
  42. package/dist/src/components/fhir-structure-view.js.map +1 -0
  43. package/dist/src/components/fhir-structure-view.stories.d.ts +7 -0
  44. package/dist/src/components/fhir-structure-view.stories.d.ts.map +1 -0
  45. package/dist/src/components/fhir-structure-view.stories.js +447 -0
  46. package/dist/src/components/fhir-structure-view.stories.js.map +1 -0
  47. package/dist/src/components/patient-table.d.ts +73 -0
  48. package/dist/src/components/patient-table.d.ts.map +1 -0
  49. package/dist/src/components/patient-table.js +921 -0
  50. package/dist/src/components/patient-table.js.map +1 -0
  51. package/dist/src/components/patient-table.stories.d.ts +111 -0
  52. package/dist/src/components/patient-table.stories.d.ts.map +1 -0
  53. package/dist/src/components/patient-table.stories.js +172 -0
  54. package/dist/src/components/patient-table.stories.js.map +1 -0
  55. package/dist/src/components/request-line-editor.d.ts +13 -35
  56. package/dist/src/components/request-line-editor.d.ts.map +1 -1
  57. package/dist/src/components/request-line-editor.js +72 -49
  58. package/dist/src/components/request-line-editor.js.map +1 -1
  59. package/dist/src/components/request-line-editor.stories.d.ts.map +1 -1
  60. package/dist/src/components/request-line-editor.stories.js +17 -53
  61. package/dist/src/components/request-line-editor.stories.js.map +1 -1
  62. package/dist/src/components/segment-control.d.ts +16 -0
  63. package/dist/src/components/segment-control.d.ts.map +1 -0
  64. package/dist/src/components/segment-control.js +48 -0
  65. package/dist/src/components/segment-control.js.map +1 -0
  66. package/dist/src/components/segment-control.stories.d.ts +15 -0
  67. package/dist/src/components/segment-control.stories.d.ts.map +1 -0
  68. package/dist/src/components/segment-control.stories.js +33 -0
  69. package/dist/src/components/segment-control.stories.js.map +1 -0
  70. package/dist/src/components/split-button.d.ts +5 -0
  71. package/dist/src/components/split-button.d.ts.map +1 -0
  72. package/dist/src/components/split-button.js +12 -0
  73. package/dist/src/components/split-button.js.map +1 -0
  74. package/dist/src/components/split-button.stories.d.ts +7 -0
  75. package/dist/src/components/split-button.stories.d.ts.map +1 -0
  76. package/dist/src/components/split-button.stories.js +57 -0
  77. package/dist/src/components/split-button.stories.js.map +1 -0
  78. package/dist/src/components/tree-view.d.ts +22 -0
  79. package/dist/src/components/tree-view.d.ts.map +1 -0
  80. package/dist/src/components/tree-view.js +101 -0
  81. package/dist/src/components/tree-view.js.map +1 -0
  82. package/dist/src/components/tree-view.stories.d.ts +13 -0
  83. package/dist/src/components/tree-view.stories.d.ts.map +1 -0
  84. package/dist/src/components/tree-view.stories.js +274 -0
  85. package/dist/src/components/tree-view.stories.js.map +1 -0
  86. package/dist/src/icons.d.ts +9 -0
  87. package/dist/src/icons.d.ts.map +1 -0
  88. package/dist/src/icons.js +279 -0
  89. package/dist/src/icons.js.map +1 -0
  90. package/dist/src/index.css +42 -3
  91. package/dist/src/index.d.ts +9 -1
  92. package/dist/src/index.d.ts.map +1 -1
  93. package/dist/src/index.js +9 -1
  94. package/dist/src/index.js.map +1 -1
  95. package/dist/src/shadcn/components/ui/accordion.d.ts.map +1 -1
  96. package/dist/src/shadcn/components/ui/accordion.js +23 -5
  97. package/dist/src/shadcn/components/ui/accordion.js.map +1 -1
  98. package/dist/src/shadcn/components/ui/alert-dialog.d.ts +3 -1
  99. package/dist/src/shadcn/components/ui/alert-dialog.d.ts.map +1 -1
  100. package/dist/src/shadcn/components/ui/alert-dialog.js +5 -2
  101. package/dist/src/shadcn/components/ui/alert-dialog.js.map +1 -1
  102. package/dist/src/shadcn/components/ui/alert.d.ts.map +1 -1
  103. package/dist/src/shadcn/components/ui/alert.js +12 -5
  104. package/dist/src/shadcn/components/ui/alert.js.map +1 -1
  105. package/dist/src/shadcn/components/ui/avatar.d.ts.map +1 -1
  106. package/dist/src/shadcn/components/ui/avatar.js +4 -3
  107. package/dist/src/shadcn/components/ui/avatar.js.map +1 -1
  108. package/dist/src/shadcn/components/ui/badge.d.ts.map +1 -1
  109. package/dist/src/shadcn/components/ui/badge.js +16 -5
  110. package/dist/src/shadcn/components/ui/badge.js.map +1 -1
  111. package/dist/src/shadcn/components/ui/breadcrumb.d.ts.map +1 -1
  112. package/dist/src/shadcn/components/ui/breadcrumb.js +6 -6
  113. package/dist/src/shadcn/components/ui/breadcrumb.js.map +1 -1
  114. package/dist/src/shadcn/components/ui/button.d.ts.map +1 -1
  115. package/dist/src/shadcn/components/ui/button.js +19 -11
  116. package/dist/src/shadcn/components/ui/button.js.map +1 -1
  117. package/dist/src/shadcn/components/ui/card.d.ts.map +1 -1
  118. package/dist/src/shadcn/components/ui/card.js +14 -6
  119. package/dist/src/shadcn/components/ui/card.js.map +1 -1
  120. package/dist/src/shadcn/components/ui/checkbox.d.ts.map +1 -1
  121. package/dist/src/shadcn/components/ui/checkbox.js +20 -5
  122. package/dist/src/shadcn/components/ui/checkbox.js.map +1 -1
  123. package/dist/src/shadcn/components/ui/checkbox.stories.d.ts.map +1 -1
  124. package/dist/src/shadcn/components/ui/checkbox.stories.js +44 -35
  125. package/dist/src/shadcn/components/ui/checkbox.stories.js.map +1 -1
  126. package/dist/src/shadcn/components/ui/combobox.d.ts +18 -0
  127. package/dist/src/shadcn/components/ui/combobox.d.ts.map +1 -0
  128. package/dist/src/shadcn/components/ui/combobox.js +121 -0
  129. package/dist/src/shadcn/components/ui/combobox.js.map +1 -0
  130. package/dist/src/shadcn/components/ui/combobox.stories.d.ts +11 -0
  131. package/dist/src/shadcn/components/ui/combobox.stories.d.ts.map +1 -0
  132. package/dist/src/shadcn/components/ui/combobox.stories.js +16 -0
  133. package/dist/src/shadcn/components/ui/combobox.stories.js.map +1 -0
  134. package/dist/src/shadcn/components/ui/command.d.ts.map +1 -1
  135. package/dist/src/shadcn/components/ui/command.js +73 -12
  136. package/dist/src/shadcn/components/ui/command.js.map +1 -1
  137. package/dist/src/shadcn/components/ui/command.stories.js +0 -1
  138. package/dist/src/shadcn/components/ui/command.stories.js.map +1 -1
  139. package/dist/src/shadcn/components/ui/dialog.d.ts.map +1 -1
  140. package/dist/src/shadcn/components/ui/dialog.js +35 -7
  141. package/dist/src/shadcn/components/ui/dialog.js.map +1 -1
  142. package/dist/src/shadcn/components/ui/drawer.d.ts.map +1 -1
  143. package/dist/src/shadcn/components/ui/drawer.js +26 -5
  144. package/dist/src/shadcn/components/ui/drawer.js.map +1 -1
  145. package/dist/src/shadcn/components/ui/dropdown-menu.d.ts.map +1 -1
  146. package/dist/src/shadcn/components/ui/dropdown-menu.js +12 -1
  147. package/dist/src/shadcn/components/ui/dropdown-menu.js.map +1 -1
  148. package/dist/src/shadcn/components/ui/form.d.ts.map +1 -1
  149. package/dist/src/shadcn/components/ui/form.js +12 -4
  150. package/dist/src/shadcn/components/ui/form.js.map +1 -1
  151. package/dist/src/shadcn/components/ui/input.d.ts +3 -1
  152. package/dist/src/shadcn/components/ui/input.d.ts.map +1 -1
  153. package/dist/src/shadcn/components/ui/input.js +126 -17
  154. package/dist/src/shadcn/components/ui/input.js.map +1 -1
  155. package/dist/src/shadcn/components/ui/label.d.ts.map +1 -1
  156. package/dist/src/shadcn/components/ui/label.js +8 -1
  157. package/dist/src/shadcn/components/ui/label.js.map +1 -1
  158. package/dist/src/shadcn/components/ui/menubar.d.ts.map +1 -1
  159. package/dist/src/shadcn/components/ui/menubar.js +35 -13
  160. package/dist/src/shadcn/components/ui/menubar.js.map +1 -1
  161. package/dist/src/shadcn/components/ui/pagination.d.ts.map +1 -1
  162. package/dist/src/shadcn/components/ui/pagination.js +6 -6
  163. package/dist/src/shadcn/components/ui/pagination.js.map +1 -1
  164. package/dist/src/shadcn/components/ui/popover.d.ts.map +1 -1
  165. package/dist/src/shadcn/components/ui/popover.js +12 -1
  166. package/dist/src/shadcn/components/ui/popover.js.map +1 -1
  167. package/dist/src/shadcn/components/ui/progress.d.ts.map +1 -1
  168. package/dist/src/shadcn/components/ui/progress.js +6 -2
  169. package/dist/src/shadcn/components/ui/progress.js.map +1 -1
  170. package/dist/src/shadcn/components/ui/radio-group.d.ts.map +1 -1
  171. package/dist/src/shadcn/components/ui/radio-group.js +11 -6
  172. package/dist/src/shadcn/components/ui/radio-group.js.map +1 -1
  173. package/dist/src/shadcn/components/ui/radio-group.stories.d.ts.map +1 -1
  174. package/dist/src/shadcn/components/ui/radio-group.stories.js +57 -34
  175. package/dist/src/shadcn/components/ui/radio-group.stories.js.map +1 -1
  176. package/dist/src/shadcn/components/ui/scroll-area.d.ts.map +1 -1
  177. package/dist/src/shadcn/components/ui/scroll-area.js +9 -3
  178. package/dist/src/shadcn/components/ui/scroll-area.js.map +1 -1
  179. package/dist/src/shadcn/components/ui/select.d.ts.map +1 -1
  180. package/dist/src/shadcn/components/ui/select.js +49 -14
  181. package/dist/src/shadcn/components/ui/select.js.map +1 -1
  182. package/dist/src/shadcn/components/ui/select.stories.d.ts.map +1 -1
  183. package/dist/src/shadcn/components/ui/select.stories.js +1 -4
  184. package/dist/src/shadcn/components/ui/select.stories.js.map +1 -1
  185. package/dist/src/shadcn/components/ui/separator.d.ts.map +1 -1
  186. package/dist/src/shadcn/components/ui/separator.js +7 -1
  187. package/dist/src/shadcn/components/ui/separator.js.map +1 -1
  188. package/dist/src/shadcn/components/ui/sidebar.d.ts.map +1 -1
  189. package/dist/src/shadcn/components/ui/sidebar.js +20 -6
  190. package/dist/src/shadcn/components/ui/sidebar.js.map +1 -1
  191. package/dist/src/shadcn/components/ui/skeleton.d.ts.map +1 -1
  192. package/dist/src/shadcn/components/ui/skeleton.js +3 -1
  193. package/dist/src/shadcn/components/ui/skeleton.js.map +1 -1
  194. package/dist/src/shadcn/components/ui/slider.d.ts.map +1 -1
  195. package/dist/src/shadcn/components/ui/slider.js +34 -4
  196. package/dist/src/shadcn/components/ui/slider.js.map +1 -1
  197. package/dist/src/shadcn/components/ui/sonner.d.ts +16 -1
  198. package/dist/src/shadcn/components/ui/sonner.d.ts.map +1 -1
  199. package/dist/src/shadcn/components/ui/sonner.js +23 -3
  200. package/dist/src/shadcn/components/ui/sonner.js.map +1 -1
  201. package/dist/src/shadcn/components/ui/sonner.stories.d.ts.map +1 -1
  202. package/dist/src/shadcn/components/ui/sonner.stories.js +19 -11
  203. package/dist/src/shadcn/components/ui/sonner.stories.js.map +1 -1
  204. package/dist/src/shadcn/components/ui/switch.d.ts.map +1 -1
  205. package/dist/src/shadcn/components/ui/switch.js +18 -2
  206. package/dist/src/shadcn/components/ui/switch.js.map +1 -1
  207. package/dist/src/shadcn/components/ui/table.d.ts.map +1 -1
  208. package/dist/src/shadcn/components/ui/table.js +12 -8
  209. package/dist/src/shadcn/components/ui/table.js.map +1 -1
  210. package/dist/src/shadcn/components/ui/tabs.d.ts +21 -3
  211. package/dist/src/shadcn/components/ui/tabs.d.ts.map +1 -1
  212. package/dist/src/shadcn/components/ui/tabs.js +315 -9
  213. package/dist/src/shadcn/components/ui/tabs.js.map +1 -1
  214. package/dist/src/shadcn/components/ui/tabs.stories.d.ts.map +1 -1
  215. package/dist/src/shadcn/components/ui/tabs.stories.js +50 -1
  216. package/dist/src/shadcn/components/ui/tabs.stories.js.map +1 -1
  217. package/dist/src/shadcn/components/ui/textarea.d.ts.map +1 -1
  218. package/dist/src/shadcn/components/ui/textarea.js +15 -1
  219. package/dist/src/shadcn/components/ui/textarea.js.map +1 -1
  220. package/dist/src/shadcn/components/ui/toggle-group.d.ts.map +1 -1
  221. package/dist/src/shadcn/components/ui/toggle-group.js +6 -2
  222. package/dist/src/shadcn/components/ui/toggle-group.js.map +1 -1
  223. package/dist/src/shadcn/components/ui/toggle.d.ts.map +1 -1
  224. package/dist/src/shadcn/components/ui/toggle.js +18 -6
  225. package/dist/src/shadcn/components/ui/toggle.js.map +1 -1
  226. package/dist/src/shadcn/components/ui/tooltip.d.ts.map +1 -1
  227. package/dist/src/shadcn/components/ui/tooltip.js +11 -1
  228. package/dist/src/shadcn/components/ui/tooltip.js.map +1 -1
  229. package/dist/src/shadcn/components/ui/tree.d.ts +28 -0
  230. package/dist/src/shadcn/components/ui/tree.d.ts.map +1 -0
  231. package/dist/src/shadcn/components/ui/tree.js +122 -0
  232. package/dist/src/shadcn/components/ui/tree.js.map +1 -0
  233. package/dist/src/typography.css +12 -0
  234. package/package.json +13 -2
  235. package/src/components/code-editor/http/grammar/http.grammar +74 -0
  236. package/src/components/code-editor/http/grammar/http.terms.ts +9 -0
  237. package/src/components/code-editor/http/grammar/http.test.ts +110 -0
  238. package/src/components/code-editor/http/grammar/http.ts +21 -0
  239. package/src/components/code-editor/http/index.ts +87 -0
  240. package/src/components/code-editor/index.tsx +307 -21
  241. package/src/components/code-editor.stories.tsx +295 -1
  242. package/src/components/copy-icon.tsx +57 -3
  243. package/src/components/data-table.stories.tsx +38 -0
  244. package/src/components/data-table.tsx +117 -0
  245. package/src/components/fhir-structure-view.stories.tsx +439 -0
  246. package/src/components/fhir-structure-view.tsx +231 -0
  247. package/src/components/patient-table.stories.tsx +111 -0
  248. package/src/components/patient-table.tsx +1301 -0
  249. package/src/components/request-line-editor.stories.tsx +17 -27
  250. package/src/components/request-line-editor.tsx +98 -61
  251. package/src/components/segment-control.stories.tsx +29 -0
  252. package/src/components/segment-control.tsx +80 -0
  253. package/src/components/split-button.stories.tsx +49 -0
  254. package/src/components/split-button.tsx +17 -0
  255. package/src/components/tree-view.stories.tsx +259 -0
  256. package/src/components/tree-view.tsx +172 -0
  257. package/src/icons.tsx +287 -0
  258. package/src/index.css +42 -3
  259. package/src/index.tsx +9 -2
  260. package/src/shadcn/components/ui/accordion.tsx +66 -8
  261. package/src/shadcn/components/ui/alert-dialog.tsx +6 -2
  262. package/src/shadcn/components/ui/alert.tsx +53 -15
  263. package/src/shadcn/components/ui/avatar.tsx +17 -6
  264. package/src/shadcn/components/ui/badge.tsx +67 -18
  265. package/src/shadcn/components/ui/breadcrumb.tsx +35 -7
  266. package/src/shadcn/components/ui/button.tsx +118 -57
  267. package/src/shadcn/components/ui/card.tsx +44 -13
  268. package/src/shadcn/components/ui/checkbox.stories.tsx +20 -24
  269. package/src/shadcn/components/ui/checkbox.tsx +45 -4
  270. package/src/shadcn/components/ui/combobox.stories.tsx +19 -0
  271. package/src/shadcn/components/ui/combobox.tsx +142 -0
  272. package/src/shadcn/components/ui/command.stories.tsx +1 -1
  273. package/src/shadcn/components/ui/command.tsx +192 -36
  274. package/src/shadcn/components/ui/dialog.tsx +101 -13
  275. package/src/shadcn/components/ui/drawer.tsx +93 -18
  276. package/src/shadcn/components/ui/dropdown-menu.tsx +37 -9
  277. package/src/shadcn/components/ui/form.tsx +16 -4
  278. package/src/shadcn/components/ui/input.tsx +400 -29
  279. package/src/shadcn/components/ui/label.tsx +21 -4
  280. package/src/shadcn/components/ui/menubar.tsx +188 -43
  281. package/src/shadcn/components/ui/pagination.tsx +12 -6
  282. package/src/shadcn/components/ui/popover.tsx +35 -4
  283. package/src/shadcn/components/ui/progress.tsx +21 -5
  284. package/src/shadcn/components/ui/radio-group.stories.tsx +22 -14
  285. package/src/shadcn/components/ui/radio-group.tsx +42 -5
  286. package/src/shadcn/components/ui/scroll-area.tsx +33 -5
  287. package/src/shadcn/components/ui/select.stories.tsx +0 -2
  288. package/src/shadcn/components/ui/select.tsx +184 -33
  289. package/src/shadcn/components/ui/separator.tsx +15 -5
  290. package/src/shadcn/components/ui/sidebar.tsx +68 -26
  291. package/src/shadcn/components/ui/skeleton.tsx +4 -1
  292. package/src/shadcn/components/ui/slider.tsx +82 -11
  293. package/src/shadcn/components/ui/sonner.stories.tsx +19 -15
  294. package/src/shadcn/components/ui/sonner.tsx +53 -3
  295. package/src/shadcn/components/ui/switch.tsx +53 -7
  296. package/src/shadcn/components/ui/table.tsx +38 -11
  297. package/src/shadcn/components/ui/tabs.stories.tsx +32 -0
  298. package/src/shadcn/components/ui/tabs.tsx +456 -17
  299. package/src/shadcn/components/ui/textarea.tsx +42 -4
  300. package/src/shadcn/components/ui/toggle-group.tsx +27 -5
  301. package/src/shadcn/components/ui/toggle.tsx +59 -18
  302. package/src/shadcn/components/ui/tooltip.tsx +33 -8
  303. package/src/shadcn/components/ui/tree.tsx +233 -0
  304. package/src/typography.css +12 -0
@@ -1,10 +1,89 @@
1
1
  "use client";
2
2
  import * as TabsPrimitive from "@radix-ui/react-tabs";
3
3
  import { cva, type VariantProps } from "class-variance-authority";
4
- import { Plus, X } from "lucide-react";
5
- import type * as React from "react";
4
+ import {
5
+ ChevronDownIcon,
6
+ ChevronLeft,
7
+ ChevronRight,
8
+ Plus,
9
+ X,
10
+ } from "lucide-react";
11
+ import * as React from "react";
6
12
  import { cn } from "#shadcn/lib/utils";
7
13
  import { Button } from "./button";
14
+ import {
15
+ Command,
16
+ CommandEmpty,
17
+ CommandInput,
18
+ CommandItem,
19
+ CommandList,
20
+ } from "./command";
21
+ import { Popover, PopoverContent, PopoverTrigger } from "./popover";
22
+
23
+ // Base tabs styles
24
+ const baseTabsStyles = cn("flex", "flex-col", "h-full");
25
+
26
+ // Tabs add button container styles
27
+ const tabsAddButtonContainerStyles = cn(
28
+ "grow",
29
+ "h-full",
30
+ "bg-bg-secondary",
31
+ "border-l",
32
+ "border-b",
33
+ );
34
+
35
+ // Tabs list styles
36
+ const tabsListStyles = cn(
37
+ "inline-flex",
38
+ "w-fit",
39
+ "items-center",
40
+ "no-scrollbar",
41
+ );
42
+
43
+ // Base tabs trigger styles
44
+ const baseTabsTriggerStyles = cn(
45
+ // Layout & Sizing
46
+ "box-border",
47
+ "flex-1",
48
+ "h-10",
49
+ "inline-flex",
50
+ "items-center",
51
+ "justify-center",
52
+ "px-3",
53
+ "whitespace-nowrap",
54
+ // Spacing & Padding
55
+ "pb-2",
56
+ "pt-2.5",
57
+ // Typography
58
+ "typo-body",
59
+ // Colors & States
60
+ "cursor-pointer",
61
+ "text-text-tertiary",
62
+ "hover:bg-bg-secondary/60",
63
+ "hover:text-text-tertiary_hover",
64
+ "data-[state=active]:text-text-primary",
65
+ "data-[state=active]:border-b-border-brand",
66
+ "disabled:opacity-50",
67
+ "disabled:pointer-events-none",
68
+ // Borders
69
+ "border-b-2",
70
+ "border-b-transparent",
71
+ // Focus & Accessibility
72
+ "focus-visible:ring-2",
73
+ "focus-visible:ring-utility-blue/70",
74
+ "focus-visible:outline-1",
75
+ // Transitions
76
+ "transition-[color,box-shadow]",
77
+ // Icons
78
+ "[&_svg]:pointer-events-none",
79
+ "[&_svg]:shrink-0",
80
+ "[&_svg:not([class*='size-'])]:size-4",
81
+ // Groups
82
+ "group/tabs-trigger",
83
+ );
84
+
85
+ // Tabs content styles
86
+ const tabsContentStyles = cn("grow", "outline-none", "overflow-auto");
8
87
 
9
88
  const tabsVariants = cva("", {
10
89
  variants: {
@@ -20,7 +99,9 @@ const tabsVariants = cva("", {
20
99
  **:data-[slot=tabs-list]:divide-x`,
21
100
  // TabsTrigger
22
101
  `**:data-[slot=tabs-trigger]:max-w-80
102
+ **:data-[slot=tabs-trigger]:w-60
23
103
  **:data-[slot=tabs-trigger]:min-w-40
104
+ **:data-[slot=tabs-trigger]:data-[state=inactive]:text-text-secondary
24
105
  **:data-[slot=tabs-trigger]:data-[state=inactive]:border-b-1
25
106
  **:data-[slot=tabs-trigger]:data-[state=inactive]:border-b-border-secondary
26
107
  **:data-[slot=tabs-trigger]:data-[state=inactive]:pt-[9px]
@@ -39,7 +120,7 @@ function Tabs({
39
120
  return (
40
121
  <TabsPrimitive.Root
41
122
  data-slot="tabs"
42
- className={cn("flex flex-col", tabsVariants({ variant }), className)}
123
+ className={cn(baseTabsStyles, tabsVariants({ variant }), className)}
43
124
  {...props}
44
125
  />
45
126
  );
@@ -47,7 +128,7 @@ function Tabs({
47
128
 
48
129
  export function TabsAddButton(props: React.ComponentProps<typeof Button>) {
49
130
  return (
50
- <div className="grow h-full bg-bg-secondary border-l border-b">
131
+ <div className={tabsAddButtonContainerStyles}>
51
132
  <Button
52
133
  data-slot="tabs-add-button"
53
134
  variant="link"
@@ -60,19 +141,384 @@ export function TabsAddButton(props: React.ComponentProps<typeof Button>) {
60
141
  );
61
142
  }
62
143
 
144
+ const horizontalScroll = (event: React.WheelEvent) => {
145
+ const mode = event.deltaMode;
146
+ let deltaPx = 0;
147
+
148
+ if (mode === 0) {
149
+ deltaPx = event.deltaY;
150
+ } else if (mode === 1) {
151
+ deltaPx = event.deltaY * 160;
152
+ } else if (mode === 2) {
153
+ deltaPx = event.currentTarget.clientWidth;
154
+ }
155
+
156
+ const newScrollLeft = event.currentTarget.scrollLeft + deltaPx;
157
+
158
+ event.currentTarget.scrollTo({
159
+ left: newScrollLeft,
160
+ behavior: "smooth",
161
+ });
162
+ };
163
+
164
+ const performHorizontalScroll = (
165
+ tabsListRef: React.RefObject<HTMLDivElement | null>,
166
+ direction: "left" | "right",
167
+ ) => {
168
+ if (!tabsListRef.current) return;
169
+ const scrollAmount = 160;
170
+ let newScrollLeft = tabsListRef.current.scrollLeft;
171
+
172
+ if (direction === "left") {
173
+ newScrollLeft -= scrollAmount;
174
+ newScrollLeft -= newScrollLeft % scrollAmount;
175
+ } else {
176
+ newScrollLeft += scrollAmount;
177
+
178
+ const rightCoord = newScrollLeft + tabsListRef.current.clientWidth;
179
+
180
+ if (rightCoord % scrollAmount !== 0) {
181
+ newScrollLeft += scrollAmount - (rightCoord % scrollAmount);
182
+ }
183
+ }
184
+
185
+ tabsListRef.current.scrollTo({
186
+ left: newScrollLeft,
187
+ behavior: "smooth",
188
+ });
189
+ };
190
+
191
+ type EdgeScrollPosition = "touch" | "depart";
192
+ type FlowType = "overflow" | "underflow";
193
+
194
+ type TabsListProps = {
195
+ onLeftEdge?: (position: EdgeScrollPosition) => void;
196
+ onRightEdge?: (position: EdgeScrollPosition) => void;
197
+ onFlow?: (flow: FlowType) => void;
198
+ onResize?: (entries: ResizeObserverEntry[]) => void;
199
+ onTabChange?: (mutationRecords: MutationRecord[]) => void;
200
+ } & React.ComponentProps<typeof TabsPrimitive.List>;
201
+
63
202
  function TabsList({
64
203
  className,
204
+ onLeftEdge,
205
+ onRightEdge,
206
+ onResize,
207
+ onFlow,
208
+ onTabChange,
65
209
  ...props
66
- }: React.ComponentProps<typeof TabsPrimitive.List>) {
210
+ }: TabsListProps) {
211
+ const tabListRef = React.useRef<HTMLDivElement | null>(null);
212
+
213
+ const onLeftEdgeRef = React.useRef(onLeftEdge);
214
+ React.useEffect(() => {
215
+ onLeftEdgeRef.current = onLeftEdge;
216
+ }, [onLeftEdge]);
217
+
218
+ const onResizeRef = React.useRef(onResize);
219
+ React.useEffect(() => {
220
+ onResizeRef.current = onResize;
221
+ }, [onResize]);
222
+
223
+ const onRightEdgeRef = React.useRef(onRightEdge);
224
+ React.useEffect(() => {
225
+ onRightEdgeRef.current = onRightEdge;
226
+ }, [onRightEdge]);
227
+
228
+ const onFlowRef = React.useRef(onFlow);
229
+ React.useEffect(() => {
230
+ onFlowRef.current = onFlow;
231
+ }, [onFlow]);
232
+
233
+ const onTabChangeRef = React.useRef(onTabChange);
234
+ React.useEffect(() => {
235
+ onTabChangeRef.current = onTabChange;
236
+ }, [onTabChange]);
237
+
238
+ React.useEffect(() => {
239
+ if (tabListRef.current === null) {
240
+ return;
241
+ }
242
+ const tabList = tabListRef.current;
243
+
244
+ let last: {
245
+ scrollLeft: number;
246
+ scrollWidth: number;
247
+ clientWidth: number;
248
+ } | null = null;
249
+
250
+ const handleScroll = () => {
251
+ if (onLeftEdgeRef.current) {
252
+ const newState: EdgeScrollPosition =
253
+ tabList.scrollLeft < 1 ? "touch" : "depart";
254
+
255
+ if (last === null) {
256
+ onLeftEdgeRef.current(newState);
257
+ } else {
258
+ const lastState: EdgeScrollPosition =
259
+ last.scrollLeft < 1 ? "touch" : "depart";
260
+
261
+ if (lastState !== newState) {
262
+ onLeftEdgeRef.current(newState);
263
+ }
264
+ }
265
+ }
266
+
267
+ if (onRightEdgeRef.current) {
268
+ const newState: EdgeScrollPosition =
269
+ tabList.scrollWidth - tabList.clientWidth - tabList.scrollLeft < 1
270
+ ? "touch"
271
+ : "depart";
272
+
273
+ if (last === null) {
274
+ onRightEdgeRef.current(newState);
275
+ } else {
276
+ const lastState: EdgeScrollPosition =
277
+ last.scrollWidth - last.clientWidth - last.scrollLeft < 1
278
+ ? "touch"
279
+ : "depart";
280
+
281
+ if (lastState !== newState) {
282
+ onRightEdgeRef.current(newState);
283
+ }
284
+ }
285
+ }
286
+
287
+ if (onFlowRef.current) {
288
+ const newState: FlowType =
289
+ tabList.scrollWidth > tabList.clientWidth ? "overflow" : "underflow";
290
+
291
+ if (last === null) {
292
+ onFlowRef.current(newState);
293
+ } else {
294
+ const lastState =
295
+ last.scrollWidth > last.clientWidth ? "overflow" : "underflow";
296
+ if (lastState !== newState) {
297
+ onFlowRef.current(newState);
298
+ }
299
+ }
300
+ }
301
+
302
+ last = {
303
+ scrollLeft: tabList.scrollLeft,
304
+ scrollWidth: tabList.scrollWidth,
305
+ clientWidth: tabList.clientWidth,
306
+ };
307
+ };
308
+
309
+ const scrollCallback = (_ev: unknown) => handleScroll();
310
+ const resizeObserver = new ResizeObserver((entries) => {
311
+ handleScroll();
312
+ if (onResizeRef.current) {
313
+ onResizeRef.current(entries);
314
+ }
315
+ });
316
+ const mutationObserver = new MutationObserver((mutationRecords) => {
317
+ handleScroll();
318
+ if (onTabChangeRef.current) {
319
+ onTabChangeRef.current(mutationRecords);
320
+ }
321
+ });
322
+
323
+ tabList.addEventListener("scroll", scrollCallback, { passive: true });
324
+ resizeObserver.observe(tabList);
325
+ mutationObserver.observe(tabList, { childList: true });
326
+
327
+ return () => {
328
+ tabList.removeEventListener("scroll", scrollCallback);
329
+ resizeObserver.disconnect();
330
+ mutationObserver.disconnect();
331
+ };
332
+ }, []);
333
+
67
334
  return (
68
335
  <TabsPrimitive.List
69
336
  data-slot="tabs-list"
70
337
  className={cn("inline-flex w-fit items-center", className)}
71
338
  {...props}
339
+ ref={(element) => {
340
+ tabListRef.current = element;
341
+ if (props.ref !== undefined && props.ref !== null) {
342
+ if (typeof props.ref === "function") {
343
+ props.ref(element);
344
+ } else {
345
+ props.ref.current = element;
346
+ }
347
+ }
348
+ }}
72
349
  />
73
350
  );
74
351
  }
75
352
 
353
+ type TabScrollButtonProps = {
354
+ disabled: boolean;
355
+ onClick: () => void;
356
+ };
357
+
358
+ function TabScrollLeftButton({
359
+ disabled,
360
+ onClick,
361
+ }: TabScrollButtonProps): React.ReactElement {
362
+ return (
363
+ <Button
364
+ variant="link"
365
+ size="small"
366
+ disabled={disabled}
367
+ className="h-full border-r border-b bg-bg-secondary"
368
+ onClick={onClick}
369
+ >
370
+ <ChevronLeft />
371
+ </Button>
372
+ );
373
+ }
374
+
375
+ function TabScrollRightButton({
376
+ disabled,
377
+ onClick,
378
+ }: TabScrollButtonProps): React.ReactElement {
379
+ return (
380
+ <Button
381
+ variant="link"
382
+ size="small"
383
+ disabled={disabled}
384
+ className="h-full border-l border-b bg-bg-secondary"
385
+ onClick={onClick}
386
+ >
387
+ <ChevronRight />
388
+ </Button>
389
+ );
390
+ }
391
+
392
+ function TabsBrowserList({
393
+ className,
394
+ children,
395
+ ...props
396
+ }: React.ComponentProps<typeof TabsPrimitive.List>) {
397
+ const tabsListRef = React.useRef<HTMLDivElement | null>(null);
398
+
399
+ const [showScrollButtons, setShowScrollButtons] = React.useState(false);
400
+ const [canScrollLeft, setCanScrollLeft] = React.useState(false);
401
+ const [canScrollRight, setCanScrollRight] = React.useState(false);
402
+
403
+ return (
404
+ <React.Fragment>
405
+ {showScrollButtons && (
406
+ <TabScrollLeftButton
407
+ disabled={!canScrollLeft}
408
+ onClick={() => performHorizontalScroll(tabsListRef, "left")}
409
+ />
410
+ )}
411
+
412
+ <TabsList
413
+ onLeftEdge={(edgeState) => {
414
+ if (edgeState === "touch") {
415
+ setCanScrollLeft(false);
416
+ } else {
417
+ setCanScrollLeft(true);
418
+ }
419
+ }}
420
+ onRightEdge={(edgeState) => {
421
+ if (edgeState === "touch") {
422
+ setCanScrollRight(false);
423
+ } else {
424
+ setCanScrollRight(true);
425
+ }
426
+ }}
427
+ onFlow={(flow) => {
428
+ if (flow === "overflow") {
429
+ setShowScrollButtons(true);
430
+ } else {
431
+ setShowScrollButtons(false);
432
+ }
433
+ }}
434
+ onResize={() => {
435
+ tabsListRef.current
436
+ ?.querySelector<HTMLButtonElement>('button[data-state="active"]')
437
+ ?.scrollIntoView();
438
+ }}
439
+ onTabChange={(entries) => {
440
+ if (
441
+ entries.filter((entry) => entry.addedNodes.length !== 0).length !==
442
+ 0
443
+ ) {
444
+ tabsListRef.current
445
+ ?.querySelector<HTMLButtonElement>('button[data-state="active"]')
446
+ ?.scrollIntoView();
447
+ }
448
+ }}
449
+ data-slot="tabs-list"
450
+ className={cn(tabsListStyles, className)}
451
+ onWheel={(event) => horizontalScroll(event)}
452
+ {...props}
453
+ ref={tabsListRef}
454
+ >
455
+ {children}
456
+ </TabsList>
457
+
458
+ {showScrollButtons && (
459
+ <TabScrollRightButton
460
+ disabled={!canScrollRight}
461
+ onClick={() => performHorizontalScroll(tabsListRef, "right")}
462
+ />
463
+ )}
464
+ </React.Fragment>
465
+ );
466
+ }
467
+
468
+ export function TabsListDropdown({
469
+ tabs,
470
+ handleTabSelect,
471
+ handleCloseTab,
472
+ }: {
473
+ tabs: { id: string; content: React.ReactNode }[];
474
+ handleTabSelect?: (tabId: string) => void;
475
+ handleCloseTab?: (tabId: string) => void;
476
+ }) {
477
+ const [isMenuOpen, setIsMenuOpen] = React.useState(false);
478
+ return (
479
+ <Popover open={isMenuOpen} onOpenChange={setIsMenuOpen}>
480
+ <PopoverTrigger asChild>
481
+ <Button variant="link" className="bg-bg-secondary h-full border-b pr-6">
482
+ <ChevronDownIcon className="size-4" />
483
+ </Button>
484
+ </PopoverTrigger>
485
+ <PopoverContent className="w-80 p-0 mr-3" align="end">
486
+ <Command>
487
+ <CommandInput placeholder="Search tabs..." />
488
+ <CommandList>
489
+ <CommandEmpty>Not tabs found.</CommandEmpty>
490
+ {tabs.map((tab) => (
491
+ <CommandItem
492
+ key={tab.id}
493
+ onSelect={() => {
494
+ handleTabSelect?.(tab.id);
495
+ setIsMenuOpen(false);
496
+ }}
497
+ className="group flex items-center justify-between"
498
+ >
499
+ {tab.content}
500
+ {tabs.length > 1 && (
501
+ <Button
502
+ variant="ghost"
503
+ size="small"
504
+ className="opacity-0 group-hover:opacity-100 transition-opacity p-1 ml-2"
505
+ onClick={(e) => {
506
+ e.stopPropagation();
507
+ handleCloseTab?.(tab.id);
508
+ }}
509
+ >
510
+ <X className="size-3" />
511
+ </Button>
512
+ )}
513
+ </CommandItem>
514
+ ))}
515
+ </CommandList>
516
+ </Command>
517
+ </PopoverContent>
518
+ </Popover>
519
+ );
520
+ }
521
+
76
522
  function TabsTrigger({
77
523
  className,
78
524
  onClose,
@@ -84,15 +530,8 @@ function TabsTrigger({
84
530
  <TabsPrimitive.Trigger
85
531
  data-slot="tabs-trigger"
86
532
  className={cn(
87
- "group/tabs-trigger",
88
- "box-border h-10 typo-body px-3 pb-2 pt-2.5 cursor-pointer text-text-tertiary data-[state=active]:text-text-primary",
89
- "data-[state=active]:border-b-border-brand border-b-2 border-b-transparent hover:text-text-tertiary-hover focus-visible:border-ring",
90
- "focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:text-muted-foreground",
91
- "inline-flex flex-1 items-center justify-center whitespace-nowrap transition-[color,box-shadow]",
92
- "focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50",
93
- "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
94
- "hover:bg-bg-secondary/60",
95
- onClose ? "justify-between" : "",
533
+ baseTabsTriggerStyles,
534
+ onClose ? "justify-between" : "justify-start",
96
535
  className,
97
536
  )}
98
537
  {...props}
@@ -107,7 +546,7 @@ function TabsTrigger({
107
546
  }}
108
547
  variant="link"
109
548
  size="small"
110
- className="p-0 ml-2"
549
+ className="p-0 ml-2 opacity-0 group-hover/tabs-trigger:opacity-100 transition-opacity"
111
550
  asChild
112
551
  >
113
552
  <span>
@@ -126,10 +565,10 @@ function TabsContent({
126
565
  return (
127
566
  <TabsPrimitive.Content
128
567
  data-slot="tabs-content"
129
- className={cn("flex-1 outline-none", className)}
568
+ className={cn(tabsContentStyles, className)}
130
569
  {...props}
131
570
  />
132
571
  );
133
572
  }
134
573
 
135
- export { Tabs, TabsList, TabsTrigger, TabsContent };
574
+ export { Tabs, TabsList, TabsTrigger, TabsContent, TabsBrowserList };
@@ -2,14 +2,52 @@ import type * as React from "react";
2
2
 
3
3
  import { cn } from "#shadcn/lib/utils";
4
4
 
5
+ // Textarea styles
6
+ const textareaStyles = cn(
7
+ // Layout
8
+ "flex",
9
+ "w-full",
10
+ "min-h-16",
11
+ "field-sizing-content",
12
+ // Shape
13
+ "rounded-md",
14
+ // Borders
15
+ "border",
16
+ "border-border-primary",
17
+ // Background & Colors
18
+ "bg-transparent",
19
+ "text-base",
20
+ // Spacing
21
+ "px-3",
22
+ "py-2",
23
+ // Typography
24
+ "md:text-sm",
25
+ // Placeholder
26
+ "placeholder:text-text-tertiary",
27
+ // Transitions
28
+ "transition-[color,box-shadow]",
29
+ "outline-none",
30
+ // Hover
31
+ "hover:border-border-primary_hover",
32
+ // Focus
33
+ "focus-visible:border-border-link",
34
+ "focus-visible:ring-2",
35
+ "focus-visible:ring-utility-blue/70",
36
+ // Invalid
37
+ "aria-invalid:border-border-error",
38
+ "aria-invalid:ring-2",
39
+ "aria-invalid:ring-utility-red/70",
40
+ // Disabled
41
+ "disabled:cursor-not-allowed",
42
+ "disabled:opacity-50",
43
+ "disabled:border-border-disabled",
44
+ );
45
+
5
46
  function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
6
47
  return (
7
48
  <textarea
8
49
  data-slot="textarea"
9
- className={cn(
10
- "border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
11
- className,
12
- )}
50
+ className={cn(textareaStyles, className)}
13
51
  {...props}
14
52
  />
15
53
  );
@@ -5,6 +5,31 @@ import * as React from "react";
5
5
  import { toggleVariants } from "#shadcn/components/ui/toggle";
6
6
  import { cn } from "#shadcn/lib/utils";
7
7
 
8
+ // Toggle group styles
9
+ const toggleGroupStyles = cn(
10
+ "group/toggle-group",
11
+ "flex",
12
+ "w-fit",
13
+ "items-center",
14
+ "rounded-md",
15
+ "data-[variant=outline]:shadow-xs",
16
+ );
17
+
18
+ // Toggle group item styles
19
+ const toggleGroupItemStyles = cn(
20
+ "min-w-0",
21
+ "flex-1",
22
+ "shrink-0",
23
+ "rounded-none",
24
+ "shadow-none",
25
+ "first:rounded-l-md",
26
+ "last:rounded-r-md",
27
+ "focus:z-10",
28
+ "focus-visible:z-10",
29
+ "data-[variant=outline]:border-l-0",
30
+ "data-[variant=outline]:first:border-l",
31
+ );
32
+
8
33
  const ToggleGroupContext = React.createContext<
9
34
  VariantProps<typeof toggleVariants>
10
35
  >({
@@ -25,10 +50,7 @@ function ToggleGroup({
25
50
  data-slot="toggle-group"
26
51
  data-variant={variant}
27
52
  data-size={size}
28
- className={cn(
29
- "group/toggle-group flex w-fit items-center rounded-md data-[variant=outline]:shadow-xs",
30
- className,
31
- )}
53
+ className={cn(toggleGroupStyles, className)}
32
54
  {...props}
33
55
  >
34
56
  <ToggleGroupContext.Provider value={{ variant, size }}>
@@ -58,7 +80,7 @@ function ToggleGroupItem({
58
80
  variant: context.variant || variant,
59
81
  size: context.size || size,
60
82
  }),
61
- "min-w-0 flex-1 shrink-0 rounded-none shadow-none first:rounded-l-md last:rounded-r-md focus:z-10 focus-visible:z-10 data-[variant=outline]:border-l-0 data-[variant=outline]:first:border-l",
83
+ toggleGroupItemStyles,
62
84
  className,
63
85
  )}
64
86
  {...props}