@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,298 @@
|
|
|
1
|
+
import React, { forwardRef } from "react";
|
|
2
|
+
import { RichTreeView } from "@mui/x-tree-view/RichTreeView";
|
|
3
|
+
import {
|
|
4
|
+
useTreeItem,
|
|
5
|
+
type UseTreeItemParameters,
|
|
6
|
+
} from "@mui/x-tree-view/useTreeItem";
|
|
7
|
+
import { useTreeItemModel, useTreeItemUtils } from "@mui/x-tree-view/hooks";
|
|
8
|
+
import { TreeItemProvider } from "@mui/x-tree-view/TreeItemProvider";
|
|
9
|
+
import {
|
|
10
|
+
TreeItemRoot,
|
|
11
|
+
TreeItemContent,
|
|
12
|
+
TreeItemIconContainer,
|
|
13
|
+
TreeItemGroupTransition,
|
|
14
|
+
TreeItemLabel,
|
|
15
|
+
} from "@mui/x-tree-view/TreeItem";
|
|
16
|
+
import { TreeItemIcon } from "@mui/x-tree-view/TreeItemIcon";
|
|
17
|
+
import {
|
|
18
|
+
filterStylingProps,
|
|
19
|
+
type RecursicaOverStyled,
|
|
20
|
+
} from "../../utils/filterStylingProps";
|
|
21
|
+
import {
|
|
22
|
+
type RecursicaTreeProps,
|
|
23
|
+
type RecursicaTreeNode,
|
|
24
|
+
} from "@recursica/adapter-common";
|
|
25
|
+
import { Button } from "../Button/Button";
|
|
26
|
+
import styles from "./Tree.module.css";
|
|
27
|
+
|
|
28
|
+
export type TreeProps = RecursicaOverStyled<
|
|
29
|
+
RecursicaTreeProps & Omit<React.ComponentPropsWithoutRef<"ul">, "children">
|
|
30
|
+
>;
|
|
31
|
+
|
|
32
|
+
function collectAllValues(nodes: RecursicaTreeNode[]): string[] {
|
|
33
|
+
const values: string[] = [];
|
|
34
|
+
const walk = (list: RecursicaTreeNode[]) => {
|
|
35
|
+
list.forEach((node) => {
|
|
36
|
+
values.push(node.value);
|
|
37
|
+
if (node.children) walk(node.children);
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
walk(nodes);
|
|
41
|
+
return values;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Chevron glyph; rendered inside a `Button` below. MUI renders a different component for
|
|
45
|
+
* expanded vs collapsed rather than one rotating icon (unlike Mantine's `[data-expanded]`
|
|
46
|
+
* approach), so `rotated` picks the CSS class that applies the rotation. Uses `currentColor` so
|
|
47
|
+
* it matches Button's own tokened icon color for the "text" variant. */
|
|
48
|
+
function ChevronGlyph({ rotated }: { rotated?: boolean }) {
|
|
49
|
+
return (
|
|
50
|
+
<svg
|
|
51
|
+
className={
|
|
52
|
+
rotated ? `${styles.chevron} ${styles.chevronExpanded}` : styles.chevron
|
|
53
|
+
}
|
|
54
|
+
viewBox="0 0 16 16"
|
|
55
|
+
width="1em"
|
|
56
|
+
height="1em"
|
|
57
|
+
fill="none"
|
|
58
|
+
stroke="currentColor"
|
|
59
|
+
strokeWidth="2"
|
|
60
|
+
strokeLinecap="round"
|
|
61
|
+
strokeLinejoin="round"
|
|
62
|
+
aria-hidden="true"
|
|
63
|
+
>
|
|
64
|
+
<path d="M5 3l5 5-5 5" />
|
|
65
|
+
</svg>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Never independently focusable/tab-stoppable (tabIndex={-1}, aria-hidden) — expand/collapse is
|
|
70
|
+
* driven by the surrounding `TreeItemIconContainer`'s own click handling (see `CustomTreeItem`),
|
|
71
|
+
* not by this Button itself, so the row stays the only focusable element and the button never
|
|
72
|
+
* shows its own focus state. Rendered for every row, including leaf items, so row alignment
|
|
73
|
+
* stays consistent; `hidden` (visibility, not display) is used for leaf rows instead of omitting
|
|
74
|
+
* the button, so the layout space is reserved without duplicating Button's own size tokens.
|
|
75
|
+
* `onMouseDown` prevents the browser's default click-focuses-the-button behavior (tabIndex={-1}
|
|
76
|
+
* only removes it from the tab order, it doesn't stop a direct mouse click on the chevron from
|
|
77
|
+
* focusing this button) — without this, clicking the chevron leaves the (aria-hidden) button
|
|
78
|
+
* focused, which browsers now flag as an accessibility violation ("focus must not be hidden from
|
|
79
|
+
* assistive technology"). */
|
|
80
|
+
function ExpandToggleButton({
|
|
81
|
+
rotated,
|
|
82
|
+
hidden,
|
|
83
|
+
}: {
|
|
84
|
+
rotated?: boolean;
|
|
85
|
+
hidden?: boolean;
|
|
86
|
+
}) {
|
|
87
|
+
return (
|
|
88
|
+
<Button
|
|
89
|
+
overStyled
|
|
90
|
+
variant="text"
|
|
91
|
+
size="small"
|
|
92
|
+
icon={<ChevronGlyph rotated={rotated} />}
|
|
93
|
+
aria-label="Toggle subtree"
|
|
94
|
+
aria-hidden="true"
|
|
95
|
+
tabIndex={-1}
|
|
96
|
+
onMouseDown={(event) => event.preventDefault()}
|
|
97
|
+
className={
|
|
98
|
+
hidden
|
|
99
|
+
? `${styles.expandButton} ${styles.expandButtonHidden}`
|
|
100
|
+
: styles.expandButton
|
|
101
|
+
}
|
|
102
|
+
/>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
function ExpandGlyph() {
|
|
106
|
+
return <ExpandToggleButton />;
|
|
107
|
+
}
|
|
108
|
+
function CollapseGlyph() {
|
|
109
|
+
return <ExpandToggleButton rotated />;
|
|
110
|
+
}
|
|
111
|
+
/** Rendered for leaf items so the icon-container box (and therefore row alignment) stays
|
|
112
|
+
* consistent whether or not a row has an expand chevron. */
|
|
113
|
+
function EndGlyph() {
|
|
114
|
+
return <ExpandToggleButton hidden />;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
interface CustomTreeItemProps extends UseTreeItemParameters {
|
|
118
|
+
className?: string;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** Custom `slots.item` renderer. Mirrors the mantine-adapter's `renderNode`: every visual
|
|
122
|
+
* property comes from Tree.module.css rather than @mui/x-tree-view's own default TreeItem
|
|
123
|
+
* styles. `useTreeItemModel` retrieves the *original* `RecursicaTreeNode` (with its real
|
|
124
|
+
* `React.ReactNode` label) — `getItemLabel` on `RichTreeView` only ever sees a coerced string
|
|
125
|
+
* (required for its internal a11y/typeahead search), so this is the only way to render rich
|
|
126
|
+
* (non-string) labels. See IMPLEMENTATION_NOTES.md. */
|
|
127
|
+
const CustomTreeItem = forwardRef<HTMLLIElement, CustomTreeItemProps>(
|
|
128
|
+
function CustomTreeItem(
|
|
129
|
+
{ id, itemId, label, disabled, children, className, ...rest },
|
|
130
|
+
ref,
|
|
131
|
+
) {
|
|
132
|
+
const {
|
|
133
|
+
getContextProviderProps,
|
|
134
|
+
getRootProps,
|
|
135
|
+
getContentProps,
|
|
136
|
+
getIconContainerProps,
|
|
137
|
+
getLabelProps,
|
|
138
|
+
getGroupTransitionProps,
|
|
139
|
+
status,
|
|
140
|
+
} = useTreeItem({ id, itemId, children, label, disabled, rootRef: ref });
|
|
141
|
+
|
|
142
|
+
// Exposes the same select/expand actions `useTreeItem`'s internal keyboard-navigation plugin
|
|
143
|
+
// uses, so we can override just the `Enter` key below without reimplementing selection.
|
|
144
|
+
const { interactions } = useTreeItemUtils({ itemId, children });
|
|
145
|
+
|
|
146
|
+
const item = useTreeItemModel<RecursicaTreeNode>(itemId);
|
|
147
|
+
|
|
148
|
+
const iconContainerProps = getIconContainerProps({
|
|
149
|
+
className: styles.iconContainer,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// `Enter` selects the focused node, full stop — never expands it, unlike
|
|
153
|
+
// `@mui/x-tree-view`'s own default (which expands an expandable node on `Enter` and only
|
|
154
|
+
// falls back to selecting leaf nodes). Setting `defaultMuiPrevented` is the documented
|
|
155
|
+
// extension point `createRootHandleKeyDown` checks before running its own handling, so this
|
|
156
|
+
// fully replaces rather than races the built-in behavior. `Space` already selects-only by
|
|
157
|
+
// default, so it needs no override.
|
|
158
|
+
const handleRootKeyDown = (
|
|
159
|
+
event: React.KeyboardEvent<HTMLLIElement> & {
|
|
160
|
+
defaultMuiPrevented?: boolean;
|
|
161
|
+
},
|
|
162
|
+
) => {
|
|
163
|
+
if (event.key !== "Enter") return;
|
|
164
|
+
event.preventDefault();
|
|
165
|
+
event.defaultMuiPrevented = true;
|
|
166
|
+
// `handleSelection` only reads modifier keys (shiftKey/ctrlKey/metaKey) off the event and
|
|
167
|
+
// forwards it on for focus bookkeeping — its `React.MouseEvent` type is narrower than
|
|
168
|
+
// necessary for what it actually uses, so a KeyboardEvent works fine at runtime here.
|
|
169
|
+
interactions.handleSelection(event as unknown as React.MouseEvent);
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
return (
|
|
173
|
+
<TreeItemProvider {...getContextProviderProps()}>
|
|
174
|
+
<TreeItemRoot
|
|
175
|
+
{...getRootProps({
|
|
176
|
+
...rest,
|
|
177
|
+
className: `${styles.node} ${className ?? ""}`,
|
|
178
|
+
onKeyDown: handleRootKeyDown,
|
|
179
|
+
})}
|
|
180
|
+
>
|
|
181
|
+
<TreeItemContent
|
|
182
|
+
{...getContentProps({ className: styles.row })}
|
|
183
|
+
status={status}
|
|
184
|
+
>
|
|
185
|
+
<TreeItemIconContainer
|
|
186
|
+
{...iconContainerProps}
|
|
187
|
+
// Stops the click from also reaching `TreeItemContent`'s own click handler, which
|
|
188
|
+
// otherwise selects on *any* click inside it (including the icon container) once
|
|
189
|
+
// `expansionTrigger` is `"iconContainer"` — the button must expand/collapse
|
|
190
|
+
// without ever selecting.
|
|
191
|
+
onClick={(event) => {
|
|
192
|
+
event.stopPropagation();
|
|
193
|
+
iconContainerProps.onClick(event);
|
|
194
|
+
}}
|
|
195
|
+
>
|
|
196
|
+
<TreeItemIcon status={status} />
|
|
197
|
+
</TreeItemIconContainer>
|
|
198
|
+
<TreeItemLabel {...getLabelProps({ className: styles.label })}>
|
|
199
|
+
{item?.label ?? label}
|
|
200
|
+
</TreeItemLabel>
|
|
201
|
+
</TreeItemContent>
|
|
202
|
+
{children && (
|
|
203
|
+
<TreeItemGroupTransition
|
|
204
|
+
{...getGroupTransitionProps({ className: styles.subtree })}
|
|
205
|
+
/>
|
|
206
|
+
)}
|
|
207
|
+
</TreeItemRoot>
|
|
208
|
+
</TreeItemProvider>
|
|
209
|
+
);
|
|
210
|
+
},
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Recursively renders hierarchical `data` as an expandable/selectable tree.
|
|
215
|
+
*
|
|
216
|
+
* **Recursica Abstract:**
|
|
217
|
+
* Wraps `@mui/x-tree-view`'s `RichTreeView` with a fully custom item renderer so every visual
|
|
218
|
+
* aspect (row box model, selected/unselected colors and typography, indent, item spacing)
|
|
219
|
+
* comes from Recursica's `tree` design tokens rather than MUI's defaults.
|
|
220
|
+
*
|
|
221
|
+
* **Interaction pattern (fixed, not prop-configurable):** expand/collapse and select are
|
|
222
|
+
* independent — the chevron button toggles a node's subtree only, clicking the rest of a row
|
|
223
|
+
* (or pressing `Enter`/`Space`) selects it only, and `ArrowLeft`/`ArrowRight` toggle expansion
|
|
224
|
+
* only. See `RecursicaTreeProps` for the full breakdown.
|
|
225
|
+
*/
|
|
226
|
+
export const Tree = forwardRef<HTMLUListElement, TreeProps>(function Tree(
|
|
227
|
+
{
|
|
228
|
+
overStyled = false,
|
|
229
|
+
data,
|
|
230
|
+
initialExpandedValues,
|
|
231
|
+
initialSelectedValues,
|
|
232
|
+
multiple = false,
|
|
233
|
+
disabled = false,
|
|
234
|
+
onNodeExpand,
|
|
235
|
+
onNodeCollapse,
|
|
236
|
+
onSelectedChange,
|
|
237
|
+
...rest
|
|
238
|
+
},
|
|
239
|
+
ref,
|
|
240
|
+
) {
|
|
241
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
242
|
+
|
|
243
|
+
const defaultExpandedItems =
|
|
244
|
+
initialExpandedValues === "*"
|
|
245
|
+
? collectAllValues(data)
|
|
246
|
+
: initialExpandedValues;
|
|
247
|
+
|
|
248
|
+
const classNameProp = (sanitizedProps as Record<string, unknown>)
|
|
249
|
+
.className as string | undefined;
|
|
250
|
+
const rootClass = classNameProp
|
|
251
|
+
? `${styles.root} ${classNameProp}`
|
|
252
|
+
: styles.root;
|
|
253
|
+
|
|
254
|
+
return (
|
|
255
|
+
<RichTreeView
|
|
256
|
+
ref={ref}
|
|
257
|
+
{...(sanitizedProps as unknown as Record<string, unknown>)}
|
|
258
|
+
items={data}
|
|
259
|
+
getItemId={(item: RecursicaTreeNode) => item.value}
|
|
260
|
+
getItemLabel={(item: RecursicaTreeNode) =>
|
|
261
|
+
typeof item.label === "string" ? item.label : item.value
|
|
262
|
+
}
|
|
263
|
+
defaultExpandedItems={defaultExpandedItems}
|
|
264
|
+
defaultSelectedItems={
|
|
265
|
+
multiple ? (initialSelectedValues ?? []) : initialSelectedValues?.[0]
|
|
266
|
+
}
|
|
267
|
+
multiSelect={multiple}
|
|
268
|
+
// Whole-tree `disabled` reuses `@mui/x-tree-view`'s own per-item `isItemDisabled` — marking
|
|
269
|
+
// every item disabled at once — rather than a bespoke mechanism, since MUI already handles
|
|
270
|
+
// blocking click/keyboard select/expand and dimming (`.row[data-disabled]` in
|
|
271
|
+
// Tree.module.css) for disabled items internally.
|
|
272
|
+
isItemDisabled={disabled ? () => true : undefined}
|
|
273
|
+
// Fixed, not prop-driven: only the icon container (the chevron button) expands/collapses
|
|
274
|
+
// on click; clicking anywhere else on the row selects instead. `CustomTreeItem` additionally
|
|
275
|
+
// stops the icon container's click from also bubbling into the content's own selection
|
|
276
|
+
// handler — see IMPLEMENTATION_NOTES.md.
|
|
277
|
+
expansionTrigger="iconContainer"
|
|
278
|
+
onItemExpansionToggle={(_event, itemId, isExpanded) => {
|
|
279
|
+
if (isExpanded) onNodeExpand?.(itemId);
|
|
280
|
+
else onNodeCollapse?.(itemId);
|
|
281
|
+
}}
|
|
282
|
+
onSelectedItemsChange={(_event, itemIds) => {
|
|
283
|
+
onSelectedChange?.(
|
|
284
|
+
Array.isArray(itemIds) ? itemIds : itemIds ? [itemIds] : [],
|
|
285
|
+
);
|
|
286
|
+
}}
|
|
287
|
+
slots={{
|
|
288
|
+
expandIcon: ExpandGlyph,
|
|
289
|
+
collapseIcon: CollapseGlyph,
|
|
290
|
+
endIcon: EndGlyph,
|
|
291
|
+
item: CustomTreeItem,
|
|
292
|
+
}}
|
|
293
|
+
classes={{ root: rootClass }}
|
|
294
|
+
/>
|
|
295
|
+
);
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
Tree.displayName = "Tree";
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Tree - Usage Guide
|
|
2
|
+
|
|
3
|
+
This document describes how to integrate and use the `Tree` component in your projects using `@recursica/adapter-mui-v7`.
|
|
4
|
+
|
|
5
|
+
> [!IMPORTANT]
|
|
6
|
+
> This component requires `@mui/x-tree-view` (MIT-licensed, free community edition) as a peer dependency, in addition to `@mui/material`. Install it alongside your other MUI packages: `npm install @mui/x-tree-view`.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 1. Import Reference
|
|
11
|
+
|
|
12
|
+
```tsx
|
|
13
|
+
import { Tree } from "@recursica/adapter-mui-v7";
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 2. Basic Example
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import React from "react";
|
|
22
|
+
import { Tree } from "@recursica/adapter-mui-v7";
|
|
23
|
+
|
|
24
|
+
export default function Demo() {
|
|
25
|
+
return (
|
|
26
|
+
<Tree
|
|
27
|
+
data={[
|
|
28
|
+
{
|
|
29
|
+
value: "1",
|
|
30
|
+
label: "Root",
|
|
31
|
+
children: [
|
|
32
|
+
{ value: "1.1", label: "Child A" },
|
|
33
|
+
{ value: "1.2", label: "Child B" },
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
{ value: "2", label: "Sibling" },
|
|
37
|
+
]}
|
|
38
|
+
/>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Each node needs a unique `value` and a `label`. Any node with a `children` array (even an empty one) renders an expand/collapse chevron.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 3. Controlled Selection / Expansion
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
<Tree
|
|
51
|
+
data={data}
|
|
52
|
+
initialExpandedValues={["1"]}
|
|
53
|
+
initialSelectedValues={["1.1"]}
|
|
54
|
+
multiple
|
|
55
|
+
onSelectedChange={(values) => console.log("selected:", values)}
|
|
56
|
+
onNodeExpand={(value) => console.log("expanded:", value)}
|
|
57
|
+
onNodeCollapse={(value) => console.log("collapsed:", value)}
|
|
58
|
+
/>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
- `initialExpandedValues` accepts an array of node values, or `"*"` to start with every node expanded.
|
|
62
|
+
- `multiple` allows more than one node to be selected at once (default: single-select).
|
|
63
|
+
|
|
64
|
+
### Interaction pattern
|
|
65
|
+
|
|
66
|
+
Expanding/collapsing and selecting are independent, fixed interactions (not prop-configurable):
|
|
67
|
+
|
|
68
|
+
- Clicking the expand/collapse chevron toggles that node's subtree only — it never selects.
|
|
69
|
+
- Clicking anywhere else on a row selects it — it never toggles expansion.
|
|
70
|
+
- `Enter`/`Space` on a focused node selects it, even if the node has children.
|
|
71
|
+
- `ArrowLeft`/`ArrowRight` expand/collapse the focused node only, without changing selection.
|
|
72
|
+
- `ArrowUp`/`ArrowDown` move focus between rows.
|
|
73
|
+
|
|
74
|
+
### Disabled
|
|
75
|
+
|
|
76
|
+
```tsx
|
|
77
|
+
<Tree data={data} initialSelectedValues={["1.1"]} disabled />
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
`disabled` disables the whole tree — no expand/collapse or select via click or keyboard, dimmed to the standard disabled opacity. A pre-selected node stays visibly selected, just dimmed along with the rest. There's no per-node disabled state (see **Known Constraints** below).
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## 4. Design System Integration
|
|
85
|
+
|
|
86
|
+
All Recursica components in the `@recursica/adapter-mui-v7` package adhere strictly to design system spacing, scaling, and behavior patterns.
|
|
87
|
+
|
|
88
|
+
> [!IMPORTANT]
|
|
89
|
+
>
|
|
90
|
+
> - **Anti-override protection**: Rogue style injections (like inline `style` or arbitrary `className`) are automatically blocked by our prop layer unless `overStyled={true}` is explicitly provided.
|
|
91
|
+
> - **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.
|
|
92
|
+
> - **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.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## 5. Known Constraints
|
|
97
|
+
|
|
98
|
+
- No checkbox/multi-check styling is exposed — `@mui/x-tree-view` supports checkbox selection, but Recursica's `tree` design tokens don't yet define a checked visual state, so it isn't part of the Recursica API.
|
|
99
|
+
- No per-node `disabled` state — the Figma UI Kit tokens don't define one, and `RecursicaTreeNode` has no `disabled` field either.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./Tree";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Typography – Implementation Notes
|
|
2
|
+
|
|
3
|
+
`Typography` is the shared rendering base for both `Text` and `Heading` in adapter-mui-v7 — anything
|
|
4
|
+
applied here reaches both components.
|
|
5
|
+
|
|
6
|
+
## `.root` `text-wrap: balance` (Matt Massey, 2026-08-28)
|
|
7
|
+
|
|
8
|
+
**Decision:** Added `text-wrap: balance` via a new `Typography.module.css` `.root` class, merged
|
|
9
|
+
onto the typography class alongside the caller's own `className`. Since both `Text` and `Heading`
|
|
10
|
+
render through this component, it covers all `order` heading levels (h1–h6) and paragraph text in
|
|
11
|
+
one place.
|
|
12
|
+
|
|
13
|
+
**Implementation:** UX asked for more evenly balanced multi-line wrapping instead of a ragged last
|
|
14
|
+
line. Not a design token — it's a layout algorithm choice, so it's hardcoded rather than pulled
|
|
15
|
+
from `recursica_variables_scoped.css`. Most effective on short text (headings); Chromium/Firefox
|
|
16
|
+
only balance up to ~6 lines, so long paragraphs silently fall back to normal wrapping past that
|
|
17
|
+
point. No fallback needed — browsers that don't support the value just ignore the declaration.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* HARDCODED VALUES
|
|
3
|
+
* - `.root` `text-wrap: balance` — not a design token; a layout algorithm choice requested by
|
|
4
|
+
* UX (Matt Massey, 2026-08-28) to even out wrapped line lengths. See TEXT_IMPLEMENTATION_NOTES.md.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
.root {
|
|
8
|
+
/* HARDCODE: balances wrapped line lengths instead of leaving a ragged short last line. Most
|
|
9
|
+
effective on short text; browsers cap balancing at ~6 lines, so long paragraphs silently
|
|
10
|
+
fall back to normal wrapping past that point — no fallback needed, unsupported browsers
|
|
11
|
+
just ignore the declaration. */
|
|
12
|
+
text-wrap: balance;
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Placeholder for future Typography component tests. Add tests here if/when needed.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React, { forwardRef } from "react";
|
|
2
|
+
import {
|
|
3
|
+
Typography as MuiTypography,
|
|
4
|
+
type TypographyProps as MuiTypographyProps,
|
|
5
|
+
} from "@mui/material";
|
|
6
|
+
import {
|
|
7
|
+
filterStylingProps,
|
|
8
|
+
type RecursicaOverStyled,
|
|
9
|
+
} from "../../utils/filterStylingProps";
|
|
10
|
+
import styles from "./Typography.module.css";
|
|
11
|
+
|
|
12
|
+
export type TypographyProps = RecursicaOverStyled<
|
|
13
|
+
Omit<MuiTypographyProps, "variant"> & {
|
|
14
|
+
/**
|
|
15
|
+
* Internal typography class mapping
|
|
16
|
+
*/
|
|
17
|
+
typographyClass: string;
|
|
18
|
+
component?: React.ElementType;
|
|
19
|
+
}
|
|
20
|
+
>;
|
|
21
|
+
|
|
22
|
+
export const Typography = forwardRef<HTMLElement, TypographyProps>(
|
|
23
|
+
function Typography({ typographyClass, overStyled = false, ...rest }, ref) {
|
|
24
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
25
|
+
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
26
|
+
|
|
27
|
+
const classNameProp = restRecord.className as string | undefined;
|
|
28
|
+
const finalClass = [typographyClass, styles.root, classNameProp]
|
|
29
|
+
.filter(Boolean)
|
|
30
|
+
.join(" ");
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<MuiTypography
|
|
34
|
+
ref={ref}
|
|
35
|
+
className={finalClass}
|
|
36
|
+
variant="inherit"
|
|
37
|
+
{...sanitizedProps}
|
|
38
|
+
/>
|
|
39
|
+
);
|
|
40
|
+
},
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
Typography.displayName = "Typography";
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Typography - Usage Guide
|
|
2
|
+
|
|
3
|
+
This document describes how to integrate and use the `Typography` component in your projects using `@recursica/adapter-mui-v7`.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Import Reference
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { Typography } from "@recursica/adapter-mui-v7";
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 2. Basic Example
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import React from "react";
|
|
19
|
+
import { Typography } from "@recursica/adapter-mui-v7";
|
|
20
|
+
|
|
21
|
+
export default function Demo() {
|
|
22
|
+
return (
|
|
23
|
+
<Typography variant="body1">
|
|
24
|
+
Typography is used for presenting textual content cleanly.
|
|
25
|
+
</Typography>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 3. Design System Integration
|
|
33
|
+
|
|
34
|
+
All Recursica components in the `@recursica/adapter-mui-v7` 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.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./Typography";
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export * from "./Accordion";
|
|
2
|
+
export * from "./AssistiveElement";
|
|
3
|
+
export * from "./AutoComplete";
|
|
4
|
+
export * from "./Avatar";
|
|
5
|
+
export * from "./Badge";
|
|
6
|
+
export * from "./Breadcrumb";
|
|
7
|
+
export * from "./Button";
|
|
8
|
+
export * from "./Card";
|
|
9
|
+
export * from "./Checkbox";
|
|
10
|
+
export * from "./Chip";
|
|
11
|
+
export * from "./Container";
|
|
12
|
+
export * from "./DatePicker";
|
|
13
|
+
export * from "./Dropdown";
|
|
14
|
+
export * from "./FileInput";
|
|
15
|
+
export * from "./FileUpload";
|
|
16
|
+
export * from "./Flex";
|
|
17
|
+
export * from "./FormControlLayout";
|
|
18
|
+
export * from "./FormControlWrapper";
|
|
19
|
+
export * from "./Grid";
|
|
20
|
+
export * from "./Group";
|
|
21
|
+
export * from "./Heading";
|
|
22
|
+
export * from "./HoverCard";
|
|
23
|
+
export * from "./Label";
|
|
24
|
+
export * from "./Link";
|
|
25
|
+
export * from "./Loader";
|
|
26
|
+
export * from "./Menu";
|
|
27
|
+
export * from "./Modal";
|
|
28
|
+
export * from "./NumberInput";
|
|
29
|
+
export * from "./Pagination";
|
|
30
|
+
export * from "./Panel";
|
|
31
|
+
export * from "./Popover";
|
|
32
|
+
export * from "./Radio";
|
|
33
|
+
export * from "./ReadOnlyField";
|
|
34
|
+
export * from "./SegmentedControl";
|
|
35
|
+
export * from "./Slider";
|
|
36
|
+
export * from "./Stack";
|
|
37
|
+
export * from "./Stepper";
|
|
38
|
+
export * from "./Switch";
|
|
39
|
+
export * from "./Table";
|
|
40
|
+
export * from "./Tabs";
|
|
41
|
+
export * from "./Text";
|
|
42
|
+
export * from "./TextArea";
|
|
43
|
+
export * from "./TextField";
|
|
44
|
+
export * from "./TimePicker";
|
|
45
|
+
export * from "./Timeline";
|
|
46
|
+
export * from "./Toast";
|
|
47
|
+
export * from "./Tooltip";
|
|
48
|
+
export * from "./TransferList";
|
|
49
|
+
export * from "./Typography";
|
|
50
|
+
export * from "./Tree";
|