@recursica/adapter-mantine-v8 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.storybook/commonArgTypes.ts +148 -0
- package/ARCHITECTURE.md +18 -0
- package/CHANGELOG.md +688 -0
- package/LICENSE +21 -0
- package/OVERSTYLING.md +56 -0
- package/README.md +70 -0
- package/SETUP.md +93 -0
- package/USAGE.md +57 -0
- package/dist/adapter-mantine-v8.cjs +12 -0
- package/dist/adapter-mantine-v8.cjs.map +1 -0
- package/dist/adapter-mantine-v8.css +1 -0
- package/dist/adapter-mantine-v8.js +5759 -0
- package/dist/adapter-mantine-v8.js.map +1 -0
- package/dist/index.d.ts +2095 -0
- package/dist/test.html +1 -0
- package/dist/vite.svg +1 -0
- package/docs/PHILOSOPHY.md +39 -0
- package/llms.txt +74 -0
- package/package.json +131 -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 +154 -0
- package/src/OverStyling.tsx +79 -0
- package/src/Version.tsx +44 -0
- package/src/components/Accordion/ACCORDION_IMPLEMENTATION_NOTES.md +72 -0
- package/src/components/Accordion/Accordion.module.css +367 -0
- package/src/components/Accordion/Accordion.stories.tsx +189 -0
- package/src/components/Accordion/Accordion.test.tsx +1 -0
- package/src/components/Accordion/Accordion.tsx +220 -0
- package/src/components/Accordion/USAGE.md +51 -0
- package/src/components/Accordion/index.ts +1 -0
- package/src/components/AssistiveElement/ASSISTIVEELEMENT_IMPLEMENTATION_NOTES.md +45 -0
- package/src/components/AssistiveElement/AssistiveElement.module.css +111 -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 +93 -0
- package/src/components/AssistiveElement/USAGE.md +36 -0
- package/src/components/AutoComplete/AUTOCOMPLETE_IMPLEMENTATION_NOTES.md +42 -0
- package/src/components/AutoComplete/AutoComplete.module.css +430 -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 +179 -0
- package/src/components/AutoComplete/USAGE.md +80 -0
- package/src/components/Avatar/AVATAR_IMPLEMENTATION_NOTES.md +34 -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 +108 -0
- package/src/components/Avatar/USAGE.md +38 -0
- package/src/components/Avatar/index.ts +1 -0
- package/src/components/Badge/BADGE_IMPLEMENTATION_NOTES.md +18 -0
- package/src/components/Badge/Badge.module.css +127 -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 +64 -0
- package/src/components/Badge/USAGE.md +56 -0
- package/src/components/Breadcrumb/BREADCRUMB_IMPLEMENTATION_NOTES.md +47 -0
- package/src/components/Breadcrumb/Breadcrumb.module.css +48 -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 +85 -0
- package/src/components/Breadcrumb/USAGE.md +55 -0
- package/src/components/Breadcrumb/markCurrentPageItem.test.ts +49 -0
- package/src/components/Button/Button.module.css +446 -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 +184 -0
- package/src/components/Button/IMPLEMENTATION_NOTES.md +109 -0
- package/src/components/Button/USAGE.md +80 -0
- package/src/components/Button/index.ts +1 -0
- package/src/components/Card/CARD_IMPLEMENTATION_NOTES.md +17 -0
- package/src/components/Card/Card.module.css +119 -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 +248 -0
- package/src/components/Card/USAGE.md +63 -0
- package/src/components/Checkbox/CHECKBOX_IMPLEMENTATION_NOTES.md +25 -0
- package/src/components/Checkbox/Checkbox.module.css +267 -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 +151 -0
- package/src/components/Checkbox/CheckboxGroup.stories.tsx +139 -0
- package/src/components/Checkbox/CheckboxGroup.tsx +147 -0
- package/src/components/Checkbox/USAGE.md +48 -0
- package/src/components/Chip/CHIP_IMPLEMENTATION_NOTES.md +110 -0
- package/src/components/Chip/Chip.module.css +288 -0
- package/src/components/Chip/Chip.stories.tsx +128 -0
- package/src/components/Chip/Chip.test.tsx +1 -0
- package/src/components/Chip/Chip.tsx +157 -0
- package/src/components/Chip/USAGE.md +55 -0
- package/src/components/Container/CONTAINER_IMPLEMENTATION_NOTES.md +4 -0
- package/src/components/Container/Container.module.css +7 -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 +69 -0
- package/src/components/Container/USAGE.md +47 -0
- package/src/components/DatePicker/DATEPICKER_IMPLEMENTATION_NOTES.md +31 -0
- package/src/components/DatePicker/DatePicker.icons.tsx +27 -0
- package/src/components/DatePicker/DatePicker.module.css +566 -0
- package/src/components/DatePicker/DatePicker.stories.tsx +158 -0
- package/src/components/DatePicker/DatePicker.test.tsx +1 -0
- package/src/components/DatePicker/DatePicker.tsx +218 -0
- package/src/components/DatePicker/USAGE.md +49 -0
- package/src/components/Dropdown/BareDropdown.tsx +97 -0
- package/src/components/Dropdown/DROPDOWN_IMPLEMENTATION_NOTES.md +12 -0
- package/src/components/Dropdown/Dropdown.module.css +477 -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 +213 -0
- package/src/components/Dropdown/USAGE.md +69 -0
- package/src/components/FileInput/FILEINPUT_IMPLEMENTATION_NOTES.md +153 -0
- package/src/components/FileInput/FileInput.module.css +280 -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 +417 -0
- package/src/components/FileInput/USAGE.md +145 -0
- package/src/components/FileUpload/FILEUPLOAD_IMPLEMENTATION_NOTES.md +244 -0
- package/src/components/FileUpload/FileUpload.module.css +205 -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 +354 -0
- package/src/components/FileUpload/USAGE.md +199 -0
- package/src/components/Flex/FLEX_IMPLEMENTATION_NOTES.md +4 -0
- package/src/components/Flex/Flex.module.css +7 -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 +75 -0
- package/src/components/Flex/USAGE.md +48 -0
- package/src/components/FormControlLayout/FormControlLayout.module.css +90 -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 +74 -0
- package/src/components/FormControlLayout/USAGE.md +40 -0
- package/src/components/FormControlWrapper/FORMCONTROLWRAPPER_IMPLEMENTATION_NOTES.md +32 -0
- package/src/components/FormControlWrapper/FormControlWrapper.module.css +75 -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 +151 -0
- package/src/components/FormControlWrapper/USAGE.md +47 -0
- package/src/components/Grid/GRID_IMPLEMENTATION_NOTES.md +18 -0
- package/src/components/Grid/Grid.module.css +11 -0
- package/src/components/Grid/Grid.stories.tsx +206 -0
- package/src/components/Grid/Grid.test.tsx +1 -0
- package/src/components/Grid/Grid.tsx +140 -0
- package/src/components/Grid/USAGE.md +47 -0
- package/src/components/Group/GROUP_IMPLEMENTATION_NOTES.md +4 -0
- package/src/components/Group/Group.module.css +7 -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 +60 -0
- package/src/components/Group/USAGE.md +48 -0
- package/src/components/Heading/HEADING_IMPLEMENTATION_NOTES.md +18 -0
- package/src/components/Heading/Heading.module.css +13 -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 +52 -0
- package/src/components/Heading/USAGE.md +36 -0
- package/src/components/HoverCard/HOVERCARD_IMPLEMENTATION_NOTES.md +77 -0
- package/src/components/HoverCard/HoverCard.module.css +90 -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 +133 -0
- package/src/components/HoverCard/USAGE.md +52 -0
- package/src/components/Label/LABEL_IMPLEMENTATION_NOTES.md +48 -0
- package/src/components/Label/Label.module.css +141 -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 +113 -0
- package/src/components/Label/USAGE.md +47 -0
- package/src/components/Label/index.ts +1 -0
- package/src/components/Layer/USAGE.md +54 -0
- package/src/components/Link/IMPLEMENTATION_NOTES.md +19 -0
- package/src/components/Link/Link.module.css +110 -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 +67 -0
- package/src/components/Link/USAGE.md +56 -0
- package/src/components/Link/index.ts +1 -0
- package/src/components/Loader/LOADER_IMPLEMENTATION_NOTES.md +24 -0
- package/src/components/Loader/Loader.animate.dom.test.tsx +82 -0
- package/src/components/Loader/Loader.module.css +63 -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 +69 -0
- package/src/components/Loader/USAGE.md +44 -0
- package/src/components/Menu/MENU_IMPLEMENTATION_NOTES.md +88 -0
- package/src/components/Menu/Menu.module.css +280 -0
- package/src/components/Menu/Menu.stories.tsx +371 -0
- package/src/components/Menu/Menu.test.tsx +1 -0
- package/src/components/Menu/Menu.tsx +373 -0
- package/src/components/Menu/USAGE.md +55 -0
- package/src/components/Modal/MODAL_IMPLEMENTATION_NOTES.md +32 -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 +368 -0
- package/src/components/Modal/USAGE.md +58 -0
- package/src/components/Modal/index.ts +1 -0
- package/src/components/NumberInput/NUMBER_INPUT_IMPLEMENTATION_NOTES.md +24 -0
- package/src/components/NumberInput/NumberInput.module.css +302 -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 +157 -0
- package/src/components/NumberInput/USAGE.md +52 -0
- package/src/components/Pagination/IMPLEMENTATION_NOTES.md +16 -0
- package/src/components/Pagination/Pagination.icons.tsx +66 -0
- package/src/components/Pagination/Pagination.module.css +188 -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 +265 -0
- package/src/components/Pagination/USAGE.md +36 -0
- package/src/components/Pagination/index.ts +5 -0
- package/src/components/Panel/PANEL_IMPLEMENTATION_NOTES.md +116 -0
- package/src/components/Panel/Panel.module.css +209 -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 +269 -0
- package/src/components/Panel/USAGE.md +56 -0
- package/src/components/Popover/IMPLEMENTATION_NOTES.md +77 -0
- package/src/components/Popover/Popover.module.css +86 -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 +142 -0
- package/src/components/Popover/USAGE.md +61 -0
- package/src/components/Popover/index.ts +1 -0
- package/src/components/Radio/Radio.module.css +231 -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 +168 -0
- package/src/components/Radio/RadioGroup.stories.tsx +117 -0
- package/src/components/Radio/RadioGroup.tsx +124 -0
- package/src/components/Radio/USAGE.md +36 -0
- package/src/components/ReadOnlyField/READ_ONLY_FIELD_IMPLEMENTATION_NOTES.md +15 -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 +114 -0
- package/src/components/ReadOnlyField/ReadOnlySwitchField.tsx +21 -0
- package/src/components/ReadOnlyField/ReadOnlyTextField.tsx +48 -0
- package/src/components/ReadOnlyField/USAGE.md +44 -0
- package/src/components/ReadOnlyField/WithReadOnlyWrapper.tsx +93 -0
- package/src/components/ReadOnlyField/index.ts +5 -0
- package/src/components/RecursicaThemeProvider/USAGE.md +60 -0
- package/src/components/SegmentedControl/IMPLEMENTATION_NOTES.md +25 -0
- package/src/components/SegmentedControl/SegmentedControl.module.css +185 -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 +110 -0
- package/src/components/SegmentedControl/USAGE.md +55 -0
- package/src/components/Slider/IMPLEMENTATION_NOTES.md +92 -0
- package/src/components/Slider/Slider.module.css +588 -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 +391 -0
- package/src/components/Slider/USAGE.md +56 -0
- package/src/components/Stack/STACK_IMPLEMENTATION_NOTES.md +4 -0
- package/src/components/Stack/Stack.module.css +7 -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 +62 -0
- package/src/components/Stack/USAGE.md +48 -0
- package/src/components/Stepper/IMPLEMENTATION_NOTES.md +28 -0
- package/src/components/Stepper/Stepper.module.css +404 -0
- package/src/components/Stepper/Stepper.stories.tsx +148 -0
- package/src/components/Stepper/Stepper.test.tsx +1 -0
- package/src/components/Stepper/Stepper.tsx +93 -0
- package/src/components/Stepper/USAGE.md +41 -0
- package/src/components/Switch/SWITCH_IMPLEMENTATION_NOTES.md +64 -0
- package/src/components/Switch/Switch.module.css +279 -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 +177 -0
- package/src/components/Switch/SwitchGroup.stories.tsx +132 -0
- package/src/components/Switch/SwitchGroup.tsx +127 -0
- package/src/components/Switch/USAGE.md +42 -0
- package/src/components/Table/TABLE_IMPLEMENTATION_NOTES.md +78 -0
- package/src/components/Table/Table.icons.tsx +40 -0
- package/src/components/Table/Table.module.css +444 -0
- package/src/components/Table/Table.stories.tsx +140 -0
- package/src/components/Table/Table.test.tsx +1 -0
- package/src/components/Table/Table.tsx +243 -0
- package/src/components/Table/USAGE.md +78 -0
- package/src/components/Tabs/IMPLEMENTATION_NOTES.md +27 -0
- package/src/components/Tabs/Tabs.module.css +591 -0
- package/src/components/Tabs/Tabs.stories.tsx +154 -0
- package/src/components/Tabs/Tabs.test.tsx +1 -0
- package/src/components/Tabs/Tabs.tsx +114 -0
- package/src/components/Tabs/USAGE.md +45 -0
- package/src/components/Text/TEXT_IMPLEMENTATION_NOTES.md +12 -0
- package/src/components/Text/Text.module.css +13 -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 +53 -0
- package/src/components/Text/USAGE.md +40 -0
- package/src/components/TextArea/TEXTAREA_IMPLEMENTATION_NOTES.md +7 -0
- package/src/components/TextArea/TextArea.module.css +183 -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 +137 -0
- package/src/components/TextArea/USAGE.md +48 -0
- package/src/components/TextField/TEXTFIELD_IMPLEMENTATION_NOTES.md +19 -0
- package/src/components/TextField/TextField.module.css +264 -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 +139 -0
- package/src/components/TextField/USAGE.md +44 -0
- package/src/components/TimePicker/TIMEPICKER_IMPLEMENTATION_NOTES.md +119 -0
- package/src/components/TimePicker/TimePicker.module.css +291 -0
- package/src/components/TimePicker/TimePicker.stories.tsx +141 -0
- package/src/components/TimePicker/TimePicker.test.tsx +1 -0
- package/src/components/TimePicker/TimePicker.tsx +304 -0
- package/src/components/TimePicker/USAGE.md +57 -0
- package/src/components/Timeline/TIMELINE_IMPLEMENTATION_NOTES.md +13 -0
- package/src/components/Timeline/Timeline.module.css +373 -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 +73 -0
- package/src/components/Timeline/TimelineItem.tsx +79 -0
- package/src/components/Timeline/USAGE.md +49 -0
- package/src/components/Toast/TOAST_IMPLEMENTATION_NOTES.md +39 -0
- package/src/components/Toast/Toast.module.css +184 -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 +82 -0
- package/src/components/Toast/USAGE.md +50 -0
- package/src/components/Toast/index.ts +1 -0
- package/src/components/Tooltip/TOOLTIP_IMPLEMENTATION_NOTES.md +85 -0
- package/src/components/Tooltip/Tooltip.module.css +91 -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 +117 -0
- package/src/components/Tooltip/USAGE.md +80 -0
- package/src/components/TransferList/TRANSFERLIST_IMPLEMENTATION_NOTES.md +111 -0
- package/src/components/TransferList/TransferList.module.css +182 -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/Tree/IMPLEMENTATION_NOTES.md +48 -0
- package/src/components/Tree/Tree.module.css +232 -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 +220 -0
- package/src/components/Tree/USAGE.md +96 -0
- package/src/components/Tree/index.ts +1 -0
- package/src/components/index.ts +52 -0
- package/src/env.d.ts +7 -0
- package/src/index.ts +179 -0
- package/src/types/index.ts +9 -0
- package/src/types/mantine.d.ts +7 -0
- package/src/types/scss-modules.d.ts +9 -0
- package/src/utils/ColorSchemeWrapper.tsx +27 -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 +150 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/renderRichOption.tsx +65 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/* HARDCODED VALUES:
|
|
2
|
+
- border-style: solid: Structural rendering rule for the panel border.
|
|
3
|
+
- .inner { left: 0 }: Prevents the fixed Drawer portal from being pushed off-screen in centered flex environments (like Storybook Canvas).
|
|
4
|
+
- flexbox layout on .content & .body: Required to create a vertical flex context that pushes the footer to the bottom.
|
|
5
|
+
- position: sticky & negative margins on .footer: A CSS technique used to break the footer out of the .body padding constraints so it stretches edge-to-edge, while remaining fixed at the bottom of the scroll container.
|
|
6
|
+
- z-index: 10 on .footer: Ensures the footer covers the body content as it scrolls underneath.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/* ======================================
|
|
10
|
+
PANEL CONTENT (outer drawer container)
|
|
11
|
+
====================================== */
|
|
12
|
+
|
|
13
|
+
.content {
|
|
14
|
+
background-color: var(
|
|
15
|
+
--recursica_ui-kit_components_panel_properties_colors_background-color
|
|
16
|
+
);
|
|
17
|
+
border-style: solid;
|
|
18
|
+
border-width: var(--recursica_ui-kit_components_panel_properties_border-size);
|
|
19
|
+
border-color: var(
|
|
20
|
+
--recursica_ui-kit_components_panel_properties_colors_border-color
|
|
21
|
+
);
|
|
22
|
+
border-radius: var(
|
|
23
|
+
--recursica_ui-kit_components_panel_properties_border-radius
|
|
24
|
+
);
|
|
25
|
+
box-shadow: var(--recursica_ui-kit_components_panel_properties_elevation);
|
|
26
|
+
min-width: var(--recursica_ui-kit_components_panel_properties_min-width);
|
|
27
|
+
max-width: var(--recursica_ui-kit_components_panel_properties_max-width);
|
|
28
|
+
|
|
29
|
+
display: flex;
|
|
30
|
+
flex-direction: column;
|
|
31
|
+
height: 100%;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.inner {
|
|
35
|
+
/* Forces the Drawer Inner container to the left edge, preventing it from inheriting
|
|
36
|
+
a centered static position in flex environments like Storybook's Canvas wrapper */
|
|
37
|
+
left: 0;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/* ======================================
|
|
41
|
+
PANEL HEADER
|
|
42
|
+
====================================== */
|
|
43
|
+
|
|
44
|
+
.header {
|
|
45
|
+
background-color: var(
|
|
46
|
+
--recursica_ui-kit_components_panel_properties_colors_header-background-color
|
|
47
|
+
);
|
|
48
|
+
padding: var(
|
|
49
|
+
--recursica_ui-kit_components_panel_properties_header-footer-vertical-padding
|
|
50
|
+
)
|
|
51
|
+
var(
|
|
52
|
+
--recursica_ui-kit_components_panel_properties_header-footer-horizontal-padding
|
|
53
|
+
);
|
|
54
|
+
border-bottom: var(
|
|
55
|
+
--recursica_ui-kit_components_panel_properties_divider-size
|
|
56
|
+
)
|
|
57
|
+
solid
|
|
58
|
+
var(--recursica_ui-kit_components_panel_properties_colors_divider-color);
|
|
59
|
+
gap: var(--recursica_ui-kit_components_panel_properties_header-close-gap);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/* ======================================
|
|
63
|
+
PANEL TITLE
|
|
64
|
+
====================================== */
|
|
65
|
+
|
|
66
|
+
.title {
|
|
67
|
+
color: var(--recursica_ui-kit_components_panel_properties_colors_title);
|
|
68
|
+
|
|
69
|
+
/* Direct Figma Typography Mapping */
|
|
70
|
+
font-family: var(
|
|
71
|
+
--recursica_ui-kit_components_panel_properties_header-style_fontFamily
|
|
72
|
+
);
|
|
73
|
+
font-size: var(
|
|
74
|
+
--recursica_ui-kit_components_panel_properties_header-style_fontSize
|
|
75
|
+
);
|
|
76
|
+
font-style: var(
|
|
77
|
+
--recursica_ui-kit_components_panel_properties_header-style_fontStyle
|
|
78
|
+
);
|
|
79
|
+
font-weight: var(
|
|
80
|
+
--recursica_ui-kit_components_panel_properties_header-style_fontWeight
|
|
81
|
+
);
|
|
82
|
+
letter-spacing: var(
|
|
83
|
+
--recursica_ui-kit_components_panel_properties_header-style_letterSpacing
|
|
84
|
+
);
|
|
85
|
+
line-height: var(
|
|
86
|
+
--recursica_ui-kit_components_panel_properties_header-style_lineHeight
|
|
87
|
+
);
|
|
88
|
+
text-transform: var(
|
|
89
|
+
--recursica_ui-kit_components_panel_properties_header-style_textCase
|
|
90
|
+
);
|
|
91
|
+
text-decoration: var(
|
|
92
|
+
--recursica_ui-kit_components_panel_properties_header-style_textDecoration
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.titleTruncate {
|
|
97
|
+
composes: title;
|
|
98
|
+
white-space: nowrap;
|
|
99
|
+
overflow: clip; /* HARDCODE: `hidden` clips descenders (e.g. "g") when text_line-height is
|
|
100
|
+
tighter than the font's natural ascent+descent; overflow-clip-margin gives ink a small bleed
|
|
101
|
+
allowance while still clipping genuinely overflowing text (see Chip's IMPLEMENTATION_NOTES.md). */
|
|
102
|
+
overflow-clip-margin: 0.35em;
|
|
103
|
+
text-overflow: ellipsis;
|
|
104
|
+
display: block;
|
|
105
|
+
flex: 1;
|
|
106
|
+
min-width: 0;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* ======================================
|
|
110
|
+
PANEL BODY
|
|
111
|
+
====================================== */
|
|
112
|
+
|
|
113
|
+
.body {
|
|
114
|
+
padding: var(
|
|
115
|
+
--recursica_ui-kit_components_panel_properties_content-vertical-padding
|
|
116
|
+
)
|
|
117
|
+
var(
|
|
118
|
+
--recursica_ui-kit_components_panel_properties_content-horizontal-padding
|
|
119
|
+
);
|
|
120
|
+
color: var(--recursica_ui-kit_components_panel_properties_colors_content);
|
|
121
|
+
|
|
122
|
+
flex: 1;
|
|
123
|
+
display: flex;
|
|
124
|
+
flex-direction: column;
|
|
125
|
+
overflow-y: auto;
|
|
126
|
+
|
|
127
|
+
/* Direct Figma Typography Mapping */
|
|
128
|
+
font-family: var(
|
|
129
|
+
--recursica_ui-kit_components_panel_properties_content-style_fontFamily
|
|
130
|
+
);
|
|
131
|
+
font-size: var(
|
|
132
|
+
--recursica_ui-kit_components_panel_properties_content-style_fontSize
|
|
133
|
+
);
|
|
134
|
+
font-style: var(
|
|
135
|
+
--recursica_ui-kit_components_panel_properties_content-style_fontStyle
|
|
136
|
+
);
|
|
137
|
+
font-weight: var(
|
|
138
|
+
--recursica_ui-kit_components_panel_properties_content-style_fontWeight
|
|
139
|
+
);
|
|
140
|
+
letter-spacing: var(
|
|
141
|
+
--recursica_ui-kit_components_panel_properties_content-style_letterSpacing
|
|
142
|
+
);
|
|
143
|
+
line-height: var(
|
|
144
|
+
--recursica_ui-kit_components_panel_properties_content-style_lineHeight
|
|
145
|
+
);
|
|
146
|
+
text-transform: var(
|
|
147
|
+
--recursica_ui-kit_components_panel_properties_content-style_textCase
|
|
148
|
+
);
|
|
149
|
+
text-decoration: var(
|
|
150
|
+
--recursica_ui-kit_components_panel_properties_content-style_textDecoration
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/* ======================================
|
|
155
|
+
PANEL FOOTER
|
|
156
|
+
====================================== */
|
|
157
|
+
|
|
158
|
+
.footer {
|
|
159
|
+
background-color: var(
|
|
160
|
+
--recursica_ui-kit_components_panel_properties_colors_footer-background-color
|
|
161
|
+
);
|
|
162
|
+
padding: var(
|
|
163
|
+
--recursica_ui-kit_components_panel_properties_header-footer-vertical-padding
|
|
164
|
+
)
|
|
165
|
+
var(
|
|
166
|
+
--recursica_ui-kit_components_panel_properties_header-footer-horizontal-padding
|
|
167
|
+
);
|
|
168
|
+
border-top: var(--recursica_ui-kit_components_panel_properties_divider-size)
|
|
169
|
+
solid
|
|
170
|
+
var(--recursica_ui-kit_components_panel_properties_colors_divider-color);
|
|
171
|
+
|
|
172
|
+
display: flex;
|
|
173
|
+
align-items: center;
|
|
174
|
+
justify-content: flex-end;
|
|
175
|
+
gap: var(--recursica_ui-kit_components_panel_properties_footer-button-gap);
|
|
176
|
+
|
|
177
|
+
/* Ensure footer sticks to the bottom of the scroll container */
|
|
178
|
+
margin-top: auto;
|
|
179
|
+
position: sticky;
|
|
180
|
+
|
|
181
|
+
/* Break out of .body padding constraints to stretch edge-to-edge */
|
|
182
|
+
bottom: calc(
|
|
183
|
+
var(
|
|
184
|
+
--recursica_ui-kit_components_panel_properties_content-vertical-padding
|
|
185
|
+
) *
|
|
186
|
+
-1
|
|
187
|
+
);
|
|
188
|
+
margin-left: calc(
|
|
189
|
+
var(
|
|
190
|
+
--recursica_ui-kit_components_panel_properties_content-horizontal-padding
|
|
191
|
+
) *
|
|
192
|
+
-1
|
|
193
|
+
);
|
|
194
|
+
margin-right: calc(
|
|
195
|
+
var(
|
|
196
|
+
--recursica_ui-kit_components_panel_properties_content-horizontal-padding
|
|
197
|
+
) *
|
|
198
|
+
-1
|
|
199
|
+
);
|
|
200
|
+
margin-bottom: calc(
|
|
201
|
+
var(
|
|
202
|
+
--recursica_ui-kit_components_panel_properties_content-vertical-padding
|
|
203
|
+
) *
|
|
204
|
+
-1
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
/* Render over scrolling content */
|
|
208
|
+
z-index: 10;
|
|
209
|
+
}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
|
+
import { Panel, type PanelProps } from "./Panel";
|
|
4
|
+
import { Button } from "../Button";
|
|
5
|
+
import { Text } from "../Text/Text";
|
|
6
|
+
|
|
7
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8
|
+
type PanelStoryArgs = Record<string, any>;
|
|
9
|
+
|
|
10
|
+
const meta: Meta = {
|
|
11
|
+
title: "UI-Kit/Panel",
|
|
12
|
+
component: Panel,
|
|
13
|
+
tags: ["autodocs"],
|
|
14
|
+
argTypes: {
|
|
15
|
+
placement: {
|
|
16
|
+
control: "select",
|
|
17
|
+
options: ["left", "right", "top", "bottom"],
|
|
18
|
+
description: "Side of the screen the panel slides in from.",
|
|
19
|
+
},
|
|
20
|
+
title: {
|
|
21
|
+
control: "text",
|
|
22
|
+
description: "Panel title displayed in the header.",
|
|
23
|
+
},
|
|
24
|
+
withOverlay: {
|
|
25
|
+
control: "boolean",
|
|
26
|
+
description: "Whether to display a background overlay.",
|
|
27
|
+
},
|
|
28
|
+
withCloseButton: {
|
|
29
|
+
control: "boolean",
|
|
30
|
+
description: "Whether to display the close button in the header.",
|
|
31
|
+
},
|
|
32
|
+
wrapHeaderText: {
|
|
33
|
+
control: "boolean",
|
|
34
|
+
description:
|
|
35
|
+
"If true, forces the header text to a single line and truncates with an ellipsis.",
|
|
36
|
+
},
|
|
37
|
+
// Hide auto-detected HTML attributes
|
|
38
|
+
defaultChecked: { table: { disable: true } },
|
|
39
|
+
defaultValue: { table: { disable: true } },
|
|
40
|
+
suppressContentEditableWarning: { table: { disable: true } },
|
|
41
|
+
suppressHydrationWarning: { table: { disable: true } },
|
|
42
|
+
},
|
|
43
|
+
parameters: {
|
|
44
|
+
layout: "fullscreen",
|
|
45
|
+
docs: {
|
|
46
|
+
description: {
|
|
47
|
+
component: `
|
|
48
|
+
The \`Panel\` component slides in or expands from the edge of the screen to reveal additional content or functionality. Built on Mantine's \`Drawer\`, it enforces Recursica design tokens for styling.
|
|
49
|
+
|
|
50
|
+
### Anatomy
|
|
51
|
+
1. **Header** — Title and close icon, remains fixed on scroll
|
|
52
|
+
2. **Divider** — Separates header/footer from content
|
|
53
|
+
3. **Body (Slot)** — Scrollable content area for custom content
|
|
54
|
+
4. **Footer** — Fixed action buttons (Recursica-specific)
|
|
55
|
+
|
|
56
|
+
### Usage
|
|
57
|
+
\`\`\`tsx
|
|
58
|
+
const [opened, { open, close }] = useDisclosure(false);
|
|
59
|
+
|
|
60
|
+
<Button onClick={open}>Open Panel</Button>
|
|
61
|
+
<Panel opened={opened} onClose={close} title="Settings" placement="right">
|
|
62
|
+
Content goes here
|
|
63
|
+
<Panel.Footer>
|
|
64
|
+
<Button variant="outline">Cancel</Button>
|
|
65
|
+
<Button variant="solid">Save</Button>
|
|
66
|
+
</Panel.Footer>
|
|
67
|
+
</Panel>
|
|
68
|
+
\`\`\`
|
|
69
|
+
`,
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export default meta;
|
|
76
|
+
|
|
77
|
+
type Story = StoryObj<PanelStoryArgs>;
|
|
78
|
+
|
|
79
|
+
export const Default: Story = {
|
|
80
|
+
args: {
|
|
81
|
+
placement: "right",
|
|
82
|
+
title: "Panel Title",
|
|
83
|
+
withOverlay: true,
|
|
84
|
+
withCloseButton: true,
|
|
85
|
+
wrapHeaderText: false,
|
|
86
|
+
},
|
|
87
|
+
render: ({ wrapHeaderText, ...args }: PanelStoryArgs) => {
|
|
88
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
89
|
+
const [opened, setOpened] = useState(false);
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
<>
|
|
93
|
+
<Button variant="solid" onClick={() => setOpened(true)}>
|
|
94
|
+
Open Panel
|
|
95
|
+
</Button>
|
|
96
|
+
<Panel
|
|
97
|
+
{...(args as PanelProps)}
|
|
98
|
+
opened={opened}
|
|
99
|
+
onClose={() => setOpened(false)}
|
|
100
|
+
title="Panel Title"
|
|
101
|
+
placement="right"
|
|
102
|
+
wrapHeaderText={wrapHeaderText}
|
|
103
|
+
>
|
|
104
|
+
<Text>
|
|
105
|
+
This is the panel body content area. Panels slide in from the edge
|
|
106
|
+
of the screen to reveal supplementary information, navigation
|
|
107
|
+
options, or toolsets.
|
|
108
|
+
</Text>
|
|
109
|
+
<Panel.Footer>
|
|
110
|
+
<Button variant="outline" onClick={() => setOpened(false)}>
|
|
111
|
+
Cancel
|
|
112
|
+
</Button>
|
|
113
|
+
<Button variant="solid">Save</Button>
|
|
114
|
+
</Panel.Footer>
|
|
115
|
+
</Panel>
|
|
116
|
+
</>
|
|
117
|
+
);
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
export const LeftPlacement: Story = {
|
|
122
|
+
args: {
|
|
123
|
+
placement: "left",
|
|
124
|
+
title: "Navigation",
|
|
125
|
+
withOverlay: true,
|
|
126
|
+
withCloseButton: true,
|
|
127
|
+
wrapHeaderText: false,
|
|
128
|
+
},
|
|
129
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
130
|
+
render: ({ withLayer, layer, ...args }: PanelStoryArgs) => {
|
|
131
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
132
|
+
const [opened, setOpened] = useState(false);
|
|
133
|
+
|
|
134
|
+
return (
|
|
135
|
+
<>
|
|
136
|
+
<Button variant="outline" onClick={() => setOpened(true)}>
|
|
137
|
+
Open Left Panel
|
|
138
|
+
</Button>
|
|
139
|
+
<Panel
|
|
140
|
+
{...(args as PanelProps)}
|
|
141
|
+
opened={opened}
|
|
142
|
+
onClose={() => setOpened(false)}
|
|
143
|
+
>
|
|
144
|
+
<Text>
|
|
145
|
+
A panel sliding in from the left, commonly used for navigation menus
|
|
146
|
+
or sidebars.
|
|
147
|
+
</Text>
|
|
148
|
+
</Panel>
|
|
149
|
+
</>
|
|
150
|
+
);
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
export const ScrollableContent: Story = {
|
|
155
|
+
args: {
|
|
156
|
+
placement: "right",
|
|
157
|
+
title: "Scrollable Panel",
|
|
158
|
+
withOverlay: true,
|
|
159
|
+
withCloseButton: true,
|
|
160
|
+
wrapHeaderText: false,
|
|
161
|
+
},
|
|
162
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
163
|
+
render: ({ withLayer, layer, ...args }: PanelStoryArgs) => {
|
|
164
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
165
|
+
const [opened, setOpened] = useState(false);
|
|
166
|
+
|
|
167
|
+
return (
|
|
168
|
+
<>
|
|
169
|
+
<Button variant="solid" onClick={() => setOpened(true)}>
|
|
170
|
+
Open Scrollable Panel
|
|
171
|
+
</Button>
|
|
172
|
+
<Panel
|
|
173
|
+
{...(args as PanelProps)}
|
|
174
|
+
opened={opened}
|
|
175
|
+
onClose={() => setOpened(false)}
|
|
176
|
+
>
|
|
177
|
+
{Array.from({ length: 20 }).map((_, i) => (
|
|
178
|
+
<p key={i} style={{ marginBottom: "1rem" }}>
|
|
179
|
+
Paragraph {i + 1}: This is sample content to demonstrate the
|
|
180
|
+
scrollable behavior of the panel when content exceeds the viewport
|
|
181
|
+
height.
|
|
182
|
+
</p>
|
|
183
|
+
))}
|
|
184
|
+
<Panel.Footer>
|
|
185
|
+
<Button variant="outline" onClick={() => setOpened(false)}>
|
|
186
|
+
Close
|
|
187
|
+
</Button>
|
|
188
|
+
<Button variant="solid">Apply</Button>
|
|
189
|
+
</Panel.Footer>
|
|
190
|
+
</Panel>
|
|
191
|
+
</>
|
|
192
|
+
);
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
export const LongTitle: Story = {
|
|
197
|
+
args: {
|
|
198
|
+
placement: "right",
|
|
199
|
+
title:
|
|
200
|
+
"This is a ridiculously long panel title designed to test how the header CSS handles text overflow and whether it truncates correctly or breaks the layout",
|
|
201
|
+
withOverlay: true,
|
|
202
|
+
withCloseButton: true,
|
|
203
|
+
wrapHeaderText: true,
|
|
204
|
+
},
|
|
205
|
+
render: ({ ...args }: PanelStoryArgs) => {
|
|
206
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
207
|
+
const [opened, setOpened] = useState(false);
|
|
208
|
+
|
|
209
|
+
return (
|
|
210
|
+
<>
|
|
211
|
+
<Button variant="solid" onClick={() => setOpened(true)}>
|
|
212
|
+
Open Long Title Panel
|
|
213
|
+
</Button>
|
|
214
|
+
<Panel
|
|
215
|
+
{...(args as PanelProps)}
|
|
216
|
+
opened={opened}
|
|
217
|
+
onClose={() => setOpened(false)}
|
|
218
|
+
>
|
|
219
|
+
<Text>
|
|
220
|
+
Check the header to see if the long title is handled gracefully
|
|
221
|
+
without pushing the close button off screen.
|
|
222
|
+
</Text>
|
|
223
|
+
</Panel>
|
|
224
|
+
</>
|
|
225
|
+
);
|
|
226
|
+
},
|
|
227
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Placeholder for future Panel component tests. Add tests here if/when needed.
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import { forwardRef } from "react";
|
|
2
|
+
import {
|
|
3
|
+
Drawer as MantineDrawer,
|
|
4
|
+
type DrawerProps as MantineDrawerProps,
|
|
5
|
+
type DrawerRootProps as MantineDrawerRootProps,
|
|
6
|
+
type DrawerOverlayProps as MantineDrawerOverlayProps,
|
|
7
|
+
type DrawerContentProps as MantineDrawerContentProps,
|
|
8
|
+
type DrawerHeaderProps as MantineDrawerHeaderProps,
|
|
9
|
+
type DrawerTitleProps as MantineDrawerTitleProps,
|
|
10
|
+
type DrawerCloseButtonProps as MantineDrawerCloseButtonProps,
|
|
11
|
+
type DrawerBodyProps as MantineDrawerBodyProps,
|
|
12
|
+
} from "@mantine/core";
|
|
13
|
+
import {
|
|
14
|
+
filterStylingProps,
|
|
15
|
+
mergeClassNames,
|
|
16
|
+
withCallerOverride,
|
|
17
|
+
type RecursicaOverStyled,
|
|
18
|
+
} from "../../utils/filterStylingProps";
|
|
19
|
+
import styles from "./Panel.module.css";
|
|
20
|
+
|
|
21
|
+
// ============================================================
|
|
22
|
+
// PANEL (Drawer)
|
|
23
|
+
// ============================================================
|
|
24
|
+
|
|
25
|
+
import { type RecursicaPanelProps as BaseRecursicaPanelProps } from "@recursica/adapter-common";
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Recursica Panel root props. Extends Mantine Drawer.
|
|
29
|
+
*/
|
|
30
|
+
export interface RecursicaPanelProps
|
|
31
|
+
extends Omit<
|
|
32
|
+
MantineDrawerProps,
|
|
33
|
+
"size" | "styles" | "classNames" | "style" | "position" | "opened"
|
|
34
|
+
>,
|
|
35
|
+
BaseRecursicaPanelProps {}
|
|
36
|
+
|
|
37
|
+
export type PanelProps = RecursicaOverStyled<RecursicaPanelProps>;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Recursica Panel component wrapping Mantine's Drawer.
|
|
41
|
+
*
|
|
42
|
+
* Panels slide in or expand from the edge of the screen to reveal
|
|
43
|
+
* additional content or functionality. They are commonly used to provide
|
|
44
|
+
* supplementary information, navigation options, or toolsets without
|
|
45
|
+
* cluttering the main interface.
|
|
46
|
+
*
|
|
47
|
+
* ```tsx
|
|
48
|
+
* <Panel opened={opened} onClose={close} title="Panel Title" placement="right">
|
|
49
|
+
* <Panel.Body>
|
|
50
|
+
* Content goes here
|
|
51
|
+
* </Panel.Body>
|
|
52
|
+
* </Panel>
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* Mantine Drawer sub-components available via dot-notation:
|
|
56
|
+
* - `Panel.Header` — Top section with title and close button
|
|
57
|
+
* - `Panel.Title` — Title text within the header
|
|
58
|
+
* - `Panel.CloseButton` — Close button within the header
|
|
59
|
+
* - `Panel.Body` — Scrollable body content area
|
|
60
|
+
* - `Panel.Content` — Outer content container
|
|
61
|
+
* - `Panel.Overlay` — Background overlay
|
|
62
|
+
* - `Panel.Root` — Root element for advanced composition
|
|
63
|
+
* - `Panel.Stack` — Stacked drawer context
|
|
64
|
+
*/
|
|
65
|
+
const PanelBase = function Panel({
|
|
66
|
+
overStyled = false,
|
|
67
|
+
placement = "right",
|
|
68
|
+
keepMounted = true,
|
|
69
|
+
wrapHeaderText = true,
|
|
70
|
+
...rest
|
|
71
|
+
}: PanelProps) {
|
|
72
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
73
|
+
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
74
|
+
|
|
75
|
+
// Bind CSS module classes to Mantine's internal classNames API
|
|
76
|
+
const mergedClassNames = mergeClassNames(
|
|
77
|
+
{
|
|
78
|
+
content: styles.content,
|
|
79
|
+
header: styles.header,
|
|
80
|
+
title: wrapHeaderText ? styles.titleTruncate : styles.title,
|
|
81
|
+
body: styles.body,
|
|
82
|
+
inner: styles.inner,
|
|
83
|
+
},
|
|
84
|
+
restRecord.classNames as Partial<Record<string, string>> | undefined,
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<MantineDrawer
|
|
89
|
+
{...(sanitizedProps as unknown as MantineDrawerProps)}
|
|
90
|
+
position={placement} /* Recursica default: right; Mantine default: left */
|
|
91
|
+
keepMounted={keepMounted}
|
|
92
|
+
closeOnClickOutside={withCallerOverride(
|
|
93
|
+
Boolean(rest.opened),
|
|
94
|
+
rest.closeOnClickOutside,
|
|
95
|
+
)}
|
|
96
|
+
classNames={mergedClassNames}
|
|
97
|
+
/>
|
|
98
|
+
);
|
|
99
|
+
};
|
|
100
|
+
PanelBase.displayName = "Panel";
|
|
101
|
+
|
|
102
|
+
// ============================================================
|
|
103
|
+
// PANEL FOOTER (custom — Mantine Drawer has no Footer sub-component)
|
|
104
|
+
// ============================================================
|
|
105
|
+
|
|
106
|
+
export type PanelFooterProps = RecursicaOverStyled<
|
|
107
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
108
|
+
>;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Panel footer section with action buttons.
|
|
112
|
+
* Separated from the body by a divider. Remains fixed at the bottom.
|
|
113
|
+
* This is a Recursica-specific sub-component; Mantine Drawer does not
|
|
114
|
+
* natively provide a footer.
|
|
115
|
+
*/
|
|
116
|
+
export const PanelFooter = forwardRef<HTMLDivElement, PanelFooterProps>(
|
|
117
|
+
function PanelFooter({ overStyled = false, ...rest }, ref) {
|
|
118
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
119
|
+
const classNameProp = (sanitizedProps as Record<string, unknown>)
|
|
120
|
+
.className as string | undefined;
|
|
121
|
+
|
|
122
|
+
const finalClassName = classNameProp
|
|
123
|
+
? `${styles.footer} ${classNameProp}`
|
|
124
|
+
: styles.footer;
|
|
125
|
+
|
|
126
|
+
return <div ref={ref} {...sanitizedProps} className={finalClassName} />;
|
|
127
|
+
},
|
|
128
|
+
);
|
|
129
|
+
PanelFooter.displayName = "PanelFooter";
|
|
130
|
+
|
|
131
|
+
// ============================================================
|
|
132
|
+
// PANEL SUB-COMPONENTS (wrapped so overStyled/filterStylingProps applies)
|
|
133
|
+
// ============================================================
|
|
134
|
+
|
|
135
|
+
export type PanelRootProps = RecursicaOverStyled<MantineDrawerRootProps>;
|
|
136
|
+
|
|
137
|
+
export const PanelRoot = forwardRef<HTMLDivElement, PanelRootProps>(
|
|
138
|
+
function PanelRoot({ overStyled = false, ...rest }, ref) {
|
|
139
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
140
|
+
return (
|
|
141
|
+
<MantineDrawer.Root
|
|
142
|
+
ref={ref}
|
|
143
|
+
{...(sanitizedProps as unknown as MantineDrawerRootProps)}
|
|
144
|
+
/>
|
|
145
|
+
);
|
|
146
|
+
},
|
|
147
|
+
);
|
|
148
|
+
PanelRoot.displayName = "PanelRoot";
|
|
149
|
+
|
|
150
|
+
export type PanelOverlayProps = RecursicaOverStyled<MantineDrawerOverlayProps>;
|
|
151
|
+
|
|
152
|
+
export const PanelOverlay = forwardRef<HTMLDivElement, PanelOverlayProps>(
|
|
153
|
+
function PanelOverlay({ overStyled = false, ...rest }, ref) {
|
|
154
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
155
|
+
return (
|
|
156
|
+
<MantineDrawer.Overlay
|
|
157
|
+
ref={ref}
|
|
158
|
+
{...(sanitizedProps as unknown as MantineDrawerOverlayProps)}
|
|
159
|
+
/>
|
|
160
|
+
);
|
|
161
|
+
},
|
|
162
|
+
);
|
|
163
|
+
PanelOverlay.displayName = "PanelOverlay";
|
|
164
|
+
|
|
165
|
+
export type PanelContentProps = RecursicaOverStyled<MantineDrawerContentProps>;
|
|
166
|
+
|
|
167
|
+
export const PanelContent = forwardRef<HTMLDivElement, PanelContentProps>(
|
|
168
|
+
function PanelContent({ overStyled = false, ...rest }, ref) {
|
|
169
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
170
|
+
return (
|
|
171
|
+
<MantineDrawer.Content
|
|
172
|
+
ref={ref}
|
|
173
|
+
{...(sanitizedProps as unknown as MantineDrawerContentProps)}
|
|
174
|
+
/>
|
|
175
|
+
);
|
|
176
|
+
},
|
|
177
|
+
);
|
|
178
|
+
PanelContent.displayName = "PanelContent";
|
|
179
|
+
|
|
180
|
+
export type PanelHeaderProps = RecursicaOverStyled<MantineDrawerHeaderProps>;
|
|
181
|
+
|
|
182
|
+
export const PanelHeader = forwardRef<HTMLElement, PanelHeaderProps>(
|
|
183
|
+
function PanelHeader({ overStyled = false, ...rest }, ref) {
|
|
184
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
185
|
+
return (
|
|
186
|
+
<MantineDrawer.Header
|
|
187
|
+
ref={ref}
|
|
188
|
+
{...(sanitizedProps as unknown as MantineDrawerHeaderProps)}
|
|
189
|
+
/>
|
|
190
|
+
);
|
|
191
|
+
},
|
|
192
|
+
);
|
|
193
|
+
PanelHeader.displayName = "PanelHeader";
|
|
194
|
+
|
|
195
|
+
export type PanelTitleProps = RecursicaOverStyled<MantineDrawerTitleProps>;
|
|
196
|
+
|
|
197
|
+
export const PanelTitle = forwardRef<HTMLHeadingElement, PanelTitleProps>(
|
|
198
|
+
function PanelTitle({ overStyled = false, ...rest }, ref) {
|
|
199
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
200
|
+
return (
|
|
201
|
+
<MantineDrawer.Title
|
|
202
|
+
ref={ref}
|
|
203
|
+
{...(sanitizedProps as unknown as MantineDrawerTitleProps)}
|
|
204
|
+
/>
|
|
205
|
+
);
|
|
206
|
+
},
|
|
207
|
+
);
|
|
208
|
+
PanelTitle.displayName = "PanelTitle";
|
|
209
|
+
|
|
210
|
+
export type PanelCloseButtonProps =
|
|
211
|
+
RecursicaOverStyled<MantineDrawerCloseButtonProps>;
|
|
212
|
+
|
|
213
|
+
export const PanelCloseButton = forwardRef<
|
|
214
|
+
HTMLButtonElement,
|
|
215
|
+
PanelCloseButtonProps
|
|
216
|
+
>(function PanelCloseButton({ overStyled = false, ...rest }, ref) {
|
|
217
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
218
|
+
return (
|
|
219
|
+
<MantineDrawer.CloseButton
|
|
220
|
+
ref={ref}
|
|
221
|
+
{...(sanitizedProps as unknown as MantineDrawerCloseButtonProps)}
|
|
222
|
+
/>
|
|
223
|
+
);
|
|
224
|
+
});
|
|
225
|
+
PanelCloseButton.displayName = "PanelCloseButton";
|
|
226
|
+
|
|
227
|
+
export type PanelBodyProps = RecursicaOverStyled<MantineDrawerBodyProps>;
|
|
228
|
+
|
|
229
|
+
export const PanelBody = forwardRef<HTMLDivElement, PanelBodyProps>(
|
|
230
|
+
function PanelBody({ overStyled = false, ...rest }, ref) {
|
|
231
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
232
|
+
return (
|
|
233
|
+
<MantineDrawer.Body
|
|
234
|
+
ref={ref}
|
|
235
|
+
{...(sanitizedProps as unknown as MantineDrawerBodyProps)}
|
|
236
|
+
/>
|
|
237
|
+
);
|
|
238
|
+
},
|
|
239
|
+
);
|
|
240
|
+
PanelBody.displayName = "PanelBody";
|
|
241
|
+
|
|
242
|
+
// ============================================================
|
|
243
|
+
// DOT NOTATION EXPORT
|
|
244
|
+
// ============================================================
|
|
245
|
+
|
|
246
|
+
type PanelComponent = typeof PanelBase & {
|
|
247
|
+
Root: typeof PanelRoot;
|
|
248
|
+
Overlay: typeof PanelOverlay;
|
|
249
|
+
Content: typeof PanelContent;
|
|
250
|
+
Header: typeof PanelHeader;
|
|
251
|
+
Title: typeof PanelTitle;
|
|
252
|
+
CloseButton: typeof PanelCloseButton;
|
|
253
|
+
Body: typeof PanelBody;
|
|
254
|
+
Stack: typeof MantineDrawer.Stack;
|
|
255
|
+
Footer: typeof PanelFooter;
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
export const Panel = PanelBase as PanelComponent;
|
|
259
|
+
Panel.Root = PanelRoot;
|
|
260
|
+
Panel.Overlay = PanelOverlay;
|
|
261
|
+
Panel.Content = PanelContent;
|
|
262
|
+
Panel.Header = PanelHeader;
|
|
263
|
+
Panel.Title = PanelTitle;
|
|
264
|
+
Panel.CloseButton = PanelCloseButton;
|
|
265
|
+
Panel.Body = PanelBody;
|
|
266
|
+
// Panel.Stack (DrawerStack) only accepts `children` — no styling props to
|
|
267
|
+
// strip, so re-exporting Mantine's implementation directly is not a gap.
|
|
268
|
+
Panel.Stack = MantineDrawer.Stack;
|
|
269
|
+
Panel.Footer = PanelFooter;
|