shadcn_view_component 0.3.3

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 (507) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +255 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.md +604 -0
  5. data/app/assets/stylesheets/shadcn-themes.css +1075 -0
  6. data/app/assets/stylesheets/shadcn.css +853 -0
  7. data/app/components/shadcn/accordion/component.rb +44 -0
  8. data/app/components/shadcn/accordion/content/component.rb +44 -0
  9. data/app/components/shadcn/accordion/item/component.rb +41 -0
  10. data/app/components/shadcn/accordion/preview.rb +16 -0
  11. data/app/components/shadcn/accordion/previews/default.html.erb +10 -0
  12. data/app/components/shadcn/accordion/previews/multiple.html.erb +13 -0
  13. data/app/components/shadcn/accordion/trigger/component.rb +52 -0
  14. data/app/components/shadcn/alert/component.rb +52 -0
  15. data/app/components/shadcn/alert/preview.rb +11 -0
  16. data/app/components/shadcn/alert/previews/default.html.erb +8 -0
  17. data/app/components/shadcn/alert.rb +17 -0
  18. data/app/components/shadcn/alert_dialog/action/component.rb +35 -0
  19. data/app/components/shadcn/alert_dialog/cancel/component.rb +16 -0
  20. data/app/components/shadcn/alert_dialog/component.rb +20 -0
  21. data/app/components/shadcn/alert_dialog/content/component.rb +55 -0
  22. data/app/components/shadcn/alert_dialog/header/component.rb +33 -0
  23. data/app/components/shadcn/alert_dialog/preview.rb +16 -0
  24. data/app/components/shadcn/alert_dialog/previews/default.html.erb +13 -0
  25. data/app/components/shadcn/alert_dialog/previews/small_with_media.html.erb +38 -0
  26. data/app/components/shadcn/alert_dialog.rb +32 -0
  27. data/app/components/shadcn/application_view_component.rb +225 -0
  28. data/app/components/shadcn/application_view_component_preview.rb +8 -0
  29. data/app/components/shadcn/aspect_ratio/component.rb +34 -0
  30. data/app/components/shadcn/aspect_ratio/preview.rb +16 -0
  31. data/app/components/shadcn/aspect_ratio/previews/default.html.erb +5 -0
  32. data/app/components/shadcn/aspect_ratio/previews/ratios.html.erb +12 -0
  33. data/app/components/shadcn/attachment/action/component.rb +19 -0
  34. data/app/components/shadcn/attachment/component.rb +76 -0
  35. data/app/components/shadcn/attachment/media/component.rb +56 -0
  36. data/app/components/shadcn/attachment/preview.rb +11 -0
  37. data/app/components/shadcn/attachment/previews/default.html.erb +80 -0
  38. data/app/components/shadcn/attachment/trigger/component.rb +31 -0
  39. data/app/components/shadcn/attachment.rb +42 -0
  40. data/app/components/shadcn/avatar/component.rb +43 -0
  41. data/app/components/shadcn/avatar/fallback/component.rb +23 -0
  42. data/app/components/shadcn/avatar/image/component.rb +20 -0
  43. data/app/components/shadcn/avatar/preview.rb +11 -0
  44. data/app/components/shadcn/avatar/previews/default.html.erb +13 -0
  45. data/app/components/shadcn/avatar.rb +32 -0
  46. data/app/components/shadcn/badge/component.rb +57 -0
  47. data/app/components/shadcn/badge/preview.rb +11 -0
  48. data/app/components/shadcn/badge/previews/default.html.erb +5 -0
  49. data/app/components/shadcn/breadcrumb/component.rb +15 -0
  50. data/app/components/shadcn/breadcrumb/ellipsis/component.rb +28 -0
  51. data/app/components/shadcn/breadcrumb/page/component.rb +25 -0
  52. data/app/components/shadcn/breadcrumb/preview.rb +16 -0
  53. data/app/components/shadcn/breadcrumb/previews/custom_separator.html.erb +17 -0
  54. data/app/components/shadcn/breadcrumb/previews/default.html.erb +15 -0
  55. data/app/components/shadcn/breadcrumb/separator/component.rb +31 -0
  56. data/app/components/shadcn/breadcrumb.rb +18 -0
  57. data/app/components/shadcn/bubble/component.rb +90 -0
  58. data/app/components/shadcn/bubble/preview.rb +16 -0
  59. data/app/components/shadcn/bubble/previews/alignment.html.erb +33 -0
  60. data/app/components/shadcn/bubble/previews/default.html.erb +22 -0
  61. data/app/components/shadcn/bubble/reactions/component.rb +54 -0
  62. data/app/components/shadcn/bubble.rb +24 -0
  63. data/app/components/shadcn/button/component.rb +85 -0
  64. data/app/components/shadcn/button/preview.rb +31 -0
  65. data/app/components/shadcn/button/previews/default.html.erb +8 -0
  66. data/app/components/shadcn/button/previews/sizes.html.erb +5 -0
  67. data/app/components/shadcn/button/previews/variants.html.erb +5 -0
  68. data/app/components/shadcn/button_group/component.rb +53 -0
  69. data/app/components/shadcn/button_group/preview.rb +15 -0
  70. data/app/components/shadcn/button_group/previews/default.html.erb +18 -0
  71. data/app/components/shadcn/button_group/previews/vertical.html.erb +5 -0
  72. data/app/components/shadcn/button_group/separator/component.rb +30 -0
  73. data/app/components/shadcn/button_group/text/component.rb +20 -0
  74. data/app/components/shadcn/calendar/component.rb +558 -0
  75. data/app/components/shadcn/calendar/month.rb +74 -0
  76. data/app/components/shadcn/calendar/preview.rb +64 -0
  77. data/app/components/shadcn/calendar/previews/booked.html.erb +18 -0
  78. data/app/components/shadcn/calendar/previews/custom_cell_size.html.erb +11 -0
  79. data/app/components/shadcn/calendar/previews/date_and_time.html.erb +31 -0
  80. data/app/components/shadcn/calendar/previews/default.html.erb +8 -0
  81. data/app/components/shadcn/calendar/previews/dropdown_caption.html.erb +11 -0
  82. data/app/components/shadcn/calendar/previews/in_a_form.html.erb +8 -0
  83. data/app/components/shadcn/calendar/previews/presets.html.erb +20 -0
  84. data/app/components/shadcn/calendar/previews/range.html.erb +10 -0
  85. data/app/components/shadcn/calendar/previews/week_numbers.html.erb +8 -0
  86. data/app/components/shadcn/card/component.rb +24 -0
  87. data/app/components/shadcn/card/header/component.rb +26 -0
  88. data/app/components/shadcn/card/preview.rb +16 -0
  89. data/app/components/shadcn/card/previews/default.html.erb +18 -0
  90. data/app/components/shadcn/card/previews/image.html.erb +37 -0
  91. data/app/components/shadcn/card.rb +21 -0
  92. data/app/components/shadcn/carousel/component.rb +61 -0
  93. data/app/components/shadcn/carousel/content/component.rb +86 -0
  94. data/app/components/shadcn/carousel/item/component.rb +42 -0
  95. data/app/components/shadcn/carousel/next/component.rb +59 -0
  96. data/app/components/shadcn/carousel/preview.rb +22 -0
  97. data/app/components/shadcn/carousel/previews/default.html.erb +22 -0
  98. data/app/components/shadcn/carousel/previews/sizes.html.erb +42 -0
  99. data/app/components/shadcn/carousel/previews/vertical.html.erb +27 -0
  100. data/app/components/shadcn/carousel/previous/component.rb +59 -0
  101. data/app/components/shadcn/chart/area/component.rb +43 -0
  102. data/app/components/shadcn/chart/bar/component.rb +75 -0
  103. data/app/components/shadcn/chart/cartesian/component.rb +152 -0
  104. data/app/components/shadcn/chart/component.rb +124 -0
  105. data/app/components/shadcn/chart/focusable.rb +38 -0
  106. data/app/components/shadcn/chart/legend/component.rb +55 -0
  107. data/app/components/shadcn/chart/line/component.rb +50 -0
  108. data/app/components/shadcn/chart/pie/component.rb +169 -0
  109. data/app/components/shadcn/chart/plot.rb +147 -0
  110. data/app/components/shadcn/chart/preview.rb +45 -0
  111. data/app/components/shadcn/chart/previews/area.html.erb +31 -0
  112. data/app/components/shadcn/chart/previews/bar.html.erb +32 -0
  113. data/app/components/shadcn/chart/previews/bar_stacked.html.erb +30 -0
  114. data/app/components/shadcn/chart/previews/default.html.erb +30 -0
  115. data/app/components/shadcn/chart/previews/donut.html.erb +16 -0
  116. data/app/components/shadcn/chart/previews/line.html.erb +30 -0
  117. data/app/components/shadcn/chart/previews/percentages.html.erb +17 -0
  118. data/app/components/shadcn/chart/table/component.rb +75 -0
  119. data/app/components/shadcn/chart/tooltip/component.rb +111 -0
  120. data/app/components/shadcn/checkbox/component.rb +109 -0
  121. data/app/components/shadcn/checkbox/preview.rb +16 -0
  122. data/app/components/shadcn/checkbox/previews/default.html.erb +14 -0
  123. data/app/components/shadcn/checkbox/previews/states.html.erb +23 -0
  124. data/app/components/shadcn/collapsible/component.rb +35 -0
  125. data/app/components/shadcn/collapsible/content/component.rb +20 -0
  126. data/app/components/shadcn/collapsible/preview.rb +11 -0
  127. data/app/components/shadcn/collapsible/previews/default.html.erb +9 -0
  128. data/app/components/shadcn/collapsible/trigger/component.rb +23 -0
  129. data/app/components/shadcn/combobox/chip/component.rb +60 -0
  130. data/app/components/shadcn/combobox/chip_input/component.rb +43 -0
  131. data/app/components/shadcn/combobox/chips/component.rb +54 -0
  132. data/app/components/shadcn/combobox/clear/component.rb +32 -0
  133. data/app/components/shadcn/combobox/component.rb +113 -0
  134. data/app/components/shadcn/combobox/content/component.rb +59 -0
  135. data/app/components/shadcn/combobox/empty/component.rb +23 -0
  136. data/app/components/shadcn/combobox/input/component.rb +85 -0
  137. data/app/components/shadcn/combobox/item/component.rb +69 -0
  138. data/app/components/shadcn/combobox/list/component.rb +27 -0
  139. data/app/components/shadcn/combobox/preview.rb +31 -0
  140. data/app/components/shadcn/combobox/previews/default.html.erb +20 -0
  141. data/app/components/shadcn/combobox/previews/grouped.html.erb +25 -0
  142. data/app/components/shadcn/combobox/previews/multiple.html.erb +28 -0
  143. data/app/components/shadcn/combobox/previews/with_clear.html.erb +16 -0
  144. data/app/components/shadcn/combobox/trigger/component.rb +54 -0
  145. data/app/components/shadcn/combobox.rb +16 -0
  146. data/app/components/shadcn/command/component.rb +67 -0
  147. data/app/components/shadcn/command/dialog/component.rb +72 -0
  148. data/app/components/shadcn/command/empty/component.rb +29 -0
  149. data/app/components/shadcn/command/group/component.rb +63 -0
  150. data/app/components/shadcn/command/input/component.rb +66 -0
  151. data/app/components/shadcn/command/item/component.rb +62 -0
  152. data/app/components/shadcn/command/list/component.rb +36 -0
  153. data/app/components/shadcn/command/preview.rb +26 -0
  154. data/app/components/shadcn/command/previews/default.html.erb +41 -0
  155. data/app/components/shadcn/command/previews/dialog.html.erb +33 -0
  156. data/app/components/shadcn/command/previews/ranking.html.erb +16 -0
  157. data/app/components/shadcn/command/separator/component.rb +33 -0
  158. data/app/components/shadcn/command.rb +14 -0
  159. data/app/components/shadcn/concerns/modal_root.rb +43 -0
  160. data/app/components/shadcn/concerns/submits_value.rb +81 -0
  161. data/app/components/shadcn/context_menu/component.rb +45 -0
  162. data/app/components/shadcn/context_menu/content/component.rb +40 -0
  163. data/app/components/shadcn/context_menu/preview.rb +16 -0
  164. data/app/components/shadcn/context_menu/previews/default.html.erb +34 -0
  165. data/app/components/shadcn/context_menu/previews/items.html.erb +35 -0
  166. data/app/components/shadcn/context_menu/sub/component.rb +47 -0
  167. data/app/components/shadcn/context_menu/sub_content/component.rb +31 -0
  168. data/app/components/shadcn/context_menu/trigger/component.rb +50 -0
  169. data/app/components/shadcn/context_menu.rb +43 -0
  170. data/app/components/shadcn/dialog/close/component.rb +20 -0
  171. data/app/components/shadcn/dialog/component.rb +20 -0
  172. data/app/components/shadcn/dialog/content/component.rb +78 -0
  173. data/app/components/shadcn/dialog/header/component.rb +23 -0
  174. data/app/components/shadcn/dialog/overlay/component.rb +28 -0
  175. data/app/components/shadcn/dialog/preview.rb +28 -0
  176. data/app/components/shadcn/dialog/previews/default.html.erb +17 -0
  177. data/app/components/shadcn/dialog/previews/inside_stacking_context.html.erb +25 -0
  178. data/app/components/shadcn/dialog/previews/no_close_button.html.erb +15 -0
  179. data/app/components/shadcn/dialog/previews/scrollable_content.html.erb +29 -0
  180. data/app/components/shadcn/dialog/trigger/component.rb +24 -0
  181. data/app/components/shadcn/dialog.rb +17 -0
  182. data/app/components/shadcn/drawer/component.rb +33 -0
  183. data/app/components/shadcn/drawer/content/component.rb +95 -0
  184. data/app/components/shadcn/drawer/header/component.rb +34 -0
  185. data/app/components/shadcn/drawer/preview.rb +29 -0
  186. data/app/components/shadcn/drawer/previews/default.html.erb +21 -0
  187. data/app/components/shadcn/drawer/previews/scrollable.html.erb +20 -0
  188. data/app/components/shadcn/drawer/previews/scrollable_side.html.erb +21 -0
  189. data/app/components/shadcn/drawer/previews/sides.html.erb +17 -0
  190. data/app/components/shadcn/drawer.rb +27 -0
  191. data/app/components/shadcn/dropdown_menu/checkbox_item/component.rb +61 -0
  192. data/app/components/shadcn/dropdown_menu/component.rb +48 -0
  193. data/app/components/shadcn/dropdown_menu/content/component.rb +49 -0
  194. data/app/components/shadcn/dropdown_menu/group/component.rb +16 -0
  195. data/app/components/shadcn/dropdown_menu/item/component.rb +50 -0
  196. data/app/components/shadcn/dropdown_menu/preview.rb +16 -0
  197. data/app/components/shadcn/dropdown_menu/previews/checkboxes_and_radio.html.erb +34 -0
  198. data/app/components/shadcn/dropdown_menu/previews/default.html.erb +23 -0
  199. data/app/components/shadcn/dropdown_menu/radio_group/component.rb +16 -0
  200. data/app/components/shadcn/dropdown_menu/radio_item/component.rb +63 -0
  201. data/app/components/shadcn/dropdown_menu/sub/component.rb +44 -0
  202. data/app/components/shadcn/dropdown_menu/sub_content/component.rb +45 -0
  203. data/app/components/shadcn/dropdown_menu/sub_trigger/component.rb +58 -0
  204. data/app/components/shadcn/dropdown_menu/trigger/component.rb +25 -0
  205. data/app/components/shadcn/dropdown_menu.rb +18 -0
  206. data/app/components/shadcn/empty/component.rb +17 -0
  207. data/app/components/shadcn/empty/media/component.rb +48 -0
  208. data/app/components/shadcn/empty/preview.rb +16 -0
  209. data/app/components/shadcn/empty/previews/default.html.erb +15 -0
  210. data/app/components/shadcn/empty/previews/media.html.erb +32 -0
  211. data/app/components/shadcn/empty.rb +26 -0
  212. data/app/components/shadcn/field/component.rb +61 -0
  213. data/app/components/shadcn/field/error/component.rb +49 -0
  214. data/app/components/shadcn/field/legend/component.rb +30 -0
  215. data/app/components/shadcn/field/preview.rb +17 -0
  216. data/app/components/shadcn/field/previews/default.html.erb +29 -0
  217. data/app/components/shadcn/field/previews/form_builder.html.erb +38 -0
  218. data/app/components/shadcn/field/separator/component.rb +35 -0
  219. data/app/components/shadcn/field.rb +44 -0
  220. data/app/components/shadcn/hover_card/component.rb +51 -0
  221. data/app/components/shadcn/hover_card/content/component.rb +45 -0
  222. data/app/components/shadcn/hover_card/preview.rb +16 -0
  223. data/app/components/shadcn/hover_card/previews/default.html.erb +36 -0
  224. data/app/components/shadcn/hover_card/previews/sides.html.erb +15 -0
  225. data/app/components/shadcn/hover_card/trigger/component.rb +33 -0
  226. data/app/components/shadcn/icon/component.rb +76 -0
  227. data/app/components/shadcn/icon.rb +43 -0
  228. data/app/components/shadcn/input/component.rb +26 -0
  229. data/app/components/shadcn/input/preview.rb +16 -0
  230. data/app/components/shadcn/input/previews/default.html.erb +5 -0
  231. data/app/components/shadcn/input/previews/states.html.erb +20 -0
  232. data/app/components/shadcn/input_group/addon/component.rb +65 -0
  233. data/app/components/shadcn/input_group/button/component.rb +40 -0
  234. data/app/components/shadcn/input_group/component.rb +43 -0
  235. data/app/components/shadcn/input_group/input/component.rb +25 -0
  236. data/app/components/shadcn/input_group/preview.rb +17 -0
  237. data/app/components/shadcn/input_group/previews/addons.html.erb +53 -0
  238. data/app/components/shadcn/input_group/previews/default.html.erb +25 -0
  239. data/app/components/shadcn/input_group/text/component.rb +20 -0
  240. data/app/components/shadcn/input_group/textarea/component.rb +21 -0
  241. data/app/components/shadcn/input_otp/component.rb +95 -0
  242. data/app/components/shadcn/input_otp/preview.rb +17 -0
  243. data/app/components/shadcn/input_otp/previews/default.html.erb +19 -0
  244. data/app/components/shadcn/input_otp/previews/variations.html.erb +33 -0
  245. data/app/components/shadcn/input_otp/separator/component.rb +21 -0
  246. data/app/components/shadcn/input_otp/slot/component.rb +60 -0
  247. data/app/components/shadcn/input_otp.rb +11 -0
  248. data/app/components/shadcn/item/component.rb +56 -0
  249. data/app/components/shadcn/item/group/component.rb +53 -0
  250. data/app/components/shadcn/item/media/component.rb +53 -0
  251. data/app/components/shadcn/item/preview.rb +20 -0
  252. data/app/components/shadcn/item/previews/default.html.erb +32 -0
  253. data/app/components/shadcn/item/previews/link.html.erb +39 -0
  254. data/app/components/shadcn/item/previews/outline.html.erb +8 -0
  255. data/app/components/shadcn/item/separator/component.rb +24 -0
  256. data/app/components/shadcn/item.rb +34 -0
  257. data/app/components/shadcn/kbd/component.rb +23 -0
  258. data/app/components/shadcn/kbd/group/component.rb +17 -0
  259. data/app/components/shadcn/kbd/preview.rb +11 -0
  260. data/app/components/shadcn/kbd/previews/default.html.erb +4 -0
  261. data/app/components/shadcn/label/component.rb +20 -0
  262. data/app/components/shadcn/label/preview.rb +11 -0
  263. data/app/components/shadcn/label/previews/default.html.erb +4 -0
  264. data/app/components/shadcn/marker/component.rb +46 -0
  265. data/app/components/shadcn/marker/icon/component.rb +23 -0
  266. data/app/components/shadcn/marker/preview.rb +17 -0
  267. data/app/components/shadcn/marker/previews/default.html.erb +18 -0
  268. data/app/components/shadcn/marker/previews/status.html.erb +32 -0
  269. data/app/components/shadcn/marker.rb +17 -0
  270. data/app/components/shadcn/menubar/component.rb +36 -0
  271. data/app/components/shadcn/menubar/content/component.rb +49 -0
  272. data/app/components/shadcn/menubar/menu/component.rb +39 -0
  273. data/app/components/shadcn/menubar/preview.rb +16 -0
  274. data/app/components/shadcn/menubar/previews/default.html.erb +52 -0
  275. data/app/components/shadcn/menubar/previews/items.html.erb +38 -0
  276. data/app/components/shadcn/menubar/sub/component.rb +43 -0
  277. data/app/components/shadcn/menubar/sub_content/component.rb +31 -0
  278. data/app/components/shadcn/menubar/sub_trigger/component.rb +31 -0
  279. data/app/components/shadcn/menubar/trigger/component.rb +41 -0
  280. data/app/components/shadcn/menubar.rb +47 -0
  281. data/app/components/shadcn/message/component.rb +33 -0
  282. data/app/components/shadcn/message/preview.rb +16 -0
  283. data/app/components/shadcn/message/previews/actions.html.erb +51 -0
  284. data/app/components/shadcn/message/previews/default.html.erb +35 -0
  285. data/app/components/shadcn/message.rb +35 -0
  286. data/app/components/shadcn/message_scroller/button/component.rb +78 -0
  287. data/app/components/shadcn/message_scroller/component.rb +59 -0
  288. data/app/components/shadcn/message_scroller/content/component.rb +50 -0
  289. data/app/components/shadcn/message_scroller/item/component.rb +45 -0
  290. data/app/components/shadcn/message_scroller/preview.rb +11 -0
  291. data/app/components/shadcn/message_scroller/previews/default.html.erb +72 -0
  292. data/app/components/shadcn/message_scroller/viewport/component.rb +41 -0
  293. data/app/components/shadcn/mode_switcher/component.rb +67 -0
  294. data/app/components/shadcn/mode_switcher/preview.rb +11 -0
  295. data/app/components/shadcn/mode_switcher/previews/default.html.erb +5 -0
  296. data/app/components/shadcn/mode_toggle/component.rb +75 -0
  297. data/app/components/shadcn/mode_toggle/preview.rb +11 -0
  298. data/app/components/shadcn/mode_toggle/previews/default.html.erb +20 -0
  299. data/app/components/shadcn/native_select/component.rb +59 -0
  300. data/app/components/shadcn/native_select/preview.rb +16 -0
  301. data/app/components/shadcn/native_select/previews/default.html.erb +9 -0
  302. data/app/components/shadcn/native_select/previews/groups.html.erb +26 -0
  303. data/app/components/shadcn/native_select.rb +16 -0
  304. data/app/components/shadcn/navigation_menu/component.rb +51 -0
  305. data/app/components/shadcn/navigation_menu/content/component.rb +58 -0
  306. data/app/components/shadcn/navigation_menu/preview.rb +11 -0
  307. data/app/components/shadcn/navigation_menu/previews/default.html.erb +49 -0
  308. data/app/components/shadcn/navigation_menu/trigger/component.rb +59 -0
  309. data/app/components/shadcn/navigation_menu.rb +28 -0
  310. data/app/components/shadcn/pagination/component.rb +19 -0
  311. data/app/components/shadcn/pagination/ellipsis/component.rb +28 -0
  312. data/app/components/shadcn/pagination/link/component.rb +37 -0
  313. data/app/components/shadcn/pagination/next/component.rb +31 -0
  314. data/app/components/shadcn/pagination/preview.rb +16 -0
  315. data/app/components/shadcn/pagination/previews/default.html.erb +18 -0
  316. data/app/components/shadcn/pagination/previews/simple.html.erb +39 -0
  317. data/app/components/shadcn/pagination/previous/component.rb +31 -0
  318. data/app/components/shadcn/pagination.rb +14 -0
  319. data/app/components/shadcn/parts.rb +38 -0
  320. data/app/components/shadcn/popover/anchor/component.rb +17 -0
  321. data/app/components/shadcn/popover/component.rb +42 -0
  322. data/app/components/shadcn/popover/content/component.rb +40 -0
  323. data/app/components/shadcn/popover/preview.rb +28 -0
  324. data/app/components/shadcn/popover/previews/align.html.erb +13 -0
  325. data/app/components/shadcn/popover/previews/default.html.erb +9 -0
  326. data/app/components/shadcn/popover/previews/inside_containing_block.html.erb +41 -0
  327. data/app/components/shadcn/popover/previews/inside_stacking_context.html.erb +30 -0
  328. data/app/components/shadcn/popover/trigger/component.rb +24 -0
  329. data/app/components/shadcn/popover.rb +16 -0
  330. data/app/components/shadcn/progress/component.rb +62 -0
  331. data/app/components/shadcn/progress/preview.rb +11 -0
  332. data/app/components/shadcn/progress/previews/default.html.erb +5 -0
  333. data/app/components/shadcn/radio_group/component.rb +51 -0
  334. data/app/components/shadcn/radio_group/item/component.rb +74 -0
  335. data/app/components/shadcn/radio_group/preview.rb +16 -0
  336. data/app/components/shadcn/radio_group/previews/default.html.erb +15 -0
  337. data/app/components/shadcn/radio_group/previews/states.html.erb +41 -0
  338. data/app/components/shadcn/resizable/component.rb +59 -0
  339. data/app/components/shadcn/resizable/handle/component.rb +70 -0
  340. data/app/components/shadcn/resizable/panel/component.rb +53 -0
  341. data/app/components/shadcn/resizable/preview.rb +23 -0
  342. data/app/components/shadcn/resizable/previews/default.html.erb +25 -0
  343. data/app/components/shadcn/resizable/previews/vertical.html.erb +19 -0
  344. data/app/components/shadcn/resizable/previews/with_handle.html.erb +17 -0
  345. data/app/components/shadcn/scroll_area/component.rb +84 -0
  346. data/app/components/shadcn/scroll_area/preview.rb +11 -0
  347. data/app/components/shadcn/scroll_area/previews/default.html.erb +36 -0
  348. data/app/components/shadcn/scroll_area/scrollbar/component.rb +72 -0
  349. data/app/components/shadcn/scroll_area/viewport/component.rb +70 -0
  350. data/app/components/shadcn/scroll_area.rb +14 -0
  351. data/app/components/shadcn/select/component.rb +67 -0
  352. data/app/components/shadcn/select/content/component.rb +157 -0
  353. data/app/components/shadcn/select/empty/component.rb +38 -0
  354. data/app/components/shadcn/select/group/component.rb +16 -0
  355. data/app/components/shadcn/select/item/component.rb +71 -0
  356. data/app/components/shadcn/select/list/component.rb +41 -0
  357. data/app/components/shadcn/select/preview.rb +24 -0
  358. data/app/components/shadcn/select/previews/default.html.erb +17 -0
  359. data/app/components/shadcn/select/previews/scrollable.html.erb +19 -0
  360. data/app/components/shadcn/select/previews/searchable.html.erb +18 -0
  361. data/app/components/shadcn/select/previews/states.html.erb +25 -0
  362. data/app/components/shadcn/select/search/component.rb +54 -0
  363. data/app/components/shadcn/select/trigger/component.rb +78 -0
  364. data/app/components/shadcn/select/value/component.rb +28 -0
  365. data/app/components/shadcn/select.rb +15 -0
  366. data/app/components/shadcn/separator/component.rb +41 -0
  367. data/app/components/shadcn/separator/preview.rb +11 -0
  368. data/app/components/shadcn/separator/previews/default.html.erb +9 -0
  369. data/app/components/shadcn/sheet/component.rb +16 -0
  370. data/app/components/shadcn/sheet/content/component.rb +98 -0
  371. data/app/components/shadcn/sheet/header/component.rb +23 -0
  372. data/app/components/shadcn/sheet/preview.rb +16 -0
  373. data/app/components/shadcn/sheet/previews/default.html.erb +16 -0
  374. data/app/components/shadcn/sheet/previews/no_close_button.html.erb +14 -0
  375. data/app/components/shadcn/sheet.rb +22 -0
  376. data/app/components/shadcn/sidebar/component.rb +232 -0
  377. data/app/components/shadcn/sidebar/input/component.rb +25 -0
  378. data/app/components/shadcn/sidebar/menu_action/component.rb +58 -0
  379. data/app/components/shadcn/sidebar/menu_button/component.rb +100 -0
  380. data/app/components/shadcn/sidebar/menu_skeleton/component.rb +51 -0
  381. data/app/components/shadcn/sidebar/menu_sub_button/component.rb +60 -0
  382. data/app/components/shadcn/sidebar/preview.rb +22 -0
  383. data/app/components/shadcn/sidebar/previews/default.html.erb +189 -0
  384. data/app/components/shadcn/sidebar/previews/floating.html.erb +39 -0
  385. data/app/components/shadcn/sidebar/previews/inset.html.erb +48 -0
  386. data/app/components/shadcn/sidebar/provider/component.rb +53 -0
  387. data/app/components/shadcn/sidebar/rail/component.rb +43 -0
  388. data/app/components/shadcn/sidebar/separator/component.rb +23 -0
  389. data/app/components/shadcn/sidebar/trigger/component.rb +39 -0
  390. data/app/components/shadcn/sidebar.rb +98 -0
  391. data/app/components/shadcn/skeleton/component.rb +14 -0
  392. data/app/components/shadcn/skeleton/preview.rb +11 -0
  393. data/app/components/shadcn/skeleton/previews/default.html.erb +7 -0
  394. data/app/components/shadcn/slider/component.rb +145 -0
  395. data/app/components/shadcn/slider/preview.rb +16 -0
  396. data/app/components/shadcn/slider/previews/default.html.erb +17 -0
  397. data/app/components/shadcn/slider/previews/vertical.html.erb +7 -0
  398. data/app/components/shadcn/slider/range/component.rb +51 -0
  399. data/app/components/shadcn/slider/thumb/component.rb +58 -0
  400. data/app/components/shadcn/slider/track/component.rb +32 -0
  401. data/app/components/shadcn/spinner/component.rb +21 -0
  402. data/app/components/shadcn/spinner/preview.rb +11 -0
  403. data/app/components/shadcn/spinner/previews/default.html.erb +7 -0
  404. data/app/components/shadcn/switch/component.rb +104 -0
  405. data/app/components/shadcn/switch/preview.rb +11 -0
  406. data/app/components/shadcn/switch/previews/default.html.erb +24 -0
  407. data/app/components/shadcn/table/component.rb +26 -0
  408. data/app/components/shadcn/table/preview.rb +16 -0
  409. data/app/components/shadcn/table/previews/default.html.erb +19 -0
  410. data/app/components/shadcn/table/previews/footer.html.erb +25 -0
  411. data/app/components/shadcn/table.rb +33 -0
  412. data/app/components/shadcn/tabs/component.rb +40 -0
  413. data/app/components/shadcn/tabs/content/component.rb +34 -0
  414. data/app/components/shadcn/tabs/list/component.rb +51 -0
  415. data/app/components/shadcn/tabs/preview.rb +16 -0
  416. data/app/components/shadcn/tabs/previews/default.html.erb +21 -0
  417. data/app/components/shadcn/tabs/previews/line.html.erb +23 -0
  418. data/app/components/shadcn/tabs/trigger/component.rb +66 -0
  419. data/app/components/shadcn/textarea/component.rb +24 -0
  420. data/app/components/shadcn/textarea/preview.rb +16 -0
  421. data/app/components/shadcn/textarea/previews/default.html.erb +3 -0
  422. data/app/components/shadcn/textarea/previews/states.html.erb +18 -0
  423. data/app/components/shadcn/theme_selector/component.rb +88 -0
  424. data/app/components/shadcn/theme_selector/preview.rb +17 -0
  425. data/app/components/shadcn/theme_selector/previews/all_themes.html.erb +20 -0
  426. data/app/components/shadcn/theme_selector/previews/default.html.erb +18 -0
  427. data/app/components/shadcn/toaster/component.rb +139 -0
  428. data/app/components/shadcn/toaster/preview.rb +16 -0
  429. data/app/components/shadcn/toaster/previews/default.html.erb +19 -0
  430. data/app/components/shadcn/toaster/previews/from_the_server.html.erb +15 -0
  431. data/app/components/shadcn/toaster/toast/component.rb +134 -0
  432. data/app/components/shadcn/toggle/component.rb +81 -0
  433. data/app/components/shadcn/toggle/preview.rb +11 -0
  434. data/app/components/shadcn/toggle/previews/default.html.erb +6 -0
  435. data/app/components/shadcn/toggle_group/component.rb +62 -0
  436. data/app/components/shadcn/toggle_group/item/component.rb +59 -0
  437. data/app/components/shadcn/toggle_group/preview.rb +16 -0
  438. data/app/components/shadcn/toggle_group/previews/default.html.erb +12 -0
  439. data/app/components/shadcn/toggle_group/previews/sizes.html.erb +37 -0
  440. data/app/components/shadcn/tooltip/component.rb +38 -0
  441. data/app/components/shadcn/tooltip/content/component.rb +62 -0
  442. data/app/components/shadcn/tooltip/preview.rb +21 -0
  443. data/app/components/shadcn/tooltip/previews/default.html.erb +4 -0
  444. data/app/components/shadcn/tooltip/previews/sides.html.erb +19 -0
  445. data/app/components/shadcn/tooltip/previews/with_keyboard_shortcut.html.erb +11 -0
  446. data/app/components/shadcn/tooltip/provider/component.rb +28 -0
  447. data/app/components/shadcn/tooltip/trigger/component.rb +25 -0
  448. data/app/helpers/shadcn_view_component/form_helper.rb +25 -0
  449. data/app/helpers/shadcn_view_component/theme_helper.rb +61 -0
  450. data/app/javascript/shadcn/animation.js +180 -0
  451. data/app/javascript/shadcn/command_score.js +110 -0
  452. data/app/javascript/shadcn/controllers/accordion_controller.js +127 -0
  453. data/app/javascript/shadcn/controllers/avatar_controller.js +32 -0
  454. data/app/javascript/shadcn/controllers/calendar_controller.js +633 -0
  455. data/app/javascript/shadcn/controllers/carousel_controller.js +139 -0
  456. data/app/javascript/shadcn/controllers/chart_controller.js +110 -0
  457. data/app/javascript/shadcn/controllers/checkbox_controller.js +61 -0
  458. data/app/javascript/shadcn/controllers/collapsible_controller.js +55 -0
  459. data/app/javascript/shadcn/controllers/combobox_controller.js +360 -0
  460. data/app/javascript/shadcn/controllers/command_controller.js +199 -0
  461. data/app/javascript/shadcn/controllers/dialog_controller.js +154 -0
  462. data/app/javascript/shadcn/controllers/drawer_controller.js +265 -0
  463. data/app/javascript/shadcn/controllers/dropdown_menu_controller.js +259 -0
  464. data/app/javascript/shadcn/controllers/hover_card_controller.js +85 -0
  465. data/app/javascript/shadcn/controllers/input_group_controller.js +17 -0
  466. data/app/javascript/shadcn/controllers/input_otp_controller.js +80 -0
  467. data/app/javascript/shadcn/controllers/menubar_controller.js +151 -0
  468. data/app/javascript/shadcn/controllers/message_scroller_controller.js +456 -0
  469. data/app/javascript/shadcn/controllers/navigation_menu_controller.js +211 -0
  470. data/app/javascript/shadcn/controllers/popover_controller.js +66 -0
  471. data/app/javascript/shadcn/controllers/radio_group_controller.js +69 -0
  472. data/app/javascript/shadcn/controllers/resizable_controller.js +167 -0
  473. data/app/javascript/shadcn/controllers/scroll_area_controller.js +253 -0
  474. data/app/javascript/shadcn/controllers/select_controller.js +320 -0
  475. data/app/javascript/shadcn/controllers/sidebar_controller.js +273 -0
  476. data/app/javascript/shadcn/controllers/slider_controller.js +230 -0
  477. data/app/javascript/shadcn/controllers/switch_controller.js +39 -0
  478. data/app/javascript/shadcn/controllers/tabs_controller.js +81 -0
  479. data/app/javascript/shadcn/controllers/theme_controller.js +67 -0
  480. data/app/javascript/shadcn/controllers/toaster_controller.js +281 -0
  481. data/app/javascript/shadcn/controllers/toggle_controller.js +24 -0
  482. data/app/javascript/shadcn/controllers/toggle_group_controller.js +73 -0
  483. data/app/javascript/shadcn/controllers/tooltip_controller.js +58 -0
  484. data/app/javascript/shadcn/direction.js +41 -0
  485. data/app/javascript/shadcn/dismiss.js +73 -0
  486. data/app/javascript/shadcn/floating.js +207 -0
  487. data/app/javascript/shadcn/focus.js +86 -0
  488. data/app/javascript/shadcn/id.js +14 -0
  489. data/app/javascript/shadcn/index.js +110 -0
  490. data/app/javascript/shadcn/popper.js +262 -0
  491. data/app/javascript/shadcn/scroll_geometry.js +267 -0
  492. data/app/javascript/shadcn/theme.js +161 -0
  493. data/app/javascript/shadcn/top_layer.js +59 -0
  494. data/app/javascript/shadcn/typeahead.js +99 -0
  495. data/config/importmap.rb +6 -0
  496. data/config/locales/en.yml +62 -0
  497. data/lib/generators/shadcn_view_component/install/install_generator.rb +149 -0
  498. data/lib/shadcn_view_component/engine.rb +73 -0
  499. data/lib/shadcn_view_component/form_builder.rb +264 -0
  500. data/lib/shadcn_view_component/icon_registry.rb +66 -0
  501. data/lib/shadcn_view_component/icons.rb +32 -0
  502. data/lib/shadcn_view_component/themes.rb +1065 -0
  503. data/lib/shadcn_view_component/version.rb +3 -0
  504. data/lib/shadcn_view_component.rb +82 -0
  505. data/lib/tasks/icons.rake +53 -0
  506. data/lib/tasks/themes.rake +171 -0
  507. metadata +608 -0
@@ -0,0 +1,853 @@
1
+ /*
2
+ * shadcn_view_component — design tokens, theme mapping and the animation
3
+ * utilities the components rely on.
4
+ *
5
+ * Ported from shadcn/ui `apps/v4/app/globals.css` plus the subset of
6
+ * `tw-animate-css` referenced by the component classes, reimplemented here so
7
+ * the gem needs no npm dependency.
8
+ *
9
+ * Import it from your Tailwind v4 entrypoint, after `@import "tailwindcss"`.
10
+ */
11
+
12
+ @custom-variant dark (&:is(.dark *));
13
+
14
+ /* --------------------------------------------------------------------------
15
+ * Design tokens
16
+ * ------------------------------------------------------------------------ */
17
+
18
+ /* shadcn-tokens:begin — generated by `rake themes:build`, do not edit.
19
+ * The default palette is neutral; `.theme-*` in shadcn-themes.css
20
+ * overrides these. */
21
+
22
+ :root {
23
+ --background: oklch(1 0 0);
24
+ --foreground: oklch(0.145 0 0);
25
+ --card: oklch(1 0 0);
26
+ --card-foreground: oklch(0.145 0 0);
27
+ --popover: oklch(1 0 0);
28
+ --popover-foreground: oklch(0.145 0 0);
29
+ --primary: oklch(0.205 0 0);
30
+ --primary-foreground: oklch(0.985 0 0);
31
+ --secondary: oklch(0.97 0 0);
32
+ --secondary-foreground: oklch(0.205 0 0);
33
+ --muted: oklch(0.97 0 0);
34
+ --muted-foreground: oklch(0.556 0 0);
35
+ --accent: oklch(0.97 0 0);
36
+ --accent-foreground: oklch(0.205 0 0);
37
+ --destructive: oklch(0.577 0.245 27.325);
38
+ --border: oklch(0.922 0 0);
39
+ --input: oklch(0.922 0 0);
40
+ --ring: oklch(0.708 0 0);
41
+ --chart-1: oklch(0.87 0 0);
42
+ --chart-2: oklch(0.556 0 0);
43
+ --chart-3: oklch(0.439 0 0);
44
+ --chart-4: oklch(0.371 0 0);
45
+ --chart-5: oklch(0.269 0 0);
46
+ --radius: 0.625rem;
47
+ --sidebar: oklch(0.985 0 0);
48
+ --sidebar-foreground: oklch(0.145 0 0);
49
+ --sidebar-primary: oklch(0.205 0 0);
50
+ --sidebar-primary-foreground: oklch(0.985 0 0);
51
+ --sidebar-accent: oklch(0.97 0 0);
52
+ --sidebar-accent-foreground: oklch(0.205 0 0);
53
+ --sidebar-border: oklch(0.922 0 0);
54
+ --sidebar-ring: oklch(0.708 0 0);
55
+ }
56
+
57
+ .dark {
58
+ --background: oklch(0.145 0 0);
59
+ --foreground: oklch(0.985 0 0);
60
+ --card: oklch(0.205 0 0);
61
+ --card-foreground: oklch(0.985 0 0);
62
+ --popover: oklch(0.205 0 0);
63
+ --popover-foreground: oklch(0.985 0 0);
64
+ --primary: oklch(0.922 0 0);
65
+ --primary-foreground: oklch(0.205 0 0);
66
+ --secondary: oklch(0.269 0 0);
67
+ --secondary-foreground: oklch(0.985 0 0);
68
+ --muted: oklch(0.269 0 0);
69
+ --muted-foreground: oklch(0.708 0 0);
70
+ --accent: oklch(0.269 0 0);
71
+ --accent-foreground: oklch(0.985 0 0);
72
+ --destructive: oklch(0.704 0.191 22.216);
73
+ --border: oklch(1 0 0 / 10%);
74
+ --input: oklch(1 0 0 / 15%);
75
+ --ring: oklch(0.556 0 0);
76
+ --chart-1: oklch(0.87 0 0);
77
+ --chart-2: oklch(0.556 0 0);
78
+ --chart-3: oklch(0.439 0 0);
79
+ --chart-4: oklch(0.371 0 0);
80
+ --chart-5: oklch(0.269 0 0);
81
+ --sidebar: oklch(0.205 0 0);
82
+ --sidebar-foreground: oklch(0.985 0 0);
83
+ --sidebar-primary: oklch(0.488 0.243 264.376);
84
+ --sidebar-primary-foreground: oklch(0.985 0 0);
85
+ --sidebar-accent: oklch(0.269 0 0);
86
+ --sidebar-accent-foreground: oklch(0.985 0 0);
87
+ --sidebar-border: oklch(1 0 0 / 10%);
88
+ --sidebar-ring: oklch(0.556 0 0);
89
+ }
90
+
91
+ /* shadcn-tokens:end */
92
+
93
+ /* --------------------------------------------------------------------------
94
+ * Theme mapping — makes `bg-primary`, `rounded-lg`, … resolve to the tokens
95
+ * ------------------------------------------------------------------------ */
96
+
97
+ @theme inline {
98
+ --radius-sm: calc(var(--radius) * 0.6);
99
+ --radius-md: calc(var(--radius) * 0.8);
100
+ --radius-lg: var(--radius);
101
+ --radius-xl: calc(var(--radius) * 1.4);
102
+ --radius-2xl: calc(var(--radius) * 1.8);
103
+ --radius-3xl: calc(var(--radius) * 2.2);
104
+ --radius-4xl: calc(var(--radius) * 2.6);
105
+ --color-background: var(--background);
106
+ --color-foreground: var(--foreground);
107
+ --color-card: var(--card);
108
+ --color-card-foreground: var(--card-foreground);
109
+ --color-popover: var(--popover);
110
+ --color-popover-foreground: var(--popover-foreground);
111
+ --color-primary: var(--primary);
112
+ --color-primary-foreground: var(--primary-foreground);
113
+ --color-secondary: var(--secondary);
114
+ --color-secondary-foreground: var(--secondary-foreground);
115
+ --color-muted: var(--muted);
116
+ --color-muted-foreground: var(--muted-foreground);
117
+ --color-accent: var(--accent);
118
+ --color-accent-foreground: var(--accent-foreground);
119
+ --color-destructive: var(--destructive);
120
+ --color-border: var(--border);
121
+ --color-input: var(--input);
122
+ --color-ring: var(--ring);
123
+ --color-chart-1: var(--chart-1);
124
+ --color-chart-2: var(--chart-2);
125
+ --color-chart-3: var(--chart-3);
126
+ --color-chart-4: var(--chart-4);
127
+ --color-chart-5: var(--chart-5);
128
+ --color-sidebar: var(--sidebar);
129
+ --color-sidebar-foreground: var(--sidebar-foreground);
130
+ --color-sidebar-primary: var(--sidebar-primary);
131
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
132
+ --color-sidebar-accent: var(--sidebar-accent);
133
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
134
+ --color-sidebar-border: var(--sidebar-border);
135
+ --color-sidebar-ring: var(--sidebar-ring);
136
+
137
+ }
138
+
139
+ /* Only `surface-*`, `code-*` and `selection-*` from shadcn's globals.css are
140
+ * left out: they dress ui.shadcn.com's own chrome, no ported component uses
141
+ * them, and none of the registry palettes defines them. `destructive-foreground`
142
+ * is gone for the same reason — shadcn v4 pairs `destructive` with `text-white`
143
+ * directly. */
144
+
145
+ @layer base {
146
+ /* shadcn components lean on `border` picking up the token, exactly as the
147
+ upstream globals.css does. */
148
+ * {
149
+ @apply border-border outline-ring/50;
150
+ }
151
+
152
+ /* Closed dialogs, popovers, menus and panels are rendered with `hidden` and
153
+ hidden by this rule. Tailwind's preflight has an equivalent, but a host app
154
+ may import Tailwind without it — and then every overlay would paint open on
155
+ load. Scoped to this library's own elements so it cannot fight the host's
156
+ styles. */
157
+ [data-slot][hidden] {
158
+ display: none !important;
159
+ }
160
+
161
+ /* Content on its way out stays painted but stops intercepting clicks, as
162
+ Radix does. The marker is written by `ExitQueue` and lives only for the
163
+ length of the animation.
164
+
165
+ Keyed on the marker rather than on `[data-state="closed"]`, which is also
166
+ written to *triggers* — `floating.js` sets it on the trigger,
167
+ `accordion_controller` on the trigger and its header — and every one of
168
+ those carries a `data-slot`. Keying on state would make each closed select,
169
+ dropdown and accordion permanently unclickable.
170
+
171
+ `!important`, as on `[data-slot][hidden]` above: this is here to stop a bug
172
+ rather than to style anything, so an ordinary utility landing on the same
173
+ element should not be able to switch it off by accident. It costs a host
174
+ the ordinary way of switching it off on purpose too: a layered `!important`
175
+ beats an unlayered one, so what is left is an inline style or a layer of
176
+ their own declared ahead of this file's.
177
+
178
+ The accordion is where the rule stops. What it is for is a layer sitting
179
+ over the page — an overlay swallowing the click aimed at what is behind
180
+ it. A collapsing panel sits in the flow with nothing behind it to reach,
181
+ so the rule buys nothing there and only takes away the panel's own links
182
+ and buttons for the length of the collapse. */
183
+ [data-slot][data-exiting]:not([data-slot="accordion-content"]) {
184
+ pointer-events: none !important;
185
+ }
186
+
187
+ /* Floating layers are promoted to the top layer with the Popover API, so a
188
+ stacking context above them cannot bury them. That brings a set of UA
189
+ defaults — `inset: 0`, `width: fit-content`, a border, a background — which
190
+ would fight the components' own classes.
191
+
192
+ This lives in `@layer base` on purpose. An unlayered rule would beat every
193
+ Tailwind utility no matter how specific, because unlayered author styles
194
+ outrank layered ones; from `base` the utilities win, which is what we want.
195
+ `:where()` then drops the specificity to zero so even a single class does. */
196
+ :where([popover][data-slot]),
197
+ :where([popover][data-radix-popper-content-wrapper]) {
198
+ inset: auto;
199
+ width: auto;
200
+ height: auto;
201
+ max-width: none;
202
+ max-height: none;
203
+ margin: 0;
204
+ padding: 0;
205
+ border: 0;
206
+ overflow: visible;
207
+ background-color: transparent;
208
+ color: inherit;
209
+ }
210
+ }
211
+
212
+ /* --------------------------------------------------------------------------
213
+ * Animations
214
+ *
215
+ * `enter`/`exit` reproduce tailwindcss-animate: the modifier utilities below
216
+ * only set custom properties, and the single pair of keyframes reads them.
217
+ * Duration comes from Tailwind's own `duration-*` (`--tw-duration`), so
218
+ * `data-[state=open]:animate-in duration-200` behaves as it does in React.
219
+ * ------------------------------------------------------------------------ */
220
+
221
+ @keyframes enter {
222
+ from {
223
+ opacity: var(--tw-enter-opacity, 1);
224
+ transform: translate3d(var(--tw-enter-translate-x, 0), var(--tw-enter-translate-y, 0), 0)
225
+ scale3d(
226
+ var(--tw-enter-scale, 1),
227
+ var(--tw-enter-scale, 1),
228
+ var(--tw-enter-scale, 1)
229
+ )
230
+ rotate(var(--tw-enter-rotate, 0));
231
+ }
232
+ }
233
+
234
+ @keyframes exit {
235
+ to {
236
+ opacity: var(--tw-exit-opacity, 1);
237
+ transform: translate3d(var(--tw-exit-translate-x, 0), var(--tw-exit-translate-y, 0), 0)
238
+ scale3d(
239
+ var(--tw-exit-scale, 1),
240
+ var(--tw-exit-scale, 1),
241
+ var(--tw-exit-scale, 1)
242
+ )
243
+ rotate(var(--tw-exit-rotate, 0));
244
+ }
245
+ }
246
+
247
+ @keyframes accordion-down {
248
+ from {
249
+ height: 0;
250
+ }
251
+ to {
252
+ height: var(--radix-accordion-content-height);
253
+ }
254
+ }
255
+
256
+ @keyframes accordion-up {
257
+ from {
258
+ height: var(--radix-accordion-content-height);
259
+ }
260
+ to {
261
+ height: 0;
262
+ }
263
+ }
264
+
265
+ @keyframes caret-blink {
266
+ 0%,
267
+ 70%,
268
+ 100% {
269
+ opacity: 1;
270
+ }
271
+ 20%,
272
+ 50% {
273
+ opacity: 0;
274
+ }
275
+ }
276
+
277
+ /* A declared departure from upstream: tw-animate-css ships no reduced-motion
278
+ handling. Nested inside each utility rather than a top-level `.animate-in`/
279
+ `.animate-out` rule, because most components apply these through variants
280
+ such as `data-[state=open]:animate-in` — a single, bracket-containing class
281
+ token a hand-written `.animate-in` selector would not match, even though
282
+ `tooltip/content` applies the bare `animate-in` form the same selector
283
+ would have matched. Nesting reaches both compiled shapes uniformly.
284
+
285
+ Unlike the accordion pair below, neither utility needs `!important` here:
286
+ that requirement comes from `--animate-accordion-*` also existing as a
287
+ theme key, which arms Tailwind's own built-in `animate-*` utility for the
288
+ same class name. No `--animate-in` or `--animate-out` key exists today,
289
+ here or upstream; if one is ever added, this pair would need `!important`
290
+ too. */
291
+ @utility animate-in {
292
+ animation-name: enter;
293
+ animation-duration: var(--tw-duration, 150ms);
294
+ --tw-enter-opacity: initial;
295
+ --tw-enter-scale: initial;
296
+ --tw-enter-rotate: initial;
297
+ --tw-enter-translate-x: initial;
298
+ --tw-enter-translate-y: initial;
299
+
300
+ @media (prefers-reduced-motion: reduce) {
301
+ animation-duration: 0.01ms;
302
+ }
303
+ }
304
+
305
+ @utility animate-out {
306
+ animation-name: exit;
307
+ animation-duration: var(--tw-duration, 150ms);
308
+ --tw-exit-opacity: initial;
309
+ --tw-exit-scale: initial;
310
+ --tw-exit-rotate: initial;
311
+ --tw-exit-translate-x: initial;
312
+ --tw-exit-translate-y: initial;
313
+
314
+ @media (prefers-reduced-motion: reduce) {
315
+ animation-duration: 0.01ms;
316
+ }
317
+ }
318
+
319
+ /* Not `@theme inline`, unlike the tokens above: `inline` substitutes the
320
+ literal value at every place a theme variable is used, so a host could only
321
+ retune the accordion by rebuilding with an overridden token. A plain
322
+ `@theme` block keeps `var(--animate-accordion-down)` below as a live
323
+ reference, so a host's own `:root { --animate-accordion-up: … }` — written
324
+ after this stylesheet loads, no rebuild required — still reaches it. */
325
+ @theme {
326
+ --animate-accordion-down: accordion-down 0.2s ease-out;
327
+ --animate-accordion-up: accordion-up 0.2s ease-out;
328
+ --animate-caret-blink: caret-blink 1.25s ease-out infinite;
329
+ }
330
+
331
+ /* Defined as utilities rather than staying `@theme`-only entries, because a
332
+ utility body is the only place a media query can reach them.
333
+
334
+ `animate-accordion-down`/`animate-accordion-up` are both a utility name
335
+ here *and* an `--animate-*` theme key above, so Tailwind's own built-in
336
+ `animate-*` utility — which is driven by matching theme keys, not by
337
+ anything written here — also matches them: it contributes a second
338
+ `animation:` declaration to the same compiled rule, after this one,
339
+ resetting `animation-duration` regardless of `prefers-reduced-motion`.
340
+ Both resolve to the same text here, so the bundle carries one `animation:`
341
+ line rather than two and what the appended declaration leaves visible is
342
+ the order: this rule compiles `@media` first and `animation:` last, the
343
+ reverse of the source and of `animate-in` above. Removing the theme key
344
+ restores the source order. That collision exists in any build where the
345
+ token is defined, including a host's own if they retune the accordion by
346
+ writing their own `--animate-accordion-up` — dropping the token to avoid
347
+ the collision was rejected for exactly that reason, since it would just
348
+ move the collision into every host that defines one. `!important` on the
349
+ override is what survives it either way; confirmed in headless Chrome with
350
+ `--force-prefers-reduced-motion`. */
351
+ @utility animate-accordion-down {
352
+ animation: var(--animate-accordion-down);
353
+
354
+ @media (prefers-reduced-motion: reduce) {
355
+ animation-duration: 0.01ms !important;
356
+ }
357
+ }
358
+
359
+ @utility animate-accordion-up {
360
+ animation: var(--animate-accordion-up);
361
+
362
+ @media (prefers-reduced-motion: reduce) {
363
+ animation-duration: 0.01ms !important;
364
+ }
365
+ }
366
+
367
+ /* The one `infinite` animation in this stylesheet, and the only one whose
368
+ reduced-motion answer is not `0.01ms`. Collapsing the *duration* of an
369
+ endless animation does not stop it — it runs the cycle a hundred thousand
370
+ times a second, which is a flicker rather than the stillness the setting
371
+ asked for. `animation: none` leaves the caret at its own opacity, which is
372
+ visible, which is what a caret is for.
373
+
374
+ `!important` for the same reason the accordion's has it: the name is also an
375
+ `--animate-*` theme key, so Tailwind's own `animate-*` utility contributes a
376
+ second `animation:` declaration to the same rule, after this one. */
377
+ @utility animate-caret-blink {
378
+ animation: var(--animate-caret-blink);
379
+
380
+ @media (prefers-reduced-motion: reduce) {
381
+ animation: none !important;
382
+ }
383
+ }
384
+
385
+ @utility fade-in-* {
386
+ --tw-enter-opacity: calc(--value(integer) / 100);
387
+ }
388
+
389
+ @utility fade-out-* {
390
+ --tw-exit-opacity: calc(--value(integer) / 100);
391
+ }
392
+
393
+ @utility fade-in {
394
+ --tw-enter-opacity: 0;
395
+ }
396
+
397
+ @utility fade-out {
398
+ --tw-exit-opacity: 0;
399
+ }
400
+
401
+ @utility zoom-in-* {
402
+ --tw-enter-scale: calc(--value(integer) / 100);
403
+ }
404
+
405
+ @utility zoom-out-* {
406
+ --tw-exit-scale: calc(--value(integer) / 100);
407
+ }
408
+
409
+ @utility slide-in-from-top-* {
410
+ --tw-enter-translate-y: calc(--value(integer) * var(--spacing) * -1);
411
+ }
412
+
413
+ @utility slide-in-from-bottom-* {
414
+ --tw-enter-translate-y: calc(--value(integer) * var(--spacing));
415
+ }
416
+
417
+ @utility slide-in-from-left-* {
418
+ --tw-enter-translate-x: calc(--value(integer) * var(--spacing) * -1);
419
+ }
420
+
421
+ @utility slide-in-from-right-* {
422
+ --tw-enter-translate-x: calc(--value(integer) * var(--spacing));
423
+ }
424
+
425
+ @utility slide-out-to-top-* {
426
+ --tw-exit-translate-y: calc(--value(integer) * var(--spacing) * -1);
427
+ }
428
+
429
+ @utility slide-out-to-bottom-* {
430
+ --tw-exit-translate-y: calc(--value(integer) * var(--spacing));
431
+ }
432
+
433
+ @utility slide-out-to-left-* {
434
+ --tw-exit-translate-x: calc(--value(integer) * var(--spacing) * -1);
435
+ }
436
+
437
+ @utility slide-out-to-right-* {
438
+ --tw-exit-translate-x: calc(--value(integer) * var(--spacing));
439
+ }
440
+
441
+ @utility slide-in-from-top {
442
+ --tw-enter-translate-y: -100%;
443
+ }
444
+
445
+ @utility slide-in-from-bottom {
446
+ --tw-enter-translate-y: 100%;
447
+ }
448
+
449
+ @utility slide-in-from-left {
450
+ --tw-enter-translate-x: -100%;
451
+ }
452
+
453
+ @utility slide-in-from-right {
454
+ --tw-enter-translate-x: 100%;
455
+ }
456
+
457
+ @utility slide-out-to-top {
458
+ --tw-exit-translate-y: -100%;
459
+ }
460
+
461
+ @utility slide-out-to-bottom {
462
+ --tw-exit-translate-y: 100%;
463
+ }
464
+
465
+ @utility slide-out-to-left {
466
+ --tw-exit-translate-x: -100%;
467
+ }
468
+
469
+ @utility slide-out-to-right {
470
+ --tw-exit-translate-x: 100%;
471
+ }
472
+
473
+ /* --------------------------------------------------------------------------
474
+ * Three utilities that are shadcn's own CSS, not Tailwind's
475
+ *
476
+ * `attachment.tsx` reaches for `shimmer`, `scroll-fade-x` and `scrollbar-none`
477
+ * the way it reaches for `truncate`, but none of the three is a Tailwind
478
+ * utility: they are defined in shadcn's stylesheet, which is **not vendored
479
+ * here** — `vendor/shadcn/` holds the TSX, the examples and `themes.json` and
480
+ * no CSS at all. Without these declarations Tailwind emits nothing for the
481
+ * three class names and the attachment ships them inert, which `parity_spec`
482
+ * would not notice: it compares class *text*, not generated CSS.
483
+ *
484
+ * So, unlike every other rule in this file, these were read from the
485
+ * stylesheet ui.shadcn.com serves rather than from a vendored source, on
486
+ * 2026-08-09. That means there is nothing in this repository to diff them
487
+ * against, and no spec can tell you when upstream changes them. Treat the
488
+ * values as measured-once rather than as tracked.
489
+ *
490
+ * One deliberate omission: upstream also ships a second `.shimmer`
491
+ * `background-image` built with `color-mix`, which softens the gradient's
492
+ * midpoints. It appeared as a bare override in the served CSS with no
493
+ * `@supports` around it that could be recovered from the CSSOM, and applying
494
+ * it unconditionally would change the gradient rather than progressively
495
+ * enhance it, so only the base definition is reproduced.
496
+ * ------------------------------------------------------------------------ */
497
+
498
+ @property --shimmer-angle {
499
+ syntax: "<angle>";
500
+ inherits: true;
501
+ initial-value: 20deg;
502
+ }
503
+
504
+ @property --scroll-fade-s {
505
+ syntax: "<length-percentage>";
506
+ inherits: false;
507
+ initial-value: 0;
508
+ }
509
+
510
+ @property --scroll-fade-e {
511
+ syntax: "<length-percentage>";
512
+ inherits: false;
513
+ initial-value: 0;
514
+ }
515
+
516
+ @property --scroll-fade-mask {
517
+ syntax: "*";
518
+ inherits: false;
519
+ }
520
+
521
+ @keyframes tw-shimmer {
522
+ 0% {
523
+ background-position: 100% 0;
524
+ }
525
+
526
+ to {
527
+ background-position: 0 0;
528
+ }
529
+ }
530
+
531
+ @keyframes scroll-fade-reveal-s {
532
+ 0% {
533
+ --scroll-fade-s: 0px;
534
+ }
535
+
536
+ to {
537
+ --scroll-fade-s: var(--_scroll-fade-size-s);
538
+ }
539
+ }
540
+
541
+ @keyframes scroll-fade-reveal-e {
542
+ 0% {
543
+ --scroll-fade-e: var(--_scroll-fade-size-e);
544
+ }
545
+
546
+ to {
547
+ --scroll-fade-e: 0px;
548
+ }
549
+ }
550
+
551
+ /* A gradient clipped to the text, swept across it. The reduced-motion block is
552
+ upstream's own and does more than stop the sweep: with `background-clip:
553
+ text` and a transparent fill, freezing the animation would leave the text
554
+ painted by whatever slice of the gradient it stopped on, so the fill colour
555
+ has to come back too. */
556
+ @utility shimmer {
557
+ --_spread: var(--shimmer-spread, calc(3ch + 40px));
558
+ --_base: currentColor;
559
+ --_highlight: var(--shimmer-color, oklch(from currentColor l c h / calc(alpha * 0.2)));
560
+ background-image: var(
561
+ --shimmer-image,
562
+ linear-gradient(
563
+ calc(90deg + var(--shimmer-angle)),
564
+ var(--_base) calc(50% - var(--_spread)),
565
+ var(--_highlight) calc(50% - var(--_spread) * 0.5),
566
+ var(--_highlight) 50%,
567
+ var(--_highlight) calc(50% + var(--_spread) * 0.5),
568
+ var(--_base) calc(50% + var(--_spread))
569
+ )
570
+ );
571
+ background-repeat: no-repeat;
572
+ background-size: calc(200% + var(--_spread) * 2) 100%;
573
+ background-position: 0 0;
574
+ background-clip: text;
575
+ -webkit-text-fill-color: var(--shimmer-text-fill, transparent);
576
+ animation: tw-shimmer var(--shimmer-duration, 2s) linear infinite;
577
+
578
+ @media (prefers-reduced-motion: reduce) {
579
+ background-image: none;
580
+ -webkit-text-fill-color: currentColor;
581
+ animation: none !important;
582
+ }
583
+ }
584
+
585
+ /* Fades the edges of a horizontal scroller, driven by a scroll timeline rather
586
+ than by script: the two 1ms animations exist only to interpolate the two
587
+ mask offsets across the first and last stretch of the scroll. */
588
+ @utility scroll-fade-x {
589
+ --_scroll-fade-size-s: var(--scroll-fade-s-size, var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10))));
590
+ --_scroll-fade-size-e: var(--scroll-fade-e-size, var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10))));
591
+ --scroll-fade-inline: linear-gradient(to right, transparent 0, #000 var(--scroll-fade-s, 0px), #000 calc(100% - var(--scroll-fade-e, 0px)), transparent 100%);
592
+ --scroll-fade-s: var(--_scroll-fade-size-s);
593
+ --scroll-fade-e: var(--_scroll-fade-size-e);
594
+ -webkit-mask-image: var(--scroll-fade-mask, var(--scroll-fade-inline));
595
+ mask-image: var(--scroll-fade-mask, var(--scroll-fade-inline));
596
+ animation: 1ms ease-in-out scroll-fade-reveal-s, 1ms ease-in-out scroll-fade-reveal-e;
597
+ animation-timeline: scroll(self inline), scroll(self inline);
598
+ animation-range: 0 var(--scroll-fade-reveal, calc(var(--spacing) * 24)), calc(100% - var(--scroll-fade-reveal, calc(var(--spacing) * 24))) 100%;
599
+ animation-fill-mode: both;
600
+ }
601
+
602
+ @utility scrollbar-none {
603
+ scrollbar-width: none;
604
+
605
+ &::-webkit-scrollbar {
606
+ display: none;
607
+ }
608
+ }
609
+
610
+ /* The message scroller's three, read the same way and on the same terms as the
611
+ attachment's above — from the stylesheet ui.shadcn.com serves, on 2026-08-09,
612
+ with nothing in this repository to diff them against.
613
+
614
+ `scroll-fade-b` is the vertical sibling of `scroll-fade-x` and was read
615
+ rather than derived from it: it turns out to differ in more than an axis. It
616
+ fades one edge, not two, so it carries a single animation instead of a pair;
617
+ its mask composites with `mask-composite: intersect`, which the horizontal
618
+ one does not do; and its timeline is `scroll(self y)` against
619
+ `scroll(self inline)`. Deriving it would have got all three wrong. */
620
+
621
+ @property --scroll-fade-b {
622
+ syntax: "<length-percentage>";
623
+ inherits: false;
624
+ initial-value: 0;
625
+ }
626
+
627
+ @keyframes scroll-fade-reveal-b {
628
+ 0% {
629
+ --scroll-fade-b: var(--_scroll-fade-size-b);
630
+ }
631
+
632
+ to {
633
+ --scroll-fade-b: 0px;
634
+ }
635
+ }
636
+
637
+ @utility scroll-fade-b {
638
+ --_scroll-fade-size-b: var(--scroll-fade-b-size, var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10))));
639
+ --scroll-fade-mask: linear-gradient(to bottom, #000 0, #000 calc(100% - var(--scroll-fade-b, 0px)), transparent 100%);
640
+ --scroll-fade-b: var(--_scroll-fade-size-b);
641
+ -webkit-mask-image: var(--scroll-fade-mask);
642
+ mask-image: var(--scroll-fade-mask);
643
+ -webkit-mask-repeat: no-repeat;
644
+ mask-repeat: no-repeat;
645
+ -webkit-mask-composite: source-in;
646
+ mask-composite: intersect;
647
+ animation: 1ms ease-in-out scroll-fade-reveal-b;
648
+ animation-timeline: scroll(self y);
649
+ animation-range: calc(100% - var(--scroll-fade-reveal, calc(var(--spacing) * 24))) 100%;
650
+ animation-fill-mode: both;
651
+ }
652
+
653
+ @utility scrollbar-thin {
654
+ scrollbar-width: thin;
655
+ }
656
+
657
+ @utility scrollbar-gutter-stable {
658
+ scrollbar-gutter: stable;
659
+ }
660
+
661
+ /* What Radix injects as a `<style>` tag from its viewport
662
+ (vendor/radix/ui/scroll-area.tsx:266-278). Keyed on the slot rather than on a
663
+ class: it is the component working rather than something to style, so a host
664
+ should not be able to switch it off by accident — and there is no class token
665
+ for `parity_spec` to look for and miss. */
666
+ [data-slot="scroll-area-viewport"] {
667
+ scrollbar-width: none;
668
+ -ms-overflow-style: none;
669
+ -webkit-overflow-scrolling: touch;
670
+ }
671
+
672
+ [data-slot="scroll-area-viewport"]::-webkit-scrollbar {
673
+ display: none;
674
+ }
675
+
676
+ /* --------------------------------------------------------------------------
677
+ * The Drawer's own stylesheet, which is vaul's rather than shadcn's
678
+ *
679
+ * `drawer.tsx` renders no entrance animation and no `touch-action`: both are in
680
+ * the stylesheet vaul's package ships, and the component does not work without
681
+ * them. `touch-action: none` is load-bearing rather than decorative — without
682
+ * it the browser claims the vertical gesture, the pointer stream is cancelled
683
+ * mid-drag and the drawer never moves.
684
+ *
685
+ * Reproduced from `vendor/vaul/style.css`, which is vendored so this can be
686
+ * diffed against something. `parity_spec` still cannot see any of it: it
687
+ * compares Tailwind class *text* and a stylesheet rule is not a class.
688
+ *
689
+ * `[data-vaul-snap-points='false']` is in every selector because it is in
690
+ * vaul's, and the attribute is emitted as a constant `false` — this port has no
691
+ * snap points. Dropping the condition would be a smaller diff and a worse one:
692
+ * the day snap points arrive, these rules have to stop applying, and a selector
693
+ * that already says so is the difference between adding a feature and
694
+ * remembering to.
695
+ * -------------------------------------------------------------------------- */
696
+
697
+ [data-vaul-drawer] {
698
+ touch-action: none;
699
+ will-change: transform;
700
+ transition: transform 0.5s cubic-bezier(0.32, 0.72, 0, 1);
701
+ animation-duration: 0.5s;
702
+ animation-timing-function: cubic-bezier(0.32, 0.72, 0, 1);
703
+ }
704
+
705
+ [data-vaul-drawer][data-vaul-snap-points="false"][data-vaul-drawer-direction="bottom"][data-state="open"] {
706
+ animation-name: shadcn-drawer-from-bottom;
707
+ }
708
+ [data-vaul-drawer][data-vaul-snap-points="false"][data-vaul-drawer-direction="bottom"][data-state="closed"] {
709
+ animation-name: shadcn-drawer-to-bottom;
710
+ }
711
+ [data-vaul-drawer][data-vaul-snap-points="false"][data-vaul-drawer-direction="top"][data-state="open"] {
712
+ animation-name: shadcn-drawer-from-top;
713
+ }
714
+ [data-vaul-drawer][data-vaul-snap-points="false"][data-vaul-drawer-direction="top"][data-state="closed"] {
715
+ animation-name: shadcn-drawer-to-top;
716
+ }
717
+ [data-vaul-drawer][data-vaul-snap-points="false"][data-vaul-drawer-direction="left"][data-state="open"] {
718
+ animation-name: shadcn-drawer-from-left;
719
+ }
720
+ [data-vaul-drawer][data-vaul-snap-points="false"][data-vaul-drawer-direction="left"][data-state="closed"] {
721
+ animation-name: shadcn-drawer-to-left;
722
+ }
723
+ [data-vaul-drawer][data-vaul-snap-points="false"][data-vaul-drawer-direction="right"][data-state="open"] {
724
+ animation-name: shadcn-drawer-from-right;
725
+ }
726
+ [data-vaul-drawer][data-vaul-snap-points="false"][data-vaul-drawer-direction="right"][data-state="closed"] {
727
+ animation-name: shadcn-drawer-to-right;
728
+ }
729
+
730
+ @keyframes shadcn-drawer-from-bottom {
731
+ from { transform: translate3d(0, var(--initial-transform, 100%), 0); }
732
+ to { transform: translate3d(0, 0, 0); }
733
+ }
734
+ @keyframes shadcn-drawer-to-bottom {
735
+ to { transform: translate3d(0, var(--initial-transform, 100%), 0); }
736
+ }
737
+ @keyframes shadcn-drawer-from-top {
738
+ from { transform: translate3d(0, calc(var(--initial-transform, 100%) * -1), 0); }
739
+ to { transform: translate3d(0, 0, 0); }
740
+ }
741
+ @keyframes shadcn-drawer-to-top {
742
+ to { transform: translate3d(0, calc(var(--initial-transform, 100%) * -1), 0); }
743
+ }
744
+ @keyframes shadcn-drawer-from-left {
745
+ from { transform: translate3d(calc(var(--initial-transform, 100%) * -1), 0, 0); }
746
+ to { transform: translate3d(0, 0, 0); }
747
+ }
748
+ @keyframes shadcn-drawer-to-left {
749
+ to { transform: translate3d(calc(var(--initial-transform, 100%) * -1), 0, 0); }
750
+ }
751
+ @keyframes shadcn-drawer-from-right {
752
+ from { transform: translate3d(var(--initial-transform, 100%), 0, 0); }
753
+ to { transform: translate3d(0, 0, 0); }
754
+ }
755
+ @keyframes shadcn-drawer-to-right {
756
+ to { transform: translate3d(var(--initial-transform, 100%), 0, 0); }
757
+ }
758
+
759
+ @media (prefers-reduced-motion: reduce) {
760
+ [data-vaul-drawer] {
761
+ transition-duration: 0.01ms;
762
+ animation-duration: 0.01ms;
763
+ }
764
+ }
765
+
766
+ /* --------------------------------------------------------------------------
767
+ * The carousel's viewport, which is a scroller rather than a transformed track
768
+ *
769
+ * Upstream drives this component with embla, which translates the track inside
770
+ * an `overflow-hidden` box. This port drives it with the scroll container the
771
+ * box already is — `overflow: hidden` still makes one, which is why
772
+ * `carousel-content` keeps upstream's class exactly and nothing here fights it.
773
+ *
774
+ * What these rules add is the half a hidden overflow does not give: a finger
775
+ * can drag it, and a release lands on a slide instead of between two. The
776
+ * scrollbar is hidden because upstream's carousel shows none, and the same
777
+ * pair of declarations does it for `scroll-area`'s viewport a few rules above.
778
+ *
779
+ * Keyed on the `data-slot` for that reason: it is the shape this file already
780
+ * uses when behaviour has to reach an element whose classes are upstream's.
781
+ * -------------------------------------------------------------------------- */
782
+
783
+ [data-slot="carousel-content"] {
784
+ overflow-x: auto;
785
+ scroll-snap-type: x mandatory;
786
+ scrollbar-width: none;
787
+ overscroll-behavior-x: contain;
788
+ }
789
+
790
+ [data-slot="carousel-content"][data-orientation="vertical"] {
791
+ overflow-x: hidden;
792
+ overflow-y: auto;
793
+ scroll-snap-type: y mandatory;
794
+ overscroll-behavior-y: contain;
795
+ }
796
+
797
+ [data-slot="carousel-content"]::-webkit-scrollbar {
798
+ display: none;
799
+ }
800
+
801
+ [data-slot="carousel-item"] {
802
+ scroll-snap-align: start;
803
+ }
804
+
805
+ /* The slide. Declared rather than asked for from JavaScript so the browser
806
+ * keeps the decision: a context that will not animate simply lands, where a
807
+ * `behavior: "smooth"` it has decided to ignore can leave the scroll unstarted.
808
+ * Guarded, because a carousel that slides is exactly what someone who asked for
809
+ * less motion asked not to have. */
810
+ @media (prefers-reduced-motion: no-preference) {
811
+ [data-slot="carousel-content"] {
812
+ scroll-behavior: smooth;
813
+ }
814
+ }
815
+
816
+ /* --------------------------------------------------------------------------
817
+ * The one-time-code field's invisible input
818
+ *
819
+ * `input-otp.tsx` gives this element one class, `disabled:cursor-not-allowed`,
820
+ * and the rest of what makes it work comes from the package it wraps — inline
821
+ * styles, read here from the rendered demo rather than from the TSX, which
822
+ * shows none of it.
823
+ *
824
+ * It is a technique rather than a look, which is why it is a rule and not a
825
+ * class string. The input is a real, *opaque* input lying over the boxes: that
826
+ * is what lets a phone offer a code from a message and a password manager see
827
+ * a field at all. What is hidden is its text and its caret, not the input. The
828
+ * negative letter spacing keeps the value from reaching past the boxes, and the
829
+ * font size is the boxes' own height so a native selection paints across them
830
+ * rather than across a line of text nobody can see.
831
+ * -------------------------------------------------------------------------- */
832
+
833
+ [data-slot="input-otp"] {
834
+ position: absolute;
835
+ inset: 0;
836
+ width: 100%;
837
+ height: 100%;
838
+ display: flex;
839
+ text-align: left;
840
+ opacity: 1;
841
+ color: transparent;
842
+ background: transparent;
843
+ caret-color: transparent;
844
+ border: 0 solid transparent;
845
+ outline: 0 solid transparent;
846
+ box-shadow: none;
847
+ pointer-events: all;
848
+ line-height: 1;
849
+ letter-spacing: -0.5em;
850
+ font-size: var(--shadcn-input-otp-height, 2.25rem);
851
+ font-family: monospace;
852
+ font-variant-numeric: tabular-nums;
853
+ }