@justanarthur/modo-ui 0.5.0 → 0.6.0-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (461) hide show
  1. package/DESIGN.md +608 -0
  2. package/README.md +61 -39
  3. package/blocks/sidebar-app/examples.mdx +33 -0
  4. package/blocks/sidebar-app/index.tsx +218 -0
  5. package/blocks/sidebar-app/inset-topbar.tsx +25 -0
  6. package/blocks/sidebar-app/menu-grid.ts +26 -0
  7. package/blocks/sidebar-app/nav-data.ts +36 -0
  8. package/blocks/sidebar-app/search-field.tsx +48 -0
  9. package/blocks/sidebar-app/user-footer.tsx +67 -0
  10. package/blocks/sidebar-app/workspace-header.tsx +129 -0
  11. package/components/AI/input-message/examples.mdx +124 -0
  12. package/components/AI/input-message/file-thumbnail.tsx +173 -0
  13. package/components/AI/input-message/index.tsx +1383 -0
  14. package/components/AI/thinking-indicator/examples.mdx +27 -0
  15. package/components/AI/thinking-indicator/index.tsx +210 -0
  16. package/components/accordion/examples.mdx +148 -0
  17. package/components/accordion/index.tsx +1034 -0
  18. package/components/avatar/examples.mdx +95 -0
  19. package/components/avatar/index.tsx +129 -0
  20. package/components/badge/change-demo.tsx +29 -0
  21. package/components/badge/examples.mdx +120 -0
  22. package/components/badge/index.tsx +225 -0
  23. package/components/badge/variants.ts +73 -0
  24. package/components/button/examples.mdx +164 -0
  25. package/components/button/index.tsx +416 -0
  26. package/components/button/loading-demo.tsx +25 -0
  27. package/components/button/variants.ts +166 -0
  28. package/components/card/examples.mdx +212 -0
  29. package/components/card/index.tsx +1037 -0
  30. package/components/copy/examples.mdx +87 -0
  31. package/components/copy/index.tsx +482 -0
  32. package/components/inputs/checkbox/examples.mdx +83 -0
  33. package/components/inputs/checkbox/index.tsx +611 -0
  34. package/components/inputs/checkbox/select-all-demo.tsx +48 -0
  35. package/components/inputs/color-picker/examples.mdx +72 -0
  36. package/components/inputs/color-picker/index.tsx +1955 -0
  37. package/components/inputs/color-picker/variants.ts +401 -0
  38. package/components/inputs/combobox/examples.mdx +273 -0
  39. package/components/inputs/combobox/index.tsx +1436 -0
  40. package/components/inputs/combobox/remote-demo.tsx +101 -0
  41. package/components/inputs/date-time/calendar/examples.mdx +34 -0
  42. package/components/inputs/date-time/calendar/index.tsx +351 -0
  43. package/components/inputs/date-time/calendar/use-month-window.ts +163 -0
  44. package/components/inputs/date-time/date-picker/examples.mdx +166 -0
  45. package/components/inputs/date-time/date-picker/index.tsx +385 -0
  46. package/components/inputs/date-time/date-picker/masked-date-input.tsx +336 -0
  47. package/components/inputs/date-time/date-range-picker/examples.mdx +29 -0
  48. package/components/inputs/date-time/date-range-picker/index.tsx +217 -0
  49. package/components/inputs/date-time/duration-picker/examples.mdx +16 -0
  50. package/components/inputs/date-time/duration-picker/index.tsx +189 -0
  51. package/components/inputs/date-time/month-picker/examples.mdx +16 -0
  52. package/components/inputs/date-time/month-picker/index.tsx +190 -0
  53. package/components/inputs/date-time/picker-shell.tsx +395 -0
  54. package/components/inputs/date-time/time-columns.tsx +91 -0
  55. package/components/inputs/date-time/time-picker/examples.mdx +26 -0
  56. package/components/inputs/date-time/time-picker/index.tsx +166 -0
  57. package/components/inputs/field/examples.mdx +113 -0
  58. package/components/inputs/field/index.tsx +267 -0
  59. package/components/inputs/file-dropzone/examples.mdx +73 -0
  60. package/components/inputs/file-dropzone/file-row.tsx +201 -0
  61. package/components/inputs/file-dropzone/index.tsx +296 -0
  62. package/components/inputs/file-dropzone/upload-demo.tsx +67 -0
  63. package/components/inputs/file-dropzone/variants.ts +94 -0
  64. package/components/inputs/input/examples.mdx +135 -0
  65. package/components/inputs/input/index.tsx +494 -0
  66. package/components/inputs/input/password-demo.tsx +30 -0
  67. package/components/inputs/label/examples.mdx +67 -0
  68. package/components/inputs/label/index.tsx +85 -0
  69. package/components/inputs/number-input/examples.mdx +56 -0
  70. package/components/inputs/number-input/index.tsx +214 -0
  71. package/components/inputs/radio/examples.mdx +77 -0
  72. package/components/inputs/radio/index.tsx +636 -0
  73. package/components/inputs/search/examples.mdx +74 -0
  74. package/components/inputs/search/index.tsx +333 -0
  75. package/components/inputs/select/examples.mdx +218 -0
  76. package/components/inputs/select/index.tsx +862 -0
  77. package/components/inputs/select/variants.ts +32 -0
  78. package/components/inputs/slider/examples.mdx +127 -0
  79. package/components/inputs/slider/index.tsx +1725 -0
  80. package/components/inputs/switch/examples.mdx +94 -0
  81. package/components/inputs/switch/index.tsx +504 -0
  82. package/components/inputs/textarea/examples.mdx +88 -0
  83. package/components/inputs/textarea/index.tsx +161 -0
  84. package/components/navigation/navigation-menu/examples.mdx +109 -0
  85. package/components/navigation/navigation-menu/index.tsx +613 -0
  86. package/components/navigation/pagination/examples.mdx +64 -0
  87. package/components/navigation/pagination/index.tsx +395 -0
  88. package/components/navigation/sidebar/examples.mdx +319 -0
  89. package/components/navigation/sidebar/index.tsx +453 -0
  90. package/components/navigation/sidebar/sidebar-core.tsx +1408 -0
  91. package/components/navigation/sidebar/sidebar-menu.tsx +1495 -0
  92. package/components/navigation/sidebar/sidebar.css +74 -0
  93. package/components/navigation/sidebar/variants.ts +55 -0
  94. package/components/navigation/tabs/examples.mdx +89 -0
  95. package/components/navigation/tabs/index.tsx +494 -0
  96. package/components/navigation/tabs-subtle/examples.mdx +49 -0
  97. package/components/navigation/tabs-subtle/index.tsx +512 -0
  98. package/components/overlays/alert-dialog/examples.mdx +123 -0
  99. package/components/overlays/alert-dialog/index.tsx +258 -0
  100. package/components/overlays/alert-dialog/pending-demo.tsx +36 -0
  101. package/components/overlays/command/examples.mdx +113 -0
  102. package/components/overlays/command/index.tsx +416 -0
  103. package/components/overlays/context-menu/examples.mdx +56 -0
  104. package/components/overlays/context-menu/index.tsx +279 -0
  105. package/components/overlays/dialog/examples.mdx +144 -0
  106. package/components/overlays/dialog/index.tsx +366 -0
  107. package/components/overlays/dropdown/dropdown-search.tsx +395 -0
  108. package/components/overlays/dropdown/examples.mdx +294 -0
  109. package/components/overlays/dropdown/index.tsx +1168 -0
  110. package/components/overlays/dropdown/menu-item.tsx +464 -0
  111. package/components/overlays/dropdown/menu-parts.tsx +660 -0
  112. package/components/overlays/popover/anchored-demo.tsx +59 -0
  113. package/components/overlays/popover/examples.mdx +180 -0
  114. package/components/overlays/popover/index.tsx +315 -0
  115. package/components/overlays/preview-card/examples.mdx +61 -0
  116. package/components/overlays/preview-card/index.tsx +204 -0
  117. package/components/overlays/sheet/examples.mdx +89 -0
  118. package/components/overlays/sheet/index.tsx +247 -0
  119. package/components/overlays/toast/examples.mdx +68 -0
  120. package/components/overlays/toast/global-demo.tsx +72 -0
  121. package/components/overlays/toast/index.tsx +474 -0
  122. package/components/overlays/toast/manager.ts +193 -0
  123. package/components/overlays/tooltip/examples.mdx +106 -0
  124. package/components/overlays/tooltip/index.tsx +519 -0
  125. package/components/progress/examples.mdx +59 -0
  126. package/components/progress/index.tsx +174 -0
  127. package/components/progress/progress.css +49 -0
  128. package/components/progress/step-demo.tsx +27 -0
  129. package/components/table/examples.mdx +184 -0
  130. package/components/table/index.tsx +510 -0
  131. package/components/table/sort-demo.tsx +61 -0
  132. package/dist/base.css +100 -0
  133. package/dist/blocks/sidebar-app/index.js +39 -26
  134. package/dist/components/AI/input-message/index.js +22 -16
  135. package/dist/components/AI/thinking-indicator/index.js +9 -6
  136. package/dist/components/accordion/index.js +16 -13
  137. package/dist/components/avatar/index.d.ts +46 -0
  138. package/dist/components/avatar/index.js +18 -0
  139. package/dist/components/badge/index.d.ts +18 -11
  140. package/dist/components/badge/index.js +11 -7
  141. package/dist/components/badge/variants.d.ts +33 -0
  142. package/dist/components/badge/variants.js +10 -0
  143. package/dist/components/button/index.d.ts +53 -17
  144. package/dist/components/button/index.js +10 -6
  145. package/dist/components/button/variants.d.ts +39 -0
  146. package/dist/components/button/variants.js +8 -0
  147. package/dist/components/card/index.d.ts +16 -3
  148. package/dist/components/card/index.js +16 -11
  149. package/dist/components/copy/index.js +13 -9
  150. package/dist/components/inputs/checkbox/index.d.ts +28 -9
  151. package/dist/components/inputs/checkbox/index.js +17 -13
  152. package/dist/components/inputs/color-picker/index.d.ts +13 -13
  153. package/dist/components/inputs/color-picker/index.js +25 -18
  154. package/dist/components/inputs/color-picker/variants.d.ts +61 -0
  155. package/dist/components/inputs/color-picker/variants.js +28 -0
  156. package/dist/components/inputs/combobox/index.d.ts +60 -17
  157. package/dist/components/inputs/combobox/index.js +26 -18
  158. package/dist/components/inputs/date-time/calendar/index.js +14 -11
  159. package/dist/components/inputs/date-time/date-picker/index.d.ts +53 -11
  160. package/dist/components/inputs/date-time/date-picker/index.js +33 -25
  161. package/dist/components/inputs/date-time/date-range-picker/index.d.ts +3 -3
  162. package/dist/components/inputs/date-time/date-range-picker/index.js +32 -24
  163. package/dist/components/inputs/date-time/duration-picker/index.d.ts +3 -3
  164. package/dist/components/inputs/date-time/duration-picker/index.js +32 -24
  165. package/dist/components/inputs/date-time/month-picker/index.d.ts +3 -3
  166. package/dist/components/inputs/date-time/month-picker/index.js +31 -23
  167. package/dist/components/inputs/date-time/time-picker/index.d.ts +3 -3
  168. package/dist/components/inputs/date-time/time-picker/index.js +32 -24
  169. package/dist/components/inputs/field/index.d.ts +116 -0
  170. package/dist/components/inputs/field/index.js +28 -0
  171. package/dist/components/inputs/file-dropzone/index.d.ts +165 -0
  172. package/dist/components/inputs/file-dropzone/index.js +32 -0
  173. package/dist/components/inputs/file-dropzone/variants.d.ts +35 -0
  174. package/dist/components/inputs/file-dropzone/variants.js +12 -0
  175. package/dist/components/inputs/input/index.d.ts +95 -13
  176. package/dist/components/inputs/input/index.js +17 -9
  177. package/dist/components/inputs/label/index.d.ts +32 -0
  178. package/dist/components/inputs/label/index.js +11 -0
  179. package/dist/components/inputs/number-input/index.d.ts +84 -0
  180. package/dist/components/inputs/number-input/index.js +20 -0
  181. package/dist/components/inputs/radio/index.d.ts +20 -5
  182. package/dist/components/inputs/radio/index.js +15 -12
  183. package/dist/components/inputs/search/index.js +25 -18
  184. package/dist/components/inputs/select/index.d.ts +41 -11
  185. package/dist/components/inputs/select/index.js +27 -14
  186. package/dist/components/inputs/select/variants.d.ts +5 -0
  187. package/dist/components/inputs/select/variants.js +6 -0
  188. package/dist/components/inputs/slider/index.js +7 -5
  189. package/dist/components/inputs/switch/index.d.ts +8 -2
  190. package/dist/components/inputs/switch/index.js +14 -12
  191. package/dist/components/inputs/textarea/index.d.ts +4 -0
  192. package/dist/components/inputs/textarea/index.js +8 -6
  193. package/dist/components/navigation/navigation-menu/index.d.ts +114 -0
  194. package/dist/components/navigation/navigation-menu/index.js +40 -0
  195. package/dist/components/navigation/pagination/index.d.ts +73 -0
  196. package/dist/components/navigation/pagination/index.js +39 -0
  197. package/dist/components/navigation/sidebar/index.d.ts +44 -21
  198. package/dist/components/navigation/sidebar/index.js +41 -31
  199. package/dist/components/navigation/sidebar/variants.d.ts +25 -0
  200. package/dist/components/navigation/sidebar/variants.js +28 -0
  201. package/dist/components/navigation/tabs/index.d.ts +8 -2
  202. package/dist/components/navigation/tabs/index.js +14 -10
  203. package/dist/components/navigation/tabs-subtle/index.js +12 -10
  204. package/dist/components/overlays/alert-dialog/index.d.ts +121 -15
  205. package/dist/components/overlays/alert-dialog/index.js +22 -13
  206. package/dist/components/overlays/command/index.js +24 -17
  207. package/dist/components/overlays/context-menu/index.d.ts +33 -17
  208. package/dist/components/overlays/context-menu/index.js +27 -18
  209. package/dist/components/overlays/dialog/index.js +17 -12
  210. package/dist/components/overlays/dropdown/index.d.ts +257 -31
  211. package/dist/components/overlays/dropdown/index.js +42 -17
  212. package/dist/components/overlays/popover/index.d.ts +31 -9
  213. package/dist/components/overlays/popover/index.js +12 -9
  214. package/dist/components/overlays/preview-card/index.js +11 -8
  215. package/dist/components/overlays/sheet/index.js +18 -13
  216. package/dist/components/overlays/toast/index.d.ts +123 -47
  217. package/dist/components/overlays/toast/index.js +18 -10
  218. package/dist/components/overlays/tooltip/index.d.ts +113 -21
  219. package/dist/components/overlays/tooltip/index.js +15 -6
  220. package/dist/components/progress/index.d.ts +56 -0
  221. package/dist/components/progress/index.js +15 -0
  222. package/dist/components/table/index.d.ts +63 -8
  223. package/dist/components/table/index.js +19 -9
  224. package/dist/index.d.ts +2201 -736
  225. package/dist/index.js +223 -82
  226. package/dist/lib/date-locale.d.ts +14 -0
  227. package/dist/lib/date-locale.js +16 -0
  228. package/dist/lib/field-classes.d.ts +144 -0
  229. package/dist/lib/field-classes.js +40 -0
  230. package/dist/lib/field-variants.d.ts +47 -0
  231. package/dist/lib/field-variants.js +26 -0
  232. package/dist/lib/fluid-hover-highlight.d.ts +112 -0
  233. package/dist/lib/fluid-hover-highlight.js +17 -0
  234. package/dist/lib/focus-ring.d.ts +18 -0
  235. package/dist/lib/focus-ring.js +10 -0
  236. package/dist/lib/goo-indicator.d.ts +46 -0
  237. package/dist/lib/goo-indicator.js +14 -0
  238. package/dist/lib/icon-context.d.ts +30 -0
  239. package/dist/lib/icon-context.js +12 -0
  240. package/dist/lib/inert.d.ts +9 -0
  241. package/dist/lib/inert.js +8 -0
  242. package/dist/lib/morph-layers.d.ts +93 -0
  243. package/dist/lib/morph-layers.js +13 -0
  244. package/dist/lib/morph-part.d.ts +21 -0
  245. package/dist/lib/morph-part.js +12 -0
  246. package/dist/lib/popup.d.ts +20 -0
  247. package/dist/lib/popup.js +12 -0
  248. package/dist/lib/reduced-motion.d.ts +9 -0
  249. package/dist/lib/reduced-motion.js +6 -0
  250. package/dist/lib/row-index.d.ts +10 -0
  251. package/dist/lib/row-index.js +8 -0
  252. package/dist/lib/row-order.d.ts +28 -0
  253. package/dist/lib/row-order.js +10 -0
  254. package/dist/lib/scroll-column.d.ts +27 -0
  255. package/dist/lib/scroll-column.js +18 -0
  256. package/dist/lib/shape-context.d.ts +30 -0
  257. package/dist/lib/shape-context.js +12 -0
  258. package/dist/lib/size-context.d.ts +94 -0
  259. package/dist/lib/size-context.js +20 -0
  260. package/dist/lib/size-scale.d.ts +79 -0
  261. package/dist/lib/size-scale.js +8 -0
  262. package/dist/lib/slot.d.ts +12 -0
  263. package/dist/lib/slot.js +6 -0
  264. package/dist/lib/springs.d.ts +44 -0
  265. package/dist/lib/springs.js +8 -0
  266. package/dist/lib/surface-classes.d.ts +19 -0
  267. package/dist/lib/surface-classes.js +10 -0
  268. package/dist/lib/surface-context.d.ts +9 -0
  269. package/dist/lib/surface-context.js +8 -0
  270. package/dist/lib/use-controllable-state.d.ts +2 -0
  271. package/dist/lib/use-controllable-state.js +6 -0
  272. package/dist/lib/use-fluid-hover.d.ts +138 -0
  273. package/dist/lib/use-fluid-hover.js +14 -0
  274. package/dist/lib/use-is-mobile.d.ts +2 -0
  275. package/dist/lib/use-is-mobile.js +6 -0
  276. package/dist/lib/use-keyboard-nav-gate.d.ts +20 -0
  277. package/dist/lib/use-keyboard-nav-gate.js +7 -0
  278. package/dist/lib/use-merge-split.d.ts +47 -0
  279. package/dist/lib/use-merge-split.js +15 -0
  280. package/dist/lib/use-morph.d.ts +101 -0
  281. package/dist/lib/use-morph.js +20 -0
  282. package/dist/lib/use-touch-primary.d.ts +2 -0
  283. package/dist/lib/use-touch-primary.js +6 -0
  284. package/dist/lib/utils.d.ts +3 -0
  285. package/dist/lib/utils.js +6 -0
  286. package/dist/preset.d.ts +17 -0
  287. package/dist/preset.js +22 -2
  288. package/dist/primitives/code/index.js +7 -5
  289. package/dist/primitives/craft/index.js +9 -6
  290. package/dist/primitives/fluid-hover/index.js +9 -8
  291. package/dist/primitives/morph/index.js +15 -10
  292. package/dist/primitives/motion/index.js +10 -8
  293. package/dist/primitives/scroll-area/index.js +4 -3
  294. package/dist/primitives/separator/index.d.ts +25 -0
  295. package/dist/primitives/separator/index.js +9 -0
  296. package/dist/primitives/sizes/index.js +6 -4
  297. package/dist/primitives/skeleton/index.d.ts +35 -0
  298. package/dist/primitives/skeleton/index.js +12 -0
  299. package/dist/primitives/surface/index.js +6 -4
  300. package/dist/shared/{components-3mkepka5.js → components-0jmqhx2k.js} +28 -25
  301. package/dist/shared/components-124epb7f.js +53 -0
  302. package/dist/shared/{components-gz8zf3ec.js → components-1k0wv53d.js} +15 -43
  303. package/dist/shared/components-26snnbs9.js +322 -0
  304. package/dist/shared/{components-2dxkv6zm.js → components-2c0qcfx4.js} +8 -7
  305. package/dist/shared/{components-473g814w.js → components-2mt9te6d.js} +243 -137
  306. package/dist/shared/{components-hawvy2qz.js → components-2z48g4fp.js} +9 -30
  307. package/dist/shared/components-34txk9rj.js +35 -0
  308. package/dist/shared/components-3h92d94m.js +23 -0
  309. package/dist/shared/{components-zfnmn5d4.js → components-3sp623ae.js} +36 -31
  310. package/dist/shared/{components-jwst3vtj.js → components-3wxkjgqn.js} +186 -76
  311. package/dist/shared/{components-s2bz1xpk.js → components-49bsynbw.js} +8 -5
  312. package/dist/shared/components-4bwsd46w.js +71 -0
  313. package/dist/shared/components-4n4f5m3e.js +297 -0
  314. package/dist/shared/{components-0q0sqfh4.js → components-4y816hwp.js} +27 -49
  315. package/dist/shared/components-52ngsgca.js +399 -0
  316. package/dist/shared/{components-y9y0g8er.js → components-52r5763g.js} +22 -19
  317. package/dist/shared/components-559tf7yb.js +28 -0
  318. package/dist/shared/components-5mkga9hj.js +440 -0
  319. package/dist/shared/{components-kwa6mrf9.js → components-5s0nfqvw.js} +14 -9
  320. package/dist/shared/{components-dk0gjr5a.js → components-60atskhp.js} +19 -18
  321. package/dist/shared/{components-rr7a6ja9.js → components-658b26nb.js} +21 -18
  322. package/dist/shared/{components-xxvdw7k1.js → components-65vwfjs6.js} +37 -34
  323. package/dist/shared/{components-frw34b65.js → components-6j2fh74k.js} +114 -123
  324. package/dist/shared/components-6zg1yft7.js +167 -0
  325. package/dist/shared/components-6zng858q.js +53 -0
  326. package/dist/shared/components-72w4ge68.js +64 -0
  327. package/dist/shared/{components-cv16mryv.js → components-78x40gee.js} +13 -7
  328. package/dist/shared/{components-b2wyq2cq.js → components-7d4r7hh1.js} +39 -57
  329. package/dist/shared/components-7ntvvegr.js +316 -0
  330. package/dist/shared/components-8nwsqjn8.js +34 -0
  331. package/dist/shared/{components-5xc2j8jz.js → components-8tt3xbb5.js} +19 -18
  332. package/dist/shared/{components-vc7vq5nz.js → components-9as3rf68.js} +6 -3
  333. package/dist/shared/components-9mys9jna.js +255 -0
  334. package/dist/shared/components-adkarj8n.js +35 -0
  335. package/dist/shared/{components-b3c5et5b.js → components-ae9fncz4.js} +32 -31
  336. package/dist/shared/{components-hqeq3w9q.js → components-awra5sff.js} +24 -16
  337. package/dist/shared/components-b1e239g3.js +28 -0
  338. package/dist/shared/{components-q5xj5c16.js → components-b1f2bjf1.js} +9 -8
  339. package/dist/shared/{components-qmmjx1qw.js → components-bn42vq6d.js} +71 -72
  340. package/dist/shared/components-c96g82th.js +1444 -0
  341. package/dist/shared/components-c9yr4ed1.js +44 -0
  342. package/dist/shared/components-d3shbwqq.js +95 -0
  343. package/dist/shared/{components-jjw69c4c.js → components-dcc02hs2.js} +7 -4
  344. package/dist/shared/{components-men63rwj.js → components-de99ykt7.js} +3 -2
  345. package/dist/shared/components-dhgk6mbt.js +16 -0
  346. package/dist/shared/components-drxrtnp2.js +25 -0
  347. package/dist/shared/{components-6p8tfcd6.js → components-ds9fqat9.js} +21 -18
  348. package/dist/shared/{components-mjthm1kf.js → components-egy4tyjt.js} +11 -8
  349. package/dist/shared/components-f0xfpkhh.js +82 -0
  350. package/dist/shared/components-f7h57m6t.js +59 -0
  351. package/dist/shared/{components-d6xtjht3.js → components-fjkpbg6n.js} +33 -30
  352. package/dist/shared/{components-gc5vtq2f.js → components-gh0qeey3.js} +63 -29
  353. package/dist/shared/{components-39jq9va1.js → components-gvbapfen.js} +29 -24
  354. package/dist/shared/{components-5vgpnxgy.js → components-gzesg7hy.js} +19 -16
  355. package/dist/shared/components-h6p86be3.js +19 -0
  356. package/dist/shared/components-h83az0bz.js +33 -0
  357. package/dist/shared/components-jjrj6ymn.js +104 -0
  358. package/dist/shared/{components-wvp1m52g.js → components-jp5v0m0f.js} +15 -14
  359. package/dist/shared/{components-zrkzcayz.js → components-jqpefjsn.js} +54 -6
  360. package/dist/shared/{components-1z6tdadk.js → components-k74j4hwh.js} +20 -17
  361. package/dist/shared/components-kswxnm3h.js +24 -0
  362. package/dist/shared/{components-jbbmdr74.js → components-mkkbbgb7.js} +36 -17
  363. package/dist/shared/{components-pbmqctfa.js → components-mpw667rb.js} +169 -65
  364. package/dist/shared/{components-s5ngg32c.js → components-paa08427.js} +121 -47
  365. package/dist/shared/{components-vfbhxf5r.js → components-pd42emw3.js} +6 -5
  366. package/dist/shared/{components-hw9yk32z.js → components-pmfszv7a.js} +35 -23
  367. package/dist/shared/{components-chacnk61.js → components-pw06rbxq.js} +19 -19
  368. package/dist/shared/components-q03cktx8.js +246 -0
  369. package/dist/shared/{components-kvr7f9hy.js → components-qdm3yh26.js} +19 -10
  370. package/dist/shared/{components-27nnvrwe.js → components-qs4rkqsj.js} +15 -14
  371. package/dist/shared/{components-s083f38z.js → components-r6gbmkew.js} +22 -21
  372. package/dist/shared/{components-ta7shw28.js → components-r8eqs7gz.js} +4 -4
  373. package/dist/shared/{components-sn1rxx1d.js → components-rm02h9nt.js} +12 -11
  374. package/dist/shared/{components-c6s6b43g.js → components-rrbpmfx4.js} +3 -2
  375. package/dist/shared/{components-n7mjr357.js → components-tz1fv35x.js} +3 -2
  376. package/dist/shared/components-tz4gaf1v.js +23 -0
  377. package/dist/shared/{components-zx6b6yby.js → components-vf45j12c.js} +4 -18
  378. package/dist/shared/{components-3ky44908.js → components-vfjc9jzz.js} +2 -3
  379. package/dist/shared/{components-39vmfq9s.js → components-vsa625vk.js} +21 -20
  380. package/dist/shared/components-wawnmkph.js +500 -0
  381. package/dist/shared/components-wktrrb4m.js +38 -0
  382. package/dist/shared/{components-8snj490h.js → components-wwd363me.js} +78 -32
  383. package/dist/shared/{components-5pnw8183.js → components-xcwvgcrd.js} +23 -22
  384. package/dist/shared/components-xdqmt6ed.js +20 -0
  385. package/dist/shared/{components-h2ajmhwn.js → components-y1w3a6wx.js} +107 -35
  386. package/dist/shared/{components-ar66gnt0.js → components-y6578b8h.js} +37 -34
  387. package/dist/shared/{components-59efxjd9.js → components-yhgq0qxx.js} +13 -12
  388. package/dist/shared/{components-jthe1pwb.js → components-yz84gpkq.js} +101 -404
  389. package/dist/shared/components-z3v0n0de.js +11 -0
  390. package/dist/shared/{components-7r3etddy.js → components-z9n19fyk.js} +19 -54
  391. package/dist/shared/components-zbvjzh1p.js +141 -0
  392. package/dist/styles.css +241 -16
  393. package/dist/tailwind.css +13 -0
  394. package/dist/tokens.css +34 -0
  395. package/index.ts +60 -0
  396. package/lib/date-locale.ts +50 -0
  397. package/lib/field-classes.ts +115 -0
  398. package/lib/field-variants.ts +117 -0
  399. package/lib/fluid-hover-highlight.tsx +139 -0
  400. package/lib/focus-ring.tsx +46 -0
  401. package/lib/goo-indicator.tsx +261 -0
  402. package/lib/icon-context.tsx +310 -0
  403. package/lib/inert.ts +22 -0
  404. package/lib/morph-layers.tsx +102 -0
  405. package/lib/morph-part.tsx +49 -0
  406. package/lib/popup.ts +52 -0
  407. package/lib/reduced-motion.ts +19 -0
  408. package/lib/row-index.tsx +29 -0
  409. package/lib/row-order.tsx +115 -0
  410. package/lib/scroll-column.tsx +244 -0
  411. package/lib/shape-context.tsx +124 -0
  412. package/lib/size-context.tsx +66 -0
  413. package/lib/size-scale.ts +115 -0
  414. package/lib/slot.ts +25 -0
  415. package/lib/springs.ts +62 -0
  416. package/lib/surface-classes.ts +58 -0
  417. package/lib/surface-context.tsx +21 -0
  418. package/lib/use-controllable-state.ts +44 -0
  419. package/lib/use-fluid-hover.ts +541 -0
  420. package/lib/use-is-mobile.ts +25 -0
  421. package/lib/use-keyboard-nav-gate.ts +45 -0
  422. package/lib/use-merge-split.tsx +209 -0
  423. package/lib/use-morph.ts +557 -0
  424. package/lib/use-touch-primary.tsx +43 -0
  425. package/lib/utils.ts +37 -0
  426. package/package.json +177 -4
  427. package/preset.ts +196 -0
  428. package/primitives/code/examples.mdx +27 -0
  429. package/primitives/code/index.tsx +80 -0
  430. package/primitives/craft/demos.tsx +173 -0
  431. package/primitives/craft/examples.mdx +138 -0
  432. package/primitives/craft/index.tsx +76 -0
  433. package/primitives/fluid-hover/examples.mdx +84 -0
  434. package/primitives/fluid-hover/index.tsx +316 -0
  435. package/primitives/morph/examples.mdx +135 -0
  436. package/primitives/morph/index.tsx +192 -0
  437. package/primitives/motion/examples.mdx +100 -0
  438. package/primitives/motion/index.tsx +160 -0
  439. package/primitives/scroll-area/examples.mdx +58 -0
  440. package/primitives/scroll-area/index.tsx +200 -0
  441. package/primitives/separator/examples.mdx +30 -0
  442. package/primitives/separator/index.tsx +53 -0
  443. package/primitives/sizes/examples.mdx +167 -0
  444. package/primitives/sizes/index.tsx +89 -0
  445. package/primitives/skeleton/examples.mdx +51 -0
  446. package/primitives/skeleton/index.tsx +72 -0
  447. package/primitives/skeleton/skeleton.css +15 -0
  448. package/primitives/surface/examples.mdx +173 -0
  449. package/primitives/surface/index.tsx +109 -0
  450. package/primitives/surface/surface.css +176 -0
  451. package/dist/shared/components-0sn7ypjw.js +0 -61
  452. package/dist/shared/components-1434p1mh.js +0 -123
  453. package/dist/shared/components-a86dytt0.js +0 -986
  454. package/dist/shared/components-gf5s6ap9.js +0 -42
  455. package/dist/shared/components-hyq23phv.js +0 -310
  456. package/dist/shared/components-ng72k97e.js +0 -128
  457. package/dist/shared/components-raknhppb.js +0 -64
  458. package/dist/shared/components-vynjtrk6.js +0 -19
  459. package/dist/shared/components-wy9jpqny.js +0 -146
  460. /package/dist/shared/{components-1v7rxytx.js → components-3ey0hzpb.js} +0 -0
  461. /package/dist/shared/{components-ezxhrmer.js → components-jcnjay5g.js} +0 -0
@@ -0,0 +1,166 @@
1
+ // biome-ignore-all lint: vendored upstream code keeps its own patterns (see the header)
2
+ /*
3
+ * Ported from Fluid Functionalism — github.com/mickadesign/fluid-functionalism
4
+ * `registry/base/button.tsx` @ b3587bdbd83fc66c2a6aae3817ffb856cb09260b
5
+ * MIT License © 2026 Micka Touillaud — fluidfunctionalism.com (notice: LICENSE.fluid-functionalism)
6
+ * Local modifications:
7
+ * - The class recipe (`buttonVariants`) and the size aliases, split out of
8
+ * `index.tsx` so server code can call them: no JSX, hooks or contexts here.
9
+ * `index.tsx` re-exports them.
10
+ * - Styling reads DS tokens (see `index.tsx`).
11
+ * - Variants `outline` (an alias of `tertiary`), `destructive`, `success` and
12
+ * `link`, and the `xs` size alias (→ `compact`), for hosts with a
13
+ * shadcn-style API; see `index.tsx` for the look.
14
+ * - `buttonVariants` takes the size aliases too (resolved as the Button
15
+ * resolves them), so a host can re-export it as is.
16
+ * - `surface: true` (local): the fill, ring, hover, press and disabled look
17
+ * as root classes, for an element that is not a Button (`<a>`), which has
18
+ * no surface layer of its own. Static: no press shrink, no loading morph.
19
+ * The transition list moved into compounds so one element gets exactly one.
20
+ */
21
+
22
+ import { cva, type VariantProps } from 'class-variance-authority'
23
+
24
+ type ButtonVariant = 'primary' | 'secondary' | 'tertiary' | 'outline' | 'ghost' | 'destructive' | 'success' | 'link'
25
+
26
+ type SurfacedVariant = Exclude<ButtonVariant, 'link'>
27
+
28
+ const SURFACED: SurfacedVariant[] = ['primary', 'secondary', 'tertiary', 'outline', 'ghost', 'destructive', 'success']
29
+
30
+ /* The Button draws its fill on an inner layer 1px inside the root and fills
31
+ that pixel back out with a same-color spread. Without the layer the root
32
+ is the surface, so the fill sits on the root and the outline ring is an
33
+ inset hairline on the same edge. Same tokens and mixes as the layer
34
+ (`index.tsx` bgVariants); plain `hover:` / `active:` instead of `group-*`. */
35
+ const surfaceVariants: Record<SurfacedVariant, string> = {
36
+ primary:
37
+ '[--btn-bg:var(--foreground)] hover:[--btn-bg:color-mix(in_oklab,var(--foreground)_90%,var(--background))] active:[--btn-bg:color-mix(in_oklab,var(--foreground)_80%,var(--background))] bg-[var(--btn-bg)]',
38
+ secondary:
39
+ '[--btn-bg:var(--accent)] hover:[--btn-bg:color-mix(in_oklab,var(--accent)_80%,var(--background))] active:[--btn-bg:var(--accent)] bg-[var(--btn-bg)]',
40
+ tertiary: 'shadow-[inset_0_0_0_1px_var(--border)] hover:bg-hover active:bg-active',
41
+ outline: 'shadow-[inset_0_0_0_1px_var(--border)] hover:bg-hover active:bg-active',
42
+ ghost: 'hover:bg-hover active:bg-active',
43
+ destructive: 'bg-destructive-wash hover:bg-destructive-wash-hover active:bg-destructive-wash-active',
44
+ success: 'bg-success-wash hover:bg-success-wash-hover active:bg-success-wash-active',
45
+ }
46
+
47
+ const buttonRecipe = cva(
48
+ [
49
+ 'group relative isolate inline-flex items-center justify-center outline-none cursor-pointer',
50
+ 'duration-fast',
51
+ 'disabled:opacity-50 disabled:pointer-events-none',
52
+ 'focus-visible:ring-1 focus-visible:ring-focus-ring',
53
+ ],
54
+ {
55
+ variants: {
56
+ variant: {
57
+ primary: 'text-background',
58
+ secondary: 'text-foreground',
59
+ tertiary: 'text-foreground',
60
+ outline: 'text-foreground',
61
+ ghost: 'text-muted-foreground hover:text-foreground',
62
+ destructive: 'text-destructive-strong',
63
+ success: 'text-success-strong',
64
+ // The underline is always drawn and fades its color in, so hovering
65
+ // never shifts a pixel of the label.
66
+ link: 'text-foreground underline underline-offset-4 decoration-transparent hover:decoration-current',
67
+ },
68
+ // The two-step size ladder shared by every control — see /docs/sizes.
69
+ // default = 36px control height, compact = 28px for dense surfaces.
70
+ size: {
71
+ default: 'h-9 px-4 text-body gap-1.5',
72
+ compact: 'h-7 px-3 text-body-compact gap-1',
73
+ icon: 'h-9 w-9 p-0 [&_svg]:h-4 [&_svg]:w-4',
74
+ 'icon-compact': 'h-7 w-7 p-0 [&_svg]:h-3.5 [&_svg]:w-3.5',
75
+ },
76
+ iconLeft: { true: '' },
77
+ iconRight: { true: '' },
78
+ // The fill and ring as root classes, for a non-Button host (an anchor).
79
+ surface: {
80
+ true: [
81
+ 'rounded-lg',
82
+ 'aria-disabled:opacity-50 aria-disabled:pointer-events-none',
83
+ '[&_svg]:shrink-0 [&_svg]:stroke-[1.5] [&_svg]:transition-[stroke-width] [&_svg]:duration-fast hover:[&_svg]:stroke-[2]',
84
+ ],
85
+ false: '',
86
+ },
87
+ },
88
+ // An icon sits 4px closer to its edge than text does: 12px default and
89
+ // 8px compact, against the 16px / 12px base padding.
90
+ compoundVariants: [
91
+ { size: 'compact', iconLeft: true, className: 'pl-2' },
92
+ { size: 'default', iconLeft: true, className: 'pl-3' },
93
+ { size: 'compact', iconRight: true, className: 'pr-2' },
94
+ { size: 'default', iconRight: true, className: 'pr-3' },
95
+ // A link is text: no surface to pad, but it keeps the control height so
96
+ // it still lines up with the buttons beside it.
97
+ { variant: 'link', size: ['default', 'compact'], className: 'px-0' },
98
+ // One transition list per element: a link fades its underline, a
99
+ // surface its fill and ring.
100
+ { variant: 'link', className: 'transition-[color,opacity,text-decoration-color]' },
101
+ { variant: SURFACED, surface: false, className: 'transition-[color,opacity]' },
102
+ {
103
+ variant: SURFACED,
104
+ surface: true,
105
+ className: 'no-underline transition-[color,opacity,background-color,box-shadow]',
106
+ },
107
+ ...SURFACED.map(variant => ({ variant, surface: true, className: surfaceVariants[variant] })),
108
+ // The Button sizes its icons by prop; children of a surface host are sized here.
109
+ { surface: true, size: 'default', className: '[&_svg]:size-4' },
110
+ { surface: true, size: 'compact', className: '[&_svg]:size-3.5' },
111
+ ],
112
+ defaultVariants: {
113
+ variant: 'primary',
114
+ size: 'default',
115
+ surface: false,
116
+ },
117
+ },
118
+ )
119
+
120
+ type ButtonSizeCanonical = 'default' | 'compact' | 'icon' | 'icon-compact'
121
+
122
+ /** Public size values: the canonical two-size scale plus aliases, kept so
123
+ * existing call sites keep compiling. Aliases resolve onto the canonical
124
+ * ladder (sm, xs → compact; md/lg → default). The ladder has two steps, so
125
+ * `xs` is compact rather than a third height. */
126
+ type ButtonSize = ButtonSizeCanonical | 'xs' | 'sm' | 'md' | 'lg' | 'icon-sm' | 'icon-lg'
127
+
128
+ const legacySizeAliases: Partial<Record<ButtonSize, ButtonSizeCanonical>> = {
129
+ xs: 'compact',
130
+ sm: 'compact',
131
+ md: 'default',
132
+ lg: 'default',
133
+ 'icon-sm': 'icon-compact',
134
+ 'icon-lg': 'icon',
135
+ }
136
+
137
+ type ButtonRecipeOptions = NonNullable<Parameters<typeof buttonRecipe>[0]>
138
+
139
+ /** Options of `buttonVariants`: the Button's look, picked without rendering one. */
140
+ interface ButtonVariantsOptions extends Omit<ButtonRecipeOptions, 'size'> {
141
+ /** Visual style. Defaults to `"primary"`. */
142
+ variant?: ButtonVariant | null
143
+ /** Step on the size ladder; the aliases resolve as on the Button (xs, sm → compact; md, lg → default; icon-sm → icon-compact; icon-lg → icon). Defaults to `"default"`. */
144
+ size?: ButtonSize | null
145
+ /** Draw the fill, ring, hover, press and disabled (`aria-disabled`) look on the element itself, for a host that is not a Button, such as an `<a>`. Static: no press shrink or loading morph — prefer `<Button asChild>` when you can render a component. Defaults to `false`. */
146
+ surface?: boolean | null
147
+ }
148
+
149
+ /**
150
+ * The Button's class recipe, callable from server code (no JSX, hooks or
151
+ * context). Without `surface` it returns the root classes the Button builds
152
+ * on: layout, label color, size, focus ring — the fill lives on the Button's
153
+ * inner layer, so on its own it reads as a bare label. With `surface: true`
154
+ * the fill and ring go on the element itself, for an anchor styled as a
155
+ * button. Size aliases resolve onto the ladder; the radius is the rounded
156
+ * shape's (pass `rounded-[20px]` or read `useShape().button` for pill).
157
+ */
158
+ function buttonVariants({ size, ...options }: ButtonVariantsOptions = {}): string {
159
+ const canonical = size ? (legacySizeAliases[size] ?? (size as ButtonSizeCanonical)) : size
160
+ return buttonRecipe({ ...options, size: canonical } as ButtonRecipeOptions)
161
+ }
162
+
163
+ type ButtonVariantsProps = VariantProps<typeof buttonVariants>
164
+
165
+ export type { ButtonSize, ButtonSizeCanonical, ButtonVariant, ButtonVariantsOptions, ButtonVariantsProps }
166
+ export { buttonVariants, legacySizeAliases }
@@ -0,0 +1,212 @@
1
+ import Card from './index'
2
+ import { Circle, Moon, Paintbrush, Palette, Shield, SquareLibrary } from 'lucide-react'
3
+
4
+ # Basic
5
+
6
+ Borderless inline list: icon + a ghost action, divided by hairlines.
7
+
8
+ <div className="w-full max-w-[520px]">
9
+ <Card.Group orientation="inline">
10
+ {[
11
+ { icon: Circle, title: 'Fluid motion', description: 'Spring-tuned transitions calibrated across three tiers' },
12
+ { icon: Shield, title: 'Accessible by default', description: 'Focus-visible rings and ARIA roles in every part' },
13
+ { icon: Palette, title: 'Yours to theme', description: 'Swap radius, icons, and primitive at runtime' },
14
+ { icon: Moon, title: 'Dark mode ready', description: 'Tokens adapt to light and dark automatically' },
15
+ ].map((f) => (
16
+ <Card key={f.title} onClick={() => {}}>
17
+ <Card.Media icon={f.icon} />
18
+ <Card.Header>
19
+ <Card.Title>{f.title}</Card.Title>
20
+ <Card.Description>{f.description}</Card.Description>
21
+ </Card.Header>
22
+ <Card.Footer>
23
+ <Card.Button>Connect</Card.Button>
24
+ </Card.Footer>
25
+ </Card>
26
+ ))}
27
+ </Card.Group>
28
+ </div>
29
+
30
+ # Grid: 2-D fluid hover
31
+
32
+ Two-column grid of image tiles — `columns` above 1 turns on 2-D fluid
33
+ hover: the highlight springs to the nearest card across rows and columns.
34
+
35
+ <div className="w-full max-w-[560px]">
36
+ <Card.Group columns={2} border="outlined" separated>
37
+ {[
38
+ { title: 'Fluid motion', description: 'Spring-tuned transitions calibrated across three tiers' },
39
+ { title: 'Accessible by default', description: 'Focus-visible rings and ARIA roles in every part' },
40
+ { title: 'Yours to theme', description: 'Swap radius, icons, and primitive at runtime' },
41
+ { title: 'Dark mode ready', description: 'Tokens adapt to light and dark automatically' },
42
+ ].map((f) => (
43
+ <Card key={f.title} onClick={() => {}}>
44
+ <Card.Image src="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1 1' preserveAspectRatio='none'><radialGradient id='a' cx='.2' cy='.15' r='1'><stop stop-color='%236B97FF' stop-opacity='.9'/><stop offset='1' stop-color='%236B97FF' stop-opacity='.15'/></radialGradient><rect width='1' height='1' fill='white'/><rect width='1' height='1' fill='url(%23a)'/></svg>" />
45
+ <Card.Header>
46
+ <Card.Title>{f.title}</Card.Title>
47
+ <Card.Description>{f.description}</Card.Description>
48
+ </Card.Header>
49
+ <Card.Footer>
50
+ <Card.Button variant="primary">Get started</Card.Button>
51
+ <Card.Button variant="secondary">Learn more</Card.Button>
52
+ </Card.Footer>
53
+ </Card>
54
+ ))}
55
+ </Card.Group>
56
+ </div>
57
+
58
+ # Outlined group
59
+
60
+ One shared outlined frame, rows split by dividers: logo + primary.
61
+ Card.Media also accepts a [logoA, logoB] tuple for a connected pair.
62
+
63
+ <div className="w-full max-w-[520px]">
64
+ <Card.Group orientation="inline" border="outlined">
65
+ {[
66
+ { title: 'Fluid motion', description: 'Spring-tuned transitions calibrated across three tiers' },
67
+ { title: 'Accessible by default', description: 'Focus-visible rings and ARIA roles in every part' },
68
+ { title: 'Yours to theme', description: 'Swap radius, icons, and primitive at runtime' },
69
+ { title: 'Dark mode ready', description: 'Tokens adapt to light and dark automatically' },
70
+ ].map((f) => (
71
+ <Card key={f.title} onClick={() => {}}>
72
+ <Card.Media logo="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1 1' preserveAspectRatio='none'><radialGradient id='a' cx='.2' cy='.15' r='1'><stop stop-color='%236B97FF' stop-opacity='.9'/><stop offset='1' stop-color='%236B97FF' stop-opacity='.15'/></radialGradient><rect width='1' height='1' fill='white'/><rect width='1' height='1' fill='url(%23a)'/></svg>" />
73
+ <Card.Header>
74
+ <Card.Title>{f.title}</Card.Title>
75
+ <Card.Description>{f.description}</Card.Description>
76
+ </Card.Header>
77
+ <Card.Footer>
78
+ <Card.Button variant="primary">Get started</Card.Button>
79
+ </Card.Footer>
80
+ </Card>
81
+ ))}
82
+ </Card.Group>
83
+ </div>
84
+
85
+ # Separated tiles
86
+
87
+ Separated inline tiles with a full-height image; the action row drops
88
+ below the text (primary, secondary, ghost).
89
+
90
+ <div className="w-full max-w-[560px]">
91
+ <Card.Group orientation="inline" separated>
92
+ {[
93
+ { title: 'Fluid motion', description: 'Spring-tuned transitions calibrated across three tiers' },
94
+ { title: 'Accessible by default', description: 'Focus-visible rings and ARIA roles in every part' },
95
+ { title: 'Yours to theme', description: 'Swap radius, icons, and primitive at runtime' },
96
+ { title: 'Dark mode ready', description: 'Tokens adapt to light and dark automatically' },
97
+ ].map((f) => (
98
+ <Card key={f.title} onClick={() => {}}>
99
+ <Card.Image src="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1 1' preserveAspectRatio='none'><radialGradient id='a' cx='.2' cy='.15' r='1'><stop stop-color='%236B97FF' stop-opacity='.9'/><stop offset='1' stop-color='%236B97FF' stop-opacity='.15'/></radialGradient><rect width='1' height='1' fill='white'/><rect width='1' height='1' fill='url(%23a)'/></svg>" />
100
+ <Card.Header>
101
+ <Card.Title>{f.title}</Card.Title>
102
+ <Card.Description>{f.description}</Card.Description>
103
+ </Card.Header>
104
+ <Card.Footer>
105
+ <Card.Button variant="primary">Get started</Card.Button>
106
+ <Card.Button variant="secondary">Learn more</Card.Button>
107
+ <Card.Button>Connect</Card.Button>
108
+ </Card.Footer>
109
+ </Card>
110
+ ))}
111
+ </Card.Group>
112
+ </div>
113
+
114
+ # Fully yours — compose anything
115
+
116
+ A standalone promo card tuned to a narrow 300px column: banner, features,
117
+ actions and a dismiss control revealed on hover or focus. (Upstream's demo
118
+ hides the card on dismiss; here `onDismiss` is a no-op.)
119
+
120
+ <div className="w-full max-w-[300px]">
121
+ <Card dismissible onDismiss={() => {}} className="border border-border/60 overflow-hidden rounded-xl">
122
+ <Card.Image src="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1 1' preserveAspectRatio='none'><radialGradient id='a' cx='.2' cy='.15' r='1'><stop stop-color='%236B97FF' stop-opacity='.9'/><stop offset='1' stop-color='%236B97FF' stop-opacity='.15'/></radialGradient><rect width='1' height='1' fill='white'/><rect width='1' height='1' fill='url(%23a)'/></svg>" />
123
+ <Card.Header>
124
+ <Card.Title>Meet the new Card component</Card.Title>
125
+ </Card.Header>
126
+ <Card.Content className="flex flex-col gap-3">
127
+ <Card.Feature icon={Paintbrush} title="Always pixel-perfect" description="Renders your design exactly — token-driven and crisp in light and dark, at any radius" />
128
+ <Card.Feature icon={SquareLibrary} title="Stacked, inline, or grid" description="One compositional API — borderless by default, with separated tiles or a shared frame" />
129
+ </Card.Content>
130
+ <Card.Footer>
131
+ <Card.Button variant="primary">Get started</Card.Button>
132
+ <Card.Button variant="ghost">Learn more</Card.Button>
133
+ </Card.Footer>
134
+ </Card>
135
+ </div>
136
+
137
+ # Selected
138
+
139
+ Clickable selection — one active card carries the fill, its title bolds,
140
+ and the group drops the dividers around it. The selection here is fixed on
141
+ the second card; drive `selected` from your own state to follow clicks.
142
+
143
+ <div className="w-full max-w-[520px]">
144
+ <Card.Group orientation="inline">
145
+ {[
146
+ { icon: Circle, title: 'Fluid motion', description: 'Spring-tuned transitions calibrated across three tiers' },
147
+ { icon: Shield, title: 'Accessible by default', description: 'Focus-visible rings and ARIA roles in every part' },
148
+ { icon: Palette, title: 'Yours to theme', description: 'Swap radius, icons, and primitive at runtime' },
149
+ { icon: Moon, title: 'Dark mode ready', description: 'Tokens adapt to light and dark automatically' },
150
+ ].map((f, i) => (
151
+ <Card key={f.title} label={f.title} selected={i === 1} onClick={() => {}}>
152
+ <Card.Media icon={f.icon} />
153
+ <Card.Header>
154
+ <Card.Title>{f.title}</Card.Title>
155
+ <Card.Description>{f.description}</Card.Description>
156
+ </Card.Header>
157
+ </Card>
158
+ ))}
159
+ </Card.Group>
160
+ </div>
161
+
162
+ # Outlined
163
+
164
+ `border="outlined"` frames a standalone card in a hairline, the same frame an
165
+ outlined group gives its tiles. Borderless stays the default.
166
+
167
+ <div className="w-full max-w-[360px]">
168
+ <Card border="outlined">
169
+ <Card.Header>
170
+ <Card.Title>Billing</Card.Title>
171
+ <Card.Description>Your plan renews on 1 November.</Card.Description>
172
+ </Card.Header>
173
+ <Card.Content className="text-body text-muted-foreground">Team plan, 12 seats, paid yearly.</Card.Content>
174
+ <Card.Footer>
175
+ <Card.Button variant="secondary">Change plan</Card.Button>
176
+ <Card.Button>View invoices</Card.Button>
177
+ </Card.Footer>
178
+ </Card>
179
+ </div>
180
+
181
+ # Divider
182
+
183
+ `Card.Divider` runs a hairline across the card between two parts, edge to
184
+ edge and spaced like the parts. In an inline card it stands upright.
185
+
186
+ <div className="flex w-full max-w-[520px] flex-col gap-6">
187
+ <Card border="outlined" className="max-w-[360px]">
188
+ <Card.Header>
189
+ <Card.Title>Request #4182</Card.Title>
190
+ <Card.Description>Submitted by Ada Lovelace</Card.Description>
191
+ </Card.Header>
192
+ <Card.Content className="text-body text-muted-foreground">Three items, waiting for approval.</Card.Content>
193
+ <Card.Divider />
194
+ <Card.Footer>
195
+ <Card.Button variant="primary">Approve</Card.Button>
196
+ <Card.Button>Decline</Card.Button>
197
+ </Card.Footer>
198
+ </Card>
199
+ <Card.Group orientation="inline" border="outlined">
200
+ <Card>
201
+ <Card.Media icon={Shield} />
202
+ <Card.Header>
203
+ <Card.Title>Two-step sign-in</Card.Title>
204
+ <Card.Description>On for every member</Card.Description>
205
+ </Card.Header>
206
+ <Card.Divider />
207
+ <Card.Footer>
208
+ <Card.Button>Manage</Card.Button>
209
+ </Card.Footer>
210
+ </Card>
211
+ </Card.Group>
212
+ </div>