@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,115 @@
|
|
|
1
|
+
/* HARDCODED VALUES:
|
|
2
|
+
- border-style: solid (needs a token if we support other border styles)
|
|
3
|
+
- box-sizing: border-box
|
|
4
|
+
- display: inline-flex
|
|
5
|
+
- align-items: center
|
|
6
|
+
- justify-content: center
|
|
7
|
+
- text-transform: uppercase (Mantine does this, but our tokens also specify it so we map it)
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
.root {
|
|
11
|
+
/* HARDCODE: Basic structural assumptions */
|
|
12
|
+
box-sizing: border-box;
|
|
13
|
+
display: inline-flex;
|
|
14
|
+
align-items: center;
|
|
15
|
+
justify-content: center;
|
|
16
|
+
border-style: solid;
|
|
17
|
+
|
|
18
|
+
/* Base style resets to fully clear Mantine's defaults before applying ours */
|
|
19
|
+
background-color: transparent;
|
|
20
|
+
color: inherit;
|
|
21
|
+
border-color: transparent;
|
|
22
|
+
|
|
23
|
+
/* Apply global badge properties */
|
|
24
|
+
border-radius: var(
|
|
25
|
+
--recursica_ui-kit_components_badge_properties_border-radius
|
|
26
|
+
);
|
|
27
|
+
border-width: var(--recursica_ui-kit_components_badge_properties_border-size);
|
|
28
|
+
box-shadow: var(--recursica_ui-kit_components_badge_properties_elevation);
|
|
29
|
+
|
|
30
|
+
padding-left: var(
|
|
31
|
+
--recursica_ui-kit_components_badge_properties_padding-horizontal
|
|
32
|
+
);
|
|
33
|
+
padding-right: var(
|
|
34
|
+
--recursica_ui-kit_components_badge_properties_padding-horizontal
|
|
35
|
+
);
|
|
36
|
+
padding-top: var(
|
|
37
|
+
--recursica_ui-kit_components_badge_properties_padding-vertical
|
|
38
|
+
);
|
|
39
|
+
padding-bottom: var(
|
|
40
|
+
--recursica_ui-kit_components_badge_properties_padding-vertical
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
font-family: var(
|
|
44
|
+
--recursica_ui-kit_components_badge_properties_text_font-family
|
|
45
|
+
);
|
|
46
|
+
font-size: var(--recursica_ui-kit_components_badge_properties_text_font-size);
|
|
47
|
+
font-weight: var(
|
|
48
|
+
--recursica_ui-kit_components_badge_properties_text_font-weight
|
|
49
|
+
);
|
|
50
|
+
font-style: var(
|
|
51
|
+
--recursica_ui-kit_components_badge_properties_text_font-style
|
|
52
|
+
);
|
|
53
|
+
letter-spacing: var(
|
|
54
|
+
--recursica_ui-kit_components_badge_properties_text_letter-spacing
|
|
55
|
+
);
|
|
56
|
+
line-height: var(
|
|
57
|
+
--recursica_ui-kit_components_badge_properties_text_line-height
|
|
58
|
+
);
|
|
59
|
+
text-decoration: var(
|
|
60
|
+
--recursica_ui-kit_components_badge_properties_text_text-decoration
|
|
61
|
+
);
|
|
62
|
+
text-transform: var(
|
|
63
|
+
--recursica_ui-kit_components_badge_properties_text_text-transform
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* Variant Definitions */
|
|
68
|
+
|
|
69
|
+
.root[data-variant="alert"] {
|
|
70
|
+
background-color: var(
|
|
71
|
+
--recursica_ui-kit_components_badge_variants_styles_alert_properties_colors_background-color
|
|
72
|
+
);
|
|
73
|
+
border-color: var(
|
|
74
|
+
--recursica_ui-kit_components_badge_variants_styles_alert_properties_colors_border-color
|
|
75
|
+
);
|
|
76
|
+
color: var(
|
|
77
|
+
--recursica_ui-kit_components_badge_variants_styles_alert_properties_colors_text-color
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.root[data-variant="primary-color"] {
|
|
82
|
+
background-color: var(
|
|
83
|
+
--recursica_ui-kit_components_badge_variants_styles_primary-color_properties_colors_background-color
|
|
84
|
+
);
|
|
85
|
+
border-color: var(
|
|
86
|
+
--recursica_ui-kit_components_badge_variants_styles_primary-color_properties_colors_border-color
|
|
87
|
+
);
|
|
88
|
+
color: var(
|
|
89
|
+
--recursica_ui-kit_components_badge_variants_styles_primary-color_properties_colors_text-color
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.root[data-variant="success"] {
|
|
94
|
+
background-color: var(
|
|
95
|
+
--recursica_ui-kit_components_badge_variants_styles_success_properties_colors_background-color
|
|
96
|
+
);
|
|
97
|
+
border-color: var(
|
|
98
|
+
--recursica_ui-kit_components_badge_variants_styles_success_properties_colors_border-color
|
|
99
|
+
);
|
|
100
|
+
color: var(
|
|
101
|
+
--recursica_ui-kit_components_badge_variants_styles_success_properties_colors_text-color
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.root[data-variant="warning"] {
|
|
106
|
+
background-color: var(
|
|
107
|
+
--recursica_ui-kit_components_badge_variants_styles_warning_properties_colors_background-color
|
|
108
|
+
);
|
|
109
|
+
border-color: var(
|
|
110
|
+
--recursica_ui-kit_components_badge_variants_styles_warning_properties_colors_border-color
|
|
111
|
+
);
|
|
112
|
+
color: var(
|
|
113
|
+
--recursica_ui-kit_components_badge_variants_styles_warning_properties_colors_text-color
|
|
114
|
+
);
|
|
115
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
|
+
import { Badge } from "./Badge";
|
|
4
|
+
import { Layer } from "@recursica/adapter-common";
|
|
5
|
+
|
|
6
|
+
type BadgeStoryProps = React.ComponentProps<typeof Badge>;
|
|
7
|
+
|
|
8
|
+
const meta: Meta<BadgeStoryProps> = {
|
|
9
|
+
title: "UI-Kit/Badge",
|
|
10
|
+
component: Badge,
|
|
11
|
+
tags: ["autodocs"],
|
|
12
|
+
argTypes: {
|
|
13
|
+
variant: {
|
|
14
|
+
control: "select",
|
|
15
|
+
options: ["alert", "primary-color", "success", "warning"],
|
|
16
|
+
description: "The style / intent mapping for the badge",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default meta;
|
|
22
|
+
|
|
23
|
+
type Story = StoryObj<BadgeStoryProps>;
|
|
24
|
+
|
|
25
|
+
export const Default: Story = {
|
|
26
|
+
args: {
|
|
27
|
+
children: "Badge Label",
|
|
28
|
+
variant: "primary-color",
|
|
29
|
+
},
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
31
|
+
render: ({ withLayer, layer, ...args }: any) => {
|
|
32
|
+
return <Badge {...args} />;
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const StaticAlert: Story = {
|
|
37
|
+
args: {
|
|
38
|
+
children: "Alert Badge",
|
|
39
|
+
variant: "alert",
|
|
40
|
+
},
|
|
41
|
+
render: (args: BadgeStoryProps) => <Badge {...args} />,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const StaticPrimary: Story = {
|
|
45
|
+
args: {
|
|
46
|
+
children: "Primary Badge",
|
|
47
|
+
variant: "primary-color",
|
|
48
|
+
},
|
|
49
|
+
render: (args: BadgeStoryProps) => <Badge {...args} />,
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const StaticSuccess: Story = {
|
|
53
|
+
args: {
|
|
54
|
+
children: "Success Badge",
|
|
55
|
+
variant: "success",
|
|
56
|
+
},
|
|
57
|
+
render: (args: BadgeStoryProps) => <Badge {...args} />,
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const StaticWarning: Story = {
|
|
61
|
+
args: {
|
|
62
|
+
children: "Warning Badge",
|
|
63
|
+
variant: "warning",
|
|
64
|
+
},
|
|
65
|
+
render: (args: BadgeStoryProps) => <Badge {...args} />,
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const LayerOneAlert: Story = {
|
|
69
|
+
args: {
|
|
70
|
+
children: "Layer 1 Alert",
|
|
71
|
+
variant: "alert",
|
|
72
|
+
},
|
|
73
|
+
render: (args: BadgeStoryProps) => (
|
|
74
|
+
<Layer layer={1} style={{ padding: "24px" }}>
|
|
75
|
+
<Badge {...args} />
|
|
76
|
+
</Layer>
|
|
77
|
+
),
|
|
78
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Placeholder for future Badge component tests. Add tests here if/when needed.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { forwardRef } from "react";
|
|
2
|
+
import {
|
|
3
|
+
Badge as MuiBadge,
|
|
4
|
+
type BadgeProps as MuiBadgeProps,
|
|
5
|
+
} from "@mui/material";
|
|
6
|
+
import {
|
|
7
|
+
filterStylingProps,
|
|
8
|
+
mergeClassNames,
|
|
9
|
+
type RecursicaOverStyled,
|
|
10
|
+
} from "../../utils/filterStylingProps";
|
|
11
|
+
import styles from "./Badge.module.css";
|
|
12
|
+
|
|
13
|
+
import { type RecursicaBadgeProps } from "@recursica/adapter-common";
|
|
14
|
+
|
|
15
|
+
export type BadgeProps = RecursicaOverStyled<
|
|
16
|
+
Omit<MuiBadgeProps, "variant" | "size" | "color" | "radius"> &
|
|
17
|
+
RecursicaBadgeProps
|
|
18
|
+
>;
|
|
19
|
+
|
|
20
|
+
const _Badge = forwardRef<HTMLDivElement, BadgeProps>(function Badge(
|
|
21
|
+
{ variant = "primary-color", overStyled = false, ...rest },
|
|
22
|
+
ref,
|
|
23
|
+
) {
|
|
24
|
+
// Strip all visual override injections unless developer has specifically opted into overStyling.
|
|
25
|
+
// External layout props like margins are safely preserved.
|
|
26
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
27
|
+
|
|
28
|
+
// Note MUI's actual prop is "classes", not "classNames" (that's Mantine's naming) — this
|
|
29
|
+
// used to read the wrong key, silently no-op-ing any caller-supplied classes.
|
|
30
|
+
const mergedClassNames = mergeClassNames(
|
|
31
|
+
{ root: styles.root },
|
|
32
|
+
(sanitizedProps as Record<string, unknown>).classes as
|
|
33
|
+
| Partial<Record<string, string>>
|
|
34
|
+
| undefined,
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const classNameProp = (sanitizedProps as Record<string, unknown>)
|
|
38
|
+
.className as string | undefined;
|
|
39
|
+
const finalClass = classNameProp
|
|
40
|
+
? `${styles.root} ${classNameProp}`
|
|
41
|
+
: styles.root;
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<MuiBadge
|
|
45
|
+
ref={ref}
|
|
46
|
+
variant="standard" // We manage visual style purely through our CSS variables mapping
|
|
47
|
+
data-variant={variant}
|
|
48
|
+
{...sanitizedProps}
|
|
49
|
+
className={finalClass}
|
|
50
|
+
classes={mergedClassNames}
|
|
51
|
+
/>
|
|
52
|
+
);
|
|
53
|
+
});
|
|
54
|
+
_Badge.displayName = "Badge";
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Recursica Badge component wrapping Mui's Badge.
|
|
58
|
+
*
|
|
59
|
+
* Supports polymorphism via the `component` prop or `renderRoot` for custom element rendering.
|
|
60
|
+
*/
|
|
61
|
+
export const Badge = _Badge;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Badge - Usage Guide
|
|
2
|
+
|
|
3
|
+
This document describes how to integrate and use the `Badge` component in your projects using `@recursica/adapter-mui-v7`.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Import Reference
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { Badge } from "@recursica/adapter-mui-v7";
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 2. Basic Example
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import React from "react";
|
|
19
|
+
import { Badge } from "@recursica/adapter-mui-v7";
|
|
20
|
+
|
|
21
|
+
export default function Demo() {
|
|
22
|
+
return (
|
|
23
|
+
<Badge variant="filled" size="md">
|
|
24
|
+
Active
|
|
25
|
+
</Badge>
|
|
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 "./Badge";
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Breadcrumb Implementation Notes
|
|
2
|
+
|
|
3
|
+
## Missing Variants and Sizes
|
|
4
|
+
|
|
5
|
+
The `Breadcrumb` currently does not establish any size (`xs`, `sm`, etc.) or variant variables in the underlying design tokens (`recursica_ui-kit.json`). Only basic structural definitions for `padding` and `item-gap` exist. Because of this, the `size` and `variant` properties have been explicitly omitted from the passed MUI props.
|
|
6
|
+
|
|
7
|
+
## Gap Styling
|
|
8
|
+
|
|
9
|
+
MUI renders items/separators inside the `<ol>`, not directly under the `<nav>` root — `gap` lives on `.ol` in `.module.css` so it lands uniformly between item/separator/item, matching mantine-adapter.
|
|
10
|
+
|
|
11
|
+
## Composition and Separators
|
|
12
|
+
|
|
13
|
+
MUI natively accepts typical anchor tags as children, wrapping each in its own `<li>` internally — Breadcrumb.tsx doesn't add any structural spans of its own, allowing developers to utilize `Link` wrappers as needed contextually.
|
|
14
|
+
The separator character is inherited natively from MUI's default configuration (`/`) unless overridden by passing `separator={<Icon />}` to the component props.
|
|
15
|
+
|
|
16
|
+
## Current-page Crumb: Best-effort Enforcement, Not a Guarantee
|
|
17
|
+
|
|
18
|
+
**The last crumb should always be plain, non-interactive text — a `<span>`, not a `Link`.** It
|
|
19
|
+
represents the current page; per standard breadcrumb UX and the ARIA breadcrumb pattern, it
|
|
20
|
+
shouldn't be clickable. Passing a `Link` (or an anchor) for the last item is a misuse of the
|
|
21
|
+
component, even though `Breadcrumb.tsx` tries to correct for it — see below.
|
|
22
|
+
|
|
23
|
+
Breadcrumb intentionally keeps the flexible MUI `children`-as-anchors interface (unlike BEAM's
|
|
24
|
+
`Breadcrumb.Item`, which renders its own `Link` internally and can't accept a caller-supplied
|
|
25
|
+
router-aware Link or `onClick`). That flexibility means Breadcrumb.tsx can't fully own what the
|
|
26
|
+
last item renders as, so it does what it can via `markCurrentPageItem` (`@recursica/adapter-common`):
|
|
27
|
+
|
|
28
|
+
- Adds `aria-current="page"` to the last child, always.
|
|
29
|
+
- If that child looks interactive (has `href` or `onClick`), strips both and sets `tabIndex={-1}`.
|
|
30
|
+
- In dev, warns to the console when it had to strip anything — a signal the caller should switch
|
|
31
|
+
that item to plain text instead of relying on this fallback.
|
|
32
|
+
|
|
33
|
+
Backed up by a CSS rule targeting `[aria-current="page"]` (Breadcrumb.module.css) that resets
|
|
34
|
+
color/text-decoration and sets `pointer-events: none`, and sets `font-family`/`font-size` to Link's own tokens
|
|
35
|
+
(per product decision: the current item should typographically match Link, just without Link's
|
|
36
|
+
color/decoration/interactivity).
|
|
37
|
+
|
|
38
|
+
**Why this isn't a real guarantee:** `cloneElement` can only override props an element actually
|
|
39
|
+
reads. A custom Link component (e.g. React Router's `<Link to="...">`) that navigates from its own
|
|
40
|
+
internal handler, independent of a passed-through `onClick`, will still navigate — stripping
|
|
41
|
+
`onClick`/`href` here doesn't touch that internal logic, and `pointer-events: none` only blocks
|
|
42
|
+
mouse activation, not keyboard/Enter on a focusable custom element. Treat all of the above as a
|
|
43
|
+
safety net for the common case (plain anchors, our own `Link`), not a substitute for callers doing
|
|
44
|
+
the right thing and passing plain text for the last crumb.
|
|
45
|
+
|
|
46
|
+
The story's `items` convenience prop demonstrates the correct pattern: every crumb except the last
|
|
47
|
+
is wrapped in `Link`, and the last is a plain `<span>`.
|
|
48
|
+
|
|
49
|
+
This logic is shared with mantine-adapter — `markCurrentPageItem` lives once in
|
|
50
|
+
`@recursica/adapter-common` (`components/Breadcrumb/markCurrentPageItem.ts`) and is unit-tested
|
|
51
|
+
there via mantine-adapter's test suite (`markCurrentPageItem.test.ts`), not duplicated here.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/* HARDCODED VALUES:
|
|
2
|
+
- align-items: center
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
.root {
|
|
6
|
+
/* Base style resets */
|
|
7
|
+
background-color: transparent;
|
|
8
|
+
color: inherit;
|
|
9
|
+
|
|
10
|
+
/* Apply global breadcrumb properties */
|
|
11
|
+
padding: var(--recursica_ui-kit_components_breadcrumb_properties_padding);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/* MUI renders items/separators inside the <ol>, not directly under <nav> (.root) — the
|
|
15
|
+
gap must live here to land uniformly between item/separator/item, matching Mantine. */
|
|
16
|
+
.ol {
|
|
17
|
+
/* HARDCODE: Basic structural flex layout for breadcrumbs */
|
|
18
|
+
display: flex;
|
|
19
|
+
align-items: center;
|
|
20
|
+
|
|
21
|
+
gap: var(--recursica_ui-kit_components_breadcrumb_properties_item-gap);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.separator {
|
|
25
|
+
/* Separator base resets if needed */
|
|
26
|
+
display: flex;
|
|
27
|
+
align-items: center;
|
|
28
|
+
justify-content: center;
|
|
29
|
+
/* Neutralize MUI's built-in 8px marginLeft/marginRight so .ol's gap alone controls spacing */
|
|
30
|
+
margin: 0;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* Current-page item (last crumb): Breadcrumb.tsx (via markCurrentPageItem) marks it
|
|
34
|
+
aria-current="page". This is a style-layer backstop in case that item still renders as a Link
|
|
35
|
+
despite having its href/onClick stripped — see BREADCRUMB_IMPLEMENTATION_NOTES.md. Two classes'
|
|
36
|
+
worth of specificity beats Link's single .root color/text-decoration rule regardless of module
|
|
37
|
+
load order. pointer-events only blocks mouse activation, not a router Link's own internal
|
|
38
|
+
handler — the last crumb should really just be plain text. */
|
|
39
|
+
.ol [aria-current="page"] {
|
|
40
|
+
color: inherit;
|
|
41
|
+
text-decoration: none;
|
|
42
|
+
pointer-events: none;
|
|
43
|
+
|
|
44
|
+
/* Per product decision: the current-page item should match Link's font-family/size (it's
|
|
45
|
+
typically rendered as plain text, with no font styling of its own — otherwise it falls back
|
|
46
|
+
to MUI's default Typography font-size) but not any of Link's other styling. */
|
|
47
|
+
font-family: var(
|
|
48
|
+
--recursica_ui-kit_components_link_properties_text_font-family
|
|
49
|
+
);
|
|
50
|
+
font-size: var(--recursica_ui-kit_components_link_properties_text_font-size);
|
|
51
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
|
+
import { Breadcrumb } from "./Breadcrumb";
|
|
4
|
+
import { Link } from "../Link";
|
|
5
|
+
|
|
6
|
+
type BreadcrumbStoryProps = React.ComponentProps<typeof Breadcrumb> & {
|
|
7
|
+
items?: string[];
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const meta: Meta<BreadcrumbStoryProps> = {
|
|
11
|
+
title: "UI-Kit/Breadcrumb",
|
|
12
|
+
component: Breadcrumb,
|
|
13
|
+
tags: ["autodocs"],
|
|
14
|
+
parameters: {
|
|
15
|
+
docs: {
|
|
16
|
+
description: {
|
|
17
|
+
component:
|
|
18
|
+
"**Proper usage** (see `Default`): every crumb except the last is a `Link`; the last " +
|
|
19
|
+
"crumb — the current page — is plain text (e.g. a `<span>`), not a link. `Breadcrumb` " +
|
|
20
|
+
"does its best to neutralize a `Link` passed as the last item anyway (see " +
|
|
21
|
+
"`LastItemAsLink`), but that's a safety net, not something to rely on — see " +
|
|
22
|
+
"BREADCRUMB_IMPLEMENTATION_NOTES.md.",
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
argTypes: {
|
|
27
|
+
children: {
|
|
28
|
+
table: {
|
|
29
|
+
disable: true,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
items: {
|
|
33
|
+
control: "object",
|
|
34
|
+
description:
|
|
35
|
+
"Array of string labels used to dynamically generate the interactive Breadcrumb nodes.",
|
|
36
|
+
table: {
|
|
37
|
+
category: "Story Controls",
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
separator: {
|
|
41
|
+
control: "text",
|
|
42
|
+
description: "Custom separator between items",
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
args: {
|
|
46
|
+
items: ["Home", "Components", "Breadcrumbs"],
|
|
47
|
+
},
|
|
48
|
+
render: ({ items, children, ...args }) => {
|
|
49
|
+
const mappedChildren = items
|
|
50
|
+
? items.map((label, index) =>
|
|
51
|
+
// The last crumb represents the current page, so it's plain text,
|
|
52
|
+
// not a link — matches standard breadcrumb UX.
|
|
53
|
+
index === items.length - 1 ? (
|
|
54
|
+
<span key={index}>{label}</span>
|
|
55
|
+
) : (
|
|
56
|
+
<Link href="#" key={index}>
|
|
57
|
+
{label}
|
|
58
|
+
</Link>
|
|
59
|
+
),
|
|
60
|
+
)
|
|
61
|
+
: children;
|
|
62
|
+
|
|
63
|
+
return <Breadcrumb children={mappedChildren} {...args} />;
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export default meta;
|
|
68
|
+
|
|
69
|
+
type Story = StoryObj<BreadcrumbStoryProps>;
|
|
70
|
+
|
|
71
|
+
export const Default: Story = {
|
|
72
|
+
args: {
|
|
73
|
+
items: ["Dashboard", "Settings", "Security"],
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const CustomSeparator: Story = {
|
|
78
|
+
args: {
|
|
79
|
+
items: ["Root", "Branch", "Leaf"],
|
|
80
|
+
separator: "→",
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export const LastItemAsLink: Story = {
|
|
85
|
+
name: "Last Item As Link (Incorrect Usage)",
|
|
86
|
+
args: {
|
|
87
|
+
// Bypass the `items` convenience prop (which always renders the last crumb as a span) to
|
|
88
|
+
// demonstrate what happens if a caller wraps every crumb, including the last, in a `Link`.
|
|
89
|
+
items: undefined,
|
|
90
|
+
children: [
|
|
91
|
+
<Link href="#" key="dashboard">
|
|
92
|
+
Dashboard
|
|
93
|
+
</Link>,
|
|
94
|
+
<Link href="#" key="settings">
|
|
95
|
+
Settings
|
|
96
|
+
</Link>,
|
|
97
|
+
<Link href="#" key="security">
|
|
98
|
+
Security
|
|
99
|
+
</Link>,
|
|
100
|
+
],
|
|
101
|
+
},
|
|
102
|
+
parameters: {
|
|
103
|
+
docs: {
|
|
104
|
+
description: {
|
|
105
|
+
story:
|
|
106
|
+
"Incorrect usage, kept as a story to prove Breadcrumb still handles it: the last " +
|
|
107
|
+
'crumb is a `Link`, but Breadcrumb adds `aria-current="page"`, strips its `href`/' +
|
|
108
|
+
"`onClick`, drops it from the tab order, and the CSS reset removes Link's color/" +
|
|
109
|
+
"underline — it renders identically to `Default`'s plain-text current item. Don't " +
|
|
110
|
+
"rely on this; pass plain text for the last crumb instead.",
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Placeholder for future Breadcrumb component tests. Add tests here if/when needed.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { forwardRef } from "react";
|
|
2
|
+
import {
|
|
3
|
+
Breadcrumbs as MuiBreadcrumbs,
|
|
4
|
+
type BreadcrumbsProps as MuiBreadcrumbsProps,
|
|
5
|
+
} from "@mui/material";
|
|
6
|
+
import {
|
|
7
|
+
filterStylingProps,
|
|
8
|
+
mergeClassNames,
|
|
9
|
+
type RecursicaOverStyled,
|
|
10
|
+
} from "../../utils/filterStylingProps";
|
|
11
|
+
import styles from "./Breadcrumb.module.css";
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
markCurrentPageItem,
|
|
15
|
+
type RecursicaBreadcrumbProps,
|
|
16
|
+
} from "@recursica/adapter-common";
|
|
17
|
+
|
|
18
|
+
export type BreadcrumbProps = RecursicaOverStyled<
|
|
19
|
+
Omit<MuiBreadcrumbsProps, "variant" | "size"> & RecursicaBreadcrumbProps
|
|
20
|
+
>;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The last child should always be plain, non-interactive text (e.g. a `<span>`) — it represents
|
|
24
|
+
* the current page and shouldn't be a link. Breadcrumb tries to correct for a Link/anchor passed
|
|
25
|
+
* there anyway via `markCurrentPageItem` (aria-current, stripped href/onClick, CSS reset in
|
|
26
|
+
* Breadcrumb.module.css), but that's a best-effort safety net, not a guarantee — it can't stop a
|
|
27
|
+
* custom Link component (e.g. a router Link) that navigates from its own internal handler. See
|
|
28
|
+
* BREADCRUMB_IMPLEMENTATION_NOTES.md.
|
|
29
|
+
*/
|
|
30
|
+
export const Breadcrumb = forwardRef<HTMLDivElement, BreadcrumbProps>(
|
|
31
|
+
function Breadcrumb(
|
|
32
|
+
{ overStyled = false, separator = ">", children, ...rest },
|
|
33
|
+
ref,
|
|
34
|
+
) {
|
|
35
|
+
const sanitizedProps = filterStylingProps(
|
|
36
|
+
{ separator, children: markCurrentPageItem(children), ...rest },
|
|
37
|
+
overStyled,
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
// Note MUI's actual prop is "classes", not "classNames" (that's Mantine's naming) — this
|
|
41
|
+
// used to read the wrong key, silently no-op-ing any caller-supplied classes.
|
|
42
|
+
const mergedClassNames = mergeClassNames(
|
|
43
|
+
{
|
|
44
|
+
root: styles.root,
|
|
45
|
+
ol: styles.ol,
|
|
46
|
+
separator: styles.separator,
|
|
47
|
+
},
|
|
48
|
+
(sanitizedProps as Record<string, unknown>).classes as
|
|
49
|
+
| Partial<Record<string, string>>
|
|
50
|
+
| undefined,
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const classNameProp = (sanitizedProps as Record<string, unknown>)
|
|
54
|
+
.className as string | undefined;
|
|
55
|
+
const finalClass = classNameProp
|
|
56
|
+
? `${styles.root} ${classNameProp}`
|
|
57
|
+
: styles.root;
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<MuiBreadcrumbs
|
|
61
|
+
ref={ref}
|
|
62
|
+
{...(sanitizedProps as unknown as MuiBreadcrumbsProps)}
|
|
63
|
+
className={finalClass}
|
|
64
|
+
classes={mergedClassNames}
|
|
65
|
+
/>
|
|
66
|
+
);
|
|
67
|
+
},
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
Breadcrumb.displayName = "Breadcrumb";
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Breadcrumb - Usage Guide
|
|
2
|
+
|
|
3
|
+
This document describes how to integrate and use the `Breadcrumb` component in your projects using `@recursica/adapter-mui-v7`.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Import Reference
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { Breadcrumb } from "@recursica/adapter-mui-v7";
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 2. Basic Example
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import React from "react";
|
|
19
|
+
import { Breadcrumb } from "@recursica/adapter-mui-v7";
|
|
20
|
+
|
|
21
|
+
export default function Demo() {
|
|
22
|
+
return (
|
|
23
|
+
<Breadcrumb>
|
|
24
|
+
<Link href="/">Home</Link>
|
|
25
|
+
<Link href="/components">Components</Link>
|
|
26
|
+
<Text>Button</Text>
|
|
27
|
+
</Breadcrumb>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 3. Design System Integration
|
|
35
|
+
|
|
36
|
+
All Recursica components in the `@recursica/adapter-mui-v7` package adhere strictly to design system spacing, scaling, and behavior patterns.
|
|
37
|
+
|
|
38
|
+
> [!IMPORTANT]
|
|
39
|
+
>
|
|
40
|
+
> - **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.
|
|
41
|
+
> - **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.
|
|
42
|
+
> - **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 "./Breadcrumb";
|