shadcn-rails 0.1.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 (315) hide show
  1. checksums.yaml +7 -0
  2. data/.dockerignore +40 -0
  3. data/CHANGELOG.md +54 -0
  4. data/CLAUDE.md +463 -0
  5. data/PROGRESS.md +485 -0
  6. data/README.md +1483 -0
  7. data/Rakefile +29 -0
  8. data/__tests__/controllers/__snapshots__/calendar_controller.test.js.snap +13 -0
  9. data/__tests__/controllers/__snapshots__/popover_controller.test.js.snap +46 -0
  10. data/__tests__/controllers/__snapshots__/sheet_controller.test.js.snap +111 -0
  11. data/__tests__/controllers/__snapshots__/tabs_controller.test.js.snap +27 -0
  12. data/__tests__/controllers/accordion_controller.test.js +904 -0
  13. data/__tests__/controllers/calendar_controller.test.js +1370 -0
  14. data/__tests__/controllers/carousel_controller.test.js +912 -0
  15. data/__tests__/controllers/checkbox_controller.test.js +454 -0
  16. data/__tests__/controllers/collapsible_controller.test.js +407 -0
  17. data/__tests__/controllers/combobox_controller.test.js +966 -0
  18. data/__tests__/controllers/context_menu_controller.test.js +627 -0
  19. data/__tests__/controllers/date_picker_controller.test.js +636 -0
  20. data/__tests__/controllers/dialog_controller.test.js +878 -0
  21. data/__tests__/controllers/drawer_controller.test.js +995 -0
  22. data/__tests__/controllers/menubar_controller.test.js +736 -0
  23. data/__tests__/controllers/navigation_menu_controller.test.js +598 -0
  24. data/__tests__/controllers/popover_controller.test.js +1007 -0
  25. data/__tests__/controllers/radio_group_controller.test.js +640 -0
  26. data/__tests__/controllers/resizable_controller.test.js +680 -0
  27. data/__tests__/controllers/select_controller.test.js +674 -0
  28. data/__tests__/controllers/sheet_controller.test.js +986 -0
  29. data/__tests__/controllers/slider_controller.test.js +1036 -0
  30. data/__tests__/controllers/switch_controller.test.js +424 -0
  31. data/__tests__/controllers/tabs_controller.test.js +907 -0
  32. data/__tests__/controllers/toggle_group_controller.test.js +839 -0
  33. data/__tests__/controllers/tooltip_controller.test.js +808 -0
  34. data/__tests__/helpers/stimulus-test-helper.js +203 -0
  35. data/app/assets/config/manifest.js +1 -0
  36. data/app/assets/javascripts/shadcn/controllers/accordion_controller.d.ts +53 -0
  37. data/app/assets/javascripts/shadcn/controllers/accordion_controller.js +140 -0
  38. data/app/assets/javascripts/shadcn/controllers/avatar_controller.d.ts +22 -0
  39. data/app/assets/javascripts/shadcn/controllers/avatar_controller.js +26 -0
  40. data/app/assets/javascripts/shadcn/controllers/calendar_controller.js +592 -0
  41. data/app/assets/javascripts/shadcn/controllers/carousel_controller.js +263 -0
  42. data/app/assets/javascripts/shadcn/controllers/checkbox_controller.d.ts +31 -0
  43. data/app/assets/javascripts/shadcn/controllers/checkbox_controller.js +48 -0
  44. data/app/assets/javascripts/shadcn/controllers/collapsible_controller.d.ts +43 -0
  45. data/app/assets/javascripts/shadcn/controllers/collapsible_controller.js +73 -0
  46. data/app/assets/javascripts/shadcn/controllers/combobox_controller.js +234 -0
  47. data/app/assets/javascripts/shadcn/controllers/command_controller.js +141 -0
  48. data/app/assets/javascripts/shadcn/controllers/command_dialog_controller.js +162 -0
  49. data/app/assets/javascripts/shadcn/controllers/context_menu_controller.js +202 -0
  50. data/app/assets/javascripts/shadcn/controllers/date_picker_controller.js +282 -0
  51. data/app/assets/javascripts/shadcn/controllers/dialog_controller.d.ts +67 -0
  52. data/app/assets/javascripts/shadcn/controllers/dialog_controller.js +187 -0
  53. data/app/assets/javascripts/shadcn/controllers/drawer_controller.d.ts +58 -0
  54. data/app/assets/javascripts/shadcn/controllers/drawer_controller.js +112 -0
  55. data/app/assets/javascripts/shadcn/controllers/dropdown_controller.d.ts +83 -0
  56. data/app/assets/javascripts/shadcn/controllers/dropdown_controller.js +225 -0
  57. data/app/assets/javascripts/shadcn/controllers/hover_card_controller.d.ts +59 -0
  58. data/app/assets/javascripts/shadcn/controllers/hover_card_controller.js +143 -0
  59. data/app/assets/javascripts/shadcn/controllers/input_otp_controller.d.ts +44 -0
  60. data/app/assets/javascripts/shadcn/controllers/input_otp_controller.js +206 -0
  61. data/app/assets/javascripts/shadcn/controllers/menubar_controller.js +323 -0
  62. data/app/assets/javascripts/shadcn/controllers/navigation_menu_controller.js +251 -0
  63. data/app/assets/javascripts/shadcn/controllers/popover_controller.d.ts +56 -0
  64. data/app/assets/javascripts/shadcn/controllers/popover_controller.js +141 -0
  65. data/app/assets/javascripts/shadcn/controllers/radio_group_controller.d.ts +47 -0
  66. data/app/assets/javascripts/shadcn/controllers/radio_group_controller.js +108 -0
  67. data/app/assets/javascripts/shadcn/controllers/resizable_controller.js +272 -0
  68. data/app/assets/javascripts/shadcn/controllers/scroll_area_controller.d.ts +44 -0
  69. data/app/assets/javascripts/shadcn/controllers/scroll_area_controller.js +74 -0
  70. data/app/assets/javascripts/shadcn/controllers/select_controller.d.ts +84 -0
  71. data/app/assets/javascripts/shadcn/controllers/select_controller.js +222 -0
  72. data/app/assets/javascripts/shadcn/controllers/sheet_controller.d.ts +60 -0
  73. data/app/assets/javascripts/shadcn/controllers/sheet_controller.js +151 -0
  74. data/app/assets/javascripts/shadcn/controllers/sidebar_controller.js +148 -0
  75. data/app/assets/javascripts/shadcn/controllers/slider_controller.d.ts +102 -0
  76. data/app/assets/javascripts/shadcn/controllers/slider_controller.js +364 -0
  77. data/app/assets/javascripts/shadcn/controllers/switch_controller.d.ts +46 -0
  78. data/app/assets/javascripts/shadcn/controllers/switch_controller.js +78 -0
  79. data/app/assets/javascripts/shadcn/controllers/tabs_controller.d.ts +51 -0
  80. data/app/assets/javascripts/shadcn/controllers/tabs_controller.js +126 -0
  81. data/app/assets/javascripts/shadcn/controllers/toast_controller.d.ts +37 -0
  82. data/app/assets/javascripts/shadcn/controllers/toast_controller.js +58 -0
  83. data/app/assets/javascripts/shadcn/controllers/toggle_controller.d.ts +27 -0
  84. data/app/assets/javascripts/shadcn/controllers/toggle_controller.js +42 -0
  85. data/app/assets/javascripts/shadcn/controllers/toggle_group_controller.d.ts +44 -0
  86. data/app/assets/javascripts/shadcn/controllers/toggle_group_controller.js +68 -0
  87. data/app/assets/javascripts/shadcn/controllers/tooltip_controller.d.ts +56 -0
  88. data/app/assets/javascripts/shadcn/controllers/tooltip_controller.js +117 -0
  89. data/app/assets/javascripts/shadcn/index.d.ts +74 -0
  90. data/app/assets/javascripts/shadcn/index.js +133 -0
  91. data/app/assets/stylesheets/.keep +0 -0
  92. data/app/assets/stylesheets/shadcn/base.css +445 -0
  93. data/app/assets/stylesheets/shadcn/components.css +513 -0
  94. data/app/assets/stylesheets/shadcn/index.css +18 -0
  95. data/app/assets/stylesheets/shadcn/themes/gray.css +68 -0
  96. data/app/assets/stylesheets/shadcn/themes/slate.css +68 -0
  97. data/app/assets/stylesheets/shadcn/themes/stone.css +68 -0
  98. data/app/assets/stylesheets/shadcn/themes/zinc.css +68 -0
  99. data/app/components/shadcn/accordion_component.rb +63 -0
  100. data/app/components/shadcn/accordion_content_component.rb +29 -0
  101. data/app/components/shadcn/accordion_item_component.rb +40 -0
  102. data/app/components/shadcn/accordion_trigger_component.rb +49 -0
  103. data/app/components/shadcn/alert_component.rb +75 -0
  104. data/app/components/shadcn/alert_description_component.rb +12 -0
  105. data/app/components/shadcn/alert_dialog_action_component.rb +24 -0
  106. data/app/components/shadcn/alert_dialog_cancel_component.rb +24 -0
  107. data/app/components/shadcn/alert_dialog_component.rb +71 -0
  108. data/app/components/shadcn/alert_dialog_content_component.rb +57 -0
  109. data/app/components/shadcn/alert_dialog_description_component.rb +12 -0
  110. data/app/components/shadcn/alert_dialog_footer_component.rb +19 -0
  111. data/app/components/shadcn/alert_dialog_header_component.rb +19 -0
  112. data/app/components/shadcn/alert_dialog_title_component.rb +12 -0
  113. data/app/components/shadcn/alert_title_component.rb +12 -0
  114. data/app/components/shadcn/aspect_ratio_component.rb +49 -0
  115. data/app/components/shadcn/avatar_component.rb +107 -0
  116. data/app/components/shadcn/avatar_fallback_component.rb +17 -0
  117. data/app/components/shadcn/badge_component.rb +49 -0
  118. data/app/components/shadcn/base_component.rb +100 -0
  119. data/app/components/shadcn/breadcrumb_component.rb +70 -0
  120. data/app/components/shadcn/breadcrumb_item_component.rb +50 -0
  121. data/app/components/shadcn/button_component.rb +141 -0
  122. data/app/components/shadcn/button_group_component.rb +69 -0
  123. data/app/components/shadcn/calendar_component.rb +337 -0
  124. data/app/components/shadcn/card_action_component.rb +10 -0
  125. data/app/components/shadcn/card_component.rb +63 -0
  126. data/app/components/shadcn/card_content_component.rb +19 -0
  127. data/app/components/shadcn/card_description_component.rb +12 -0
  128. data/app/components/shadcn/card_footer_component.rb +12 -0
  129. data/app/components/shadcn/card_header_component.rb +24 -0
  130. data/app/components/shadcn/card_title_component.rb +18 -0
  131. data/app/components/shadcn/carousel_component.rb +275 -0
  132. data/app/components/shadcn/checkbox_component.rb +103 -0
  133. data/app/components/shadcn/collapsible_component.rb +66 -0
  134. data/app/components/shadcn/collapsible_content_component.rb +28 -0
  135. data/app/components/shadcn/combobox_component.rb +322 -0
  136. data/app/components/shadcn/command_component.rb +52 -0
  137. data/app/components/shadcn/command_dialog_component.rb +76 -0
  138. data/app/components/shadcn/command_empty_component.rb +12 -0
  139. data/app/components/shadcn/command_group_component.rb +34 -0
  140. data/app/components/shadcn/command_input_component.rb +59 -0
  141. data/app/components/shadcn/command_item_component.rb +48 -0
  142. data/app/components/shadcn/command_list_component.rb +38 -0
  143. data/app/components/shadcn/command_separator_component.rb +12 -0
  144. data/app/components/shadcn/command_shortcut_component.rb +12 -0
  145. data/app/components/shadcn/context_menu_component.rb +64 -0
  146. data/app/components/shadcn/context_menu_content_component.rb +44 -0
  147. data/app/components/shadcn/context_menu_item_component.rb +63 -0
  148. data/app/components/shadcn/context_menu_label_component.rb +18 -0
  149. data/app/components/shadcn/context_menu_separator_component.rb +12 -0
  150. data/app/components/shadcn/context_menu_shortcut_component.rb +12 -0
  151. data/app/components/shadcn/date_picker_component.rb +368 -0
  152. data/app/components/shadcn/dialog_component.rb +77 -0
  153. data/app/components/shadcn/dialog_content_component.rb +91 -0
  154. data/app/components/shadcn/dialog_description_component.rb +12 -0
  155. data/app/components/shadcn/dialog_footer_component.rb +12 -0
  156. data/app/components/shadcn/dialog_header_component.rb +19 -0
  157. data/app/components/shadcn/dialog_title_component.rb +12 -0
  158. data/app/components/shadcn/drawer_component.rb +72 -0
  159. data/app/components/shadcn/drawer_content_component.rb +76 -0
  160. data/app/components/shadcn/drawer_description_component.rb +12 -0
  161. data/app/components/shadcn/drawer_footer_component.rb +12 -0
  162. data/app/components/shadcn/drawer_header_component.rb +19 -0
  163. data/app/components/shadcn/drawer_title_component.rb +12 -0
  164. data/app/components/shadcn/dropdown_menu_component.rb +75 -0
  165. data/app/components/shadcn/dropdown_menu_content_component.rb +49 -0
  166. data/app/components/shadcn/dropdown_menu_group_component.rb +10 -0
  167. data/app/components/shadcn/dropdown_menu_item_component.rb +63 -0
  168. data/app/components/shadcn/dropdown_menu_label_component.rb +18 -0
  169. data/app/components/shadcn/dropdown_menu_separator_component.rb +12 -0
  170. data/app/components/shadcn/dropdown_menu_shortcut_component.rb +12 -0
  171. data/app/components/shadcn/empty_component.rb +48 -0
  172. data/app/components/shadcn/empty_content_component.rb +12 -0
  173. data/app/components/shadcn/empty_description_component.rb +12 -0
  174. data/app/components/shadcn/empty_header_component.rb +29 -0
  175. data/app/components/shadcn/empty_media_component.rb +21 -0
  176. data/app/components/shadcn/empty_title_component.rb +12 -0
  177. data/app/components/shadcn/field_component.rb +113 -0
  178. data/app/components/shadcn/hover_card_component.rb +64 -0
  179. data/app/components/shadcn/hover_card_content_component.rb +36 -0
  180. data/app/components/shadcn/input_component.rb +108 -0
  181. data/app/components/shadcn/input_group_component.rb +70 -0
  182. data/app/components/shadcn/input_otp_component.rb +183 -0
  183. data/app/components/shadcn/item_actions_component.rb +12 -0
  184. data/app/components/shadcn/item_component.rb +98 -0
  185. data/app/components/shadcn/item_content_component.rb +24 -0
  186. data/app/components/shadcn/item_description_component.rb +12 -0
  187. data/app/components/shadcn/item_footer_component.rb +12 -0
  188. data/app/components/shadcn/item_group_component.rb +24 -0
  189. data/app/components/shadcn/item_header_component.rb +12 -0
  190. data/app/components/shadcn/item_media_component.rb +22 -0
  191. data/app/components/shadcn/item_separator_component.rb +12 -0
  192. data/app/components/shadcn/item_title_component.rb +12 -0
  193. data/app/components/shadcn/kbd_component.rb +36 -0
  194. data/app/components/shadcn/label_component.rb +49 -0
  195. data/app/components/shadcn/menubar_checkbox_item_component.rb +76 -0
  196. data/app/components/shadcn/menubar_component.rb +56 -0
  197. data/app/components/shadcn/menubar_content_component.rb +64 -0
  198. data/app/components/shadcn/menubar_item_component.rb +65 -0
  199. data/app/components/shadcn/menubar_label_component.rb +27 -0
  200. data/app/components/shadcn/menubar_menu_component.rb +34 -0
  201. data/app/components/shadcn/menubar_radio_group_component.rb +42 -0
  202. data/app/components/shadcn/menubar_radio_item_component.rb +76 -0
  203. data/app/components/shadcn/menubar_separator_component.rb +22 -0
  204. data/app/components/shadcn/menubar_shortcut_component.rb +21 -0
  205. data/app/components/shadcn/menubar_sub_component.rb +38 -0
  206. data/app/components/shadcn/menubar_sub_content_component.rb +45 -0
  207. data/app/components/shadcn/menubar_sub_trigger_component.rb +59 -0
  208. data/app/components/shadcn/menubar_trigger_component.rb +31 -0
  209. data/app/components/shadcn/native_select_component.rb +150 -0
  210. data/app/components/shadcn/navigation_menu_component.rb +76 -0
  211. data/app/components/shadcn/navigation_menu_content_component.rb +30 -0
  212. data/app/components/shadcn/navigation_menu_item_component.rb +39 -0
  213. data/app/components/shadcn/navigation_menu_link_component.rb +38 -0
  214. data/app/components/shadcn/navigation_menu_list_component.rb +29 -0
  215. data/app/components/shadcn/navigation_menu_trigger_component.rb +59 -0
  216. data/app/components/shadcn/pagination_component.rb +195 -0
  217. data/app/components/shadcn/pagination_content_component.rb +47 -0
  218. data/app/components/shadcn/pagination_ellipsis_component.rb +30 -0
  219. data/app/components/shadcn/pagination_item_component.rb +53 -0
  220. data/app/components/shadcn/pagination_next_component.rb +48 -0
  221. data/app/components/shadcn/pagination_previous_component.rb +48 -0
  222. data/app/components/shadcn/popover_component.rb +76 -0
  223. data/app/components/shadcn/popover_content_component.rb +25 -0
  224. data/app/components/shadcn/progress_component.rb +77 -0
  225. data/app/components/shadcn/radio_group_component.rb +129 -0
  226. data/app/components/shadcn/radio_group_item_component.rb +109 -0
  227. data/app/components/shadcn/resizable_handle_component.rb +98 -0
  228. data/app/components/shadcn/resizable_panel_component.rb +56 -0
  229. data/app/components/shadcn/resizable_panel_group_component.rb +94 -0
  230. data/app/components/shadcn/scroll_area_component.rb +110 -0
  231. data/app/components/shadcn/select_component.rb +151 -0
  232. data/app/components/shadcn/select_group_component.rb +32 -0
  233. data/app/components/shadcn/select_item_component.rb +59 -0
  234. data/app/components/shadcn/select_separator_component.rb +12 -0
  235. data/app/components/shadcn/separator_component.rb +54 -0
  236. data/app/components/shadcn/sheet_component.rb +82 -0
  237. data/app/components/shadcn/sheet_content_component.rb +95 -0
  238. data/app/components/shadcn/sheet_description_component.rb +12 -0
  239. data/app/components/shadcn/sheet_footer_component.rb +12 -0
  240. data/app/components/shadcn/sheet_header_component.rb +19 -0
  241. data/app/components/shadcn/sheet_title_component.rb +12 -0
  242. data/app/components/shadcn/sidebar_component.rb +180 -0
  243. data/app/components/shadcn/sidebar_content_component.rb +32 -0
  244. data/app/components/shadcn/sidebar_footer_component.rb +24 -0
  245. data/app/components/shadcn/sidebar_group_action_component.rb +26 -0
  246. data/app/components/shadcn/sidebar_group_component.rb +38 -0
  247. data/app/components/shadcn/sidebar_group_content_component.rb +32 -0
  248. data/app/components/shadcn/sidebar_group_label_component.rb +25 -0
  249. data/app/components/shadcn/sidebar_header_component.rb +24 -0
  250. data/app/components/shadcn/sidebar_inset_component.rb +25 -0
  251. data/app/components/shadcn/sidebar_menu_action_component.rb +37 -0
  252. data/app/components/shadcn/sidebar_menu_badge_component.rb +25 -0
  253. data/app/components/shadcn/sidebar_menu_button_component.rb +52 -0
  254. data/app/components/shadcn/sidebar_menu_component.rb +32 -0
  255. data/app/components/shadcn/sidebar_menu_item_component.rb +41 -0
  256. data/app/components/shadcn/sidebar_menu_skeleton_component.rb +46 -0
  257. data/app/components/shadcn/sidebar_menu_sub_button_component.rb +43 -0
  258. data/app/components/shadcn/sidebar_menu_sub_component.rb +33 -0
  259. data/app/components/shadcn/sidebar_menu_sub_item_component.rb +30 -0
  260. data/app/components/shadcn/sidebar_provider_component.rb +57 -0
  261. data/app/components/shadcn/sidebar_rail_component.rb +30 -0
  262. data/app/components/shadcn/sidebar_separator_component.rb +24 -0
  263. data/app/components/shadcn/sidebar_trigger_component.rb +51 -0
  264. data/app/components/shadcn/skeleton_component.rb +29 -0
  265. data/app/components/shadcn/slider_component.rb +76 -0
  266. data/app/components/shadcn/spinner_component.rb +67 -0
  267. data/app/components/shadcn/switch_component.rb +147 -0
  268. data/app/components/shadcn/table_body_component.rb +16 -0
  269. data/app/components/shadcn/table_caption_component.rb +12 -0
  270. data/app/components/shadcn/table_cell_component.rb +12 -0
  271. data/app/components/shadcn/table_component.rb +57 -0
  272. data/app/components/shadcn/table_footer_component.rb +16 -0
  273. data/app/components/shadcn/table_head_component.rb +12 -0
  274. data/app/components/shadcn/table_header_component.rb +16 -0
  275. data/app/components/shadcn/table_row_component.rb +40 -0
  276. data/app/components/shadcn/tabs_component.rb +78 -0
  277. data/app/components/shadcn/tabs_content_component.rb +32 -0
  278. data/app/components/shadcn/tabs_list_component.rb +30 -0
  279. data/app/components/shadcn/tabs_trigger_component.rb +37 -0
  280. data/app/components/shadcn/textarea_component.rb +84 -0
  281. data/app/components/shadcn/toast_action_component.rb +18 -0
  282. data/app/components/shadcn/toast_component.rb +114 -0
  283. data/app/components/shadcn/toast_description_component.rb +12 -0
  284. data/app/components/shadcn/toast_title_component.rb +12 -0
  285. data/app/components/shadcn/toast_viewport_component.rb +12 -0
  286. data/app/components/shadcn/toggle_component.rb +77 -0
  287. data/app/components/shadcn/toggle_group_component.rb +96 -0
  288. data/app/components/shadcn/toggle_group_item_component.rb +62 -0
  289. data/app/components/shadcn/tooltip_component.rb +89 -0
  290. data/app/components/shadcn/typography_component.rb +112 -0
  291. data/babel.config.cjs +5 -0
  292. data/bin/console +11 -0
  293. data/bin/setup +8 -0
  294. data/config/importmap.rb +5 -0
  295. data/fly.toml +26 -0
  296. data/jest.config.js +19 -0
  297. data/jest.setup.js +8 -0
  298. data/lib/generators/shadcn/component/component_generator.rb +188 -0
  299. data/lib/generators/shadcn/install/install_generator.rb +140 -0
  300. data/lib/generators/shadcn/install/templates/initializer.rb.tt +35 -0
  301. data/lib/generators/shadcn/install/templates/shadcn.yml.tt +35 -0
  302. data/lib/generators/shadcn/theme/theme_generator.rb +128 -0
  303. data/lib/shadcn/rails/class_merger.rb +228 -0
  304. data/lib/shadcn/rails/configuration.rb +341 -0
  305. data/lib/shadcn/rails/engine.rb +59 -0
  306. data/lib/shadcn/rails/helpers/class_name_helper.rb +35 -0
  307. data/lib/shadcn/rails/helpers/component_helper.rb +60 -0
  308. data/lib/shadcn/rails/helpers/pagination_helper.rb +187 -0
  309. data/lib/shadcn/rails/version.rb +7 -0
  310. data/lib/shadcn/rails.rb +179 -0
  311. data/package-lock.json +7415 -0
  312. data/package.json +68 -0
  313. data/rollup.config.js +29 -0
  314. data/sig/shadcn/rails.rbs +6 -0
  315. metadata +526 -0
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Stone Theme for shadcn-rails
3
+ *
4
+ * Import this file to use the Stone color theme:
5
+ * @import "shadcn/themes/stone";
6
+ */
7
+
8
+ :root {
9
+ --background: 0 0% 100%;
10
+ --foreground: 20 14.3% 4.1%;
11
+
12
+ --card: 0 0% 100%;
13
+ --card-foreground: 20 14.3% 4.1%;
14
+
15
+ --popover: 0 0% 100%;
16
+ --popover-foreground: 20 14.3% 4.1%;
17
+
18
+ --primary: 24 9.8% 10%;
19
+ --primary-foreground: 60 9.1% 97.8%;
20
+
21
+ --secondary: 60 4.8% 95.9%;
22
+ --secondary-foreground: 24 9.8% 10%;
23
+
24
+ --muted: 60 4.8% 95.9%;
25
+ --muted-foreground: 25 5.3% 44.7%;
26
+
27
+ --accent: 60 4.8% 95.9%;
28
+ --accent-foreground: 24 9.8% 10%;
29
+
30
+ --destructive: 0 84.2% 60.2%;
31
+ --destructive-foreground: 60 9.1% 97.8%;
32
+
33
+ --border: 20 5.9% 90%;
34
+ --input: 20 5.9% 90%;
35
+ --ring: 20 14.3% 4.1%;
36
+
37
+ --radius: 0.5rem;
38
+ }
39
+
40
+ .dark {
41
+ --background: 20 14.3% 4.1%;
42
+ --foreground: 60 9.1% 97.8%;
43
+
44
+ --card: 20 14.3% 4.1%;
45
+ --card-foreground: 60 9.1% 97.8%;
46
+
47
+ --popover: 20 14.3% 4.1%;
48
+ --popover-foreground: 60 9.1% 97.8%;
49
+
50
+ --primary: 60 9.1% 97.8%;
51
+ --primary-foreground: 24 9.8% 10%;
52
+
53
+ --secondary: 12 6.5% 15.1%;
54
+ --secondary-foreground: 60 9.1% 97.8%;
55
+
56
+ --muted: 12 6.5% 15.1%;
57
+ --muted-foreground: 24 5.4% 63.9%;
58
+
59
+ --accent: 12 6.5% 15.1%;
60
+ --accent-foreground: 60 9.1% 97.8%;
61
+
62
+ --destructive: 0 62.8% 30.6%;
63
+ --destructive-foreground: 60 9.1% 97.8%;
64
+
65
+ --border: 12 6.5% 15.1%;
66
+ --input: 12 6.5% 15.1%;
67
+ --ring: 24 5.7% 82.9%;
68
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Zinc Theme for shadcn-rails
3
+ *
4
+ * Import this file to use the Zinc color theme:
5
+ * @import "shadcn/themes/zinc";
6
+ */
7
+
8
+ :root {
9
+ --background: 0 0% 100%;
10
+ --foreground: 240 10% 3.9%;
11
+
12
+ --card: 0 0% 100%;
13
+ --card-foreground: 240 10% 3.9%;
14
+
15
+ --popover: 0 0% 100%;
16
+ --popover-foreground: 240 10% 3.9%;
17
+
18
+ --primary: 240 5.9% 10%;
19
+ --primary-foreground: 0 0% 98%;
20
+
21
+ --secondary: 240 4.8% 95.9%;
22
+ --secondary-foreground: 240 5.9% 10%;
23
+
24
+ --muted: 240 4.8% 95.9%;
25
+ --muted-foreground: 240 3.8% 46.1%;
26
+
27
+ --accent: 240 4.8% 95.9%;
28
+ --accent-foreground: 240 5.9% 10%;
29
+
30
+ --destructive: 0 84.2% 60.2%;
31
+ --destructive-foreground: 0 0% 98%;
32
+
33
+ --border: 240 5.9% 90%;
34
+ --input: 240 5.9% 90%;
35
+ --ring: 240 5.9% 10%;
36
+
37
+ --radius: 0.5rem;
38
+ }
39
+
40
+ .dark {
41
+ --background: 240 10% 3.9%;
42
+ --foreground: 0 0% 98%;
43
+
44
+ --card: 240 10% 3.9%;
45
+ --card-foreground: 0 0% 98%;
46
+
47
+ --popover: 240 10% 3.9%;
48
+ --popover-foreground: 0 0% 98%;
49
+
50
+ --primary: 0 0% 98%;
51
+ --primary-foreground: 240 5.9% 10%;
52
+
53
+ --secondary: 240 3.7% 15.9%;
54
+ --secondary-foreground: 0 0% 98%;
55
+
56
+ --muted: 240 3.7% 15.9%;
57
+ --muted-foreground: 240 5% 64.9%;
58
+
59
+ --accent: 240 3.7% 15.9%;
60
+ --accent-foreground: 0 0% 98%;
61
+
62
+ --destructive: 0 62.8% 30.6%;
63
+ --destructive-foreground: 0 0% 98%;
64
+
65
+ --border: 240 3.7% 15.9%;
66
+ --input: 240 3.7% 15.9%;
67
+ --ring: 240 4.9% 83.9%;
68
+ }
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ # Accordion component for collapsible content sections
5
+ # Matches shadcn/ui Accordion component
6
+ # Uses Stimulus for interactivity
7
+ #
8
+ # @example Single accordion
9
+ # <%= render Shadcn::AccordionComponent.new(type: :single, collapsible: true) do |accordion| %>
10
+ # <% accordion.with_item(value: "item-1") do |item| %>
11
+ # <% item.with_trigger { "Is it accessible?" } %>
12
+ # <% item.with_body { "Yes. It adheres to the WAI-ARIA design pattern." } %>
13
+ # <% end %>
14
+ # <% accordion.with_item(value: "item-2") do |item| %>
15
+ # <% item.with_trigger { "Is it styled?" } %>
16
+ # <% item.with_body { "Yes. It comes with default styles." } %>
17
+ # <% end %>
18
+ # <% end %>
19
+ #
20
+ # @example Multiple accordion
21
+ # <%= render Shadcn::AccordionComponent.new(type: :multiple) do |accordion| %>
22
+ # ...
23
+ # <% end %>
24
+ #
25
+ class AccordionComponent < BaseComponent
26
+ renders_many :items, lambda { |value:, **options, &block|
27
+ AccordionItemComponent.new(value: value, **options, &block)
28
+ }
29
+
30
+ # @param type [Symbol] Accordion type (:single, :multiple)
31
+ # @param collapsible [Boolean] For single type, whether all items can be collapsed
32
+ # @param default_value [String, Array] Initially expanded item(s)
33
+ def initialize(type: :single, collapsible: false, default_value: nil, **options)
34
+ super(**options)
35
+ @type = type.to_sym
36
+ @collapsible = collapsible
37
+ @default_value = default_value
38
+ end
39
+
40
+ def call
41
+ content_tag(:div, accordion_content, accordion_attributes)
42
+ end
43
+
44
+ private
45
+
46
+ def accordion_content
47
+ safe_join([items, content].compact.flatten)
48
+ end
49
+
50
+ def accordion_attributes
51
+ attrs = {
52
+ class: class_name,
53
+ "data-controller": "shadcn--accordion",
54
+ "data-shadcn--accordion-type-value": @type.to_s,
55
+ "data-shadcn--accordion-collapsible-value": @collapsible.to_s,
56
+ "data-shadcn--accordion-default-value": Array(@default_value).join(",")
57
+ }
58
+ attrs.merge!(html_options)
59
+ attrs.merge!(build_data)
60
+ attrs.compact
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ # Accordion Content component
5
+ class AccordionContentComponent < BaseComponent
6
+ BASE_CLASSES = "overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
7
+ INNER_CLASSES = "pb-4 pt-0"
8
+
9
+ def call
10
+ content_tag(:div, inner_content, content_attributes)
11
+ end
12
+
13
+ private
14
+
15
+ def inner_content
16
+ content_tag(:div, content, class: INNER_CLASSES)
17
+ end
18
+
19
+ def content_attributes
20
+ {
21
+ class: merge_classes(BASE_CLASSES),
22
+ role: "region",
23
+ "data-shadcn--accordion-target": "content",
24
+ "data-state": "closed",
25
+ hidden: true
26
+ }
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ # Accordion Item component
5
+ class AccordionItemComponent < BaseComponent
6
+ BASE_CLASSES = "border-b"
7
+
8
+ renders_one :trigger, lambda { |**options, &block|
9
+ AccordionTriggerComponent.new(**options, &block)
10
+ }
11
+ renders_one :body, lambda { |**options, &block|
12
+ AccordionContentComponent.new(**options, &block)
13
+ }
14
+
15
+ # @param value [String] Unique value identifying this item
16
+ def initialize(value:, **options)
17
+ super(**options)
18
+ @value = value
19
+ end
20
+
21
+ def call
22
+ content_tag(:div, item_content, item_attributes)
23
+ end
24
+
25
+ private
26
+
27
+ def item_content
28
+ safe_join([trigger, body].compact)
29
+ end
30
+
31
+ def item_attributes
32
+ {
33
+ class: merge_classes(BASE_CLASSES),
34
+ "data-shadcn--accordion-target": "item",
35
+ "data-value": @value,
36
+ "data-state": "closed"
37
+ }
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ # Accordion Trigger component
5
+ class AccordionTriggerComponent < BaseComponent
6
+ HEADER_CLASSES = "flex"
7
+ TRIGGER_CLASSES = "flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all hover:underline text-left [&[data-state=open]>svg]:rotate-180"
8
+
9
+ def call
10
+ content_tag(:h3, trigger_button, class: HEADER_CLASSES, "data-orientation": "vertical")
11
+ end
12
+
13
+ private
14
+
15
+ def trigger_button
16
+ content_tag(:button, button_content, trigger_attributes)
17
+ end
18
+
19
+ def button_content
20
+ safe_join([
21
+ content_tag(:span, content),
22
+ chevron_icon
23
+ ])
24
+ end
25
+
26
+ def chevron_icon
27
+ content_tag(:svg,
28
+ content_tag(:path, nil, d: "m6 9 6 6 6-6", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round"),
29
+ xmlns: "http://www.w3.org/2000/svg",
30
+ width: "16",
31
+ height: "16",
32
+ viewBox: "0 0 24 24",
33
+ fill: "none",
34
+ class: "h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200"
35
+ )
36
+ end
37
+
38
+ def trigger_attributes
39
+ {
40
+ type: "button",
41
+ class: cn(TRIGGER_CLASSES, class_name),
42
+ "data-shadcn--accordion-target": "trigger",
43
+ "data-action": "click->shadcn--accordion#toggle",
44
+ "data-state": "closed",
45
+ "aria-expanded": "false"
46
+ }
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ # Alert component for displaying important messages
5
+ # Matches shadcn/ui Alert component
6
+ #
7
+ # @example Basic alert
8
+ # <%= render Shadcn::AlertComponent.new do |alert| %>
9
+ # <% alert.with_title { "Heads up!" } %>
10
+ # <% alert.with_description { "You can add components to your app using the cli." } %>
11
+ # <% end %>
12
+ #
13
+ # @example Destructive alert
14
+ # <%= render Shadcn::AlertComponent.new(variant: :destructive) do |alert| %>
15
+ # <% alert.with_title { "Error" } %>
16
+ # <% alert.with_description { "Something went wrong." } %>
17
+ # <% end %>
18
+ #
19
+ # @example With icon
20
+ # <%= render Shadcn::AlertComponent.new do |alert| %>
21
+ # <% alert.with_icon do %>
22
+ # <%= icon "info" %>
23
+ # <% end %>
24
+ # <% alert.with_title { "Note" } %>
25
+ # <% alert.with_description { "This is an informational message." } %>
26
+ # <% end %>
27
+ #
28
+ class AlertComponent < BaseComponent
29
+ # Available alert variants
30
+ VARIANTS = {
31
+ default: "bg-background text-foreground",
32
+ destructive: "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive"
33
+ }.freeze
34
+
35
+ BASE_CLASSES = "relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7"
36
+
37
+ renders_one :icon
38
+ renders_one :title, lambda { |**options|
39
+ AlertTitleComponent.new(**options)
40
+ }
41
+ renders_one :description, lambda { |**options|
42
+ AlertDescriptionComponent.new(**options)
43
+ }
44
+
45
+ # @param variant [Symbol] Alert style variant (:default, :destructive)
46
+ def initialize(variant: :default, **options)
47
+ super(**options)
48
+ @variant = variant.to_sym
49
+ end
50
+
51
+ def call
52
+ content_tag(:div, alert_content, alert_attributes)
53
+ end
54
+
55
+ private
56
+
57
+ def alert_content
58
+ safe_join([icon, title, description, content].compact)
59
+ end
60
+
61
+ def alert_classes
62
+ cn(BASE_CLASSES, VARIANTS[@variant], class_name)
63
+ end
64
+
65
+ def alert_attributes
66
+ attrs = {
67
+ class: alert_classes,
68
+ role: "alert"
69
+ }
70
+ attrs.merge!(html_options)
71
+ attrs.merge!(build_data)
72
+ attrs.compact
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ # Alert Description component
5
+ class AlertDescriptionComponent < BaseComponent
6
+ BASE_CLASSES = "text-sm [&_p]:leading-relaxed"
7
+
8
+ def call
9
+ content_tag(:div, content, class: merge_classes(BASE_CLASSES), **html_options)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ # Alert Dialog Action button component
5
+ class AlertDialogActionComponent < BaseComponent
6
+ BASE_CLASSES = "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-primary text-primary-foreground shadow hover:bg-primary/90 h-9 px-4 py-2"
7
+
8
+ def call
9
+ content_tag(:button, content, button_attributes)
10
+ end
11
+
12
+ private
13
+
14
+ def button_attributes
15
+ attrs = {
16
+ type: "button",
17
+ class: merge_classes(BASE_CLASSES),
18
+ "data-action": "click->shadcn--dialog#close"
19
+ }
20
+ attrs.merge!(html_options)
21
+ attrs.compact
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ # Alert Dialog Cancel button component
5
+ class AlertDialogCancelComponent < BaseComponent
6
+ BASE_CLASSES = "mt-2 sm:mt-0 inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground h-9 px-4 py-2"
7
+
8
+ def call
9
+ content_tag(:button, content, button_attributes)
10
+ end
11
+
12
+ private
13
+
14
+ def button_attributes
15
+ attrs = {
16
+ type: "button",
17
+ class: merge_classes(BASE_CLASSES),
18
+ "data-action": "click->shadcn--dialog#close"
19
+ }
20
+ attrs.merge!(html_options)
21
+ attrs.compact
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ # Alert Dialog component for important confirmation dialogs
5
+ # Matches shadcn/ui AlertDialog component
6
+ # Uses Stimulus for interactivity (reuses dialog controller)
7
+ #
8
+ # @example Basic alert dialog
9
+ # <%= render Shadcn::AlertDialogComponent.new do |dialog| %>
10
+ # <% dialog.with_trigger do %>
11
+ # <%= render Shadcn::ButtonComponent.new(variant: :outline) { "Delete Account" } %>
12
+ # <% end %>
13
+ # <% dialog.with_body do |body| %>
14
+ # <% body.with_header do |header| %>
15
+ # <% header.with_title { "Are you absolutely sure?" } %>
16
+ # <% header.with_description { "This action cannot be undone." } %>
17
+ # <% end %>
18
+ # <% body.with_footer do |footer| %>
19
+ # <% footer.with_cancel { "Cancel" } %>
20
+ # <% footer.with_action { "Continue" } %>
21
+ # <% end %>
22
+ # <% end %>
23
+ # <% end %>
24
+ #
25
+ class AlertDialogComponent < BaseComponent
26
+ renders_one :trigger
27
+ renders_one :body, lambda { |**options|
28
+ AlertDialogContentComponent.new(**options)
29
+ }
30
+
31
+ # @param open [Boolean] Whether dialog starts open
32
+ def initialize(open: false, **options)
33
+ super(**options)
34
+ @open = open
35
+ end
36
+
37
+ def call
38
+ content_tag(:div, dialog_content, dialog_attributes)
39
+ end
40
+
41
+ private
42
+
43
+ def dialog_content
44
+ safe_join([
45
+ trigger_wrapper,
46
+ body
47
+ ].compact)
48
+ end
49
+
50
+ def trigger_wrapper
51
+ return unless trigger
52
+
53
+ content_tag(:div, trigger, {
54
+ "data-shadcn--dialog-target": "trigger",
55
+ "data-action": "click->shadcn--dialog#open"
56
+ })
57
+ end
58
+
59
+ def dialog_attributes
60
+ attrs = {
61
+ class: class_name,
62
+ "data-controller": "shadcn--dialog",
63
+ "data-shadcn--dialog-open-value": @open.to_s,
64
+ "data-shadcn--dialog-modal-value": "true"
65
+ }
66
+ attrs.merge!(html_options)
67
+ attrs.merge!(build_data)
68
+ attrs.compact
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ # Alert Dialog Content component
5
+ class AlertDialogContentComponent < BaseComponent
6
+ OVERLAY_CLASSES = "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0"
7
+ CONTENT_CLASSES = "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg"
8
+
9
+ renders_one :header, lambda { |**options|
10
+ AlertDialogHeaderComponent.new(**options)
11
+ }
12
+ renders_one :footer, lambda { |**options|
13
+ AlertDialogFooterComponent.new(**options)
14
+ }
15
+
16
+ def call
17
+ content_tag(:template, content_wrapper, { "data-shadcn--dialog-target": "template" })
18
+ end
19
+
20
+ private
21
+
22
+ def content_wrapper
23
+ safe_join([
24
+ overlay,
25
+ dialog_panel
26
+ ])
27
+ end
28
+
29
+ def overlay
30
+ content_tag(:div, "", {
31
+ class: OVERLAY_CLASSES,
32
+ "data-shadcn--dialog-target": "overlay",
33
+ "data-state": "closed",
34
+ "aria-hidden": "true"
35
+ })
36
+ end
37
+
38
+ def dialog_panel
39
+ content_tag(:div, panel_content, {
40
+ class: cn(CONTENT_CLASSES, class_name),
41
+ role: "alertdialog",
42
+ "aria-modal": "true",
43
+ "data-shadcn--dialog-target": "content",
44
+ "data-state": "closed",
45
+ tabindex: "-1"
46
+ })
47
+ end
48
+
49
+ def panel_content
50
+ safe_join([
51
+ header,
52
+ content,
53
+ footer
54
+ ].compact)
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ # Alert Dialog Description component
5
+ class AlertDialogDescriptionComponent < BaseComponent
6
+ BASE_CLASSES = "text-sm text-muted-foreground"
7
+
8
+ def call
9
+ content_tag(:p, content, class: merge_classes(BASE_CLASSES))
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ # Alert Dialog Footer component
5
+ class AlertDialogFooterComponent < BaseComponent
6
+ BASE_CLASSES = "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2"
7
+
8
+ renders_one :cancel, lambda { |**options|
9
+ AlertDialogCancelComponent.new(**options)
10
+ }
11
+ renders_one :action, lambda { |**options|
12
+ AlertDialogActionComponent.new(**options)
13
+ }
14
+
15
+ def call
16
+ content_tag(:div, safe_join([cancel, action, content].compact), class: merge_classes(BASE_CLASSES))
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ # Alert Dialog Header component
5
+ class AlertDialogHeaderComponent < BaseComponent
6
+ BASE_CLASSES = "flex flex-col space-y-2 text-center sm:text-left"
7
+
8
+ renders_one :title, lambda { |**options|
9
+ AlertDialogTitleComponent.new(**options)
10
+ }
11
+ renders_one :description, lambda { |**options|
12
+ AlertDialogDescriptionComponent.new(**options)
13
+ }
14
+
15
+ def call
16
+ content_tag(:div, safe_join([title, description, content].compact), class: merge_classes(BASE_CLASSES))
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ # Alert Dialog Title component
5
+ class AlertDialogTitleComponent < BaseComponent
6
+ BASE_CLASSES = "text-lg font-semibold"
7
+
8
+ def call
9
+ content_tag(:h2, content, class: merge_classes(BASE_CLASSES))
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shadcn
4
+ # Alert Title component
5
+ class AlertTitleComponent < BaseComponent
6
+ BASE_CLASSES = "mb-1 font-medium leading-none tracking-tight"
7
+
8
+ def call
9
+ content_tag(:h5, content, class: merge_classes(BASE_CLASSES), **html_options)
10
+ end
11
+ end
12
+ end