@recursica/adapter-mantine-v8 1.0.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 (362) hide show
  1. package/.storybook/commonArgTypes.ts +148 -0
  2. package/ARCHITECTURE.md +18 -0
  3. package/CHANGELOG.md +688 -0
  4. package/LICENSE +21 -0
  5. package/OVERSTYLING.md +56 -0
  6. package/README.md +70 -0
  7. package/SETUP.md +93 -0
  8. package/USAGE.md +57 -0
  9. package/dist/adapter-mantine-v8.cjs +12 -0
  10. package/dist/adapter-mantine-v8.cjs.map +1 -0
  11. package/dist/adapter-mantine-v8.css +1 -0
  12. package/dist/adapter-mantine-v8.js +5759 -0
  13. package/dist/adapter-mantine-v8.js.map +1 -0
  14. package/dist/index.d.ts +2095 -0
  15. package/dist/test.html +1 -0
  16. package/dist/vite.svg +1 -0
  17. package/docs/PHILOSOPHY.md +39 -0
  18. package/llms.txt +74 -0
  19. package/package.json +131 -0
  20. package/recursica_brand.json +2677 -0
  21. package/recursica_tokens.json +799 -0
  22. package/recursica_ui-kit.json +14981 -0
  23. package/recursica_variables_scoped.css +30489 -0
  24. package/src/GlobalExemptions.modules.css +7 -0
  25. package/src/Introduction.stories.tsx +154 -0
  26. package/src/OverStyling.tsx +79 -0
  27. package/src/Version.tsx +44 -0
  28. package/src/components/Accordion/ACCORDION_IMPLEMENTATION_NOTES.md +72 -0
  29. package/src/components/Accordion/Accordion.module.css +367 -0
  30. package/src/components/Accordion/Accordion.stories.tsx +189 -0
  31. package/src/components/Accordion/Accordion.test.tsx +1 -0
  32. package/src/components/Accordion/Accordion.tsx +220 -0
  33. package/src/components/Accordion/USAGE.md +51 -0
  34. package/src/components/Accordion/index.ts +1 -0
  35. package/src/components/AssistiveElement/ASSISTIVEELEMENT_IMPLEMENTATION_NOTES.md +45 -0
  36. package/src/components/AssistiveElement/AssistiveElement.module.css +111 -0
  37. package/src/components/AssistiveElement/AssistiveElement.stories.tsx +68 -0
  38. package/src/components/AssistiveElement/AssistiveElement.test.tsx +1 -0
  39. package/src/components/AssistiveElement/AssistiveElement.tsx +93 -0
  40. package/src/components/AssistiveElement/USAGE.md +36 -0
  41. package/src/components/AutoComplete/AUTOCOMPLETE_IMPLEMENTATION_NOTES.md +42 -0
  42. package/src/components/AutoComplete/AutoComplete.module.css +430 -0
  43. package/src/components/AutoComplete/AutoComplete.stories.tsx +336 -0
  44. package/src/components/AutoComplete/AutoComplete.test.tsx +1 -0
  45. package/src/components/AutoComplete/AutoComplete.tsx +179 -0
  46. package/src/components/AutoComplete/USAGE.md +80 -0
  47. package/src/components/Avatar/AVATAR_IMPLEMENTATION_NOTES.md +34 -0
  48. package/src/components/Avatar/Avatar.module.css +336 -0
  49. package/src/components/Avatar/Avatar.stories.tsx +92 -0
  50. package/src/components/Avatar/Avatar.test.tsx +1 -0
  51. package/src/components/Avatar/Avatar.tsx +108 -0
  52. package/src/components/Avatar/USAGE.md +38 -0
  53. package/src/components/Avatar/index.ts +1 -0
  54. package/src/components/Badge/BADGE_IMPLEMENTATION_NOTES.md +18 -0
  55. package/src/components/Badge/Badge.module.css +127 -0
  56. package/src/components/Badge/Badge.stories.tsx +78 -0
  57. package/src/components/Badge/Badge.test.tsx +1 -0
  58. package/src/components/Badge/Badge.tsx +64 -0
  59. package/src/components/Badge/USAGE.md +56 -0
  60. package/src/components/Breadcrumb/BREADCRUMB_IMPLEMENTATION_NOTES.md +47 -0
  61. package/src/components/Breadcrumb/Breadcrumb.module.css +48 -0
  62. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +114 -0
  63. package/src/components/Breadcrumb/Breadcrumb.test.tsx +1 -0
  64. package/src/components/Breadcrumb/Breadcrumb.tsx +85 -0
  65. package/src/components/Breadcrumb/USAGE.md +55 -0
  66. package/src/components/Breadcrumb/markCurrentPageItem.test.ts +49 -0
  67. package/src/components/Button/Button.module.css +446 -0
  68. package/src/components/Button/Button.stories.tsx +196 -0
  69. package/src/components/Button/Button.styleIsolation.dom.test.tsx +98 -0
  70. package/src/components/Button/Button.tsx +184 -0
  71. package/src/components/Button/IMPLEMENTATION_NOTES.md +109 -0
  72. package/src/components/Button/USAGE.md +80 -0
  73. package/src/components/Button/index.ts +1 -0
  74. package/src/components/Card/CARD_IMPLEMENTATION_NOTES.md +17 -0
  75. package/src/components/Card/Card.module.css +119 -0
  76. package/src/components/Card/Card.stories.tsx +131 -0
  77. package/src/components/Card/Card.test.tsx +1 -0
  78. package/src/components/Card/Card.tsx +248 -0
  79. package/src/components/Card/USAGE.md +63 -0
  80. package/src/components/Checkbox/CHECKBOX_IMPLEMENTATION_NOTES.md +25 -0
  81. package/src/components/Checkbox/Checkbox.module.css +267 -0
  82. package/src/components/Checkbox/Checkbox.stories.tsx +97 -0
  83. package/src/components/Checkbox/Checkbox.test.tsx +1 -0
  84. package/src/components/Checkbox/Checkbox.tsx +151 -0
  85. package/src/components/Checkbox/CheckboxGroup.stories.tsx +139 -0
  86. package/src/components/Checkbox/CheckboxGroup.tsx +147 -0
  87. package/src/components/Checkbox/USAGE.md +48 -0
  88. package/src/components/Chip/CHIP_IMPLEMENTATION_NOTES.md +110 -0
  89. package/src/components/Chip/Chip.module.css +288 -0
  90. package/src/components/Chip/Chip.stories.tsx +128 -0
  91. package/src/components/Chip/Chip.test.tsx +1 -0
  92. package/src/components/Chip/Chip.tsx +157 -0
  93. package/src/components/Chip/USAGE.md +55 -0
  94. package/src/components/Container/CONTAINER_IMPLEMENTATION_NOTES.md +4 -0
  95. package/src/components/Container/Container.module.css +7 -0
  96. package/src/components/Container/Container.stories.tsx +118 -0
  97. package/src/components/Container/Container.test.tsx +1 -0
  98. package/src/components/Container/Container.tsx +69 -0
  99. package/src/components/Container/USAGE.md +47 -0
  100. package/src/components/DatePicker/DATEPICKER_IMPLEMENTATION_NOTES.md +31 -0
  101. package/src/components/DatePicker/DatePicker.icons.tsx +27 -0
  102. package/src/components/DatePicker/DatePicker.module.css +566 -0
  103. package/src/components/DatePicker/DatePicker.stories.tsx +158 -0
  104. package/src/components/DatePicker/DatePicker.test.tsx +1 -0
  105. package/src/components/DatePicker/DatePicker.tsx +218 -0
  106. package/src/components/DatePicker/USAGE.md +49 -0
  107. package/src/components/Dropdown/BareDropdown.tsx +97 -0
  108. package/src/components/Dropdown/DROPDOWN_IMPLEMENTATION_NOTES.md +12 -0
  109. package/src/components/Dropdown/Dropdown.module.css +477 -0
  110. package/src/components/Dropdown/Dropdown.stories.tsx +252 -0
  111. package/src/components/Dropdown/Dropdown.test.tsx +1 -0
  112. package/src/components/Dropdown/Dropdown.tsx +213 -0
  113. package/src/components/Dropdown/USAGE.md +69 -0
  114. package/src/components/FileInput/FILEINPUT_IMPLEMENTATION_NOTES.md +153 -0
  115. package/src/components/FileInput/FileInput.module.css +280 -0
  116. package/src/components/FileInput/FileInput.stories.tsx +313 -0
  117. package/src/components/FileInput/FileInput.test.tsx +1 -0
  118. package/src/components/FileInput/FileInput.tsx +417 -0
  119. package/src/components/FileInput/USAGE.md +145 -0
  120. package/src/components/FileUpload/FILEUPLOAD_IMPLEMENTATION_NOTES.md +244 -0
  121. package/src/components/FileUpload/FileUpload.module.css +205 -0
  122. package/src/components/FileUpload/FileUpload.stories.tsx +362 -0
  123. package/src/components/FileUpload/FileUpload.test.tsx +1 -0
  124. package/src/components/FileUpload/FileUpload.tsx +354 -0
  125. package/src/components/FileUpload/USAGE.md +199 -0
  126. package/src/components/Flex/FLEX_IMPLEMENTATION_NOTES.md +4 -0
  127. package/src/components/Flex/Flex.module.css +7 -0
  128. package/src/components/Flex/Flex.stories.tsx +128 -0
  129. package/src/components/Flex/Flex.test.tsx +1 -0
  130. package/src/components/Flex/Flex.tsx +75 -0
  131. package/src/components/Flex/USAGE.md +48 -0
  132. package/src/components/FormControlLayout/FormControlLayout.module.css +90 -0
  133. package/src/components/FormControlLayout/FormControlLayout.stories.tsx +118 -0
  134. package/src/components/FormControlLayout/FormControlLayout.test.tsx +1 -0
  135. package/src/components/FormControlLayout/FormControlLayout.tsx +74 -0
  136. package/src/components/FormControlLayout/USAGE.md +40 -0
  137. package/src/components/FormControlWrapper/FORMCONTROLWRAPPER_IMPLEMENTATION_NOTES.md +32 -0
  138. package/src/components/FormControlWrapper/FormControlWrapper.module.css +75 -0
  139. package/src/components/FormControlWrapper/FormControlWrapper.stories.tsx +129 -0
  140. package/src/components/FormControlWrapper/FormControlWrapper.test.tsx +1 -0
  141. package/src/components/FormControlWrapper/FormControlWrapper.tsx +151 -0
  142. package/src/components/FormControlWrapper/USAGE.md +47 -0
  143. package/src/components/Grid/GRID_IMPLEMENTATION_NOTES.md +18 -0
  144. package/src/components/Grid/Grid.module.css +11 -0
  145. package/src/components/Grid/Grid.stories.tsx +206 -0
  146. package/src/components/Grid/Grid.test.tsx +1 -0
  147. package/src/components/Grid/Grid.tsx +140 -0
  148. package/src/components/Grid/USAGE.md +47 -0
  149. package/src/components/Group/GROUP_IMPLEMENTATION_NOTES.md +4 -0
  150. package/src/components/Group/Group.module.css +7 -0
  151. package/src/components/Group/Group.stories.tsx +120 -0
  152. package/src/components/Group/Group.test.tsx +1 -0
  153. package/src/components/Group/Group.tsx +60 -0
  154. package/src/components/Group/USAGE.md +48 -0
  155. package/src/components/Heading/HEADING_IMPLEMENTATION_NOTES.md +18 -0
  156. package/src/components/Heading/Heading.module.css +13 -0
  157. package/src/components/Heading/Heading.stories.tsx +50 -0
  158. package/src/components/Heading/Heading.test.tsx +1 -0
  159. package/src/components/Heading/Heading.tsx +52 -0
  160. package/src/components/Heading/USAGE.md +36 -0
  161. package/src/components/HoverCard/HOVERCARD_IMPLEMENTATION_NOTES.md +77 -0
  162. package/src/components/HoverCard/HoverCard.module.css +90 -0
  163. package/src/components/HoverCard/HoverCard.stories.tsx +172 -0
  164. package/src/components/HoverCard/HoverCard.test.tsx +1 -0
  165. package/src/components/HoverCard/HoverCard.tsx +133 -0
  166. package/src/components/HoverCard/USAGE.md +52 -0
  167. package/src/components/Label/LABEL_IMPLEMENTATION_NOTES.md +48 -0
  168. package/src/components/Label/Label.module.css +141 -0
  169. package/src/components/Label/Label.stories.tsx +131 -0
  170. package/src/components/Label/Label.test.tsx +1 -0
  171. package/src/components/Label/Label.tsx +113 -0
  172. package/src/components/Label/USAGE.md +47 -0
  173. package/src/components/Label/index.ts +1 -0
  174. package/src/components/Layer/USAGE.md +54 -0
  175. package/src/components/Link/IMPLEMENTATION_NOTES.md +19 -0
  176. package/src/components/Link/Link.module.css +110 -0
  177. package/src/components/Link/Link.stories.tsx +58 -0
  178. package/src/components/Link/Link.test.tsx +1 -0
  179. package/src/components/Link/Link.tsx +67 -0
  180. package/src/components/Link/USAGE.md +56 -0
  181. package/src/components/Link/index.ts +1 -0
  182. package/src/components/Loader/LOADER_IMPLEMENTATION_NOTES.md +24 -0
  183. package/src/components/Loader/Loader.animate.dom.test.tsx +82 -0
  184. package/src/components/Loader/Loader.module.css +63 -0
  185. package/src/components/Loader/Loader.stories.tsx +123 -0
  186. package/src/components/Loader/Loader.test.tsx +1 -0
  187. package/src/components/Loader/Loader.tsx +69 -0
  188. package/src/components/Loader/USAGE.md +44 -0
  189. package/src/components/Menu/MENU_IMPLEMENTATION_NOTES.md +88 -0
  190. package/src/components/Menu/Menu.module.css +280 -0
  191. package/src/components/Menu/Menu.stories.tsx +371 -0
  192. package/src/components/Menu/Menu.test.tsx +1 -0
  193. package/src/components/Menu/Menu.tsx +373 -0
  194. package/src/components/Menu/USAGE.md +55 -0
  195. package/src/components/Modal/MODAL_IMPLEMENTATION_NOTES.md +32 -0
  196. package/src/components/Modal/Modal.module.css +302 -0
  197. package/src/components/Modal/Modal.stories.tsx +105 -0
  198. package/src/components/Modal/Modal.test.tsx +1 -0
  199. package/src/components/Modal/Modal.tsx +368 -0
  200. package/src/components/Modal/USAGE.md +58 -0
  201. package/src/components/Modal/index.ts +1 -0
  202. package/src/components/NumberInput/NUMBER_INPUT_IMPLEMENTATION_NOTES.md +24 -0
  203. package/src/components/NumberInput/NumberInput.module.css +302 -0
  204. package/src/components/NumberInput/NumberInput.stories.tsx +96 -0
  205. package/src/components/NumberInput/NumberInput.test.tsx +1 -0
  206. package/src/components/NumberInput/NumberInput.tsx +157 -0
  207. package/src/components/NumberInput/USAGE.md +52 -0
  208. package/src/components/Pagination/IMPLEMENTATION_NOTES.md +16 -0
  209. package/src/components/Pagination/Pagination.icons.tsx +66 -0
  210. package/src/components/Pagination/Pagination.module.css +188 -0
  211. package/src/components/Pagination/Pagination.stories.tsx +48 -0
  212. package/src/components/Pagination/Pagination.test.tsx +1 -0
  213. package/src/components/Pagination/Pagination.tsx +265 -0
  214. package/src/components/Pagination/USAGE.md +36 -0
  215. package/src/components/Pagination/index.ts +5 -0
  216. package/src/components/Panel/PANEL_IMPLEMENTATION_NOTES.md +116 -0
  217. package/src/components/Panel/Panel.module.css +209 -0
  218. package/src/components/Panel/Panel.stories.tsx +227 -0
  219. package/src/components/Panel/Panel.test.tsx +1 -0
  220. package/src/components/Panel/Panel.tsx +269 -0
  221. package/src/components/Panel/USAGE.md +56 -0
  222. package/src/components/Popover/IMPLEMENTATION_NOTES.md +77 -0
  223. package/src/components/Popover/Popover.module.css +86 -0
  224. package/src/components/Popover/Popover.stories.tsx +133 -0
  225. package/src/components/Popover/Popover.test.tsx +1 -0
  226. package/src/components/Popover/Popover.tsx +142 -0
  227. package/src/components/Popover/USAGE.md +61 -0
  228. package/src/components/Popover/index.ts +1 -0
  229. package/src/components/Radio/Radio.module.css +231 -0
  230. package/src/components/Radio/Radio.stories.tsx +93 -0
  231. package/src/components/Radio/Radio.test.tsx +1 -0
  232. package/src/components/Radio/Radio.tsx +168 -0
  233. package/src/components/Radio/RadioGroup.stories.tsx +117 -0
  234. package/src/components/Radio/RadioGroup.tsx +124 -0
  235. package/src/components/Radio/USAGE.md +36 -0
  236. package/src/components/ReadOnlyField/READ_ONLY_FIELD_IMPLEMENTATION_NOTES.md +15 -0
  237. package/src/components/ReadOnlyField/ReadOnlyBooleanField.tsx +21 -0
  238. package/src/components/ReadOnlyField/ReadOnlyField.module.css +54 -0
  239. package/src/components/ReadOnlyField/ReadOnlyField.stories.tsx +163 -0
  240. package/src/components/ReadOnlyField/ReadOnlyField.test.tsx +1 -0
  241. package/src/components/ReadOnlyField/ReadOnlyField.tsx +114 -0
  242. package/src/components/ReadOnlyField/ReadOnlySwitchField.tsx +21 -0
  243. package/src/components/ReadOnlyField/ReadOnlyTextField.tsx +48 -0
  244. package/src/components/ReadOnlyField/USAGE.md +44 -0
  245. package/src/components/ReadOnlyField/WithReadOnlyWrapper.tsx +93 -0
  246. package/src/components/ReadOnlyField/index.ts +5 -0
  247. package/src/components/RecursicaThemeProvider/USAGE.md +60 -0
  248. package/src/components/SegmentedControl/IMPLEMENTATION_NOTES.md +25 -0
  249. package/src/components/SegmentedControl/SegmentedControl.module.css +185 -0
  250. package/src/components/SegmentedControl/SegmentedControl.stories.tsx +106 -0
  251. package/src/components/SegmentedControl/SegmentedControl.test.tsx +1 -0
  252. package/src/components/SegmentedControl/SegmentedControl.tsx +110 -0
  253. package/src/components/SegmentedControl/USAGE.md +55 -0
  254. package/src/components/Slider/IMPLEMENTATION_NOTES.md +92 -0
  255. package/src/components/Slider/Slider.module.css +588 -0
  256. package/src/components/Slider/Slider.stories.tsx +282 -0
  257. package/src/components/Slider/Slider.test.tsx +1 -0
  258. package/src/components/Slider/Slider.tsx +391 -0
  259. package/src/components/Slider/USAGE.md +56 -0
  260. package/src/components/Stack/STACK_IMPLEMENTATION_NOTES.md +4 -0
  261. package/src/components/Stack/Stack.module.css +7 -0
  262. package/src/components/Stack/Stack.stories.tsx +108 -0
  263. package/src/components/Stack/Stack.test.tsx +1 -0
  264. package/src/components/Stack/Stack.tsx +62 -0
  265. package/src/components/Stack/USAGE.md +48 -0
  266. package/src/components/Stepper/IMPLEMENTATION_NOTES.md +28 -0
  267. package/src/components/Stepper/Stepper.module.css +404 -0
  268. package/src/components/Stepper/Stepper.stories.tsx +148 -0
  269. package/src/components/Stepper/Stepper.test.tsx +1 -0
  270. package/src/components/Stepper/Stepper.tsx +93 -0
  271. package/src/components/Stepper/USAGE.md +41 -0
  272. package/src/components/Switch/SWITCH_IMPLEMENTATION_NOTES.md +64 -0
  273. package/src/components/Switch/Switch.module.css +279 -0
  274. package/src/components/Switch/Switch.stories.tsx +114 -0
  275. package/src/components/Switch/Switch.test.tsx +1 -0
  276. package/src/components/Switch/Switch.tsx +177 -0
  277. package/src/components/Switch/SwitchGroup.stories.tsx +132 -0
  278. package/src/components/Switch/SwitchGroup.tsx +127 -0
  279. package/src/components/Switch/USAGE.md +42 -0
  280. package/src/components/Table/TABLE_IMPLEMENTATION_NOTES.md +78 -0
  281. package/src/components/Table/Table.icons.tsx +40 -0
  282. package/src/components/Table/Table.module.css +444 -0
  283. package/src/components/Table/Table.stories.tsx +140 -0
  284. package/src/components/Table/Table.test.tsx +1 -0
  285. package/src/components/Table/Table.tsx +243 -0
  286. package/src/components/Table/USAGE.md +78 -0
  287. package/src/components/Tabs/IMPLEMENTATION_NOTES.md +27 -0
  288. package/src/components/Tabs/Tabs.module.css +591 -0
  289. package/src/components/Tabs/Tabs.stories.tsx +154 -0
  290. package/src/components/Tabs/Tabs.test.tsx +1 -0
  291. package/src/components/Tabs/Tabs.tsx +114 -0
  292. package/src/components/Tabs/USAGE.md +45 -0
  293. package/src/components/Text/TEXT_IMPLEMENTATION_NOTES.md +12 -0
  294. package/src/components/Text/Text.module.css +13 -0
  295. package/src/components/Text/Text.stories.tsx +75 -0
  296. package/src/components/Text/Text.test.tsx +1 -0
  297. package/src/components/Text/Text.tsx +53 -0
  298. package/src/components/Text/USAGE.md +40 -0
  299. package/src/components/TextArea/TEXTAREA_IMPLEMENTATION_NOTES.md +7 -0
  300. package/src/components/TextArea/TextArea.module.css +183 -0
  301. package/src/components/TextArea/TextArea.stories.tsx +94 -0
  302. package/src/components/TextArea/TextArea.test.tsx +1 -0
  303. package/src/components/TextArea/TextArea.tsx +137 -0
  304. package/src/components/TextArea/USAGE.md +48 -0
  305. package/src/components/TextField/TEXTFIELD_IMPLEMENTATION_NOTES.md +19 -0
  306. package/src/components/TextField/TextField.module.css +264 -0
  307. package/src/components/TextField/TextField.stories.tsx +162 -0
  308. package/src/components/TextField/TextField.test.tsx +1 -0
  309. package/src/components/TextField/TextField.tsx +139 -0
  310. package/src/components/TextField/USAGE.md +44 -0
  311. package/src/components/TimePicker/TIMEPICKER_IMPLEMENTATION_NOTES.md +119 -0
  312. package/src/components/TimePicker/TimePicker.module.css +291 -0
  313. package/src/components/TimePicker/TimePicker.stories.tsx +141 -0
  314. package/src/components/TimePicker/TimePicker.test.tsx +1 -0
  315. package/src/components/TimePicker/TimePicker.tsx +304 -0
  316. package/src/components/TimePicker/USAGE.md +57 -0
  317. package/src/components/Timeline/TIMELINE_IMPLEMENTATION_NOTES.md +13 -0
  318. package/src/components/Timeline/Timeline.module.css +373 -0
  319. package/src/components/Timeline/Timeline.stories.tsx +128 -0
  320. package/src/components/Timeline/Timeline.test.tsx +1 -0
  321. package/src/components/Timeline/Timeline.tsx +73 -0
  322. package/src/components/Timeline/TimelineItem.tsx +79 -0
  323. package/src/components/Timeline/USAGE.md +49 -0
  324. package/src/components/Toast/TOAST_IMPLEMENTATION_NOTES.md +39 -0
  325. package/src/components/Toast/Toast.module.css +184 -0
  326. package/src/components/Toast/Toast.stories.tsx +67 -0
  327. package/src/components/Toast/Toast.test.tsx +1 -0
  328. package/src/components/Toast/Toast.tsx +82 -0
  329. package/src/components/Toast/USAGE.md +50 -0
  330. package/src/components/Toast/index.ts +1 -0
  331. package/src/components/Tooltip/TOOLTIP_IMPLEMENTATION_NOTES.md +85 -0
  332. package/src/components/Tooltip/Tooltip.module.css +91 -0
  333. package/src/components/Tooltip/Tooltip.stories.tsx +165 -0
  334. package/src/components/Tooltip/Tooltip.test.tsx +1 -0
  335. package/src/components/Tooltip/Tooltip.tsx +117 -0
  336. package/src/components/Tooltip/USAGE.md +80 -0
  337. package/src/components/TransferList/TRANSFERLIST_IMPLEMENTATION_NOTES.md +111 -0
  338. package/src/components/TransferList/TransferList.module.css +182 -0
  339. package/src/components/TransferList/TransferList.stories.tsx +121 -0
  340. package/src/components/TransferList/TransferList.test.tsx +1 -0
  341. package/src/components/TransferList/TransferList.tsx +419 -0
  342. package/src/components/TransferList/USAGE.md +77 -0
  343. package/src/components/Tree/IMPLEMENTATION_NOTES.md +48 -0
  344. package/src/components/Tree/Tree.module.css +232 -0
  345. package/src/components/Tree/Tree.stories.tsx +104 -0
  346. package/src/components/Tree/Tree.test.tsx +1 -0
  347. package/src/components/Tree/Tree.tsx +220 -0
  348. package/src/components/Tree/USAGE.md +96 -0
  349. package/src/components/Tree/index.ts +1 -0
  350. package/src/components/index.ts +52 -0
  351. package/src/env.d.ts +7 -0
  352. package/src/index.ts +179 -0
  353. package/src/types/index.ts +9 -0
  354. package/src/types/mantine.d.ts +7 -0
  355. package/src/types/scss-modules.d.ts +9 -0
  356. package/src/utils/ColorSchemeWrapper.tsx +27 -0
  357. package/src/utils/RequireAccessibleLabel.ts +1 -0
  358. package/src/utils/copyToClipboard.ts +36 -0
  359. package/src/utils/filterStylingProps.test.ts +85 -0
  360. package/src/utils/filterStylingProps.ts +150 -0
  361. package/src/utils/index.ts +1 -0
  362. package/src/utils/renderRichOption.tsx +65 -0
@@ -0,0 +1,98 @@
1
+ import React from "react";
2
+ import { describe, it, expect } from "vitest";
3
+ import { createRoot, type Root } from "react-dom/client";
4
+ import { flushSync } from "react-dom";
5
+ import { MantineProvider, Button as MantineButton } from "@mantine/core";
6
+ import { Button as RecursicaButton } from "./Button";
7
+
8
+ function mount(node: React.ReactElement): {
9
+ container: HTMLElement;
10
+ root: Root;
11
+ } {
12
+ const container = document.createElement("div");
13
+ document.body.appendChild(container);
14
+ const root = createRoot(container);
15
+ flushSync(() => root.render(node));
16
+ return { container, root };
17
+ }
18
+
19
+ function unmount({ container, root }: { container: HTMLElement; root: Root }) {
20
+ root.unmount();
21
+ container.remove();
22
+ }
23
+
24
+ function withProvider(node: React.ReactElement) {
25
+ return <MantineProvider defaultColorScheme="light">{node}</MantineProvider>;
26
+ }
27
+
28
+ /**
29
+ * Guards against Recursica's Button CSS bleeding onto (or being bled onto by) a plain,
30
+ * unwrapped Mantine Button rendered in the same document. The two must be visibly different
31
+ * (Recursica's own classes/data-attributes), but the plain kit button must render identically
32
+ * whether or not a Recursica Button exists alongside it.
33
+ */
34
+ describe("Button style isolation from the underlying Mantine kit", () => {
35
+ it("adds Recursica-only classes/attributes without leaking them onto a plain Mantine Button", () => {
36
+ const recursica = mount(
37
+ withProvider(<RecursicaButton>Recursica</RecursicaButton>),
38
+ );
39
+ const kit = mount(withProvider(<MantineButton>Plain</MantineButton>));
40
+
41
+ try {
42
+ const recursicaButton = recursica.container.querySelector("button")!;
43
+ const kitButton = kit.container.querySelector("button")!;
44
+
45
+ const recursicaClasses = Array.from(recursicaButton.classList);
46
+ const kitClasses = new Set(kitButton.classList);
47
+ const recursicaOnlyClasses = recursicaClasses.filter(
48
+ (cls) => !kitClasses.has(cls),
49
+ );
50
+
51
+ // Recursica's Button.module.css classes must exist...
52
+ expect(recursicaOnlyClasses.length).toBeGreaterThan(0);
53
+ // ...and none of them are present on the plain kit button.
54
+ for (const cls of recursicaOnlyClasses) {
55
+ expect(kitButton.classList.contains(cls)).toBe(false);
56
+ }
57
+
58
+ // Recursica-only markers confirm the two are meaningfully different components.
59
+ expect(recursicaButton.getAttribute("data-variant")).toBe("solid");
60
+ expect(kitButton.getAttribute("data-variant")).toBeNull();
61
+ } finally {
62
+ unmount(recursica);
63
+ unmount(kit);
64
+ }
65
+ });
66
+
67
+ it("renders a plain Mantine Button identically whether or not Recursica's Button is mounted alongside it", () => {
68
+ const recursica = mount(
69
+ withProvider(<RecursicaButton>Recursica</RecursicaButton>),
70
+ );
71
+ const kitAlongsideRecursica = mount(
72
+ withProvider(<MantineButton>Plain</MantineButton>),
73
+ );
74
+ const kitIsolated = mount(
75
+ withProvider(<MantineButton>Plain</MantineButton>),
76
+ );
77
+
78
+ try {
79
+ const kitButton =
80
+ kitAlongsideRecursica.container.querySelector("button")!;
81
+ const isolatedButton = kitIsolated.container.querySelector("button")!;
82
+
83
+ expect(Array.from(kitButton.classList).sort()).toEqual(
84
+ Array.from(isolatedButton.classList).sort(),
85
+ );
86
+
87
+ const kitStyle = getComputedStyle(kitButton);
88
+ const isolatedStyle = getComputedStyle(isolatedButton);
89
+ expect(kitStyle.borderRadius).toBe(isolatedStyle.borderRadius);
90
+ expect(kitStyle.backgroundColor).toBe(isolatedStyle.backgroundColor);
91
+ expect(kitStyle.fontFamily).toBe(isolatedStyle.fontFamily);
92
+ } finally {
93
+ unmount(recursica);
94
+ unmount(kitAlongsideRecursica);
95
+ unmount(kitIsolated);
96
+ }
97
+ });
98
+ });
@@ -0,0 +1,184 @@
1
+ import React, { forwardRef } from "react";
2
+ import { Loader } from "../Loader/Loader";
3
+ import {
4
+ Button as MantineButton,
5
+ type ButtonProps as MantineButtonProps,
6
+ createPolymorphicComponent,
7
+ } from "@mantine/core";
8
+ import {
9
+ filterStylingProps,
10
+ omitUnsupportedProps,
11
+ withCallerOverride,
12
+ mergeClassNames,
13
+ type RecursicaOverStyled,
14
+ } from "../../utils/filterStylingProps";
15
+ import styles from "./Button.module.css";
16
+
17
+ import { type RecursicaButtonProps } from "@recursica/adapter-common";
18
+
19
+ export type ButtonProps = RecursicaOverStyled<
20
+ Omit<MantineButtonProps, "variant" | "size" | "leftSection" | "fullWidth"> &
21
+ RecursicaButtonProps
22
+ >;
23
+
24
+ function hasVisibleChildren(children: React.ReactNode): boolean {
25
+ if (children == null || children === "") return false;
26
+ if (typeof children === "string") return children.trim() !== "";
27
+ return true;
28
+ }
29
+
30
+ const _Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button(
31
+ {
32
+ variant = "solid",
33
+ size = "default",
34
+ icon,
35
+ children,
36
+ overStyled = false,
37
+ loaderVariant = "oval",
38
+ loaderSize,
39
+ useRecursicaLoader = true,
40
+ ...rest
41
+ },
42
+ ref,
43
+ ) {
44
+ const mapVariant = {
45
+ solid: "filled",
46
+ outline: "outline",
47
+ text: "subtle",
48
+ } as const;
49
+
50
+ const mapSize = {
51
+ default: "md",
52
+ small: "sm",
53
+ } as const;
54
+
55
+ // Props this component intentionally doesn't support — deleted at runtime so they can't leak
56
+ // through even if a caller forces them via plain JavaScript, bypassing the `Omit<>` above.
57
+ const UNSUPPORTED_PROPS = [
58
+ "fullWidth", // Recursica Button width comes from layout/token constraints, not Mantine's boolean fullWidth toggle.
59
+ ] as const satisfies readonly (keyof MantineButtonProps)[];
60
+
61
+ const sanitizedProps = omitUnsupportedProps(
62
+ filterStylingProps(rest, overStyled) as Record<string, unknown>,
63
+ UNSUPPORTED_PROPS,
64
+ ) as Partial<typeof rest>;
65
+ const restRecord = sanitizedProps as Record<string, unknown>;
66
+
67
+ const hasLeftSection = !!icon || !!restRecord["leftSection"];
68
+ const hasRightSection = !!restRecord["rightSection"];
69
+ const hasVisibleText = hasVisibleChildren(children);
70
+ const isIconOnly = (hasLeftSection || hasRightSection) && !hasVisibleText;
71
+
72
+ let contentType = "label";
73
+ if (isIconOnly) {
74
+ contentType = "icon-only";
75
+ } else if (hasLeftSection || hasRightSection) {
76
+ contentType = "icon-label";
77
+ }
78
+
79
+ if (
80
+ typeof process !== "undefined" &&
81
+ process.env.NODE_ENV !== "production" &&
82
+ isIconOnly &&
83
+ !restRecord["aria-label"]
84
+ ) {
85
+ console.warn(
86
+ '[Recursica Button] Icon-only buttons must provide an accessible name. Pass aria-label (e.g. aria-label="Submit").',
87
+ );
88
+ }
89
+
90
+ const mergedClassNames = mergeClassNames(
91
+ {
92
+ root: styles.root,
93
+ section: styles.section,
94
+ label: styles.label,
95
+ loader: styles.loader,
96
+ },
97
+ restRecord.classNames as Partial<Record<string, string>> | undefined,
98
+ );
99
+
100
+ const classNameProp = restRecord.className as string | undefined;
101
+ const finalClass = classNameProp
102
+ ? `${styles.root} ${classNameProp}`
103
+ : styles.root;
104
+ // Note: `finalClass` is safe from being clobbered by `{...sanitizedProps}` below purely
105
+ // because of spread order — `className` (like `classNames`, `variant`, `size`, `leftSection`,
106
+ // and the `data-*` attributes) is spread first, then re-asserted after, so our computed value
107
+ // always wins. See the canonical guide's §3.3 for why ordering (not deletion) is the fix here.
108
+
109
+ const userLoaderProps = restRecord.loaderProps as
110
+ | Record<string, unknown>
111
+ | undefined;
112
+
113
+ const resolvedLoaderSize = withCallerOverride(
114
+ size === "small" ? "small" : "default",
115
+ loaderSize,
116
+ );
117
+
118
+ let mergedLoaderProps = userLoaderProps;
119
+ if (useRecursicaLoader) {
120
+ // color="var(--button-color)" makes the loader ring match this button's own text color
121
+ // (Mantine's Button sets --button-color per variant/state) instead of Loader's own
122
+ // standalone indicator-color token, which Loader.module.css's `.root` would otherwise
123
+ // apply unconditionally, ignoring this nesting context. overStyled is required to pass
124
+ // `color` at all (blocked by default) — fully internal composition, no prop threading to
125
+ // callers, so it doesn't widen Loader's public API. See Button's IMPLEMENTATION_NOTES.md.
126
+ mergedLoaderProps = {
127
+ children: (
128
+ <Loader
129
+ variant={loaderVariant}
130
+ size={resolvedLoaderSize}
131
+ overStyled
132
+ color="var(--button-color)"
133
+ />
134
+ ),
135
+ ...userLoaderProps,
136
+ };
137
+ }
138
+
139
+ return (
140
+ <MantineButton
141
+ ref={ref}
142
+ {...sanitizedProps}
143
+ className={finalClass}
144
+ classNames={mergedClassNames}
145
+ variant={mapVariant[variant]}
146
+ size={mapSize[size]}
147
+ loaderProps={mergedLoaderProps}
148
+ leftSection={
149
+ icon != null ? (
150
+ <span className={styles.iconWrapper} aria-hidden>
151
+ {icon}
152
+ </span>
153
+ ) : undefined
154
+ }
155
+ data-variant={variant}
156
+ data-size={size}
157
+ data-content={contentType}
158
+ disabled={!!restRecord.disabled || !!restRecord.loading}
159
+ >
160
+ <span className={styles.labelText}>{children}</span>
161
+ </MantineButton>
162
+ );
163
+ });
164
+ _Button.displayName = "Button";
165
+
166
+ /**
167
+ * Recursica Button component wrapping Mantine's Button.
168
+ *
169
+ * Supports polymorphism via the `component` prop or `renderRoot` for custom element rendering.
170
+ * This is particularly useful when you need a button that behaves as a hyperlink (rendering an `<a>` tag)
171
+ * or integrates with a routing library (e.g., `react-router-dom` or Next.js), while preserving full visual styling.
172
+ *
173
+ * @example
174
+ * ```tsx
175
+ * // Renders as an <a> tag natively
176
+ * <Button component="a" href="/dashboard" target="_blank">Navigate</Button>
177
+ *
178
+ * // Renders using a custom router link
179
+ * <Button renderRoot={(props) => <Link to="/home" {...props} />}>Home</Button>
180
+ * ```
181
+ */
182
+ export const Button = createPolymorphicComponent<"button", ButtonProps>(
183
+ _Button,
184
+ );
@@ -0,0 +1,109 @@
1
+ # Button – implementation notes
2
+
3
+ Decisions and design tweaks for the Recursica Button that go beyond the Component Development Guide. Use this when maintaining the Button or when adding similar behavior to other components.
4
+
5
+ ---
6
+
7
+ ## Icon size: Recursica defines it
8
+
9
+ **Decision:** Icon size is **not** left to the developer. Recursica defines it via the design tokens; the Button enforces it so callers cannot pass an arbitrarily sized icon.
10
+
11
+ **Implementation:**
12
+
13
+ - When `icon` is provided, the Button wraps it in a single element with class `iconWrapper` before passing it to Mantine’s `leftSection`.
14
+ - In `Button.module.css`, `.iconWrapper` has explicit `width` and `height` from the Recursica tokens mapping natively based on `data-size`.
15
+ - The rule `.iconWrapper > *` sets `width: 100%`, `height: 100%`, and `object-fit: contain` so whatever the caller passes scales cleanly with the token constraints.
16
+
17
+ ---
18
+
19
+ ## Icon-only buttons: accessibility and width
20
+
21
+ **Decision:** When the button has an icon and no visible label (icon-only), callers must provide an accessible name, and the button must not show extra space to the right of the icon.
22
+
23
+ **Accessibility:** We document that icon-only buttons must pass `aria-label` (e.g. `aria-label="Submit"`). In development we log a console warning if `icon` is set, `children` is empty, and `aria-label` is missing.
24
+
25
+ **Width:** Mantine’s layout natively applies structural section gaps. We detect icon-only and set a `data-icon-only` hook so that `Button.module.css` zeros out the sections spacing allowing the button to precisely hit `min-width` perfectly centered.
26
+
27
+ ---
28
+
29
+ ## Label truncation at max-width
30
+
31
+ **Decision:** When the button hits its Recursica max-width (500px), the label truncates with an ellipsis instead of wrapping.
32
+
33
+ **Implementation:**
34
+ Mantine's `.mantine-Button-label` flex centering breaks primitive truncation logic. To combat this:
35
+
36
+ - **`.root`** has `overflow: hidden`.
37
+ - **`.root > *`** forces `min-width: 0`.
38
+ - The structural children wrap into `<span className={styles.labelText}>`.
39
+ - **`.labelText`** binds `overflow: hidden; text-overflow: ellipsis; white-space: nowrap;` creating flawless string cutoffs strictly at exact UI constraints.
40
+
41
+ **Bug found (2026-08-27):** none of the above clips the button itself against a _constraining ancestor_ (e.g. `<div style={{ maxWidth: 250 }}>` — see the `TruncatedLabel` story). `.root` uses `width: fit-content` so it hugs its own content when unconstrained, but `fit-content` on this box doesn't reliably resize down against a narrower parent's resolved width — verified via Playwright: the button rendered at its full 534px `max-content` width and visually overflowed the 250px wrapper, even though the wrapper itself measured 250px. `max-width: 100%` on `.root` (percentage of the actual containing block) fixes it — it doesn't fight `width: fit-content` for the normal unconstrained case, it only kicks in when the parent is narrower than the content's intrinsic width.
42
+
43
+ ---
44
+
45
+ ## Disabled state: brand theme opacity (implicit)
46
+
47
+ **Decision:** The UI kit enforces global brand theme disabled opacities. The `.root:disabled` logic implicitly overrides visibility locally via `var(--recursica_brand_states_disabled)`.
48
+
49
+ ---
50
+
51
+ ## Loader color contrast — fixed (source-of-truth audit, 2026-08-30)
52
+
53
+ **Superseded:** the entry below originally documented an explicit decision _not_ to fix this.
54
+ Re-verified during the mantine-vs-mui source-of-truth audit by measuring actual computed styles
55
+ in the `Loading` story: the loader ring rendered `#c21b43` (Loader's own standalone
56
+ `indicator-color` token) against a label text color of `rgb(249, 249, 249)` — a real, confirmed
57
+ mismatch on the `solid` variant, not a false report.
58
+
59
+ **Root cause:** `Loader.module.css`'s `.root` unconditionally sets `--loader-color:
60
+ var(--recursica_..._loader_properties_indicator-color)` directly on the Loader's own root
61
+ `<span>`. Mantine's own Button internally wraps `loaderProps.children` in a generic `<Loader
62
+ size color>` that sets `--loader-color: var(--button-color)` as an _inline_ style on an outer
63
+ wrapper div — but our own nested `<Loader>` (rendered as `loaderProps.children`) has an identical
64
+ class (`mantine-Loader-root`) on its own root, so its own stylesheet rule locally re-declares
65
+ `--loader-color`, shadowing the inherited value from that outer wrapper for anything computed on
66
+ or under our own element (CSS custom properties resolve against the nearest self-or-ancestor
67
+ declaration — a local re-declaration always wins over what an ancestor tried to pass down,
68
+ regardless of whether the ancestor's value came from an inline style or not).
69
+
70
+ **Fix:** pass `color="var(--button-color)"` to the Button-owned `<Loader>` — Mantine's own
71
+ `Loader` factory writes any `color` prop straight through `getThemeColor()`/`parseThemeColor()`
72
+ (safely falls through unresolved CSS values like a `var()` reference verbatim, per
73
+ `@mantine/core`'s own `parse-theme-color.cjs`) into an _inline_ `--loader-color` style on that
74
+ same root span — which, being inline, now wins over our own `.root` stylesheet declaration.
75
+ Also added `--button-color` (`!important`) to each variant's own block in `Button.module.css`,
76
+ set to that variant's own `colors_text-color` token — needed because Mantine's Button sets its
77
+ own generic `--button-color: var(--mantine-color-white)` via an inline style on the button root
78
+ itself, which our external stylesheet couldn't otherwise outrank at equal/lower priority
79
+ regardless of selector specificity. Verified live: loader ring color now matches the label text
80
+ color exactly (`rgb(249, 249, 249)`) across solid/outline/text variants, no visual regression on
81
+ non-loading stories.
82
+
83
+ ---
84
+
85
+ ## Loading state enforces disabled state
86
+
87
+ **Decision:** When `loading={true}` is passed to the Button, the component explicitly forces `disabled={true}` natively on the underlying element.
88
+
89
+ **Implementation:** This ensures that loading buttons automatically inherit the brand theme disabled opacities (via the `:disabled` CSS pseudo-class) rather than relying solely on Mantine's native `data-disabled` dataset logic, which may not trigger the strict visual fade required by the Recursica design system.
90
+
91
+ ---
92
+
93
+ ## `className` overwrite bug (Matt Massey, 2026-08-08)
94
+
95
+ **Bug:** with `overStyled` and a custom `className` (surfaced by Tree embedding a `Button` for its expand chevron — see `Tree/IMPLEMENTATION_NOTES.md`), `finalClass` (`` `${styles.root} ${classNameProp}` ``) was set explicitly on `<MantineButton>`, but `{...sanitizedProps}` was spread _after_ it — and `sanitizedProps` still contained the original, unmodified `className` key, since it had only been _read_, never deleted. The later spread would silently overwrite `finalClass` with just the caller's own class. Same bug class as `Dropdown.tsx`/`BareDropdown.tsx` had.
96
+
97
+ **Why it wasn't visible here:** `classNames={{root: mergedClassNames.root, ...}}` is a _separate_ Mantine prop from the plain `className` string, unaffected by the overwrite, and `mergedClassNames.root` always includes `styles.root` independently — so the root element kept its Recursica styling regardless of the bug. mui-adapter's equivalent `Button.tsx` has no such secondary path (`@mui/material` only has a plain `className`), so the identical mistake there was fully visible (chevron rendered in MUI's own default color). Fixed in both regardless, since this is a real latent bug independent of whether it happens to be masked today.
98
+
99
+ ---
100
+
101
+ ## `.labelText` descender clipping (Matt Massey, 2026-08-28)
102
+
103
+ `.labelText` used plain `overflow: hidden` to make `text-overflow: ellipsis` work, which also
104
+ clips descenders (e.g. the "g" in a long label) whenever `text_line-height` is tighter than the
105
+ font's natural ascent+descent. Switched to `overflow: clip; overflow-clip-margin: 0.35em;` — same
106
+ truncation, but ink can bleed slightly past the line box before it's actually clipped. `.root`'s
107
+ own `overflow: hidden` (the max-width truncation bounding box) is untouched — it has padding
108
+ around the label so it isn't tight against the glyphs the way `.labelText` is. Project-wide fix;
109
+ see Chip's `CHIP_IMPLEMENTATION_NOTES.md` for the original discovery.
@@ -0,0 +1,80 @@
1
+ # Button - Usage Guide
2
+
3
+ This document describes how to integrate and use the `Button` component in your projects using `@recursica/adapter-mantine-v8`.
4
+
5
+ ---
6
+
7
+ ## 1. Import Reference
8
+
9
+ ```tsx
10
+ import { Button } from "@recursica/adapter-mantine-v8";
11
+ ```
12
+
13
+ ---
14
+
15
+ ## 2. Basic Example
16
+
17
+ ```tsx
18
+ import React from "react";
19
+ import { Button } from "@recursica/adapter-mantine-v8";
20
+
21
+ export default function Demo() {
22
+ return (
23
+ <Button variant="primary" onClick={() => console.log("Clicked!")}>
24
+ Click Me
25
+ </Button>
26
+ );
27
+ }
28
+ ```
29
+
30
+ ---
31
+
32
+ ## 3. Design System Integration
33
+
34
+ All Recursica components in the `@recursica/adapter-mantine-v8` package adhere strictly to design system spacing, scaling, and behavior patterns.
35
+
36
+ > [!IMPORTANT]
37
+ >
38
+ > - **Anti-override protection**: Rogues style injections (like inline `style` or arbitrary `className`) are automatically blocked by our prop layer unless `overStyled={true}` is explicitly provided.
39
+ > - **No Direct Layers**: Do not pass a `layer` prop to this component. To place it on a specific visual layer, wrap it in a `<Layer layer={0|1|2|3}>` component natively.
40
+ > - **Variables and Theming**: Styling is entirely determined by local CSS variables defined in `recursica_variables_scoped.css` and mapped in the component's CSS module.
41
+
42
+ ---
43
+
44
+ ## 4. Key Integration Features & Constraints
45
+
46
+ ## Icon size: Recursica defines it
47
+
48
+ Icon size is **not** left to the developer. Recursica defines it via the design tokens, so callers cannot pass an arbitrarily sized icon — whatever is passed in `icon` is scaled to fit the token-defined dimensions for the button's size.
49
+
50
+ ---
51
+
52
+ ## Icon-only buttons: accessibility
53
+
54
+ When the button has an icon and no visible label (icon-only), callers must provide an accessible name via `aria-label` (e.g. `aria-label="Submit"`). In development, a console warning is logged if `icon` is set, `children` is empty, and `aria-label` is missing.
55
+
56
+ ---
57
+
58
+ ## Label truncation at max-width
59
+
60
+ When the button hits its Recursica max-width (500px), the label truncates with an ellipsis instead of wrapping.
61
+
62
+ ---
63
+
64
+ ## Disabled state: brand theme opacity (implicit)
65
+
66
+ **Decision:** The UI kit enforces global brand theme disabled opacities. The `.root:disabled` logic implicitly overrides visibility locally via `var(--recursica_brand_states_disabled)`.
67
+
68
+ ---
69
+
70
+ ## Loader color contrast
71
+
72
+ **Decision:** When a Button is in a loading state, the `Recursica Loader` component is injected. The `Loader` component strictly defines its own colors and styles per variant, meaning it does not inherit the text color (`currentColor`) from the Button.
73
+
74
+ **Constraint:** This can lead to contrast issues (e.g., a blue dots loader inside a solid blue button). Design has explicitly decided not to address this at the moment. As such, developers using the `loading` prop must be aware that the loader's color is fixed by its internal tokens, not by the button's context.
75
+
76
+ ---
77
+
78
+ ## Loading state enforces disabled state
79
+
80
+ When `loading={true}` is passed to the Button, it is also treated as disabled — the button cannot be interacted with while loading.
@@ -0,0 +1 @@
1
+ export * from "./Button";
@@ -0,0 +1,17 @@
1
+ # Card Implementation Notes
2
+
3
+ ## Architecture Overrides
4
+
5
+ Because Mantine natively constructs `Card` bounding boxes with generic inner `<Card.Section>` elements that depend on explicit user styling (and lack implicit native designations for "Header" vs "Footer"), we implemented an explicit component wrapper departure:
6
+
7
+ - `<Card.Header>` explicitly hooks `--recursica_ui-kit_components_card_properties_header-background` and corresponding padding variables.
8
+ - `<Card.Footer>` explicitly hooks `--recursica_ui-kit_components_card_properties_footer-background` and corresponding padding variables.
9
+
10
+ Mantine's generic `<Card.Section>` calculates negative margins implicitly. Because of this, it is crucial that our local CSS module declares `--card-padding: var(--recursica_ui-kit_components_card_properties_padding)` directly on `.root` so that all generic or explicit section wrappers natively stretch across the bounding box properly.
11
+
12
+ ## Layout Alignment Exceptions
13
+
14
+ To allow Cards to fit cleanly inside dynamic/flex layouts (like dashboard panels, grid tracks, or sidebar layout segments), the Card wrapper implements a custom gatekeeper bypass for outer styling properties:
15
+
16
+ - Exposes a safe subset of flexbox/dimensions styling properties (`flex`, `flexGrow`, `flexShrink`, `flexBasis`, `grow`, `h`, `height`) on the root `<Card>` component to allow proper sizing alongside layout siblings.
17
+ - Sets `<Card.Content>` to `flex-grow: 1;` by default via CSS modules. Since the root `<Card>` has `display: flex; flex-direction: column;`, this makes the content area expand to fill all vertical space, pushing `<Card.Footer>` to align at the absolute bottom of the bounding box.
@@ -0,0 +1,119 @@
1
+ /* HARDCODED VALUES:
2
+ - display: flex on root
3
+ - flex-direction: column
4
+ - gap: section-gap
5
+ */
6
+
7
+ .root {
8
+ /* HARDCODE: Map Recursica explicitly into Mantine's variable format so internal components know the margins */
9
+ --card-padding: var(--recursica_ui-kit_components_card_properties_padding);
10
+
11
+ background-color: var(
12
+ --recursica_ui-kit_components_card_properties_colors_background-color
13
+ );
14
+ border-radius: var(
15
+ --recursica_ui-kit_components_card_properties_borders_border-radius
16
+ );
17
+ border: var(--recursica_ui-kit_components_card_properties_borders_border-size)
18
+ solid var(--recursica_ui-kit_components_card_properties_colors_border-color);
19
+ box-shadow: var(
20
+ --recursica_ui-kit_components_card_properties_elevations_elevation
21
+ );
22
+
23
+ padding: var(--card-padding);
24
+ min-width: var(--recursica_ui-kit_components_card_properties_min-width);
25
+ max-width: var(--recursica_ui-kit_components_card_properties_max-width);
26
+ color: var(--recursica_ui-kit_components_card_properties_colors_content);
27
+
28
+ display: flex;
29
+ flex-direction: column;
30
+ gap: var(--recursica_ui-kit_components_card_properties_section-gap);
31
+ }
32
+
33
+ .header {
34
+ background-color: var(
35
+ --recursica_ui-kit_components_card_properties_colors_header-background-color
36
+ );
37
+ padding: var(--recursica_ui-kit_components_card_properties_header-padding);
38
+ color: var(--recursica_ui-kit_components_card_properties_colors_title);
39
+ border-bottom: var(--recursica_ui-kit_components_card_properties_divider-size)
40
+ solid
41
+ var(--recursica_ui-kit_components_card_properties_colors_divider-color);
42
+
43
+ /* Direct Figma Typography Mapping */
44
+ font-family: var(
45
+ --recursica_ui-kit_components_card_properties_header-style_fontFamily
46
+ );
47
+ font-size: var(
48
+ --recursica_ui-kit_components_card_properties_header-style_fontSize
49
+ );
50
+ font-style: var(
51
+ --recursica_ui-kit_components_card_properties_header-style_fontStyle
52
+ );
53
+ font-weight: var(
54
+ --recursica_ui-kit_components_card_properties_header-style_fontWeight
55
+ );
56
+ letter-spacing: var(
57
+ --recursica_ui-kit_components_card_properties_header-style_letterSpacing
58
+ );
59
+ line-height: var(
60
+ --recursica_ui-kit_components_card_properties_header-style_lineHeight
61
+ );
62
+ text-transform: var(
63
+ --recursica_ui-kit_components_card_properties_header-style_textCase
64
+ );
65
+ text-decoration: var(
66
+ --recursica_ui-kit_components_card_properties_header-style_textDecoration
67
+ );
68
+ }
69
+
70
+ .footer {
71
+ background-color: var(
72
+ --recursica_ui-kit_components_card_properties_colors_footer-background-color
73
+ );
74
+ padding: var(--recursica_ui-kit_components_card_properties_footer-padding);
75
+ border-top: var(--recursica_ui-kit_components_card_properties_divider-size)
76
+ solid
77
+ var(--recursica_ui-kit_components_card_properties_colors_divider-color);
78
+ }
79
+
80
+ .section {
81
+ /* Just maps standard section spacing overrides if passed explicitly */
82
+ margin-top: var(
83
+ --recursica_ui-kit_components_card_properties_vertical-gutter
84
+ );
85
+ }
86
+
87
+ .content {
88
+ display: flex;
89
+ flex-direction: column;
90
+ gap: var(--recursica_ui-kit_components_card_properties_vertical-gutter);
91
+ padding: 0;
92
+ flex-grow: 1;
93
+
94
+ /* Direct Figma Typography Mapping */
95
+ font-family: var(
96
+ --recursica_ui-kit_components_card_properties_content-style_fontFamily
97
+ );
98
+ font-size: var(
99
+ --recursica_ui-kit_components_card_properties_content-style_fontSize
100
+ );
101
+ font-style: var(
102
+ --recursica_ui-kit_components_card_properties_content-style_fontStyle
103
+ );
104
+ font-weight: var(
105
+ --recursica_ui-kit_components_card_properties_content-style_fontWeight
106
+ );
107
+ letter-spacing: var(
108
+ --recursica_ui-kit_components_card_properties_content-style_letterSpacing
109
+ );
110
+ line-height: var(
111
+ --recursica_ui-kit_components_card_properties_content-style_lineHeight
112
+ );
113
+ text-transform: var(
114
+ --recursica_ui-kit_components_card_properties_content-style_textCase
115
+ );
116
+ text-decoration: var(
117
+ --recursica_ui-kit_components_card_properties_content-style_textDecoration
118
+ );
119
+ }