@recursica/adapter-mui-v7 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.
- package/.storybook/commonArgTypes.ts +148 -0
- package/ARCHITECTURE.md +18 -0
- package/CHANGELOG.md +582 -0
- package/LICENSE +21 -0
- package/OVERSTYLING.md +59 -0
- package/README.md +70 -0
- package/SETUP.md +92 -0
- package/USAGE.md +57 -0
- package/dist/adapter-mui-v7.cjs +292 -0
- package/dist/adapter-mui-v7.cjs.map +1 -0
- package/dist/adapter-mui-v7.css +1 -0
- package/dist/adapter-mui-v7.js +40757 -0
- package/dist/adapter-mui-v7.js.map +1 -0
- package/dist/index.d.ts +2350 -0
- package/dist/vite.svg +1 -0
- package/docs/PHILOSOPHY.md +39 -0
- package/llms.txt +76 -0
- package/package.json +151 -0
- package/recursica_brand.json +2677 -0
- package/recursica_tokens.json +799 -0
- package/recursica_ui-kit.json +14981 -0
- package/recursica_variables_scoped.css +30489 -0
- package/src/GlobalExemptions.modules.css +7 -0
- package/src/Introduction.stories.tsx +184 -0
- package/src/OverStyling.tsx +87 -0
- package/src/Version.tsx +37 -0
- package/src/components/Accordion/ACCORDION_IMPLEMENTATION_NOTES.md +107 -0
- package/src/components/Accordion/Accordion.module.css +362 -0
- package/src/components/Accordion/Accordion.stories.tsx +198 -0
- package/src/components/Accordion/Accordion.test.tsx +1 -0
- package/src/components/Accordion/Accordion.tsx +285 -0
- package/src/components/Accordion/USAGE.md +43 -0
- package/src/components/Accordion/index.ts +1 -0
- package/src/components/AssistiveElement/ASSISTIVEELEMENT_IMPLEMENTATION_NOTES.md +59 -0
- package/src/components/AssistiveElement/AssistiveElement.module.css +121 -0
- package/src/components/AssistiveElement/AssistiveElement.stories.tsx +68 -0
- package/src/components/AssistiveElement/AssistiveElement.test.tsx +1 -0
- package/src/components/AssistiveElement/AssistiveElement.tsx +94 -0
- package/src/components/AssistiveElement/USAGE.md +36 -0
- package/src/components/AssistiveElement/index.ts +1 -0
- package/src/components/AutoComplete/AutoComplete.module.css +456 -0
- package/src/components/AutoComplete/AutoComplete.stories.tsx +336 -0
- package/src/components/AutoComplete/AutoComplete.test.tsx +1 -0
- package/src/components/AutoComplete/AutoComplete.tsx +266 -0
- package/src/components/AutoComplete/IMPLEMENTATION_NOTES.md +37 -0
- package/src/components/AutoComplete/USAGE.md +68 -0
- package/src/components/AutoComplete/index.ts +1 -0
- package/src/components/Avatar/AVATAR_IMPLEMENTATION_NOTES.md +36 -0
- package/src/components/Avatar/Avatar.module.css +336 -0
- package/src/components/Avatar/Avatar.stories.tsx +92 -0
- package/src/components/Avatar/Avatar.test.tsx +1 -0
- package/src/components/Avatar/Avatar.tsx +88 -0
- package/src/components/Avatar/USAGE.md +38 -0
- package/src/components/Avatar/index.ts +1 -0
- package/src/components/Badge/Badge.module.css +115 -0
- package/src/components/Badge/Badge.stories.tsx +78 -0
- package/src/components/Badge/Badge.test.tsx +1 -0
- package/src/components/Badge/Badge.tsx +61 -0
- package/src/components/Badge/USAGE.md +40 -0
- package/src/components/Badge/index.ts +1 -0
- package/src/components/Breadcrumb/BREADCRUMB_IMPLEMENTATION_NOTES.md +51 -0
- package/src/components/Breadcrumb/Breadcrumb.module.css +51 -0
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +114 -0
- package/src/components/Breadcrumb/Breadcrumb.test.tsx +1 -0
- package/src/components/Breadcrumb/Breadcrumb.tsx +70 -0
- package/src/components/Breadcrumb/USAGE.md +42 -0
- package/src/components/Breadcrumb/index.ts +1 -0
- package/src/components/Button/BUTTON_IMPLEMENTATION_NOTES.md +123 -0
- package/src/components/Button/Button.module.css +413 -0
- package/src/components/Button/Button.stories.tsx +196 -0
- package/src/components/Button/Button.styleIsolation.dom.test.tsx +98 -0
- package/src/components/Button/Button.tsx +156 -0
- package/src/components/Button/USAGE.md +46 -0
- package/src/components/Button/index.ts +1 -0
- package/src/components/Card/CARD_IMPLEMENTATION_NOTES.md +15 -0
- package/src/components/Card/Card.module.css +155 -0
- package/src/components/Card/Card.stories.tsx +131 -0
- package/src/components/Card/Card.test.tsx +1 -0
- package/src/components/Card/Card.tsx +202 -0
- package/src/components/Card/USAGE.md +57 -0
- package/src/components/Card/index.ts +1 -0
- package/src/components/Checkbox/CHECKBOX_IMPLEMENTATION_NOTES.md +14 -0
- package/src/components/Checkbox/Checkbox.module.css +286 -0
- package/src/components/Checkbox/Checkbox.stories.tsx +97 -0
- package/src/components/Checkbox/Checkbox.test.tsx +1 -0
- package/src/components/Checkbox/Checkbox.tsx +259 -0
- package/src/components/Checkbox/CheckboxGroup.stories.tsx +139 -0
- package/src/components/Checkbox/CheckboxGroup.tsx +148 -0
- package/src/components/Checkbox/USAGE.md +36 -0
- package/src/components/Checkbox/index.ts +6 -0
- package/src/components/Chip/CHIP_IMPLEMENTATION_NOTES.md +102 -0
- package/src/components/Chip/Chip.module.css +283 -0
- package/src/components/Chip/Chip.stories.tsx +154 -0
- package/src/components/Chip/Chip.test.tsx +1 -0
- package/src/components/Chip/Chip.tsx +168 -0
- package/src/components/Chip/USAGE.md +55 -0
- package/src/components/Chip/index.ts +1 -0
- package/src/components/Container/Container.stories.tsx +118 -0
- package/src/components/Container/Container.test.tsx +1 -0
- package/src/components/Container/Container.tsx +51 -0
- package/src/components/Container/IMPLEMENTATION_NOTES.md +5 -0
- package/src/components/Container/USAGE.md +48 -0
- package/src/components/Container/index.ts +1 -0
- package/src/components/DatePicker/DATEPICKER_IMPLEMENTATION_NOTES.md +29 -0
- package/src/components/DatePicker/DatePicker.icons.tsx +35 -0
- package/src/components/DatePicker/DatePicker.module.css +464 -0
- package/src/components/DatePicker/DatePicker.stories.tsx +163 -0
- package/src/components/DatePicker/DatePicker.test.tsx +1 -0
- package/src/components/DatePicker/DatePicker.tsx +229 -0
- package/src/components/DatePicker/USAGE.md +49 -0
- package/src/components/DatePicker/index.ts +1 -0
- package/src/components/Dropdown/BareDropdown.tsx +168 -0
- package/src/components/Dropdown/DROPDOWN_IMPLEMENTATION_NOTES.md +45 -0
- package/src/components/Dropdown/Dropdown.icons.tsx +33 -0
- package/src/components/Dropdown/Dropdown.module.css +535 -0
- package/src/components/Dropdown/Dropdown.stories.tsx +252 -0
- package/src/components/Dropdown/Dropdown.test.tsx +1 -0
- package/src/components/Dropdown/Dropdown.tsx +319 -0
- package/src/components/Dropdown/USAGE.md +68 -0
- package/src/components/Dropdown/index.ts +1 -0
- package/src/components/FileInput/FILEINPUT_IMPLEMENTATION_NOTES.md +153 -0
- package/src/components/FileInput/FileInput.module.css +268 -0
- package/src/components/FileInput/FileInput.stories.tsx +313 -0
- package/src/components/FileInput/FileInput.test.tsx +1 -0
- package/src/components/FileInput/FileInput.tsx +415 -0
- package/src/components/FileInput/USAGE.md +145 -0
- package/src/components/FileInput/index.ts +1 -0
- package/src/components/FileUpload/FILEUPLOAD_IMPLEMENTATION_NOTES.md +249 -0
- package/src/components/FileUpload/FileUpload.module.css +200 -0
- package/src/components/FileUpload/FileUpload.stories.tsx +362 -0
- package/src/components/FileUpload/FileUpload.test.tsx +1 -0
- package/src/components/FileUpload/FileUpload.tsx +352 -0
- package/src/components/FileUpload/USAGE.md +199 -0
- package/src/components/FileUpload/index.ts +1 -0
- package/src/components/Flex/Flex.stories.tsx +128 -0
- package/src/components/Flex/Flex.test.tsx +1 -0
- package/src/components/Flex/Flex.tsx +89 -0
- package/src/components/Flex/USAGE.md +41 -0
- package/src/components/Flex/index.ts +1 -0
- package/src/components/FormControlLayout/FormControlLayout.module.css +92 -0
- package/src/components/FormControlLayout/FormControlLayout.stories.tsx +118 -0
- package/src/components/FormControlLayout/FormControlLayout.test.tsx +1 -0
- package/src/components/FormControlLayout/FormControlLayout.tsx +72 -0
- package/src/components/FormControlLayout/USAGE.md +40 -0
- package/src/components/FormControlLayout/index.ts +1 -0
- package/src/components/FormControlWrapper/FORMCONTROLWRAPPER_IMPLEMENTATION_NOTES.md +35 -0
- package/src/components/FormControlWrapper/FormControlWrapper.module.css +87 -0
- package/src/components/FormControlWrapper/FormControlWrapper.stories.tsx +129 -0
- package/src/components/FormControlWrapper/FormControlWrapper.test.tsx +1 -0
- package/src/components/FormControlWrapper/FormControlWrapper.tsx +149 -0
- package/src/components/FormControlWrapper/USAGE.md +40 -0
- package/src/components/FormControlWrapper/index.ts +1 -0
- package/src/components/Grid/Grid.module.css +72 -0
- package/src/components/Grid/Grid.stories.tsx +161 -0
- package/src/components/Grid/Grid.test.tsx +1 -0
- package/src/components/Grid/Grid.tsx +155 -0
- package/src/components/Grid/IMPLEMENTATION_NOTES.md +24 -0
- package/src/components/Grid/USAGE.md +53 -0
- package/src/components/Grid/index.ts +1 -0
- package/src/components/Group/Group.stories.tsx +120 -0
- package/src/components/Group/Group.test.tsx +1 -0
- package/src/components/Group/Group.tsx +116 -0
- package/src/components/Group/USAGE.md +41 -0
- package/src/components/Group/index.ts +1 -0
- package/src/components/Heading/Heading.stories.tsx +50 -0
- package/src/components/Heading/Heading.test.tsx +1 -0
- package/src/components/Heading/Heading.tsx +28 -0
- package/src/components/Heading/USAGE.md +36 -0
- package/src/components/Heading/index.ts +1 -0
- package/src/components/HoverCard/HoverCard.module.css +107 -0
- package/src/components/HoverCard/HoverCard.stories.tsx +172 -0
- package/src/components/HoverCard/HoverCard.test.tsx +1 -0
- package/src/components/HoverCard/HoverCard.tsx +145 -0
- package/src/components/HoverCard/USAGE.md +45 -0
- package/src/components/HoverCard/index.ts +1 -0
- package/src/components/Label/LABEL_IMPLEMENTATION_NOTES.md +27 -0
- package/src/components/Label/Label.module.css +169 -0
- package/src/components/Label/Label.stories.tsx +131 -0
- package/src/components/Label/Label.test.tsx +1 -0
- package/src/components/Label/Label.tsx +96 -0
- package/src/components/Label/USAGE.md +36 -0
- package/src/components/Label/index.ts +1 -0
- package/src/components/Layer/USAGE.md +50 -0
- package/src/components/Link/LINK_IMPLEMENTATION_NOTES.md +9 -0
- package/src/components/Link/Link.module.css +105 -0
- package/src/components/Link/Link.stories.tsx +58 -0
- package/src/components/Link/Link.test.tsx +1 -0
- package/src/components/Link/Link.tsx +45 -0
- package/src/components/Link/USAGE.md +40 -0
- package/src/components/Link/index.ts +1 -0
- package/src/components/Loader/LOADER_IMPLEMENTATION_NOTES.md +25 -0
- package/src/components/Loader/Loader.animate.dom.test.tsx +72 -0
- package/src/components/Loader/Loader.module.css +175 -0
- package/src/components/Loader/Loader.stories.tsx +123 -0
- package/src/components/Loader/Loader.test.tsx +1 -0
- package/src/components/Loader/Loader.tsx +72 -0
- package/src/components/Loader/USAGE.md +42 -0
- package/src/components/Loader/index.ts +1 -0
- package/src/components/Menu/IMPLEMENTATION_NOTES.md +5 -0
- package/src/components/Menu/Menu.module.css +283 -0
- package/src/components/Menu/Menu.stories.tsx +405 -0
- package/src/components/Menu/Menu.test.tsx +1 -0
- package/src/components/Menu/Menu.tsx +103 -0
- package/src/components/Menu/USAGE.md +53 -0
- package/src/components/Menu/index.ts +1 -0
- package/src/components/Modal/MODAL_IMPLEMENTATION_NOTES.md +31 -0
- package/src/components/Modal/Modal.module.css +302 -0
- package/src/components/Modal/Modal.stories.tsx +105 -0
- package/src/components/Modal/Modal.test.tsx +1 -0
- package/src/components/Modal/Modal.tsx +231 -0
- package/src/components/Modal/USAGE.md +40 -0
- package/src/components/Modal/index.ts +1 -0
- package/src/components/NumberInput/NUMBER_INPUT_IMPLEMENTATION_NOTES.md +93 -0
- package/src/components/NumberInput/NumberInput.module.css +303 -0
- package/src/components/NumberInput/NumberInput.stories.tsx +96 -0
- package/src/components/NumberInput/NumberInput.test.tsx +1 -0
- package/src/components/NumberInput/NumberInput.tsx +273 -0
- package/src/components/NumberInput/USAGE.md +36 -0
- package/src/components/NumberInput/index.ts +1 -0
- package/src/components/Pagination/IMPLEMENTATION_NOTES.md +40 -0
- package/src/components/Pagination/Pagination.icons.tsx +66 -0
- package/src/components/Pagination/Pagination.module.css +197 -0
- package/src/components/Pagination/Pagination.stories.tsx +48 -0
- package/src/components/Pagination/Pagination.test.tsx +1 -0
- package/src/components/Pagination/Pagination.tsx +123 -0
- package/src/components/Pagination/USAGE.md +36 -0
- package/src/components/Pagination/index.ts +1 -0
- package/src/components/Panel/PANEL_IMPLEMENTATION_NOTES.md +133 -0
- package/src/components/Panel/Panel.module.css +231 -0
- package/src/components/Panel/Panel.stories.tsx +227 -0
- package/src/components/Panel/Panel.test.tsx +1 -0
- package/src/components/Panel/Panel.tsx +186 -0
- package/src/components/Panel/USAGE.md +46 -0
- package/src/components/Panel/index.ts +1 -0
- package/src/components/Popover/IMPLEMENTATION_NOTES.md +22 -0
- package/src/components/Popover/Popover.module.css +118 -0
- package/src/components/Popover/Popover.stories.tsx +133 -0
- package/src/components/Popover/Popover.test.tsx +1 -0
- package/src/components/Popover/Popover.tsx +267 -0
- package/src/components/Popover/USAGE.md +69 -0
- package/src/components/Popover/index.ts +1 -0
- package/src/components/Radio/RADIO_IMPLEMENTATION_NOTES.md +12 -0
- package/src/components/Radio/Radio.module.css +247 -0
- package/src/components/Radio/Radio.stories.tsx +93 -0
- package/src/components/Radio/Radio.test.tsx +1 -0
- package/src/components/Radio/Radio.tsx +223 -0
- package/src/components/Radio/RadioGroup.stories.tsx +117 -0
- package/src/components/Radio/RadioGroup.tsx +122 -0
- package/src/components/Radio/USAGE.md +36 -0
- package/src/components/Radio/index.ts +2 -0
- package/src/components/ReadOnlyField/ReadOnlyBooleanField.tsx +21 -0
- package/src/components/ReadOnlyField/ReadOnlyField.module.css +54 -0
- package/src/components/ReadOnlyField/ReadOnlyField.stories.tsx +163 -0
- package/src/components/ReadOnlyField/ReadOnlyField.test.tsx +1 -0
- package/src/components/ReadOnlyField/ReadOnlyField.tsx +108 -0
- package/src/components/ReadOnlyField/ReadOnlySwitchField.tsx +21 -0
- package/src/components/ReadOnlyField/ReadOnlyTextField.tsx +48 -0
- package/src/components/ReadOnlyField/USAGE.md +36 -0
- package/src/components/ReadOnlyField/WithReadOnlyWrapper.tsx +93 -0
- package/src/components/ReadOnlyField/index.ts +2 -0
- package/src/components/RecursicaThemeProvider/USAGE.md +60 -0
- package/src/components/SegmentedControl/IMPLEMENTATION_NOTES.md +14 -0
- package/src/components/SegmentedControl/SegmentedControl.module.css +201 -0
- package/src/components/SegmentedControl/SegmentedControl.stories.tsx +106 -0
- package/src/components/SegmentedControl/SegmentedControl.test.tsx +1 -0
- package/src/components/SegmentedControl/SegmentedControl.tsx +149 -0
- package/src/components/SegmentedControl/USAGE.md +49 -0
- package/src/components/SegmentedControl/index.ts +1 -0
- package/src/components/Slider/IMPLEMENTATION_NOTES.md +55 -0
- package/src/components/Slider/Slider.module.css +635 -0
- package/src/components/Slider/Slider.stories.tsx +282 -0
- package/src/components/Slider/Slider.test.tsx +1 -0
- package/src/components/Slider/Slider.tsx +435 -0
- package/src/components/Slider/USAGE.md +56 -0
- package/src/components/Slider/index.ts +1 -0
- package/src/components/Stack/Stack.stories.tsx +108 -0
- package/src/components/Stack/Stack.test.tsx +1 -0
- package/src/components/Stack/Stack.tsx +43 -0
- package/src/components/Stack/USAGE.md +41 -0
- package/src/components/Stack/index.ts +1 -0
- package/src/components/Stepper/IMPLEMENTATION_NOTES.md +120 -0
- package/src/components/Stepper/Stepper.module.css +474 -0
- package/src/components/Stepper/Stepper.stories.tsx +157 -0
- package/src/components/Stepper/Stepper.test.tsx +1 -0
- package/src/components/Stepper/Stepper.tsx +240 -0
- package/src/components/Stepper/USAGE.md +45 -0
- package/src/components/Stepper/index.ts +1 -0
- package/src/components/Switch/SWITCH_IMPLEMENTATION_NOTES.md +147 -0
- package/src/components/Switch/Switch.module.css +346 -0
- package/src/components/Switch/Switch.stories.tsx +114 -0
- package/src/components/Switch/Switch.test.tsx +1 -0
- package/src/components/Switch/Switch.tsx +294 -0
- package/src/components/Switch/SwitchGroup.stories.tsx +132 -0
- package/src/components/Switch/SwitchGroup.tsx +156 -0
- package/src/components/Switch/USAGE.md +36 -0
- package/src/components/Switch/index.ts +2 -0
- package/src/components/Table/TABLE_IMPLEMENTATION_NOTES.md +75 -0
- package/src/components/Table/Table.module.css +462 -0
- package/src/components/Table/Table.stories.tsx +154 -0
- package/src/components/Table/Table.test.tsx +1 -0
- package/src/components/Table/Table.tsx +250 -0
- package/src/components/Table/USAGE.md +90 -0
- package/src/components/Table/index.ts +1 -0
- package/src/components/Tabs/IMPLEMENTATION_NOTES.md +76 -0
- package/src/components/Tabs/Tabs.module.css +801 -0
- package/src/components/Tabs/Tabs.stories.tsx +174 -0
- package/src/components/Tabs/Tabs.test.tsx +1 -0
- package/src/components/Tabs/Tabs.tsx +103 -0
- package/src/components/Tabs/USAGE.md +61 -0
- package/src/components/Tabs/index.ts +1 -0
- package/src/components/Text/TEXT_IMPLEMENTATION_NOTES.md +10 -0
- package/src/components/Text/Text.stories.tsx +75 -0
- package/src/components/Text/Text.test.tsx +1 -0
- package/src/components/Text/Text.tsx +19 -0
- package/src/components/Text/USAGE.md +40 -0
- package/src/components/Text/index.ts +1 -0
- package/src/components/TextArea/TEXTAREA_IMPLEMENTATION_NOTES.md +42 -0
- package/src/components/TextArea/TextArea.module.css +203 -0
- package/src/components/TextArea/TextArea.stories.tsx +94 -0
- package/src/components/TextArea/TextArea.test.tsx +1 -0
- package/src/components/TextArea/TextArea.tsx +162 -0
- package/src/components/TextArea/USAGE.md +38 -0
- package/src/components/TextArea/index.ts +1 -0
- package/src/components/TextField/TextField.module.css +271 -0
- package/src/components/TextField/TextField.stories.tsx +162 -0
- package/src/components/TextField/TextField.test.tsx +1 -0
- package/src/components/TextField/TextField.tsx +182 -0
- package/src/components/TextField/USAGE.md +38 -0
- package/src/components/TextField/index.ts +1 -0
- package/src/components/TimePicker/TIMEPICKER_IMPLEMENTATION_NOTES.md +89 -0
- package/src/components/TimePicker/TimePicker.module.css +262 -0
- package/src/components/TimePicker/TimePicker.stories.tsx +155 -0
- package/src/components/TimePicker/TimePicker.test.tsx +1 -0
- package/src/components/TimePicker/TimePicker.tsx +277 -0
- package/src/components/TimePicker/USAGE.md +61 -0
- package/src/components/TimePicker/index.ts +1 -0
- package/src/components/Timeline/IMPLEMENTATION_NOTES.md +42 -0
- package/src/components/Timeline/Timeline.module.css +363 -0
- package/src/components/Timeline/Timeline.stories.tsx +128 -0
- package/src/components/Timeline/Timeline.test.tsx +1 -0
- package/src/components/Timeline/Timeline.tsx +90 -0
- package/src/components/Timeline/TimelineItem.tsx +95 -0
- package/src/components/Timeline/USAGE.md +41 -0
- package/src/components/Timeline/index.ts +2 -0
- package/src/components/Toast/TOAST_IMPLEMENTATION_NOTES.md +37 -0
- package/src/components/Toast/Toast.module.css +193 -0
- package/src/components/Toast/Toast.stories.tsx +67 -0
- package/src/components/Toast/Toast.test.tsx +1 -0
- package/src/components/Toast/Toast.tsx +121 -0
- package/src/components/Toast/USAGE.md +42 -0
- package/src/components/Toast/index.ts +1 -0
- package/src/components/Tooltip/Tooltip.module.css +83 -0
- package/src/components/Tooltip/Tooltip.stories.tsx +165 -0
- package/src/components/Tooltip/Tooltip.test.tsx +1 -0
- package/src/components/Tooltip/Tooltip.tsx +78 -0
- package/src/components/Tooltip/USAGE.md +40 -0
- package/src/components/Tooltip/index.ts +1 -0
- package/src/components/TransferList/TRANSFERLIST_IMPLEMENTATION_NOTES.md +140 -0
- package/src/components/TransferList/TransferList.module.css +174 -0
- package/src/components/TransferList/TransferList.stories.tsx +121 -0
- package/src/components/TransferList/TransferList.test.tsx +1 -0
- package/src/components/TransferList/TransferList.tsx +419 -0
- package/src/components/TransferList/USAGE.md +77 -0
- package/src/components/TransferList/index.ts +1 -0
- package/src/components/Tree/IMPLEMENTATION_NOTES.md +53 -0
- package/src/components/Tree/Tree.module.css +272 -0
- package/src/components/Tree/Tree.stories.tsx +104 -0
- package/src/components/Tree/Tree.test.tsx +1 -0
- package/src/components/Tree/Tree.tsx +298 -0
- package/src/components/Tree/USAGE.md +99 -0
- package/src/components/Tree/index.ts +1 -0
- package/src/components/Typography/TYPOGRAPHY_IMPLEMENTATION_NOTES.md +17 -0
- package/src/components/Typography/Typography.module.css +13 -0
- package/src/components/Typography/Typography.test.tsx +1 -0
- package/src/components/Typography/Typography.tsx +43 -0
- package/src/components/Typography/USAGE.md +40 -0
- package/src/components/Typography/index.ts +1 -0
- package/src/components/index.ts +50 -0
- package/src/env.d.ts +7 -0
- package/src/index.ts +194 -0
- package/src/types/index.ts +9 -0
- package/src/types/scss-modules.d.ts +9 -0
- package/src/utils/ColorSchemeWrapper.tsx +23 -0
- package/src/utils/RequireAccessibleLabel.ts +1 -0
- package/src/utils/copyToClipboard.ts +36 -0
- package/src/utils/filterStylingProps.test.ts +85 -0
- package/src/utils/filterStylingProps.ts +143 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/renderRichOption.tsx +51 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Button Component Implementation Notes
|
|
2
|
+
|
|
3
|
+
**Implementation Philosophy:**
|
|
4
|
+
The Button component serves as a foundational building block in Recursica. This implementation wraps the `@mui/material/Button` component but **disables its native visual heuristics entirely.**
|
|
5
|
+
|
|
6
|
+
We explicitly pass `disableRipple` and `disableElevation` to block MUI's dynamic behaviors. Furthermore, we intentionally **do not** map our `variant` or `size` properties to MUI's native `variant` or `size` props because doing so would trigger MUI's internal CSS engines to inject styles that clash with our strict design tokens.
|
|
7
|
+
|
|
8
|
+
**Styling Strategy:**
|
|
9
|
+
|
|
10
|
+
- We utilize `filterStylingProps` to prevent rogue injections of `sx`, `style`, or `className` properties that would violate the design system.
|
|
11
|
+
- All styling is controlled directly via CSS Modules, mapping DOM attributes like `data-variant` and `data-size` to pure CSS selectors.
|
|
12
|
+
- Hover states are managed with a standard `::after` pseudo-element overlay hack rather than relying on native hover psuedo-selectors modifying background-color directly. This allows a clean `opacity` overlay based on the provided design tokens, which guarantees identical visual feedback behavior across all underlying themes without overriding background hues manually.
|
|
13
|
+
- The polymorphic `component` prop natively supported by MUI is safely forwarded to allow correct semantics (e.g. rendering as an `<a>` tag or using a router `Link`).
|
|
14
|
+
|
|
15
|
+
**Accessibility:**
|
|
16
|
+
|
|
17
|
+
- We inject a development-time warning explicitly requiring `aria-label` when the component detects an icon-only configuration.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Loader color contrast — fixed (source-of-truth audit, 2026-08-30)
|
|
22
|
+
|
|
23
|
+
**Superseded:** the entry below originally documented an explicit decision _not_ to fix this.
|
|
24
|
+
Re-verified during the mantine-vs-mui source-of-truth audit: mantine's own loader ring was
|
|
25
|
+
measured (via computed styles) rendering `#c21b43` (the Loader's standalone `indicator-color`
|
|
26
|
+
token) against a label text color of `rgb(249, 249, 249)` — a real, confirmed contrast mismatch,
|
|
27
|
+
not a false report. Fixed in both adapters; see mantine-adapter's own `IMPLEMENTATION_NOTES.md`
|
|
28
|
+
for the equivalent fix there.
|
|
29
|
+
|
|
30
|
+
**Original problem:** `Loader.module.css`'s `.root` unconditionally sets
|
|
31
|
+
`--loader-color: var(--recursica_..._loader_properties_indicator-color)` on its own root
|
|
32
|
+
element, regardless of context — so nesting a `<Loader>` inside a Button's loading state always
|
|
33
|
+
used the Loader's own standalone token, never the button's actual per-variant text color.
|
|
34
|
+
|
|
35
|
+
**Fix:** `Button.module.css` now exposes `--button-color` per variant (solid/outline/text),
|
|
36
|
+
set to that variant's own `colors_text-color` token. The Button-owned `<Loader>` instance passed
|
|
37
|
+
to MUI's `loadingIndicator` prop is now given `overStyled` + `style={{ "--loader-color":
|
|
38
|
+
"var(--button-color)" }}` — an inline style on the Loader's own root, which (being inline) beats
|
|
39
|
+
the stylesheet default and inherits whatever `--button-color` resolves to at that point in the
|
|
40
|
+
DOM. `overStyled` is required to let `style` through `filterStylingProps`; this is a fully
|
|
41
|
+
internal composition (no prop threading to callers), so it doesn't widen Loader's public API.
|
|
42
|
+
|
|
43
|
+
**Also fixed alongside this:** the loading state previously rendered the label text at full
|
|
44
|
+
opacity _and_ injected a second, redundant Loader into `startIcon` (on top of MUI's own native
|
|
45
|
+
`loadingIndicator`/`loadingWrapper` slot) — so loading buttons showed both the label and two
|
|
46
|
+
overlapping loaders instead of just one centered loader. Removed the `startIcon` loader override
|
|
47
|
+
(startIcon now only ever shows the real `icon` prop, exactly as in the non-loading case) and
|
|
48
|
+
added `.root[data-loading="true"] .labelText, .root[data-loading="true"] .iconWrapper { opacity:
|
|
49
|
+
0; }` so the label/icon stay in the DOM/layout (matching mantine's own `opacity: 0` approach,
|
|
50
|
+
not `display: none`) while only MUI's native centered `loadingIndicator` is visible. Verified
|
|
51
|
+
live against mantine's `ui-kit-button--loading` story — now pixel-equivalent.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Loader color contrast (original entry, see "fixed" above)
|
|
56
|
+
|
|
57
|
+
**Decision:** When a Button is in a loading state, the `Recursica Loader` component is injected via the `loadingIndicator` prop. The `Loader` component strictly defines its own colors and styles per variant, meaning it does not automatically inherit the text color (`currentColor`) from the Button.
|
|
58
|
+
|
|
59
|
+
**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.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Loading state enforces disabled state
|
|
64
|
+
|
|
65
|
+
**Decision:** When `loading={true}` is passed to the Button, the component explicitly forces `disabled={true}` natively on the underlying element.
|
|
66
|
+
|
|
67
|
+
**Implementation:** This ensures that loading buttons automatically inherit the brand theme disabled opacities (via the `:disabled` CSS pseudo-class) rather than relying solely on MUI's internal loading opacity adjustments.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## `className` overwrite bug (Matt Massey, 2026-08-08)
|
|
72
|
+
|
|
73
|
+
**Bug:** with `overStyled` and a custom `className` (e.g. Tree embedding a `Button` for its expand chevron), the component's own `styles.root` class silently disappeared from the rendered `<button>` — every `[data-variant]`/`[data-size]` CSS rule stopped applying, and MUI's own default styling (including its default blue "primary" color) showed through instead.
|
|
74
|
+
|
|
75
|
+
**Root cause:** `className={finalClass}` (`` `${styles.root} ${classNameProp}` ``) was set explicitly on `<MuiButton>`, but `{...sanitizedProps}` was spread _after_ it — and `sanitizedProps` still contained the original, unmodified `className` key, since it had only been _read_ to compute `finalClass`, never deleted. The later spread silently overwrote the merged class with just the caller's own class. Same bug class as `Dropdown.tsx`/`BareDropdown.tsx` had.
|
|
76
|
+
|
|
77
|
+
**Fix:** delete `className` from the sanitized props record right after reading it, before it reaches the JSX spread. mantine-adapter's `Button.tsx` had the identical mistake — masked there by a separate `classNames={{root: ...}}` object prop unaffected by the bug, but fixed there too for correctness.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## `.MuiButton-startIcon`/`.MuiButton-endIcon` selectors never matched anything (Matt Massey, 2026-08-10)
|
|
82
|
+
|
|
83
|
+
**Bug:** icon-only buttons rendered with the icon visibly off-center — shifted left, with extra empty space on the right. Not a regression from any recent change; `Button.module.css` itself was untouched, and the same unwrapped selectors already existed at `HEAD`. It had just gone unnoticed until the Tree work put an icon-only Button (the chevron) under closer visual scrutiny next to Mantine's (correctly centered) version.
|
|
84
|
+
|
|
85
|
+
**Root cause:** `.MuiButton-startIcon`/`.MuiButton-endIcon` are real global class names MUI's `Button` applies directly in the DOM — not local CSS Modules classes generated from this file. Referencing them as plain `.MuiButton-startIcon` (rather than `:global(.MuiButton-startIcon)`, the pattern already used correctly for `.Mui-disabled` elsewhere in this same file) meant Vite's CSS Modules silently hashed them into scoped names — `.Button-module__MuiButton-startIcon___<hash>` — that never matched anything real in the DOM. Every rule targeting them (the icon↔label gap margin, and the icon-only margin reset) was a total no-op; icon-only buttons were left with MUI's own unreset default `margin-right` on the icon, which is what visibly pushed the icon off-center.
|
|
86
|
+
|
|
87
|
+
**Fix:** wrapped every `.MuiButton-startIcon`/`.MuiButton-endIcon` reference in `:global(...)`.
|
|
88
|
+
|
|
89
|
+
**Not otherwise fixed, flagged separately:** the same unwrapped-global-class pattern shows up in at least `Stepper.module.css` (`.Mui-active`/`.Mui-completed`/`.MuiStepLabel-root`, fully unwrapped) and `SegmentedControl.module.css`, and partially in `Label.module.css`/`Accordion.module.css` — meaning some of those components' MUI-state-driven styling may also be silently no-op'ing. Out of scope for this fix (Button only, per what was asked); worth a dedicated sweep.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## `line-height` wiring gap vs Mantine (Matt Massey, 2026-08-19)
|
|
94
|
+
|
|
95
|
+
**Reported symptom:** descenders on letters like "p"/"g" clipped in the Default story.
|
|
96
|
+
|
|
97
|
+
**Investigation:** live-verified both adapters in Storybook (Playwright) at the `Default` and `OutlineSmall` stories, including a direct canvas `measureText` check of the `gpqjy` glyph set in Lexend at 14px (`--recursica_tokens_font_line-heights_default: 1.05em` → 14.7px line box vs ~14.0px actual glyph ink) — no visible clipping reproduced in Chromium; both adapters rendered pixel-identical crops. The line-height token itself is objectively tight (near-zero headroom), but that's shared by both adapters and isn't itself mui-specific.
|
|
98
|
+
|
|
99
|
+
**Real discrepancy found:** `.root`'s "Shared Defaults" set `line-height` once, unconditionally, from the _default_-size token, and `.labelText` merely did `line-height: inherit` — so the small-size line-height token was never actually referenced (it was `recursica-ignore`d as "redundant"). Mantine's `Button.module.css`, by contrast, sets `line-height` directly on `.labelText` per size, from each size's own token. They currently resolve to the same literal value, so this wasn't visually observable, but it's a latent divergence from the source of truth — a future token change to the small-size line-height would silently not apply in adapter-mui-v7.
|
|
100
|
+
|
|
101
|
+
**Fix:** moved `line-height` off `.root` and onto `.labelText` (default token), added `.root[data-size="small"] .labelText { line-height: ... }` (small token), and removed the now-inaccurate `recursica-ignore` for that token — matching Mantine's structure exactly.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Button doesn't shrink inside a constraining container (Genesis, 2026-08-27)
|
|
106
|
+
|
|
107
|
+
**Bug:** in the `TruncatedLabel` story (`<div style={{ maxWidth: 250 }}><Button>...long label.../Button></div>`), the button ignored the 250px wrapper entirely and rendered at its full 534px intrinsic width, overflowing the wrapper instead of shrinking and showing the ellipsis.
|
|
108
|
+
|
|
109
|
+
**Root cause:** `.root` has `width: fit-content` (to hug its own content instead of stretching in flex columns) but no `max-width`. Verified via Playwright: the wrapper measured exactly 250px, but `fit-content` on `.root` still resolved to its 534px `max-content` size — it doesn't reliably clamp against a narrower containing block on its own. Same root cause and identical fix in mantine-adapter.
|
|
110
|
+
|
|
111
|
+
**Fix:** added `max-width: 100%` to `.root`. It's a no-op when the parent is wide enough (confirmed no change to `Default`/`IconOnly`/`TextWithIcon` story widths), and clamps the button to the parent's resolved width when the parent is narrower — at which point the existing `overflow: hidden` (`.root`) + `text-overflow: ellipsis`/`white-space: nowrap` (`.labelText`) take over, exactly as already documented above.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## `.labelText` descender clipping (Matt Massey, 2026-08-28)
|
|
116
|
+
|
|
117
|
+
`.labelText` used plain `overflow: hidden` to make `text-overflow: ellipsis` work, which also
|
|
118
|
+
clips descenders (e.g. the "g" in a long label) whenever `text_line-height` is tighter than the
|
|
119
|
+
font's natural ascent+descent. Switched to `overflow: clip; overflow-clip-margin: 0.35em;` — same
|
|
120
|
+
truncation, but ink can bleed slightly past the line box before it's actually clipped. `.root`'s
|
|
121
|
+
own `overflow: hidden` (the max-width truncation bounding box, above) is untouched — it has
|
|
122
|
+
padding around the label so it isn't tight against the glyphs the way `.labelText` is.
|
|
123
|
+
Project-wide fix; see Chip's `CHIP_IMPLEMENTATION_NOTES.md` for the original discovery.
|
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
/* Brand-layer exemptions (recursica-allow-brand) — see recursica-token-analyzer README.md.
|
|
2
|
+
* Global hover/focus/disabled state tokens (recursica_variables_scoped.css header, 'Hover & Focus states' / 'Disabled state' — implicit rule for every interactive element; components must not define their own per-component treatment).
|
|
3
|
+
* recursica-allow-brand: --recursica_brand_states_focus_blur
|
|
4
|
+
* recursica-allow-brand: --recursica_brand_states_focus_border-size
|
|
5
|
+
* recursica-allow-brand: --recursica_brand_states_focus_color
|
|
6
|
+
* recursica-allow-brand: --recursica_brand_states_focus_margin
|
|
7
|
+
* recursica-allow-brand: --recursica_brand_states_hover_color
|
|
8
|
+
* recursica-allow-brand: --recursica_brand_states_hover_opacity
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/* Baseline and Reset */
|
|
12
|
+
.root {
|
|
13
|
+
box-sizing: border-box;
|
|
14
|
+
margin: 0;
|
|
15
|
+
border-style: solid;
|
|
16
|
+
overflow: hidden; /* Truncation bounding box */
|
|
17
|
+
position: relative;
|
|
18
|
+
transition: all 0.2s ease;
|
|
19
|
+
width: fit-content; /* Prevent stretching in flex columns */
|
|
20
|
+
max-width: 100%; /* Let a constraining parent (e.g. max-width container) actually shrink the button; fit-content alone ignores it */
|
|
21
|
+
|
|
22
|
+
/* Shared Defaults */
|
|
23
|
+
font-family: var(
|
|
24
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_text_font-family
|
|
25
|
+
);
|
|
26
|
+
font-size: var(
|
|
27
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_text_font-size
|
|
28
|
+
);
|
|
29
|
+
font-style: var(
|
|
30
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_text_font-style
|
|
31
|
+
);
|
|
32
|
+
font-weight: var(
|
|
33
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_text_font-weight
|
|
34
|
+
);
|
|
35
|
+
letter-spacing: var(
|
|
36
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_text_letter-spacing
|
|
37
|
+
);
|
|
38
|
+
text-decoration: var(
|
|
39
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_text_text-decoration
|
|
40
|
+
);
|
|
41
|
+
text-transform: var(
|
|
42
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_text_text-transform
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/* Reset MUI native properties */
|
|
47
|
+
.root {
|
|
48
|
+
text-transform: none;
|
|
49
|
+
min-width: 0;
|
|
50
|
+
color: inherit;
|
|
51
|
+
background-color: transparent;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* Internal layout logic for Truncation */
|
|
55
|
+
.root > *:not(:global(.MuiButton-loadingIndicator)) {
|
|
56
|
+
min-width: 0;
|
|
57
|
+
position: relative;
|
|
58
|
+
z-index: 1;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.label {
|
|
62
|
+
display: flex;
|
|
63
|
+
align-items: center;
|
|
64
|
+
min-width: 0;
|
|
65
|
+
flex: 1 1 0;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.labelText {
|
|
69
|
+
display: block;
|
|
70
|
+
min-width: 0;
|
|
71
|
+
overflow: clip; /* HARDCODE: `hidden` clips descenders (e.g. "g") when text_line-height is
|
|
72
|
+
tighter than the font's natural ascent+descent; overflow-clip-margin gives ink a small bleed
|
|
73
|
+
allowance while still clipping genuinely overflowing text (see Chip's IMPLEMENTATION_NOTES.md). */
|
|
74
|
+
overflow-clip-margin: 0.35em;
|
|
75
|
+
text-overflow: ellipsis;
|
|
76
|
+
white-space: nowrap;
|
|
77
|
+
font-size: inherit;
|
|
78
|
+
line-height: var(
|
|
79
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_text_line-height
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
/* Removed data-loading background override to rely on native disabled opacities like Mantine */
|
|
83
|
+
|
|
84
|
+
/* ==== SIZES ==== */
|
|
85
|
+
.root[data-size="default"] {
|
|
86
|
+
height: var(
|
|
87
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_height
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
.root[data-size="default"][data-content="label"] {
|
|
91
|
+
border-radius: var(
|
|
92
|
+
--recursica_ui-kit_components_button_variants_content_label_variants_sizes_default_properties_border-radius
|
|
93
|
+
);
|
|
94
|
+
min-width: var(
|
|
95
|
+
--recursica_ui-kit_components_button_variants_content_label_variants_sizes_default_properties_min-width
|
|
96
|
+
);
|
|
97
|
+
padding: 0
|
|
98
|
+
var(
|
|
99
|
+
--recursica_ui-kit_components_button_variants_content_label_variants_sizes_default_properties_horizontal-padding
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
.root[data-size="default"][data-content="icon-label"] {
|
|
103
|
+
border-radius: var(
|
|
104
|
+
--recursica_ui-kit_components_button_variants_content_icon-label_variants_sizes_default_properties_border-radius
|
|
105
|
+
);
|
|
106
|
+
min-width: var(
|
|
107
|
+
--recursica_ui-kit_components_button_variants_content_icon-label_variants_sizes_default_properties_min-width
|
|
108
|
+
);
|
|
109
|
+
padding: 0
|
|
110
|
+
var(
|
|
111
|
+
--recursica_ui-kit_components_button_variants_content_icon-label_variants_sizes_default_properties_horizontal-padding
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
.root[data-size="default"][data-content="icon-only"] {
|
|
115
|
+
border-radius: var(
|
|
116
|
+
--recursica_ui-kit_components_button_variants_content_icon-only_variants_sizes_default_properties_border-radius
|
|
117
|
+
);
|
|
118
|
+
min-width: var(
|
|
119
|
+
--recursica_ui-kit_components_button_variants_content_icon-only_variants_sizes_default_properties_min-width
|
|
120
|
+
);
|
|
121
|
+
padding: 0
|
|
122
|
+
var(
|
|
123
|
+
--recursica_ui-kit_components_button_variants_content_icon-only_variants_sizes_default_properties_horizontal-padding
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
.root[data-size="default"] .labelText {
|
|
127
|
+
max-width: var(
|
|
128
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_max-label-width
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
.root[data-size="small"] {
|
|
132
|
+
height: var(
|
|
133
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_height
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
/* Override specific typography for small */
|
|
137
|
+
font-family: var(
|
|
138
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_text_font-family
|
|
139
|
+
);
|
|
140
|
+
font-size: var(
|
|
141
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_text_font-size
|
|
142
|
+
);
|
|
143
|
+
font-weight: var(
|
|
144
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_text_font-weight
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
.root[data-size="small"][data-content="label"] {
|
|
148
|
+
border-radius: var(
|
|
149
|
+
--recursica_ui-kit_components_button_variants_content_label_variants_sizes_small_properties_border-radius
|
|
150
|
+
);
|
|
151
|
+
min-width: var(
|
|
152
|
+
--recursica_ui-kit_components_button_variants_content_label_variants_sizes_small_properties_min-width
|
|
153
|
+
);
|
|
154
|
+
padding: 0
|
|
155
|
+
var(
|
|
156
|
+
--recursica_ui-kit_components_button_variants_content_label_variants_sizes_small_properties_horizontal-padding
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
.root[data-size="small"][data-content="icon-label"] {
|
|
160
|
+
border-radius: var(
|
|
161
|
+
--recursica_ui-kit_components_button_variants_content_icon-label_variants_sizes_small_properties_border-radius
|
|
162
|
+
);
|
|
163
|
+
min-width: var(
|
|
164
|
+
--recursica_ui-kit_components_button_variants_content_icon-label_variants_sizes_small_properties_min-width
|
|
165
|
+
);
|
|
166
|
+
padding: 0
|
|
167
|
+
var(
|
|
168
|
+
--recursica_ui-kit_components_button_variants_content_icon-label_variants_sizes_small_properties_horizontal-padding
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
.root[data-size="small"][data-content="icon-only"] {
|
|
172
|
+
border-radius: var(
|
|
173
|
+
--recursica_ui-kit_components_button_variants_content_icon-only_variants_sizes_small_properties_border-radius
|
|
174
|
+
);
|
|
175
|
+
min-width: var(
|
|
176
|
+
--recursica_ui-kit_components_button_variants_content_icon-only_variants_sizes_small_properties_min-width
|
|
177
|
+
);
|
|
178
|
+
padding: 0
|
|
179
|
+
var(
|
|
180
|
+
--recursica_ui-kit_components_button_variants_content_icon-only_variants_sizes_small_properties_horizontal-padding
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
.root[data-size="small"] .labelText {
|
|
184
|
+
max-width: var(
|
|
185
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_max-label-width
|
|
186
|
+
);
|
|
187
|
+
line-height: var(
|
|
188
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_text_line-height
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/* Icon Resets */
|
|
193
|
+
.iconWrapper {
|
|
194
|
+
display: flex;
|
|
195
|
+
align-items: center;
|
|
196
|
+
justify-content: center;
|
|
197
|
+
flex-shrink: 0;
|
|
198
|
+
}
|
|
199
|
+
.iconWrapper > * {
|
|
200
|
+
width: 100%;
|
|
201
|
+
height: 100%;
|
|
202
|
+
object-fit: contain;
|
|
203
|
+
}
|
|
204
|
+
.root[data-size="default"] .iconWrapper {
|
|
205
|
+
width: var(
|
|
206
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_icon
|
|
207
|
+
);
|
|
208
|
+
height: var(
|
|
209
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_icon
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
.root[data-size="small"] .iconWrapper {
|
|
213
|
+
width: var(
|
|
214
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_icon
|
|
215
|
+
);
|
|
216
|
+
height: var(
|
|
217
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_icon
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/* Loading state: hide the label/icon (they stay in the DOM/layout, matching
|
|
222
|
+
mantine-adapter's opacity:0 approach) so only MUI's own centered
|
|
223
|
+
loadingIndicator is visible — see IMPLEMENTATION_NOTES.md. */
|
|
224
|
+
.root[data-loading="true"] .labelText,
|
|
225
|
+
.root[data-loading="true"] .iconWrapper {
|
|
226
|
+
opacity: 0;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/* MUI uses .MuiButton-startIcon and .MuiButton-endIcon — real global classes MUI applies
|
|
230
|
+
directly, not local CSS Modules classes, so they must be wrapped in :global() (same as
|
|
231
|
+
.Mui-disabled below) or Vite's CSS Modules hashes them into scoped names that never match
|
|
232
|
+
anything in the actual DOM, silently no-op'ing every rule below. */
|
|
233
|
+
.root[data-size="default"] :global(.MuiButton-startIcon) {
|
|
234
|
+
margin-left: 0;
|
|
235
|
+
margin-right: var(
|
|
236
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_icon-text-gap
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
.root[data-size="default"] :global(.MuiButton-endIcon) {
|
|
240
|
+
margin-right: 0;
|
|
241
|
+
margin-left: var(
|
|
242
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_icon-text-gap
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
.root[data-size="small"] :global(.MuiButton-startIcon) {
|
|
246
|
+
margin-left: 0;
|
|
247
|
+
margin-right: var(
|
|
248
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_icon-text-gap
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
.root[data-size="small"] :global(.MuiButton-endIcon) {
|
|
252
|
+
margin-right: 0;
|
|
253
|
+
margin-left: var(
|
|
254
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_icon-text-gap
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/* Icon-only logic overrides */
|
|
259
|
+
.root[data-content="icon-only"] .labelText {
|
|
260
|
+
display: none;
|
|
261
|
+
}
|
|
262
|
+
.root[data-content="icon-only"] :global(.MuiButton-startIcon),
|
|
263
|
+
.root[data-content="icon-only"] :global(.MuiButton-endIcon) {
|
|
264
|
+
margin-right: 0;
|
|
265
|
+
margin-left: 0;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/* Disabled */
|
|
269
|
+
.root:disabled,
|
|
270
|
+
.root:global(.Mui-disabled) {
|
|
271
|
+
cursor: not-allowed;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/* Global Hover Hack Overlay */
|
|
275
|
+
.root::after {
|
|
276
|
+
content: "";
|
|
277
|
+
position: absolute;
|
|
278
|
+
inset: 0;
|
|
279
|
+
border-radius: inherit;
|
|
280
|
+
z-index: 0;
|
|
281
|
+
pointer-events: none;
|
|
282
|
+
transition: opacity 150ms ease;
|
|
283
|
+
opacity: 0;
|
|
284
|
+
background-color: var(--recursica_brand_states_hover_color);
|
|
285
|
+
}
|
|
286
|
+
.root:hover:not(:disabled):not(:global(.Mui-disabled))::after {
|
|
287
|
+
opacity: var(--recursica_brand_states_hover_opacity);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/* ==== VARIANTS ==== */
|
|
291
|
+
|
|
292
|
+
/* SOLID */
|
|
293
|
+
.root[data-variant="solid"] {
|
|
294
|
+
border-width: var(
|
|
295
|
+
--recursica_ui-kit_components_button_variants_styles_solid_properties_border-size
|
|
296
|
+
);
|
|
297
|
+
box-shadow: var(
|
|
298
|
+
--recursica_ui-kit_components_button_variants_styles_solid_properties_elevation
|
|
299
|
+
);
|
|
300
|
+
background-color: var(
|
|
301
|
+
--recursica_ui-kit_components_button_variants_styles_solid_properties_colors_background-color
|
|
302
|
+
);
|
|
303
|
+
border-color: var(
|
|
304
|
+
--recursica_ui-kit_components_button_variants_styles_solid_properties_colors_border-color
|
|
305
|
+
);
|
|
306
|
+
color: var(
|
|
307
|
+
--recursica_ui-kit_components_button_variants_styles_solid_properties_colors_text-color
|
|
308
|
+
);
|
|
309
|
+
/* Exposed so the loading-state Loader (style={{ "--loader-color": "var(--button-color)" }}
|
|
310
|
+
in Button.tsx) matches this exact text-color token — see IMPLEMENTATION_NOTES.md. */
|
|
311
|
+
--button-color: var(
|
|
312
|
+
--recursica_ui-kit_components_button_variants_styles_solid_properties_colors_text-color
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
.root[data-variant="solid"] .iconWrapper {
|
|
316
|
+
color: var(
|
|
317
|
+
--recursica_ui-kit_components_button_variants_styles_solid_properties_colors_icon-color
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
.root[data-variant="solid"]:disabled,
|
|
321
|
+
.root[data-variant="solid"]:global(.Mui-disabled) {
|
|
322
|
+
opacity: var(
|
|
323
|
+
--recursica_ui-kit_components_button_variants_styles_solid_variants_states_disabled_properties_opacity
|
|
324
|
+
);
|
|
325
|
+
box-shadow: var(
|
|
326
|
+
--recursica_ui-kit_components_button_variants_styles_solid_variants_states_disabled_properties_elevation
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/* OUTLINE */
|
|
331
|
+
.root[data-variant="outline"] {
|
|
332
|
+
border-width: var(
|
|
333
|
+
--recursica_ui-kit_components_button_variants_styles_outline_properties_border-size
|
|
334
|
+
);
|
|
335
|
+
box-shadow: var(
|
|
336
|
+
--recursica_ui-kit_components_button_variants_styles_outline_properties_elevation
|
|
337
|
+
);
|
|
338
|
+
background-color: var(
|
|
339
|
+
--recursica_ui-kit_components_button_variants_styles_outline_properties_colors_background-color
|
|
340
|
+
);
|
|
341
|
+
border-color: var(
|
|
342
|
+
--recursica_ui-kit_components_button_variants_styles_outline_properties_colors_border-color
|
|
343
|
+
);
|
|
344
|
+
color: var(
|
|
345
|
+
--recursica_ui-kit_components_button_variants_styles_outline_properties_colors_text-color
|
|
346
|
+
);
|
|
347
|
+
--button-color: var(
|
|
348
|
+
--recursica_ui-kit_components_button_variants_styles_outline_properties_colors_text-color
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
.root[data-variant="outline"] .iconWrapper {
|
|
352
|
+
color: var(
|
|
353
|
+
--recursica_ui-kit_components_button_variants_styles_outline_properties_colors_icon-color
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
.root[data-variant="outline"]:disabled,
|
|
357
|
+
.root[data-variant="outline"]:global(.Mui-disabled) {
|
|
358
|
+
opacity: var(
|
|
359
|
+
--recursica_ui-kit_components_button_variants_styles_outline_variants_states_disabled_properties_opacity
|
|
360
|
+
);
|
|
361
|
+
box-shadow: var(
|
|
362
|
+
--recursica_ui-kit_components_button_variants_styles_outline_variants_states_disabled_properties_elevation
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/* TEXT */
|
|
367
|
+
.root[data-variant="text"] {
|
|
368
|
+
border-width: var(
|
|
369
|
+
--recursica_ui-kit_components_button_variants_styles_text_properties_border-size
|
|
370
|
+
);
|
|
371
|
+
box-shadow: var(
|
|
372
|
+
--recursica_ui-kit_components_button_variants_styles_text_properties_elevation
|
|
373
|
+
);
|
|
374
|
+
background-color: var(
|
|
375
|
+
--recursica_ui-kit_components_button_variants_styles_text_properties_colors_background-color
|
|
376
|
+
);
|
|
377
|
+
border-color: var(
|
|
378
|
+
--recursica_ui-kit_components_button_variants_styles_text_properties_colors_border-color
|
|
379
|
+
);
|
|
380
|
+
color: var(
|
|
381
|
+
--recursica_ui-kit_components_button_variants_styles_text_properties_colors_text-color
|
|
382
|
+
);
|
|
383
|
+
--button-color: var(
|
|
384
|
+
--recursica_ui-kit_components_button_variants_styles_text_properties_colors_text-color
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
.root[data-variant="text"] .iconWrapper {
|
|
388
|
+
color: var(
|
|
389
|
+
--recursica_ui-kit_components_button_variants_styles_text_properties_colors_icon-color
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
.root[data-variant="text"]:disabled,
|
|
393
|
+
.root[data-variant="text"]:global(.Mui-disabled) {
|
|
394
|
+
opacity: var(
|
|
395
|
+
--recursica_ui-kit_components_button_variants_styles_text_variants_states_disabled_properties_opacity
|
|
396
|
+
);
|
|
397
|
+
box-shadow: var(
|
|
398
|
+
--recursica_ui-kit_components_button_variants_styles_text_variants_states_disabled_properties_elevation
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/* Focus State Mapping (native browser focus outline replaced with the recursica focus ring).
|
|
403
|
+
Placed after every variant's own box-shadow (elevation) rule so it wins the cascade at equal
|
|
404
|
+
attribute-selector specificity regardless of variant. */
|
|
405
|
+
.root:focus-visible {
|
|
406
|
+
outline: none;
|
|
407
|
+
box-shadow:
|
|
408
|
+
0 0 0 var(--recursica_brand_states_focus_border-size)
|
|
409
|
+
var(--recursica_brand_states_focus_color),
|
|
410
|
+
0 0 var(--recursica_brand_states_focus_blur)
|
|
411
|
+
var(--recursica_brand_states_focus_margin)
|
|
412
|
+
var(--recursica_brand_states_focus_color);
|
|
413
|
+
}
|