@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,169 @@
|
|
|
1
|
+
.root {
|
|
2
|
+
/* Prevent default MUI absolute positioning logic */
|
|
3
|
+
position: relative;
|
|
4
|
+
transform: none;
|
|
5
|
+
pointer-events: auto;
|
|
6
|
+
white-space: normal;
|
|
7
|
+
|
|
8
|
+
/* Reset MUI structural overrides */
|
|
9
|
+
margin: 0;
|
|
10
|
+
padding: 0;
|
|
11
|
+
display: flex;
|
|
12
|
+
width: 100%;
|
|
13
|
+
|
|
14
|
+
/* Recursica Font Map */
|
|
15
|
+
font-family: var(
|
|
16
|
+
--recursica_ui-kit_components_label_properties_label-text_font-family
|
|
17
|
+
);
|
|
18
|
+
font-size: var(
|
|
19
|
+
--recursica_ui-kit_components_label_properties_label-text_font-size
|
|
20
|
+
);
|
|
21
|
+
font-style: var(
|
|
22
|
+
--recursica_ui-kit_components_label_properties_label-text_font-style
|
|
23
|
+
);
|
|
24
|
+
font-weight: var(
|
|
25
|
+
--recursica_ui-kit_components_label_properties_label-text_font-weight
|
|
26
|
+
);
|
|
27
|
+
letter-spacing: var(
|
|
28
|
+
--recursica_ui-kit_components_label_properties_label-text_letter-spacing
|
|
29
|
+
);
|
|
30
|
+
line-height: var(
|
|
31
|
+
--recursica_ui-kit_components_label_properties_label-text_line-height
|
|
32
|
+
);
|
|
33
|
+
text-decoration: var(
|
|
34
|
+
--recursica_ui-kit_components_label_properties_label-text_text-decoration
|
|
35
|
+
);
|
|
36
|
+
text-transform: var(
|
|
37
|
+
--recursica_ui-kit_components_label_properties_label-text_text-transform
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
color: var(--recursica_ui-kit_components_label_properties_colors_text-color);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.innerLayout {
|
|
44
|
+
display: flex;
|
|
45
|
+
flex-wrap: wrap;
|
|
46
|
+
align-items: center;
|
|
47
|
+
gap: var(
|
|
48
|
+
--recursica_ui-kit_components_label_properties_label-optional-text-gap
|
|
49
|
+
);
|
|
50
|
+
width: 100%;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.root[data-alignment="right"] .innerLayout {
|
|
54
|
+
justify-content: flex-end;
|
|
55
|
+
text-align: right;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.text {
|
|
59
|
+
/* Natively intercepts MUI asterisk rendering securely wrapping inline with typography */
|
|
60
|
+
display: inline;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.required {
|
|
64
|
+
/* Override the `.MuiInputLabel-asterisk` natively */
|
|
65
|
+
color: var(
|
|
66
|
+
--recursica_ui-kit_components_label_properties_colors_asterisk-color
|
|
67
|
+
);
|
|
68
|
+
margin-left: var(
|
|
69
|
+
--recursica_ui-kit_components_label_properties_required-indicator-gap
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.root :global(.MuiFormLabel-asterisk) {
|
|
74
|
+
display: none !important;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* MUI propagates .Mui-error to the label automatically on FormControl error.
|
|
78
|
+
We explicitly override this bleed to prevent the main label text from turning red,
|
|
79
|
+
while allowing the asterisk to take the error color! */
|
|
80
|
+
.root:global(.Mui-error) {
|
|
81
|
+
color: var(--recursica_ui-kit_components_label_properties_colors_text-color);
|
|
82
|
+
}
|
|
83
|
+
.root:global(.Mui-error) .required {
|
|
84
|
+
color: var(
|
|
85
|
+
--recursica_ui-kit_components_assistive-element_variants_types_error_properties_colors_text-color
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/* Same bleed, different trigger: MUI's FormControl propagates .Mui-focused to this label
|
|
90
|
+
whenever any descendant form control (e.g. a grouped Switch/Checkbox) receives focus,
|
|
91
|
+
turning the whole label MUI's primary blue via InputLabel's own default styling. No
|
|
92
|
+
Recursica design calls for a focus-reactive label color, so it's reset here — same fix as
|
|
93
|
+
the .Mui-error case above, just for the focused trigger instead of the error one. */
|
|
94
|
+
.root:global(.Mui-focused) {
|
|
95
|
+
color: var(--recursica_ui-kit_components_label_properties_colors_text-color);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.endNodes {
|
|
99
|
+
display: flex;
|
|
100
|
+
align-items: center;
|
|
101
|
+
gap: var(
|
|
102
|
+
--recursica_ui-kit_components_label_properties_label-optional-text-gap
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.optionalText {
|
|
107
|
+
/* Forces the optional text onto its own row below the label text/end nodes,
|
|
108
|
+
mirroring mantine-adapter's flex-basis: 100% wrap behavior. */
|
|
109
|
+
flex-basis: 100%;
|
|
110
|
+
color: inherit;
|
|
111
|
+
font-family: var(
|
|
112
|
+
--recursica_ui-kit_components_label_properties_optional-text_font-family
|
|
113
|
+
);
|
|
114
|
+
font-size: var(
|
|
115
|
+
--recursica_ui-kit_components_label_properties_optional-text_font-size
|
|
116
|
+
);
|
|
117
|
+
font-style: var(
|
|
118
|
+
--recursica_ui-kit_components_label_properties_optional-text_font-style
|
|
119
|
+
);
|
|
120
|
+
font-weight: var(
|
|
121
|
+
--recursica_ui-kit_components_label_properties_optional-text_font-weight
|
|
122
|
+
);
|
|
123
|
+
letter-spacing: var(
|
|
124
|
+
--recursica_ui-kit_components_label_properties_optional-text_letter-spacing
|
|
125
|
+
);
|
|
126
|
+
line-height: var(
|
|
127
|
+
--recursica_ui-kit_components_label_properties_optional-text_line-height
|
|
128
|
+
);
|
|
129
|
+
text-decoration: var(
|
|
130
|
+
--recursica_ui-kit_components_label_properties_optional-text_text-decoration
|
|
131
|
+
);
|
|
132
|
+
text-transform: var(
|
|
133
|
+
--recursica_ui-kit_components_label_properties_optional-text_text-transform
|
|
134
|
+
);
|
|
135
|
+
opacity: var(
|
|
136
|
+
--recursica_ui-kit_components_label_properties_optional-text-opacity
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.actionArea {
|
|
141
|
+
display: flex;
|
|
142
|
+
align-items: center;
|
|
143
|
+
margin-left: var(
|
|
144
|
+
--recursica_ui-kit_components_label_properties_edit-icon-gap
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.editIcon {
|
|
149
|
+
display: flex;
|
|
150
|
+
align-items: center;
|
|
151
|
+
justify-content: center;
|
|
152
|
+
cursor: pointer;
|
|
153
|
+
background: none;
|
|
154
|
+
border: none;
|
|
155
|
+
padding: 0;
|
|
156
|
+
margin-left: var(
|
|
157
|
+
--recursica_ui-kit_components_label_properties_edit-icon-gap
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
width: 16px;
|
|
161
|
+
height: 16px;
|
|
162
|
+
color: inherit;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.editIcon :global(svg) {
|
|
166
|
+
width: 100%;
|
|
167
|
+
height: 100%;
|
|
168
|
+
stroke-width: 2px;
|
|
169
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
|
+
import { Label } from "./Label";
|
|
4
|
+
import { Button } from "../Button/Button";
|
|
5
|
+
|
|
6
|
+
type LabelStoryProps = React.ComponentProps<typeof Label>;
|
|
7
|
+
|
|
8
|
+
const meta: Meta<LabelStoryProps> = {
|
|
9
|
+
title: "UI-Kit/Label",
|
|
10
|
+
component: Label,
|
|
11
|
+
tags: ["autodocs"],
|
|
12
|
+
parameters: {
|
|
13
|
+
docs: {
|
|
14
|
+
description: {
|
|
15
|
+
component:
|
|
16
|
+
"The `Label` component is a strict Recursica-styled wrapper around Mantine's native `Input.Label`. It serves as the primary compositional primitive for all form fields, preserving Mantine's accessibility associations and context while strictly enforcing the Recursica atomic design system.\n\n### Usage with Form Inputs\nThis component only renders the label itself — layout concerns like `stacked` vs `side-by-side` positioning relative to an input live on `FormControlLayout`/`FormControlWrapper`, not here. Render this `Label` in isolation to verify its own states, or see `UI-Kit/FormControlLayout` for how it composes into a full form field.",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
argTypes: {
|
|
21
|
+
labelSize: {
|
|
22
|
+
control: "inline-radio",
|
|
23
|
+
options: ["default", "small"],
|
|
24
|
+
description:
|
|
25
|
+
"Sizing metrics for the Label. Only visually distinguishable once composed inside a `side-by-side` FormControlLayout, which is where the resulting width constraint applies.",
|
|
26
|
+
},
|
|
27
|
+
labelAlignment: {
|
|
28
|
+
control: "inline-radio",
|
|
29
|
+
options: ["left", "right"],
|
|
30
|
+
description: "Text alignment of the label content.",
|
|
31
|
+
},
|
|
32
|
+
required: {
|
|
33
|
+
control: "boolean",
|
|
34
|
+
description:
|
|
35
|
+
"Renders the required asterisk (suppressed automatically when `labelWithEditIcon` is set, and mutually exclusive with `labelOptionalText`).",
|
|
36
|
+
},
|
|
37
|
+
labelOptionalText: {
|
|
38
|
+
control: "text",
|
|
39
|
+
description:
|
|
40
|
+
"Secondary text rendered beneath the label. Pass `true` for the default '(Optional)' string, or a custom node/string. Suppressed when `required` is true.",
|
|
41
|
+
},
|
|
42
|
+
labelWithEditIcon: {
|
|
43
|
+
control: "boolean",
|
|
44
|
+
description:
|
|
45
|
+
"Replaces the default edit icon slot with an interactive edit affordance; replaces the required asterisk visually when both are set.",
|
|
46
|
+
},
|
|
47
|
+
labelActionArea: {
|
|
48
|
+
table: { disable: true },
|
|
49
|
+
},
|
|
50
|
+
onLabelEditClick: {
|
|
51
|
+
table: { disable: true },
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export default meta;
|
|
57
|
+
|
|
58
|
+
type Story = StoryObj<LabelStoryProps>;
|
|
59
|
+
|
|
60
|
+
export const Default: Story = {
|
|
61
|
+
args: {
|
|
62
|
+
children: "Label",
|
|
63
|
+
labelSize: "default",
|
|
64
|
+
labelAlignment: "left",
|
|
65
|
+
required: false,
|
|
66
|
+
labelOptionalText: "",
|
|
67
|
+
labelWithEditIcon: false,
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export const Required: Story = {
|
|
72
|
+
args: {
|
|
73
|
+
children: "Required Field",
|
|
74
|
+
required: true,
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export const RequiredSuppressesOptionalText: Story = {
|
|
79
|
+
args: {
|
|
80
|
+
children: "Full Name",
|
|
81
|
+
required: true,
|
|
82
|
+
labelOptionalText: "This should not render",
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export const WithOptionalText: Story = {
|
|
87
|
+
args: {
|
|
88
|
+
children: "Bio",
|
|
89
|
+
labelOptionalText: "Max 100 characters",
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export const BooleanOptionalText: Story = {
|
|
94
|
+
args: {
|
|
95
|
+
children: "Middle Initial",
|
|
96
|
+
labelOptionalText: true,
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export const WithEditIcon: Story = {
|
|
101
|
+
args: {
|
|
102
|
+
children: "Shipping Address",
|
|
103
|
+
labelWithEditIcon: true,
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export const RequiredWithEditIcon: Story = {
|
|
108
|
+
args: {
|
|
109
|
+
children: "Primary Network Node",
|
|
110
|
+
required: true,
|
|
111
|
+
labelWithEditIcon: true,
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export const RightAligned: Story = {
|
|
116
|
+
args: {
|
|
117
|
+
children: "Status",
|
|
118
|
+
labelAlignment: "right",
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
export const WithActionArea: Story = {
|
|
123
|
+
args: {
|
|
124
|
+
children: "Configuration",
|
|
125
|
+
labelActionArea: (
|
|
126
|
+
<Button variant="text" size="small">
|
|
127
|
+
Edit
|
|
128
|
+
</Button>
|
|
129
|
+
),
|
|
130
|
+
},
|
|
131
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Placeholder for future Label component tests. Add tests here if/when needed.
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { InputLabel, type InputLabelProps } from "@mui/material";
|
|
3
|
+
import { filterStylingProps } from "../../utils/filterStylingProps";
|
|
4
|
+
import styles from "./Label.module.css";
|
|
5
|
+
|
|
6
|
+
import { type RecursicaLabelProps } from "@recursica/adapter-common";
|
|
7
|
+
|
|
8
|
+
export interface LabelProps extends InputLabelProps, RecursicaLabelProps {
|
|
9
|
+
overStyled?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const Label = React.forwardRef<HTMLLabelElement, LabelProps>(
|
|
13
|
+
function Label(props, ref) {
|
|
14
|
+
const {
|
|
15
|
+
overStyled = false,
|
|
16
|
+
required = false,
|
|
17
|
+
labelAlignment,
|
|
18
|
+
labelOptionalText = "",
|
|
19
|
+
labelWithEditIcon = false,
|
|
20
|
+
onLabelEditClick,
|
|
21
|
+
labelActionArea,
|
|
22
|
+
children,
|
|
23
|
+
className,
|
|
24
|
+
...rest
|
|
25
|
+
} = props;
|
|
26
|
+
|
|
27
|
+
const resolvedAlignment = labelAlignment || "left";
|
|
28
|
+
|
|
29
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
30
|
+
|
|
31
|
+
const PenIcon = () => (
|
|
32
|
+
<svg
|
|
33
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
34
|
+
width="24"
|
|
35
|
+
height="24"
|
|
36
|
+
viewBox="0 0 24 24"
|
|
37
|
+
fill="none"
|
|
38
|
+
stroke="currentColor"
|
|
39
|
+
strokeWidth="2"
|
|
40
|
+
strokeLinecap="round"
|
|
41
|
+
strokeLinejoin="round"
|
|
42
|
+
>
|
|
43
|
+
<path d="M12 20h9"></path>
|
|
44
|
+
<path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"></path>
|
|
45
|
+
</svg>
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
// Bypassing MUI's floating functionality by forcing shrink=true to static inline positioning.
|
|
49
|
+
return (
|
|
50
|
+
<InputLabel
|
|
51
|
+
ref={ref}
|
|
52
|
+
{...(sanitizedProps as InputLabelProps)}
|
|
53
|
+
shrink={true}
|
|
54
|
+
data-alignment={resolvedAlignment}
|
|
55
|
+
className={className ? `${styles.root} ${className}` : styles.root}
|
|
56
|
+
>
|
|
57
|
+
<div className={styles.innerLayout}>
|
|
58
|
+
<span className={styles.textWrapper}>
|
|
59
|
+
<span className={styles.text}>{children}</span>
|
|
60
|
+
{required && <span className={styles.required}> *</span>}
|
|
61
|
+
</span>
|
|
62
|
+
|
|
63
|
+
<div className={styles.endNodes}>
|
|
64
|
+
{labelActionArea && (
|
|
65
|
+
<span className={styles.actionArea}>{labelActionArea}</span>
|
|
66
|
+
)}
|
|
67
|
+
{labelWithEditIcon && (
|
|
68
|
+
<button
|
|
69
|
+
type="button"
|
|
70
|
+
className={styles.editIcon}
|
|
71
|
+
onClick={onLabelEditClick}
|
|
72
|
+
aria-label="Edit label"
|
|
73
|
+
>
|
|
74
|
+
<PenIcon />
|
|
75
|
+
</button>
|
|
76
|
+
)}
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
{!required && labelOptionalText && !labelActionArea && (
|
|
80
|
+
<span className={styles.optionalText}>
|
|
81
|
+
{(() => {
|
|
82
|
+
const resolved =
|
|
83
|
+
labelOptionalText === true ? "optional" : labelOptionalText;
|
|
84
|
+
return typeof resolved === "string"
|
|
85
|
+
? `(${resolved})`
|
|
86
|
+
: resolved;
|
|
87
|
+
})()}
|
|
88
|
+
</span>
|
|
89
|
+
)}
|
|
90
|
+
</div>
|
|
91
|
+
</InputLabel>
|
|
92
|
+
);
|
|
93
|
+
},
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
Label.displayName = "Label";
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Label - Usage Guide
|
|
2
|
+
|
|
3
|
+
This document describes how to integrate and use the `Label` component in your projects using `@recursica/adapter-mui-v7`.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Import Reference
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { Label } from "@recursica/adapter-mui-v7";
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 2. Basic Example
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import React from "react";
|
|
19
|
+
import { Label } from "@recursica/adapter-mui-v7";
|
|
20
|
+
|
|
21
|
+
export default function Demo() {
|
|
22
|
+
return <Label required>Field Label</Label>;
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 3. Design System Integration
|
|
29
|
+
|
|
30
|
+
All Recursica components in the `@recursica/adapter-mui-v7` package adhere strictly to design system spacing, scaling, and behavior patterns.
|
|
31
|
+
|
|
32
|
+
> [!IMPORTANT]
|
|
33
|
+
>
|
|
34
|
+
> - **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.
|
|
35
|
+
> - **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.
|
|
36
|
+
> - **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 "./Label";
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Layer - Usage Guide
|
|
2
|
+
|
|
3
|
+
This document describes how to integrate and use the `Layer` component in your projects using `@recursica/adapter-mui-v7`.
|
|
4
|
+
|
|
5
|
+
> [!NOTE] > `Layer` is defined once in `@recursica/adapter-common` and re-exported here so it shares the exact same behavior across every Recursica adapter.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. Import Reference
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
import { Layer } from "@recursica/adapter-mui-v7";
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 2. Basic Example
|
|
18
|
+
|
|
19
|
+
`Layer` sets `data-recursica-layer` on its root element, which is what makes the theme+layer scoped CSS variables (surface color, border, elevation, padding) in `recursica_variables_scoped.css` actually apply. [`RecursicaThemeProvider`](../RecursicaThemeProvider/USAGE.md) automatically wraps your app in a `layer={0}` `Layer` by default (via its `initLayer0` prop), so you don't need to add one yourself for the base page. You still add `Layer`s manually for anything visually elevated above the page background:
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { RecursicaThemeProvider, Layer, Card } from "@recursica/adapter-mui-v7";
|
|
23
|
+
|
|
24
|
+
function App() {
|
|
25
|
+
return (
|
|
26
|
+
<RecursicaThemeProvider theme="light">
|
|
27
|
+
{/* Page background/surface already uses layer 0, applied automatically */}
|
|
28
|
+
<Layer layer={1}>
|
|
29
|
+
<Card>Elevated content sits on layer 1</Card>
|
|
30
|
+
</Layer>
|
|
31
|
+
</RecursicaThemeProvider>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 3. Design System Integration
|
|
39
|
+
|
|
40
|
+
> [!IMPORTANT]
|
|
41
|
+
>
|
|
42
|
+
> - **Layer 0 is automatic**: `RecursicaThemeProvider` applies it for you by default. Only opt out (`initLayer0={false}`) if you need to control exactly where layer 0 starts in the tree, or need `contentsOnly` on the base layer — see [RecursicaThemeProvider usage](../RecursicaThemeProvider/USAGE.md).
|
|
43
|
+
> - **Layers 1–3 are manual**: Wrap any content that's visually elevated above the page background (a Card, Modal, Popover, etc.) in its own `<Layer layer={1|2|3}>`. Nesting `Layer`s is how Recursica communicates elevation to descendant components — do **not** pass a `layer` prop directly to other components; wrap them in a `Layer` instead (every other component's `USAGE.md` repeats this rule).
|
|
44
|
+
> - **`contentsOnly`**: When `true`, `Layer` renders with `display: contents` and omits `data-recursica-layer` entirely — use this when you need a layer boundary in your component tree without adding an extra DOM box or applying layer styling (e.g. a purely structural wrapper).
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 4. Key Integration Features & Constraints
|
|
49
|
+
|
|
50
|
+
`Layer` has no visual variants of its own — its entire purpose is to bind a subtree to a numbered layer's design tokens. It does not accept `overStyled`; instead, if you find yourself needing to override a layer's surface styling, that's a signal you may want a different layer number rather than an escape hatch.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Link Component Implementation Notes
|
|
2
|
+
|
|
3
|
+
## Focus State
|
|
4
|
+
|
|
5
|
+
There's no per-component `focus` token for Link in the design tokens. Like every other
|
|
6
|
+
interactive component (see Button), `.root:focus-visible` in `Link.module.css` replaces the
|
|
7
|
+
native browser focus outline with the global `--recursica_brand_states_focus_*` ring instead of
|
|
8
|
+
leaving it to the browser default. This was previously missing here — Link (and anything composing
|
|
9
|
+
it, e.g. Breadcrumb) fell back to the browser's native focus outline instead of Recursica's.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/* Brand-layer exemptions (recursica-allow-brand) — see recursica-token-analyzer README.md.
|
|
2
|
+
* Only source for link hover-underline; no per-component token exists (see IMPLEMENTATION_NOTES.md).
|
|
3
|
+
* recursica-allow-brand: --recursica_brand_states_link_decoration
|
|
4
|
+
* Global focus-ring tokens (recursica_variables_scoped.css header, 'Hover & Focus states' —
|
|
5
|
+
* implicit rule for every interactive element; components must not define their own per-component
|
|
6
|
+
* treatment). Same pattern as Button.module.css.
|
|
7
|
+
* recursica-allow-brand: --recursica_brand_states_focus_blur
|
|
8
|
+
* recursica-allow-brand: --recursica_brand_states_focus_border-size
|
|
9
|
+
* recursica-allow-brand: --recursica_brand_states_focus_color
|
|
10
|
+
* recursica-allow-brand: --recursica_brand_states_focus_margin
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/*
|
|
14
|
+
HARDCODED VALUES:
|
|
15
|
+
- display: inline-flex; (Base layout to align icon and text correctly)
|
|
16
|
+
- align-items: center;
|
|
17
|
+
- cursor: pointer;
|
|
18
|
+
- text-decoration: none; (Overridden by our design tokens instead of using Mantine's underline prop)
|
|
19
|
+
- color: inherit; (Reset before applying token)
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
.root {
|
|
23
|
+
/* HARDCODE: base layout */
|
|
24
|
+
display: inline;
|
|
25
|
+
cursor: pointer;
|
|
26
|
+
|
|
27
|
+
/* HARDCODE: Reset underline and color so we can explicitly use our tokens */
|
|
28
|
+
text-decoration: none;
|
|
29
|
+
color: inherit;
|
|
30
|
+
|
|
31
|
+
/* Typography Tokens */
|
|
32
|
+
font-family: var(
|
|
33
|
+
--recursica_ui-kit_components_link_properties_text_font-family
|
|
34
|
+
);
|
|
35
|
+
font-size: var(--recursica_ui-kit_components_link_properties_text_font-size);
|
|
36
|
+
font-style: var(
|
|
37
|
+
--recursica_ui-kit_components_link_properties_text_font-style
|
|
38
|
+
);
|
|
39
|
+
font-weight: var(
|
|
40
|
+
--recursica_ui-kit_components_link_properties_text_font-weight
|
|
41
|
+
);
|
|
42
|
+
letter-spacing: var(
|
|
43
|
+
--recursica_ui-kit_components_link_properties_text_letter-spacing
|
|
44
|
+
);
|
|
45
|
+
line-height: var(
|
|
46
|
+
--recursica_ui-kit_components_link_properties_text_line-height
|
|
47
|
+
);
|
|
48
|
+
text-decoration: var(
|
|
49
|
+
--recursica_ui-kit_components_link_properties_text_text-decoration
|
|
50
|
+
);
|
|
51
|
+
color: var(--recursica_ui-kit_components_link_properties_colors_text-color);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.root[data-has-icon] {
|
|
55
|
+
display: inline-flex;
|
|
56
|
+
align-items: center;
|
|
57
|
+
gap: var(--recursica_ui-kit_components_link_properties_icon-text-gap);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.root:visited {
|
|
61
|
+
color: var(
|
|
62
|
+
--recursica_ui-kit_components_link_variants_states_visited_properties_colors_text-color
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.root:hover {
|
|
67
|
+
text-decoration: var(--recursica_brand_states_link_decoration);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* Focus State Mapping (native browser focus outline replaced with the recursica focus ring).
|
|
71
|
+
Was previously unset here, so Link (and anything using it, e.g. Breadcrumb) fell back to the
|
|
72
|
+
browser's native focus outline instead of the recursica ring. */
|
|
73
|
+
.root:focus-visible {
|
|
74
|
+
outline: none;
|
|
75
|
+
box-shadow:
|
|
76
|
+
0 0 0 var(--recursica_brand_states_focus_border-size)
|
|
77
|
+
var(--recursica_brand_states_focus_color),
|
|
78
|
+
0 0 var(--recursica_brand_states_focus_blur)
|
|
79
|
+
var(--recursica_brand_states_focus_margin)
|
|
80
|
+
var(--recursica_brand_states_focus_color);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* Icon Support */
|
|
84
|
+
.iconWrapper {
|
|
85
|
+
/* HARDCODE: maintain intrinsic icon bounds */
|
|
86
|
+
display: flex;
|
|
87
|
+
align-items: center;
|
|
88
|
+
justify-content: center;
|
|
89
|
+
|
|
90
|
+
width: var(--recursica_ui-kit_components_link_properties_icon-size);
|
|
91
|
+
height: var(--recursica_ui-kit_components_link_properties_icon-size);
|
|
92
|
+
color: var(--recursica_ui-kit_components_link_properties_colors_icon-color);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.root:visited .iconWrapper {
|
|
96
|
+
color: var(
|
|
97
|
+
--recursica_ui-kit_components_link_variants_states_visited_properties_colors_icon-color
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* Label text wrapper */
|
|
102
|
+
.labelText {
|
|
103
|
+
/* HARDCODE: allows text truncation if bounded */
|
|
104
|
+
min-width: 0;
|
|
105
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
3
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
4
|
+
import { Link } from "./Link";
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof Link> = {
|
|
7
|
+
title: "UI-Kit/Link",
|
|
8
|
+
component: Link,
|
|
9
|
+
tags: ["autodocs"],
|
|
10
|
+
args: {
|
|
11
|
+
children: "Link text",
|
|
12
|
+
href: "#",
|
|
13
|
+
},
|
|
14
|
+
render: ({ withLayer, layer, ...args }: any) => <Link {...args} />,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export default meta;
|
|
18
|
+
|
|
19
|
+
type Story = StoryObj<typeof Link>;
|
|
20
|
+
|
|
21
|
+
export const Default: Story = {};
|
|
22
|
+
|
|
23
|
+
export const WithIcon: Story = {
|
|
24
|
+
args: {
|
|
25
|
+
icon: (
|
|
26
|
+
<svg
|
|
27
|
+
width="24"
|
|
28
|
+
height="24"
|
|
29
|
+
viewBox="0 0 24 24"
|
|
30
|
+
fill="none"
|
|
31
|
+
stroke="currentColor"
|
|
32
|
+
strokeWidth="2"
|
|
33
|
+
strokeLinecap="round"
|
|
34
|
+
strokeLinejoin="round"
|
|
35
|
+
>
|
|
36
|
+
<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path>
|
|
37
|
+
<path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path>
|
|
38
|
+
</svg>
|
|
39
|
+
),
|
|
40
|
+
children: "Link with Icon",
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const Polymorphic: Story = {
|
|
45
|
+
args: {
|
|
46
|
+
component: "button",
|
|
47
|
+
onClick: () => alert("Button clicked!"),
|
|
48
|
+
children: "Rendered as <button>",
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const InlineText: Story = {
|
|
53
|
+
render: () => (
|
|
54
|
+
<p>
|
|
55
|
+
Here is some text with an <Link href="#">inline link</Link> inside it.
|
|
56
|
+
</p>
|
|
57
|
+
),
|
|
58
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Placeholder for future Link component tests. Add tests here if/when needed.
|