uikit_rails 0.1.1

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 (378) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +301 -0
  3. data/Rakefile +12 -0
  4. data/app/controllers/uikit_rails/styleguide_controller.rb +72 -0
  5. data/app/views/layouts/uikit_rails/application.html.erb +412 -0
  6. data/app/views/uikit_rails/styleguide/index.html.erb +27 -0
  7. data/app/views/uikit_rails/styleguide/show.html.erb +56 -0
  8. data/config/routes.rb +6 -0
  9. data/lib/uikit_rails/engine.rb +13 -0
  10. data/lib/uikit_rails/generators/add_generator.rb +110 -0
  11. data/lib/uikit_rails/generators/install_generator.rb +62 -0
  12. data/lib/uikit_rails/generators/templates/base_component.rb.tt +32 -0
  13. data/lib/uikit_rails/generators/templates/uikit_rails.css.tt +69 -0
  14. data/lib/uikit_rails/templates/components/accordion/USAGE +30 -0
  15. data/lib/uikit_rails/templates/components/accordion/accordion.css +74 -0
  16. data/lib/uikit_rails/templates/components/accordion/component.html.erb +13 -0
  17. data/lib/uikit_rails/templates/components/accordion/component.rb +35 -0
  18. data/lib/uikit_rails/templates/components/accordion/preview.yml +81 -0
  19. data/lib/uikit_rails/templates/components/alert/USAGE +25 -0
  20. data/lib/uikit_rails/templates/components/alert/alert.css +60 -0
  21. data/lib/uikit_rails/templates/components/alert/component.html.erb +9 -0
  22. data/lib/uikit_rails/templates/components/alert/component.rb +27 -0
  23. data/lib/uikit_rails/templates/components/alert/preview.yml +53 -0
  24. data/lib/uikit_rails/templates/components/alert_dialog/USAGE +38 -0
  25. data/lib/uikit_rails/templates/components/alert_dialog/alert_dialog.css +108 -0
  26. data/lib/uikit_rails/templates/components/alert_dialog/component.html.erb +27 -0
  27. data/lib/uikit_rails/templates/components/alert_dialog/component.rb +23 -0
  28. data/lib/uikit_rails/templates/components/alert_dialog/preview.yml +94 -0
  29. data/lib/uikit_rails/templates/components/avatar/USAGE +20 -0
  30. data/lib/uikit_rails/templates/components/avatar/avatar.css +53 -0
  31. data/lib/uikit_rails/templates/components/avatar/component.html.erb +7 -0
  32. data/lib/uikit_rails/templates/components/avatar/component.rb +31 -0
  33. data/lib/uikit_rails/templates/components/avatar/preview.yml +42 -0
  34. data/lib/uikit_rails/templates/components/badge/USAGE +13 -0
  35. data/lib/uikit_rails/templates/components/badge/badge.css +61 -0
  36. data/lib/uikit_rails/templates/components/badge/component.rb +28 -0
  37. data/lib/uikit_rails/templates/components/badge/preview.yml +38 -0
  38. data/lib/uikit_rails/templates/components/breadcrumb/USAGE +23 -0
  39. data/lib/uikit_rails/templates/components/breadcrumb/breadcrumb.css +55 -0
  40. data/lib/uikit_rails/templates/components/breadcrumb/component.html.erb +14 -0
  41. data/lib/uikit_rails/templates/components/breadcrumb/component.rb +40 -0
  42. data/lib/uikit_rails/templates/components/breadcrumb/preview.yml +42 -0
  43. data/lib/uikit_rails/templates/components/button/USAGE +21 -0
  44. data/lib/uikit_rails/templates/components/button/button.css +125 -0
  45. data/lib/uikit_rails/templates/components/button/component.rb +44 -0
  46. data/lib/uikit_rails/templates/components/button/preview.yml +106 -0
  47. data/lib/uikit_rails/templates/components/card/USAGE +33 -0
  48. data/lib/uikit_rails/templates/components/card/card.css +63 -0
  49. data/lib/uikit_rails/templates/components/card/component.html.erb +16 -0
  50. data/lib/uikit_rails/templates/components/card/component.rb +26 -0
  51. data/lib/uikit_rails/templates/components/card/preview.yml +57 -0
  52. data/lib/uikit_rails/templates/components/checkbox/USAGE +19 -0
  53. data/lib/uikit_rails/templates/components/checkbox/checkbox.css +67 -0
  54. data/lib/uikit_rails/templates/components/checkbox/component.html.erb +6 -0
  55. data/lib/uikit_rails/templates/components/checkbox/component.rb +26 -0
  56. data/lib/uikit_rails/templates/components/checkbox/preview.yml +43 -0
  57. data/lib/uikit_rails/templates/components/collapsible/USAGE +31 -0
  58. data/lib/uikit_rails/templates/components/collapsible/collapsible.css +55 -0
  59. data/lib/uikit_rails/templates/components/collapsible/component.html.erb +8 -0
  60. data/lib/uikit_rails/templates/components/collapsible/component.rb +18 -0
  61. data/lib/uikit_rails/templates/components/collapsible/preview.yml +65 -0
  62. data/lib/uikit_rails/templates/components/dialog/USAGE +41 -0
  63. data/lib/uikit_rails/templates/components/dialog/component.html.erb +23 -0
  64. data/lib/uikit_rails/templates/components/dialog/component.rb +20 -0
  65. data/lib/uikit_rails/templates/components/dialog/dialog.css +133 -0
  66. data/lib/uikit_rails/templates/components/dialog/preview.yml +77 -0
  67. data/lib/uikit_rails/templates/components/dropdown/USAGE +40 -0
  68. data/lib/uikit_rails/templates/components/dropdown/component.html.erb +14 -0
  69. data/lib/uikit_rails/templates/components/dropdown/component.rb +62 -0
  70. data/lib/uikit_rails/templates/components/dropdown/dropdown.css +104 -0
  71. data/lib/uikit_rails/templates/components/dropdown/preview.yml +75 -0
  72. data/lib/uikit_rails/templates/components/form/USAGE +51 -0
  73. data/lib/uikit_rails/templates/components/form/builder.rb +233 -0
  74. data/lib/uikit_rails/templates/components/form/form.css +48 -0
  75. data/lib/uikit_rails/templates/components/form/preview.yml +95 -0
  76. data/lib/uikit_rails/templates/components/input/USAGE +21 -0
  77. data/lib/uikit_rails/templates/components/input/component.rb +25 -0
  78. data/lib/uikit_rails/templates/components/input/input.css +43 -0
  79. data/lib/uikit_rails/templates/components/input/preview.yml +58 -0
  80. data/lib/uikit_rails/templates/components/label/USAGE +16 -0
  81. data/lib/uikit_rails/templates/components/label/component.rb +25 -0
  82. data/lib/uikit_rails/templates/components/label/label.css +25 -0
  83. data/lib/uikit_rails/templates/components/label/preview.yml +34 -0
  84. data/lib/uikit_rails/templates/components/pagination/USAGE +45 -0
  85. data/lib/uikit_rails/templates/components/pagination/component.html.erb +7 -0
  86. data/lib/uikit_rails/templates/components/pagination/component.rb +90 -0
  87. data/lib/uikit_rails/templates/components/pagination/pagination.css +89 -0
  88. data/lib/uikit_rails/templates/components/pagination/preview.yml +61 -0
  89. data/lib/uikit_rails/templates/components/popover/USAGE +44 -0
  90. data/lib/uikit_rails/templates/components/popover/component.html.erb +8 -0
  91. data/lib/uikit_rails/templates/components/popover/component.rb +19 -0
  92. data/lib/uikit_rails/templates/components/popover/popover.css +94 -0
  93. data/lib/uikit_rails/templates/components/popover/preview.yml +102 -0
  94. data/lib/uikit_rails/templates/components/progress/USAGE +15 -0
  95. data/lib/uikit_rails/templates/components/progress/component.html.erb +3 -0
  96. data/lib/uikit_rails/templates/components/progress/component.rb +38 -0
  97. data/lib/uikit_rails/templates/components/progress/preview.yml +44 -0
  98. data/lib/uikit_rails/templates/components/progress/progress.css +20 -0
  99. data/lib/uikit_rails/templates/components/select/USAGE +19 -0
  100. data/lib/uikit_rails/templates/components/select/component.rb +38 -0
  101. data/lib/uikit_rails/templates/components/select/preview.yml +61 -0
  102. data/lib/uikit_rails/templates/components/select/select.css +46 -0
  103. data/lib/uikit_rails/templates/components/separator/USAGE +15 -0
  104. data/lib/uikit_rails/templates/components/separator/component.rb +34 -0
  105. data/lib/uikit_rails/templates/components/separator/preview.yml +32 -0
  106. data/lib/uikit_rails/templates/components/separator/separator.css +21 -0
  107. data/lib/uikit_rails/templates/components/sheet/USAGE +44 -0
  108. data/lib/uikit_rails/templates/components/sheet/component.html.erb +23 -0
  109. data/lib/uikit_rails/templates/components/sheet/component.rb +23 -0
  110. data/lib/uikit_rails/templates/components/sheet/preview.yml +105 -0
  111. data/lib/uikit_rails/templates/components/sheet/sheet.css +193 -0
  112. data/lib/uikit_rails/templates/components/skeleton/USAGE +19 -0
  113. data/lib/uikit_rails/templates/components/skeleton/component.rb +38 -0
  114. data/lib/uikit_rails/templates/components/skeleton/preview.yml +44 -0
  115. data/lib/uikit_rails/templates/components/skeleton/skeleton.css +25 -0
  116. data/lib/uikit_rails/templates/components/switch/USAGE +19 -0
  117. data/lib/uikit_rails/templates/components/switch/component.html.erb +19 -0
  118. data/lib/uikit_rails/templates/components/switch/component.rb +23 -0
  119. data/lib/uikit_rails/templates/components/switch/preview.yml +43 -0
  120. data/lib/uikit_rails/templates/components/switch/switch.css +81 -0
  121. data/lib/uikit_rails/templates/components/table/USAGE +40 -0
  122. data/lib/uikit_rails/templates/components/table/component.html.erb +14 -0
  123. data/lib/uikit_rails/templates/components/table/component.rb +25 -0
  124. data/lib/uikit_rails/templates/components/table/preview.yml +109 -0
  125. data/lib/uikit_rails/templates/components/table/table.css +86 -0
  126. data/lib/uikit_rails/templates/components/tabs/USAGE +24 -0
  127. data/lib/uikit_rails/templates/components/tabs/component.html.erb +10 -0
  128. data/lib/uikit_rails/templates/components/tabs/component.rb +35 -0
  129. data/lib/uikit_rails/templates/components/tabs/preview.yml +60 -0
  130. data/lib/uikit_rails/templates/components/tabs/tabs.css +72 -0
  131. data/lib/uikit_rails/templates/components/textarea/USAGE +19 -0
  132. data/lib/uikit_rails/templates/components/textarea/component.rb +25 -0
  133. data/lib/uikit_rails/templates/components/textarea/preview.yml +47 -0
  134. data/lib/uikit_rails/templates/components/textarea/textarea.css +39 -0
  135. data/lib/uikit_rails/templates/components/toggle/USAGE +25 -0
  136. data/lib/uikit_rails/templates/components/toggle/component.rb +39 -0
  137. data/lib/uikit_rails/templates/components/toggle/preview.yml +81 -0
  138. data/lib/uikit_rails/templates/components/toggle/toggle.css +89 -0
  139. data/lib/uikit_rails/templates/components/tooltip/USAGE +23 -0
  140. data/lib/uikit_rails/templates/components/tooltip/component.html.erb +8 -0
  141. data/lib/uikit_rails/templates/components/tooltip/component.rb +19 -0
  142. data/lib/uikit_rails/templates/components/tooltip/preview.yml +52 -0
  143. data/lib/uikit_rails/templates/components/tooltip/tooltip.css +78 -0
  144. data/lib/uikit_rails/templates/stimulus/accordion_controller.js +19 -0
  145. data/lib/uikit_rails/templates/stimulus/alert_dialog_controller.js +25 -0
  146. data/lib/uikit_rails/templates/stimulus/collapsible_controller.js +9 -0
  147. data/lib/uikit_rails/templates/stimulus/dialog_controller.js +19 -0
  148. data/lib/uikit_rails/templates/stimulus/dropdown_controller.js +47 -0
  149. data/lib/uikit_rails/templates/stimulus/popover_controller.js +47 -0
  150. data/lib/uikit_rails/templates/stimulus/sheet_controller.js +19 -0
  151. data/lib/uikit_rails/templates/stimulus/tabs_controller.js +24 -0
  152. data/lib/uikit_rails/templates/stimulus/tooltip_controller.js +13 -0
  153. data/lib/uikit_rails/version.rb +5 -0
  154. data/lib/uikit_rails.rb +59 -0
  155. data/sig/uikit_rails.rbs +4 -0
  156. data/test_app/.dockerignore +51 -0
  157. data/test_app/.gitattributes +9 -0
  158. data/test_app/.github/dependabot.yml +12 -0
  159. data/test_app/.github/workflows/ci.yml +124 -0
  160. data/test_app/.gitignore +35 -0
  161. data/test_app/.kamal/hooks/docker-setup.sample +3 -0
  162. data/test_app/.kamal/hooks/post-app-boot.sample +3 -0
  163. data/test_app/.kamal/hooks/post-deploy.sample +14 -0
  164. data/test_app/.kamal/hooks/post-proxy-reboot.sample +3 -0
  165. data/test_app/.kamal/hooks/pre-app-boot.sample +3 -0
  166. data/test_app/.kamal/hooks/pre-build.sample +51 -0
  167. data/test_app/.kamal/hooks/pre-connect.sample +47 -0
  168. data/test_app/.kamal/hooks/pre-deploy.sample +122 -0
  169. data/test_app/.kamal/hooks/pre-proxy-reboot.sample +3 -0
  170. data/test_app/.kamal/secrets +20 -0
  171. data/test_app/.rubocop.yml +8 -0
  172. data/test_app/.ruby-version +1 -0
  173. data/test_app/Dockerfile +77 -0
  174. data/test_app/Gemfile +68 -0
  175. data/test_app/Gemfile.lock +587 -0
  176. data/test_app/README.md +24 -0
  177. data/test_app/Rakefile +6 -0
  178. data/test_app/app/assets/images/.keep +0 -0
  179. data/test_app/app/assets/stylesheets/application.css +10 -0
  180. data/test_app/app/assets/stylesheets/ui/accordion.css +74 -0
  181. data/test_app/app/assets/stylesheets/ui/alert.css +60 -0
  182. data/test_app/app/assets/stylesheets/ui/alert_dialog.css +108 -0
  183. data/test_app/app/assets/stylesheets/ui/avatar.css +53 -0
  184. data/test_app/app/assets/stylesheets/ui/badge.css +61 -0
  185. data/test_app/app/assets/stylesheets/ui/breadcrumb.css +55 -0
  186. data/test_app/app/assets/stylesheets/ui/button.css +125 -0
  187. data/test_app/app/assets/stylesheets/ui/card.css +63 -0
  188. data/test_app/app/assets/stylesheets/ui/checkbox.css +67 -0
  189. data/test_app/app/assets/stylesheets/ui/collapsible.css +55 -0
  190. data/test_app/app/assets/stylesheets/ui/dialog.css +133 -0
  191. data/test_app/app/assets/stylesheets/ui/dropdown.css +104 -0
  192. data/test_app/app/assets/stylesheets/ui/form.css +48 -0
  193. data/test_app/app/assets/stylesheets/ui/input.css +43 -0
  194. data/test_app/app/assets/stylesheets/ui/label.css +25 -0
  195. data/test_app/app/assets/stylesheets/ui/pagination.css +89 -0
  196. data/test_app/app/assets/stylesheets/ui/popover.css +94 -0
  197. data/test_app/app/assets/stylesheets/ui/progress.css +20 -0
  198. data/test_app/app/assets/stylesheets/ui/select.css +46 -0
  199. data/test_app/app/assets/stylesheets/ui/separator.css +21 -0
  200. data/test_app/app/assets/stylesheets/ui/sheet.css +193 -0
  201. data/test_app/app/assets/stylesheets/ui/skeleton.css +25 -0
  202. data/test_app/app/assets/stylesheets/ui/switch.css +81 -0
  203. data/test_app/app/assets/stylesheets/ui/table.css +86 -0
  204. data/test_app/app/assets/stylesheets/ui/tabs.css +72 -0
  205. data/test_app/app/assets/stylesheets/ui/textarea.css +39 -0
  206. data/test_app/app/assets/stylesheets/ui/toggle.css +89 -0
  207. data/test_app/app/assets/stylesheets/ui/tooltip.css +78 -0
  208. data/test_app/app/assets/stylesheets/uikit_rails.css +69 -0
  209. data/test_app/app/components/ui/accordion/component.html.erb +13 -0
  210. data/test_app/app/components/ui/accordion/component.rb +35 -0
  211. data/test_app/app/components/ui/accordion/preview.yml +81 -0
  212. data/test_app/app/components/ui/alert/component.html.erb +9 -0
  213. data/test_app/app/components/ui/alert/component.rb +27 -0
  214. data/test_app/app/components/ui/alert/preview.yml +53 -0
  215. data/test_app/app/components/ui/alert_dialog/component.html.erb +27 -0
  216. data/test_app/app/components/ui/alert_dialog/component.rb +23 -0
  217. data/test_app/app/components/ui/alert_dialog/preview.yml +94 -0
  218. data/test_app/app/components/ui/avatar/component.html.erb +7 -0
  219. data/test_app/app/components/ui/avatar/component.rb +31 -0
  220. data/test_app/app/components/ui/avatar/preview.yml +42 -0
  221. data/test_app/app/components/ui/badge/component.rb +28 -0
  222. data/test_app/app/components/ui/badge/preview.yml +38 -0
  223. data/test_app/app/components/ui/base_component.rb +32 -0
  224. data/test_app/app/components/ui/breadcrumb/component.html.erb +14 -0
  225. data/test_app/app/components/ui/breadcrumb/component.rb +40 -0
  226. data/test_app/app/components/ui/breadcrumb/preview.yml +42 -0
  227. data/test_app/app/components/ui/button/component.rb +44 -0
  228. data/test_app/app/components/ui/button/preview.yml +106 -0
  229. data/test_app/app/components/ui/card/component.html.erb +16 -0
  230. data/test_app/app/components/ui/card/component.rb +26 -0
  231. data/test_app/app/components/ui/card/preview.yml +57 -0
  232. data/test_app/app/components/ui/checkbox/component.html.erb +6 -0
  233. data/test_app/app/components/ui/checkbox/component.rb +26 -0
  234. data/test_app/app/components/ui/checkbox/preview.yml +43 -0
  235. data/test_app/app/components/ui/collapsible/component.html.erb +8 -0
  236. data/test_app/app/components/ui/collapsible/component.rb +18 -0
  237. data/test_app/app/components/ui/collapsible/preview.yml +65 -0
  238. data/test_app/app/components/ui/dialog/component.html.erb +23 -0
  239. data/test_app/app/components/ui/dialog/component.rb +20 -0
  240. data/test_app/app/components/ui/dialog/preview.yml +77 -0
  241. data/test_app/app/components/ui/dropdown/component.html.erb +14 -0
  242. data/test_app/app/components/ui/dropdown/component.rb +62 -0
  243. data/test_app/app/components/ui/dropdown/preview.yml +75 -0
  244. data/test_app/app/components/ui/form/USAGE +51 -0
  245. data/test_app/app/components/ui/form/builder.rb +233 -0
  246. data/test_app/app/components/ui/form/component.rb +258 -0
  247. data/test_app/app/components/ui/form/form.css +48 -0
  248. data/test_app/app/components/ui/form/preview.yml +95 -0
  249. data/test_app/app/components/ui/input/component.rb +25 -0
  250. data/test_app/app/components/ui/input/preview.yml +58 -0
  251. data/test_app/app/components/ui/label/component.rb +25 -0
  252. data/test_app/app/components/ui/label/preview.yml +34 -0
  253. data/test_app/app/components/ui/pagination/component.html.erb +7 -0
  254. data/test_app/app/components/ui/pagination/component.rb +90 -0
  255. data/test_app/app/components/ui/pagination/preview.yml +61 -0
  256. data/test_app/app/components/ui/popover/component.html.erb +8 -0
  257. data/test_app/app/components/ui/popover/component.rb +19 -0
  258. data/test_app/app/components/ui/popover/preview.yml +102 -0
  259. data/test_app/app/components/ui/progress/component.html.erb +3 -0
  260. data/test_app/app/components/ui/progress/component.rb +38 -0
  261. data/test_app/app/components/ui/progress/preview.yml +44 -0
  262. data/test_app/app/components/ui/select/component.rb +38 -0
  263. data/test_app/app/components/ui/select/preview.yml +61 -0
  264. data/test_app/app/components/ui/separator/component.rb +34 -0
  265. data/test_app/app/components/ui/separator/preview.yml +32 -0
  266. data/test_app/app/components/ui/sheet/component.html.erb +23 -0
  267. data/test_app/app/components/ui/sheet/component.rb +23 -0
  268. data/test_app/app/components/ui/sheet/preview.yml +105 -0
  269. data/test_app/app/components/ui/skeleton/component.rb +38 -0
  270. data/test_app/app/components/ui/skeleton/preview.yml +44 -0
  271. data/test_app/app/components/ui/switch/component.html.erb +19 -0
  272. data/test_app/app/components/ui/switch/component.rb +23 -0
  273. data/test_app/app/components/ui/switch/preview.yml +43 -0
  274. data/test_app/app/components/ui/table/component.html.erb +14 -0
  275. data/test_app/app/components/ui/table/component.rb +25 -0
  276. data/test_app/app/components/ui/table/preview.yml +109 -0
  277. data/test_app/app/components/ui/tabs/component.html.erb +10 -0
  278. data/test_app/app/components/ui/tabs/component.rb +35 -0
  279. data/test_app/app/components/ui/tabs/preview.yml +60 -0
  280. data/test_app/app/components/ui/textarea/component.rb +25 -0
  281. data/test_app/app/components/ui/textarea/preview.yml +47 -0
  282. data/test_app/app/components/ui/toggle/component.rb +39 -0
  283. data/test_app/app/components/ui/toggle/preview.yml +81 -0
  284. data/test_app/app/components/ui/tooltip/component.html.erb +8 -0
  285. data/test_app/app/components/ui/tooltip/component.rb +19 -0
  286. data/test_app/app/components/ui/tooltip/preview.yml +52 -0
  287. data/test_app/app/controllers/application_controller.rb +7 -0
  288. data/test_app/app/controllers/concerns/.keep +0 -0
  289. data/test_app/app/helpers/application_helper.rb +2 -0
  290. data/test_app/app/javascript/application.js +3 -0
  291. data/test_app/app/javascript/controllers/application.js +9 -0
  292. data/test_app/app/javascript/controllers/hello_controller.js +7 -0
  293. data/test_app/app/javascript/controllers/index.js +4 -0
  294. data/test_app/app/javascript/controllers/ui/accordion_controller.js +19 -0
  295. data/test_app/app/javascript/controllers/ui/alert_dialog_controller.js +25 -0
  296. data/test_app/app/javascript/controllers/ui/collapsible_controller.js +9 -0
  297. data/test_app/app/javascript/controllers/ui/dialog_controller.js +19 -0
  298. data/test_app/app/javascript/controllers/ui/dropdown_controller.js +47 -0
  299. data/test_app/app/javascript/controllers/ui/popover_controller.js +47 -0
  300. data/test_app/app/javascript/controllers/ui/sheet_controller.js +19 -0
  301. data/test_app/app/javascript/controllers/ui/tabs_controller.js +24 -0
  302. data/test_app/app/javascript/controllers/ui/tooltip_controller.js +13 -0
  303. data/test_app/app/jobs/application_job.rb +7 -0
  304. data/test_app/app/mailers/application_mailer.rb +4 -0
  305. data/test_app/app/models/application_record.rb +3 -0
  306. data/test_app/app/models/concerns/.keep +0 -0
  307. data/test_app/app/views/layouts/application.html.erb +29 -0
  308. data/test_app/app/views/layouts/mailer.html.erb +13 -0
  309. data/test_app/app/views/layouts/mailer.text.erb +1 -0
  310. data/test_app/app/views/pwa/manifest.json.erb +22 -0
  311. data/test_app/app/views/pwa/service-worker.js +26 -0
  312. data/test_app/bin/brakeman +7 -0
  313. data/test_app/bin/bundler-audit +6 -0
  314. data/test_app/bin/ci +6 -0
  315. data/test_app/bin/dev +2 -0
  316. data/test_app/bin/docker-entrypoint +8 -0
  317. data/test_app/bin/importmap +4 -0
  318. data/test_app/bin/jobs +6 -0
  319. data/test_app/bin/kamal +16 -0
  320. data/test_app/bin/rails +4 -0
  321. data/test_app/bin/rake +4 -0
  322. data/test_app/bin/rubocop +8 -0
  323. data/test_app/bin/setup +35 -0
  324. data/test_app/bin/thrust +5 -0
  325. data/test_app/config/application.rb +27 -0
  326. data/test_app/config/boot.rb +4 -0
  327. data/test_app/config/bundler-audit.yml +5 -0
  328. data/test_app/config/cable.yml +17 -0
  329. data/test_app/config/cache.yml +16 -0
  330. data/test_app/config/ci.rb +24 -0
  331. data/test_app/config/credentials.yml.enc +1 -0
  332. data/test_app/config/database.yml +40 -0
  333. data/test_app/config/deploy.yml +119 -0
  334. data/test_app/config/environment.rb +5 -0
  335. data/test_app/config/environments/development.rb +78 -0
  336. data/test_app/config/environments/production.rb +90 -0
  337. data/test_app/config/environments/test.rb +53 -0
  338. data/test_app/config/importmap.rb +7 -0
  339. data/test_app/config/initializers/assets.rb +7 -0
  340. data/test_app/config/initializers/content_security_policy.rb +29 -0
  341. data/test_app/config/initializers/filter_parameter_logging.rb +8 -0
  342. data/test_app/config/initializers/inflections.rb +16 -0
  343. data/test_app/config/locales/en.yml +31 -0
  344. data/test_app/config/puma.rb +42 -0
  345. data/test_app/config/queue.yml +18 -0
  346. data/test_app/config/recurring.yml +15 -0
  347. data/test_app/config/routes.rb +13 -0
  348. data/test_app/config/storage.yml +27 -0
  349. data/test_app/config.ru +6 -0
  350. data/test_app/db/cable_schema.rb +11 -0
  351. data/test_app/db/cache_schema.rb +12 -0
  352. data/test_app/db/queue_schema.rb +129 -0
  353. data/test_app/db/seeds.rb +9 -0
  354. data/test_app/lib/tasks/.keep +0 -0
  355. data/test_app/log/.keep +0 -0
  356. data/test_app/public/400.html +135 -0
  357. data/test_app/public/404.html +135 -0
  358. data/test_app/public/406-unsupported-browser.html +135 -0
  359. data/test_app/public/422.html +135 -0
  360. data/test_app/public/500.html +135 -0
  361. data/test_app/public/icon.png +0 -0
  362. data/test_app/public/icon.svg +3 -0
  363. data/test_app/public/robots.txt +1 -0
  364. data/test_app/script/.keep +0 -0
  365. data/test_app/storage/.keep +0 -0
  366. data/test_app/test/controllers/.keep +0 -0
  367. data/test_app/test/fixtures/files/.keep +0 -0
  368. data/test_app/test/helpers/.keep +0 -0
  369. data/test_app/test/integration/.keep +0 -0
  370. data/test_app/test/mailers/.keep +0 -0
  371. data/test_app/test/models/.keep +0 -0
  372. data/test_app/test/test_helper.rb +15 -0
  373. data/test_app/tmp/.keep +0 -0
  374. data/test_app/tmp/pids/.keep +0 -0
  375. data/test_app/tmp/storage/.keep +0 -0
  376. data/test_app/vendor/.keep +0 -0
  377. data/test_app/vendor/javascript/.keep +0 -0
  378. metadata +448 -0
@@ -0,0 +1,55 @@
1
+ /* ============================================
2
+ * UikitRails — Collapsible
3
+ *
4
+ * Expandable/collapsible content section with
5
+ * smooth height transition.
6
+ * ============================================ */
7
+
8
+ .ui-collapsible {
9
+ font-family: var(--ui-font-family);
10
+ color: var(--ui-foreground);
11
+ }
12
+
13
+ /* --- Trigger --- */
14
+
15
+ .ui-collapsible__trigger {
16
+ display: flex;
17
+ align-items: center;
18
+ justify-content: space-between;
19
+ cursor: pointer;
20
+ padding: 0.75rem 0;
21
+ font-size: var(--ui-font-size-sm);
22
+ font-weight: 500;
23
+ user-select: none;
24
+ border-radius: var(--ui-radius);
25
+ transition: color var(--ui-transition-speed) ease;
26
+ }
27
+
28
+ .ui-collapsible__trigger:hover {
29
+ color: var(--ui-accent-foreground);
30
+ }
31
+
32
+ .ui-collapsible__trigger:focus-visible {
33
+ outline: 2px solid var(--ui-ring);
34
+ outline-offset: 2px;
35
+ }
36
+
37
+ /* --- Content --- */
38
+
39
+ .ui-collapsible__content {
40
+ overflow: hidden;
41
+ max-height: 0;
42
+ opacity: 0;
43
+ transition:
44
+ max-height var(--ui-transition-speed) ease,
45
+ opacity var(--ui-transition-speed) ease,
46
+ padding var(--ui-transition-speed) ease;
47
+ font-size: var(--ui-font-size-sm);
48
+ padding: 0;
49
+ }
50
+
51
+ .ui-collapsible__content--open {
52
+ max-height: 500px;
53
+ opacity: 1;
54
+ padding: 0.5rem 0 0.75rem;
55
+ }
@@ -0,0 +1,8 @@
1
+ <div data-controller="ui--collapsible" class="ui-collapsible" <%= tag.attributes(html_attrs) %>>
2
+ <% if trigger? %>
3
+ <div data-action="click->ui--collapsible#toggle" class="ui-collapsible__trigger"><%= trigger %></div>
4
+ <% end %>
5
+ <div data-ui--collapsible-target="content" class="ui-collapsible__content <%= 'ui-collapsible__content--open' if open %>">
6
+ <%= content %>
7
+ </div>
8
+ </div>
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ui
4
+ module Collapsible
5
+ # Expandable/collapsible content section.
6
+ class Component < Ui::BaseComponent
7
+ renders_one :trigger
8
+
9
+ attr_reader :open, :html_attrs
10
+
11
+ def initialize(open: false, **html_attrs)
12
+ @open = open
13
+ @html_attrs = html_attrs
14
+ super()
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,65 @@
1
+ description: An expandable/collapsible content section. Click the trigger area to toggle visibility of the content below it with a smooth transition.
2
+
3
+ sections:
4
+ - title: Basic Collapsible
5
+ examples:
6
+ - title: Simple toggle
7
+ code: |
8
+ <%= render Ui::Collapsible::Component.new do |collapsible| %>
9
+ <% collapsible.with_trigger do %>
10
+ <span>Toggle content</span>
11
+ <span style="font-size:var(--ui-font-size-xs);">&#9660;</span>
12
+ <% end %>
13
+ <p>This content can be shown or hidden by clicking the trigger above.</p>
14
+ <% end %>
15
+
16
+ - title: Open by default
17
+ code: |
18
+ <%= render Ui::Collapsible::Component.new(open: true) do |collapsible| %>
19
+ <% collapsible.with_trigger do %>
20
+ <span>Expanded by default</span>
21
+ <span style="font-size:var(--ui-font-size-xs);">&#9660;</span>
22
+ <% end %>
23
+ <p>This collapsible starts in the open state.</p>
24
+ <% end %>
25
+
26
+ - title: Collapsible with Rich Content
27
+ examples:
28
+ - title: List of items
29
+ code: |
30
+ <%= render Ui::Collapsible::Component.new do |collapsible| %>
31
+ <% collapsible.with_trigger do %>
32
+ <span style="font-weight:600;">3 tagged items</span>
33
+ <span style="font-size:var(--ui-font-size-xs);">&#9660;</span>
34
+ <% end %>
35
+ <div style="display:flex;flex-direction:column;gap:0.5rem;">
36
+ <div style="padding:0.5rem 0.75rem;border:1px solid var(--ui-border);border-radius:var(--ui-radius);font-size:var(--ui-font-size-sm);">@radix-ui/primitives</div>
37
+ <div style="padding:0.5rem 0.75rem;border:1px solid var(--ui-border);border-radius:var(--ui-radius);font-size:var(--ui-font-size-sm);">@radix-ui/colors</div>
38
+ <div style="padding:0.5rem 0.75rem;border:1px solid var(--ui-border);border-radius:var(--ui-radius);font-size:var(--ui-font-size-sm);">@stitches/react</div>
39
+ </div>
40
+ <% end %>
41
+
42
+ - title: Collapsible with Button Trigger
43
+ examples:
44
+ - title: Using a button as trigger
45
+ code: |
46
+ <%= render Ui::Collapsible::Component.new do |collapsible| %>
47
+ <% collapsible.with_trigger do %>
48
+ <%= render Ui::Button::Component.new(variant: :outline, size: :sm) do %>Show details<% end %>
49
+ <% end %>
50
+ <div style="margin-top:0.5rem;padding:1rem;border:1px solid var(--ui-border);border-radius:var(--ui-radius);font-size:var(--ui-font-size-sm);">
51
+ <p style="margin:0;">Here are the additional details that were hidden until the button was clicked.</p>
52
+ </div>
53
+ <% end %>
54
+
55
+ - title: Custom Attributes
56
+ examples:
57
+ - title: Collapsible with custom class
58
+ code: |
59
+ <%= render Ui::Collapsible::Component.new(class: "my-faq-item", data: { section: "faq" }) do |collapsible| %>
60
+ <% collapsible.with_trigger do %>
61
+ <span>What is UikitRails?</span>
62
+ <span style="font-size:var(--ui-font-size-xs);">&#9660;</span>
63
+ <% end %>
64
+ <p>UikitRails is a component library for Ruby on Rails applications, providing pre-built UI components with design tokens.</p>
65
+ <% end %>
@@ -0,0 +1,41 @@
1
+ Basic dialog:
2
+
3
+ <%= render Ui::Dialog::Component.new do |dialog| %>
4
+ <% dialog.with_trigger do %>
5
+ <%= render Ui::Button::Component.new do %>Open<% end %>
6
+ <% end %>
7
+ <% dialog.with_title do %>Dialog Title<% end %>
8
+ <% dialog.with_description do %>A short description.<% end %>
9
+ <p>Body content goes here.</p>
10
+ <% dialog.with_footer do %>
11
+ <%= render Ui::Button::Component.new(variant: :outline, data: { action: "click->ui--dialog#close" }) do %>Cancel<% end %>
12
+ <%= render Ui::Button::Component.new do %>Confirm<% end %>
13
+ <% end %>
14
+ <% end %>
15
+
16
+ Without footer:
17
+
18
+ <%= render Ui::Dialog::Component.new do |dialog| %>
19
+ <% dialog.with_trigger do %>
20
+ <%= render Ui::Button::Component.new do %>Info<% end %>
21
+ <% end %>
22
+ <% dialog.with_title do %>Information<% end %>
23
+ <p>This is an informational dialog.</p>
24
+ <% end %>
25
+
26
+ Slots:
27
+ trigger — Element that opens the dialog on click
28
+ title — Dialog heading (rendered as <h2>)
29
+ description — Subtitle text below the title
30
+ footer — Bottom area, typically for action buttons
31
+ content — Main body (default slot)
32
+
33
+ Close from inside the dialog:
34
+ Use data-action="click->ui--dialog#close" on any element inside.
35
+
36
+ With custom attributes:
37
+
38
+ <%= render Ui::Dialog::Component.new(class: "extra", data: { turbo: false }) do |dialog| %>
39
+ <% dialog.with_title do %>Title<% end %>
40
+ <p>Content</p>
41
+ <% end %>
@@ -0,0 +1,23 @@
1
+ <div data-controller="ui--dialog" <%= tag.attributes(html_attrs) %>>
2
+ <% if trigger? %>
3
+ <div data-action="click->ui--dialog#open"><%= trigger %></div>
4
+ <% end %>
5
+ <dialog class="ui-dialog" data-ui--dialog-target="dialog">
6
+ <div class="ui-dialog__overlay" data-action="click->ui--dialog#close"></div>
7
+ <div class="ui-dialog__content">
8
+ <% if title? || description? %>
9
+ <div class="ui-dialog__header">
10
+ <% if title? %><h2 class="ui-dialog__title"><%= title %></h2><% end %>
11
+ <% if description? %><p class="ui-dialog__description"><%= description %></p><% end %>
12
+ </div>
13
+ <% end %>
14
+ <div class="ui-dialog__body"><%= content %></div>
15
+ <% if footer? %>
16
+ <div class="ui-dialog__footer"><%= footer %></div>
17
+ <% end %>
18
+ <button class="ui-dialog__close" data-action="click->ui--dialog#close" aria-label="Close">
19
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>
20
+ </button>
21
+ </div>
22
+ </dialog>
23
+ </div>
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ui
4
+ module Dialog
5
+ # Modal dialog with backdrop overlay.
6
+ class Component < Ui::BaseComponent
7
+ renders_one :trigger
8
+ renders_one :title
9
+ renders_one :description
10
+ renders_one :footer
11
+
12
+ attr_reader :html_attrs
13
+
14
+ def initialize(**html_attrs)
15
+ @html_attrs = html_attrs
16
+ super()
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,133 @@
1
+ /* ============================================
2
+ * UikitRails — Dialog
3
+ *
4
+ * Modal dialog using native <dialog> element
5
+ * with backdrop overlay and slide-in animation.
6
+ * ============================================ */
7
+
8
+ .ui-dialog {
9
+ border: none;
10
+ padding: 0;
11
+ background: transparent;
12
+ max-width: 100vw;
13
+ max-height: 100vh;
14
+ width: 100%;
15
+ height: 100%;
16
+ position: fixed;
17
+ inset: 0;
18
+ z-index: 50;
19
+ }
20
+
21
+ .ui-dialog::backdrop {
22
+ display: none;
23
+ }
24
+
25
+ /* --- Overlay --- */
26
+
27
+ .ui-dialog__overlay {
28
+ position: fixed;
29
+ inset: 0;
30
+ background: rgba(0, 0, 0, 0.5);
31
+ animation: ui-dialog-fade-in var(--ui-transition-speed) ease;
32
+ }
33
+
34
+ /* --- Content --- */
35
+
36
+ .ui-dialog__content {
37
+ position: fixed;
38
+ left: 50%;
39
+ top: 50%;
40
+ transform: translate(-50%, -50%);
41
+ background: var(--ui-background);
42
+ color: var(--ui-foreground);
43
+ border: 1px solid var(--ui-border);
44
+ border-radius: var(--ui-radius);
45
+ padding: 1.5rem;
46
+ width: 100%;
47
+ max-width: 32rem;
48
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
49
+ z-index: 51;
50
+ font-family: var(--ui-font-family);
51
+ animation: ui-dialog-scale-in var(--ui-transition-speed) ease;
52
+ }
53
+
54
+ /* --- Header --- */
55
+
56
+ .ui-dialog__header {
57
+ margin-bottom: 1rem;
58
+ }
59
+
60
+ .ui-dialog__title {
61
+ font-size: 1.125rem;
62
+ font-weight: 600;
63
+ margin: 0;
64
+ color: var(--ui-foreground);
65
+ line-height: 1.25;
66
+ }
67
+
68
+ .ui-dialog__description {
69
+ font-size: var(--ui-font-size-sm);
70
+ color: var(--ui-muted-foreground);
71
+ margin: 0.25rem 0 0;
72
+ line-height: 1.5;
73
+ }
74
+
75
+ /* --- Body --- */
76
+
77
+ .ui-dialog__body {
78
+ font-size: var(--ui-font-size-sm);
79
+ }
80
+
81
+ /* --- Footer --- */
82
+
83
+ .ui-dialog__footer {
84
+ display: flex;
85
+ justify-content: flex-end;
86
+ gap: 0.5rem;
87
+ margin-top: 1.5rem;
88
+ }
89
+
90
+ /* --- Close Button --- */
91
+
92
+ .ui-dialog__close {
93
+ position: absolute;
94
+ top: 1rem;
95
+ right: 1rem;
96
+ background: none;
97
+ border: none;
98
+ cursor: pointer;
99
+ color: var(--ui-muted-foreground);
100
+ padding: 0.25rem;
101
+ border-radius: var(--ui-radius);
102
+ display: inline-flex;
103
+ align-items: center;
104
+ justify-content: center;
105
+ transition: color var(--ui-transition-speed) ease;
106
+ }
107
+
108
+ .ui-dialog__close:hover {
109
+ color: var(--ui-foreground);
110
+ }
111
+
112
+ .ui-dialog__close:focus-visible {
113
+ outline: 2px solid var(--ui-ring);
114
+ outline-offset: 2px;
115
+ }
116
+
117
+ /* --- Animations --- */
118
+
119
+ @keyframes ui-dialog-fade-in {
120
+ from { opacity: 0; }
121
+ to { opacity: 1; }
122
+ }
123
+
124
+ @keyframes ui-dialog-scale-in {
125
+ from {
126
+ opacity: 0;
127
+ transform: translate(-50%, -50%) scale(0.95);
128
+ }
129
+ to {
130
+ opacity: 1;
131
+ transform: translate(-50%, -50%) scale(1);
132
+ }
133
+ }
@@ -0,0 +1,77 @@
1
+ description: A modal dialog that overlays the page with a backdrop. Uses the native HTML <dialog> element for accessibility and supports title, description, body content, and footer slots.
2
+
3
+ sections:
4
+ - title: Basic Dialog
5
+ examples:
6
+ - title: Simple dialog with trigger
7
+ code: |
8
+ <%= render Ui::Dialog::Component.new do |dialog| %>
9
+ <% dialog.with_trigger do %>
10
+ <%= render Ui::Button::Component.new do %>Open Dialog<% end %>
11
+ <% end %>
12
+ <% dialog.with_title do %>Are you sure?<% end %>
13
+ <% dialog.with_description do %>This action cannot be undone.<% end %>
14
+ <p>This will permanently delete your account and all associated data.</p>
15
+ <% dialog.with_footer do %>
16
+ <%= render Ui::Button::Component.new(variant: :outline, data: { action: "click->ui--dialog#close" }) do %>Cancel<% end %>
17
+ <%= render Ui::Button::Component.new(variant: :destructive) do %>Delete<% end %>
18
+ <% end %>
19
+ <% end %>
20
+
21
+ - title: Dialog with Form
22
+ examples:
23
+ - title: Edit profile dialog
24
+ code: |
25
+ <%= render Ui::Dialog::Component.new do |dialog| %>
26
+ <% dialog.with_trigger do %>
27
+ <%= render Ui::Button::Component.new(variant: :outline) do %>Edit Profile<% end %>
28
+ <% end %>
29
+ <% dialog.with_title do %>Edit Profile<% end %>
30
+ <% dialog.with_description do %>Make changes to your profile here. Click save when you're done.<% end %>
31
+ <div style="display:flex;flex-direction:column;gap:1rem;">
32
+ <div>
33
+ <label style="font-size:var(--ui-font-size-sm);font-weight:500;">Name</label>
34
+ <input type="text" value="Jane Doe" style="width:100%;padding:0.5rem;border:1px solid var(--ui-border);border-radius:var(--ui-radius);margin-top:0.25rem;" />
35
+ </div>
36
+ <div>
37
+ <label style="font-size:var(--ui-font-size-sm);font-weight:500;">Email</label>
38
+ <input type="email" value="jane@example.com" style="width:100%;padding:0.5rem;border:1px solid var(--ui-border);border-radius:var(--ui-radius);margin-top:0.25rem;" />
39
+ </div>
40
+ </div>
41
+ <% dialog.with_footer do %>
42
+ <%= render Ui::Button::Component.new(variant: :outline, data: { action: "click->ui--dialog#close" }) do %>Cancel<% end %>
43
+ <%= render Ui::Button::Component.new do %>Save changes<% end %>
44
+ <% end %>
45
+ <% end %>
46
+
47
+ - title: Dialog without Footer
48
+ examples:
49
+ - title: Informational dialog
50
+ code: |
51
+ <%= render Ui::Dialog::Component.new do |dialog| %>
52
+ <% dialog.with_trigger do %>
53
+ <%= render Ui::Button::Component.new(variant: :secondary) do %>View Details<% end %>
54
+ <% end %>
55
+ <% dialog.with_title do %>Release Notes<% end %>
56
+ <% dialog.with_description do %>What's new in version 2.0<% end %>
57
+ <ul style="list-style:disc;padding-left:1.25rem;font-size:var(--ui-font-size-sm);line-height:1.75;">
58
+ <li>New dialog component with native HTML dialog</li>
59
+ <li>Improved dropdown positioning</li>
60
+ <li>Alert dialog for confirmations</li>
61
+ </ul>
62
+ <% end %>
63
+
64
+ - title: Custom Attributes
65
+ examples:
66
+ - title: Dialog with custom class
67
+ code: |
68
+ <%= render Ui::Dialog::Component.new(class: "my-custom-dialog", data: { turbo_frame: "modal" }) do |dialog| %>
69
+ <% dialog.with_trigger do %>
70
+ <%= render Ui::Button::Component.new do %>Open<% end %>
71
+ <% end %>
72
+ <% dialog.with_title do %>Custom Dialog<% end %>
73
+ <p>This dialog has custom attributes applied to the wrapper.</p>
74
+ <% dialog.with_footer do %>
75
+ <%= render Ui::Button::Component.new(variant: :outline, data: { action: "click->ui--dialog#close" }) do %>Close<% end %>
76
+ <% end %>
77
+ <% end %>
@@ -0,0 +1,40 @@
1
+ Basic dropdown:
2
+
3
+ <%= render Ui::Dropdown::Component.new do |dropdown| %>
4
+ <% dropdown.with_trigger do %>
5
+ <%= render Ui::Button::Component.new(variant: :outline) do %>Options<% end %>
6
+ <% end %>
7
+ <% dropdown.with_item do %>Profile<% end %>
8
+ <% dropdown.with_item do %>Settings<% end %>
9
+ <% dropdown.with_separator %>
10
+ <% dropdown.with_item do %>Log out<% end %>
11
+ <% end %>
12
+
13
+ With links:
14
+
15
+ <% dropdown.with_item(href: "/profile") do %>Profile<% end %>
16
+
17
+ With labels:
18
+
19
+ <% dropdown.with_label do %>Account<% end %>
20
+ <% dropdown.with_item do %>Profile<% end %>
21
+
22
+ Right-aligned:
23
+
24
+ <%= render Ui::Dropdown::Component.new(align: :end) do |dropdown| %>
25
+ ...
26
+ <% end %>
27
+
28
+ Item subtypes:
29
+ item — Clickable menu item (renders as <div> or <a> if href given)
30
+ separator — Horizontal divider line
31
+ label — Non-interactive group heading
32
+
33
+ Props:
34
+ align — :start (default) or :end — controls menu alignment
35
+
36
+ With custom attributes:
37
+
38
+ <%= render Ui::Dropdown::Component.new(class: "extra", data: { turbo: false }) do |dropdown| %>
39
+ ...
40
+ <% end %>
@@ -0,0 +1,14 @@
1
+ <div class="ui-dropdown" data-controller="ui--dropdown" <%= tag.attributes(html_attrs) %>>
2
+ <% if trigger? %>
3
+ <div data-action="click->ui--dropdown#toggle"><%= trigger %></div>
4
+ <% end %>
5
+ <div class="ui-dropdown__menu <%= align_class %>"
6
+ data-ui--dropdown-target="menu"
7
+ role="menu"
8
+ hidden>
9
+ <% items.each do |item| %>
10
+ <%= item %>
11
+ <% end %>
12
+ <%= content %>
13
+ </div>
14
+ </div>
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ui
4
+ module Dropdown
5
+ # Dropdown menu triggered by a button.
6
+ class Component < Ui::BaseComponent
7
+ renders_one :trigger
8
+ renders_many :items, types: {
9
+ item: { renders: ->(**attrs, &block) { Item.new(**attrs, &block) }, as: :item },
10
+ separator: { renders: -> { SeparatorItem.new }, as: :separator },
11
+ label: { renders: ->(**attrs, &block) { LabelItem.new(**attrs, &block) }, as: :label }
12
+ }
13
+
14
+ attr_reader :align, :html_attrs
15
+
16
+ def initialize(align: :start, **html_attrs)
17
+ @align = align.to_sym
18
+ @html_attrs = html_attrs
19
+ super()
20
+ end
21
+
22
+ def align_class
23
+ "ui-dropdown__menu--#{align}"
24
+ end
25
+
26
+ class Item < Ui::BaseComponent
27
+ attr_reader :href, :html_attrs
28
+
29
+ def initialize(href: nil, **html_attrs)
30
+ @href = href
31
+ @html_attrs = html_attrs
32
+ super()
33
+ end
34
+
35
+ def call
36
+ tag_name = href ? :a : :div
37
+ attrs = merge_attrs({ class: "ui-dropdown__item", href: href, role: "menuitem" }.compact, html_attrs)
38
+ content_tag(tag_name, content, **attrs)
39
+ end
40
+ end
41
+
42
+ class SeparatorItem < Ui::BaseComponent
43
+ def call
44
+ tag.div(class: "ui-dropdown__separator", role: "separator")
45
+ end
46
+ end
47
+
48
+ class LabelItem < Ui::BaseComponent
49
+ attr_reader :html_attrs
50
+
51
+ def initialize(**html_attrs)
52
+ @html_attrs = html_attrs
53
+ super()
54
+ end
55
+
56
+ def call
57
+ content_tag(:div, content, class: "ui-dropdown__label", **html_attrs)
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,104 @@
1
+ /* ============================================
2
+ * UikitRails — Dropdown
3
+ *
4
+ * Dropdown menu triggered by a button with
5
+ * items, separators, and label subtypes.
6
+ * ============================================ */
7
+
8
+ .ui-dropdown {
9
+ position: relative;
10
+ display: inline-block;
11
+ font-family: var(--ui-font-family);
12
+ }
13
+
14
+ /* --- Menu --- */
15
+
16
+ .ui-dropdown__menu {
17
+ position: absolute;
18
+ top: 100%;
19
+ z-index: 50;
20
+ min-width: 12rem;
21
+ margin-top: 0.25rem;
22
+ padding: 0.25rem;
23
+ background: var(--ui-background);
24
+ color: var(--ui-foreground);
25
+ border: 1px solid var(--ui-border);
26
+ border-radius: var(--ui-radius);
27
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);
28
+ animation: ui-dropdown-fade-in var(--ui-transition-speed) ease;
29
+ }
30
+
31
+ .ui-dropdown__menu[hidden] {
32
+ display: none;
33
+ }
34
+
35
+ /* --- Alignment --- */
36
+
37
+ .ui-dropdown__menu--start {
38
+ left: 0;
39
+ }
40
+
41
+ .ui-dropdown__menu--end {
42
+ right: 0;
43
+ }
44
+
45
+ /* --- Item --- */
46
+
47
+ .ui-dropdown__item {
48
+ display: flex;
49
+ align-items: center;
50
+ gap: 0.5rem;
51
+ width: 100%;
52
+ padding: 0.5rem 0.75rem;
53
+ font-size: var(--ui-font-size-sm);
54
+ color: var(--ui-foreground);
55
+ text-decoration: none;
56
+ border: none;
57
+ background: none;
58
+ border-radius: calc(var(--ui-radius) - 2px);
59
+ cursor: pointer;
60
+ transition: background-color var(--ui-transition-speed) ease;
61
+ line-height: 1.25;
62
+ box-sizing: border-box;
63
+ }
64
+
65
+ .ui-dropdown__item:hover {
66
+ background-color: var(--ui-accent);
67
+ color: var(--ui-accent-foreground);
68
+ }
69
+
70
+ .ui-dropdown__item:focus-visible {
71
+ outline: 2px solid var(--ui-ring);
72
+ outline-offset: -2px;
73
+ }
74
+
75
+ /* --- Separator --- */
76
+
77
+ .ui-dropdown__separator {
78
+ height: 1px;
79
+ margin: 0.25rem -0.25rem;
80
+ background-color: var(--ui-border);
81
+ }
82
+
83
+ /* --- Label --- */
84
+
85
+ .ui-dropdown__label {
86
+ padding: 0.5rem 0.75rem 0.25rem;
87
+ font-size: var(--ui-font-size-xs);
88
+ font-weight: 600;
89
+ color: var(--ui-muted-foreground);
90
+ line-height: 1.25;
91
+ }
92
+
93
+ /* --- Animation --- */
94
+
95
+ @keyframes ui-dropdown-fade-in {
96
+ from {
97
+ opacity: 0;
98
+ transform: translateY(-4px);
99
+ }
100
+ to {
101
+ opacity: 1;
102
+ transform: translateY(0);
103
+ }
104
+ }