@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,128 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
|
+
import { Chip } from "./Chip";
|
|
4
|
+
|
|
5
|
+
type ChipStoryProps = React.ComponentProps<typeof Chip>;
|
|
6
|
+
|
|
7
|
+
const meta: Meta<ChipStoryProps> = {
|
|
8
|
+
title: "UI-Kit/Chip",
|
|
9
|
+
component: Chip,
|
|
10
|
+
tags: ["autodocs"],
|
|
11
|
+
parameters: {
|
|
12
|
+
docs: {
|
|
13
|
+
description: {
|
|
14
|
+
component:
|
|
15
|
+
"The Chip component is used to represent interactive selections, descriptive tags, or dynamic filters natively bounded to Recursica variables. It can be used as a toggleable input, can render a custom leading `icon`, and handles close constraints automatically via the `onDelete` property.",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
argTypes: {
|
|
20
|
+
error: {
|
|
21
|
+
control: "boolean",
|
|
22
|
+
description: "Applies the error state styling dynamically.",
|
|
23
|
+
},
|
|
24
|
+
disabled: {
|
|
25
|
+
control: "boolean",
|
|
26
|
+
description: "Applies disabled token states.",
|
|
27
|
+
},
|
|
28
|
+
checked: {
|
|
29
|
+
control: "boolean",
|
|
30
|
+
description: "Forces the visual selected state.",
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export default meta;
|
|
36
|
+
|
|
37
|
+
type Story = StoryObj<ChipStoryProps>;
|
|
38
|
+
|
|
39
|
+
// The Default story exposing native properties for the playground.
|
|
40
|
+
export const Default: Story = {
|
|
41
|
+
args: {
|
|
42
|
+
children: "Default Chip",
|
|
43
|
+
error: false,
|
|
44
|
+
disabled: false,
|
|
45
|
+
checked: false,
|
|
46
|
+
},
|
|
47
|
+
render: (args: ChipStoryProps) => <Chip {...args} />,
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// Static Stories for Regression Snapshots
|
|
51
|
+
export const Unselected: Story = {
|
|
52
|
+
args: {
|
|
53
|
+
children: "Unselected",
|
|
54
|
+
checked: false,
|
|
55
|
+
},
|
|
56
|
+
render: (args: ChipStoryProps) => <Chip {...args} />,
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const Selected: Story = {
|
|
60
|
+
args: {
|
|
61
|
+
children: "Selected",
|
|
62
|
+
checked: true,
|
|
63
|
+
},
|
|
64
|
+
render: (args: ChipStoryProps) => <Chip {...args} onChange={() => {}} />,
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const ErrorState: Story = {
|
|
68
|
+
args: {
|
|
69
|
+
children: "Error",
|
|
70
|
+
error: true,
|
|
71
|
+
checked: false,
|
|
72
|
+
},
|
|
73
|
+
render: (args: ChipStoryProps) => <Chip {...args} />,
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export const ErrorSelected: Story = {
|
|
77
|
+
args: {
|
|
78
|
+
children: "Error Selected",
|
|
79
|
+
error: true,
|
|
80
|
+
checked: true,
|
|
81
|
+
},
|
|
82
|
+
render: (args: ChipStoryProps) => <Chip {...args} onChange={() => {}} />,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export const Removable: Story = {
|
|
86
|
+
args: {
|
|
87
|
+
children: "Dismissible",
|
|
88
|
+
checked: false,
|
|
89
|
+
onDelete: () => console.log("Removal Action Triggered"),
|
|
90
|
+
},
|
|
91
|
+
render: (args: ChipStoryProps) => <Chip {...args} />,
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const leadingIcon = (
|
|
95
|
+
<svg
|
|
96
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
97
|
+
viewBox="0 0 24 24"
|
|
98
|
+
fill="none"
|
|
99
|
+
stroke="currentColor"
|
|
100
|
+
strokeWidth="2"
|
|
101
|
+
strokeLinecap="round"
|
|
102
|
+
strokeLinejoin="round"
|
|
103
|
+
>
|
|
104
|
+
<circle cx="12" cy="12" r="10"></circle>
|
|
105
|
+
<path d="M12 8v4"></path>
|
|
106
|
+
<path d="M12 16h.01"></path>
|
|
107
|
+
</svg>
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
export const WithLeadingIcon: Story = {
|
|
111
|
+
args: {
|
|
112
|
+
children: "Leading Icon",
|
|
113
|
+
checked: false,
|
|
114
|
+
icon: leadingIcon,
|
|
115
|
+
},
|
|
116
|
+
render: (args: ChipStoryProps) => <Chip {...args} />,
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// Selecting a chip with a leading icon swaps in the checkmark rather than showing both —
|
|
120
|
+
// matches MUI's native behavior of the check icon overlaying the leading icon.
|
|
121
|
+
export const WithLeadingIconSelected: Story = {
|
|
122
|
+
args: {
|
|
123
|
+
children: "Leading Icon Selected",
|
|
124
|
+
checked: true,
|
|
125
|
+
icon: leadingIcon,
|
|
126
|
+
},
|
|
127
|
+
render: (args: ChipStoryProps) => <Chip {...args} onChange={() => {}} />,
|
|
128
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Placeholder for future Chip component tests. Add tests here if/when needed.
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import React, { forwardRef } from "react";
|
|
2
|
+
import {
|
|
3
|
+
Chip as MantineChip,
|
|
4
|
+
type ChipProps as MantineChipProps,
|
|
5
|
+
} from "@mantine/core";
|
|
6
|
+
import {
|
|
7
|
+
filterStylingProps,
|
|
8
|
+
mergeClassNames,
|
|
9
|
+
withCallerOverride,
|
|
10
|
+
type RecursicaOverStyled,
|
|
11
|
+
} from "../../utils/filterStylingProps";
|
|
12
|
+
import styles from "./Chip.module.css";
|
|
13
|
+
import { type RecursicaChipProps } from "@recursica/adapter-common";
|
|
14
|
+
|
|
15
|
+
export type ChipProps = RecursicaOverStyled<
|
|
16
|
+
Omit<MantineChipProps, "variant" | "size" | "color" | "radius"> &
|
|
17
|
+
RecursicaChipProps
|
|
18
|
+
>;
|
|
19
|
+
|
|
20
|
+
function CloseIcon(props: React.ComponentPropsWithoutRef<"svg">) {
|
|
21
|
+
return (
|
|
22
|
+
<svg
|
|
23
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
24
|
+
width="24"
|
|
25
|
+
height="24"
|
|
26
|
+
viewBox="0 0 24 24"
|
|
27
|
+
fill="none"
|
|
28
|
+
stroke="currentColor"
|
|
29
|
+
strokeWidth="2"
|
|
30
|
+
strokeLinecap="round"
|
|
31
|
+
strokeLinejoin="round"
|
|
32
|
+
{...props}
|
|
33
|
+
>
|
|
34
|
+
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
35
|
+
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
36
|
+
</svg>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const Chip = forwardRef<HTMLInputElement, ChipProps>(function Chip(
|
|
41
|
+
{
|
|
42
|
+
error = false,
|
|
43
|
+
icon,
|
|
44
|
+
onDelete,
|
|
45
|
+
deleteLabel = "Delete",
|
|
46
|
+
deleteTabIndex,
|
|
47
|
+
deleteIconRef,
|
|
48
|
+
children,
|
|
49
|
+
checked,
|
|
50
|
+
overStyled = false,
|
|
51
|
+
wrapperProps,
|
|
52
|
+
tabIndex,
|
|
53
|
+
"aria-hidden": ariaHidden,
|
|
54
|
+
...rest
|
|
55
|
+
},
|
|
56
|
+
ref,
|
|
57
|
+
) {
|
|
58
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
59
|
+
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
60
|
+
|
|
61
|
+
const mergedClassNames = mergeClassNames(
|
|
62
|
+
{
|
|
63
|
+
root: styles.root,
|
|
64
|
+
label: styles.label,
|
|
65
|
+
input: styles.input,
|
|
66
|
+
iconWrapper: styles.mantineIconWrapper,
|
|
67
|
+
checkIcon: styles.checkIcon,
|
|
68
|
+
},
|
|
69
|
+
restRecord.classNames as Partial<Record<string, string>> | undefined,
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const classNameProp = restRecord.className as string | undefined;
|
|
73
|
+
const finalClass = classNameProp
|
|
74
|
+
? `${styles.root} ${classNameProp}`
|
|
75
|
+
: styles.root;
|
|
76
|
+
|
|
77
|
+
// Determine state
|
|
78
|
+
const dataError = error ? "" : undefined;
|
|
79
|
+
const isIconOnly = !children && (!!icon || !!onDelete);
|
|
80
|
+
// A chip only counts as interactive when something actually responds to it — merely passing a
|
|
81
|
+
// `checked` value (e.g. to pin a display-only chip to a fixed visual state, as FileUpload's
|
|
82
|
+
// read-only file list does) isn't itself an interaction, since clicking it with no onChange/
|
|
83
|
+
// onClick wired does nothing observable.
|
|
84
|
+
const isInteractive =
|
|
85
|
+
onDelete !== undefined ||
|
|
86
|
+
restRecord.onClick !== undefined ||
|
|
87
|
+
restRecord.onChange !== undefined;
|
|
88
|
+
|
|
89
|
+
// Our own computed default for Mantine's `wrapperProps` — flags the internal error/interactive
|
|
90
|
+
// CSS hooks. This is a real Mantine `ChipProps` slot a caller could legitimately pass their own
|
|
91
|
+
// value for, so it must merge via `withCallerOverride`, not silently clobber theirs.
|
|
92
|
+
const computedWrapperProps = {
|
|
93
|
+
...(dataError !== undefined ? { "data-error": "" } : {}),
|
|
94
|
+
...(isInteractive ? { "data-interactive": "" } : {}),
|
|
95
|
+
} as NonNullable<MantineChipProps["wrapperProps"]>;
|
|
96
|
+
|
|
97
|
+
return (
|
|
98
|
+
<MantineChip
|
|
99
|
+
ref={ref}
|
|
100
|
+
{...sanitizedProps}
|
|
101
|
+
checked={checked}
|
|
102
|
+
className={finalClass}
|
|
103
|
+
classNames={mergedClassNames}
|
|
104
|
+
wrapperProps={withCallerOverride(computedWrapperProps, wrapperProps)}
|
|
105
|
+
data-icon-only={isIconOnly ? "" : undefined}
|
|
106
|
+
tabIndex={withCallerOverride<number | undefined>(
|
|
107
|
+
isInteractive ? undefined : -1,
|
|
108
|
+
tabIndex,
|
|
109
|
+
)}
|
|
110
|
+
aria-hidden={withCallerOverride<boolean | "true" | "false" | undefined>(
|
|
111
|
+
isInteractive ? undefined : true,
|
|
112
|
+
ariaHidden,
|
|
113
|
+
)}
|
|
114
|
+
>
|
|
115
|
+
<span className={styles.innerWrapper}>
|
|
116
|
+
{/* When checked, Mantine's own check icon (rendered in its native iconWrapper slot,
|
|
117
|
+
ahead of this children span) overlays/replaces the leading icon rather than sitting
|
|
118
|
+
next to it — matching mui-adapter's `icon={checked ? checkIcon : icon}` swap. */}
|
|
119
|
+
{icon && !checked && (
|
|
120
|
+
<span className={styles.leadingIcon} aria-hidden>
|
|
121
|
+
{icon}
|
|
122
|
+
</span>
|
|
123
|
+
)}
|
|
124
|
+
|
|
125
|
+
<span className={styles.children}>{children}</span>
|
|
126
|
+
|
|
127
|
+
{onDelete && (
|
|
128
|
+
<span
|
|
129
|
+
ref={deleteIconRef}
|
|
130
|
+
role="button"
|
|
131
|
+
className={styles.deleteIcon}
|
|
132
|
+
onClick={(e) => {
|
|
133
|
+
e.preventDefault();
|
|
134
|
+
e.stopPropagation();
|
|
135
|
+
onDelete(e);
|
|
136
|
+
}}
|
|
137
|
+
aria-label={deleteLabel}
|
|
138
|
+
onKeyDown={(e) => {
|
|
139
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
140
|
+
e.preventDefault();
|
|
141
|
+
e.stopPropagation();
|
|
142
|
+
onDelete(
|
|
143
|
+
e as unknown as React.MouseEvent<HTMLSpanElement, MouseEvent>,
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
}}
|
|
147
|
+
tabIndex={deleteTabIndex ?? 0}
|
|
148
|
+
>
|
|
149
|
+
<CloseIcon />
|
|
150
|
+
</span>
|
|
151
|
+
)}
|
|
152
|
+
</span>
|
|
153
|
+
</MantineChip>
|
|
154
|
+
);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
Chip.displayName = "Chip";
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Chip - Usage Guide
|
|
2
|
+
|
|
3
|
+
This document describes how to integrate and use the `Chip` component in your projects using `@recursica/adapter-mantine-v8`.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Import Reference
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { Chip } from "@recursica/adapter-mantine-v8";
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 2. Basic Example
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import React from "react";
|
|
19
|
+
import { Chip } from "@recursica/adapter-mantine-v8";
|
|
20
|
+
|
|
21
|
+
export default function Demo() {
|
|
22
|
+
return <Chip defaultChecked>Clickable Chip</Chip>;
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 3. Design System Integration
|
|
29
|
+
|
|
30
|
+
All Recursica components in the `@recursica/adapter-mantine-v8` 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.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## 4. Key Integration Features & Constraints
|
|
41
|
+
|
|
42
|
+
### Accessibility of Remove Action
|
|
43
|
+
|
|
44
|
+
The remove/close action is keyboard accessible — it can be activated via keyboard as well as mouse click.
|
|
45
|
+
|
|
46
|
+
### Sizing
|
|
47
|
+
|
|
48
|
+
Chip does not support a `size` prop; chips render at a fixed size.
|
|
49
|
+
|
|
50
|
+
### Building a keyboard-navigable chip group
|
|
51
|
+
|
|
52
|
+
`deleteTabIndex` and `deleteIconRef` are optional escape hatches for composing a _group_ of chips
|
|
53
|
+
with roving-tabindex keyboard navigation (Tab reaches one chip at a time, arrow keys move between
|
|
54
|
+
them) — see `FileUpload`'s file list for a working example. Ignore both for a standalone chip; they
|
|
55
|
+
default to a normal `tabIndex={0}` delete icon with no ref.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# Container Implementation Notes
|
|
2
|
+
|
|
3
|
+
The `Container` component is a generic layout wrapper mapped directly to Mantine's `Container`.
|
|
4
|
+
It serves to provide standardized centered max-width bounds around content. Mantine handles the width boundaries inherently based on size properties.
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
|
+
import { Container } from "./Container";
|
|
4
|
+
import { Text } from "../Text/Text";
|
|
5
|
+
|
|
6
|
+
type ContainerStoryProps = React.ComponentProps<typeof Container>;
|
|
7
|
+
|
|
8
|
+
const meta: Meta<ContainerStoryProps> = {
|
|
9
|
+
title: "UI-Kit/Container",
|
|
10
|
+
component: Container,
|
|
11
|
+
tags: ["autodocs"],
|
|
12
|
+
parameters: {
|
|
13
|
+
docs: {
|
|
14
|
+
description: {
|
|
15
|
+
component:
|
|
16
|
+
"Container is a generic layout wrapper that safely maps to Mantine's Container, standardizing maximum content widths across the application.",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
args: {
|
|
21
|
+
size: "md",
|
|
22
|
+
fluid: false,
|
|
23
|
+
},
|
|
24
|
+
argTypes: {
|
|
25
|
+
size: {
|
|
26
|
+
control: "select",
|
|
27
|
+
options: [
|
|
28
|
+
"xs",
|
|
29
|
+
"sm",
|
|
30
|
+
"md",
|
|
31
|
+
"lg",
|
|
32
|
+
"xl",
|
|
33
|
+
"rec-sm",
|
|
34
|
+
"rec-default",
|
|
35
|
+
"rec-md",
|
|
36
|
+
"rec-lg",
|
|
37
|
+
"rec-xl",
|
|
38
|
+
"rec-2xl",
|
|
39
|
+
],
|
|
40
|
+
description:
|
|
41
|
+
"Maximum width defined by Mantine system sizes or Recursica sizes",
|
|
42
|
+
},
|
|
43
|
+
fluid: {
|
|
44
|
+
control: "boolean",
|
|
45
|
+
description: "If true, overrides size and sets max-width to 100%",
|
|
46
|
+
},
|
|
47
|
+
defaultChecked: {
|
|
48
|
+
table: { disable: true },
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export default meta;
|
|
54
|
+
|
|
55
|
+
type Story = StoryObj<ContainerStoryProps>;
|
|
56
|
+
|
|
57
|
+
export const Default: Story = {
|
|
58
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
59
|
+
render: ({ withLayer, layer, ...args }: any) => (
|
|
60
|
+
<div style={{ backgroundColor: "#f0f0f0", padding: "16px" }}>
|
|
61
|
+
<Container
|
|
62
|
+
{...args}
|
|
63
|
+
style={{
|
|
64
|
+
backgroundColor: "white",
|
|
65
|
+
padding: "16px",
|
|
66
|
+
border: "1px solid #ccc",
|
|
67
|
+
}}
|
|
68
|
+
>
|
|
69
|
+
<Text>
|
|
70
|
+
This is a Container holding centered content. The background and
|
|
71
|
+
border are added just to demonstrate the layout bounds visually.
|
|
72
|
+
</Text>
|
|
73
|
+
</Container>
|
|
74
|
+
</div>
|
|
75
|
+
),
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export const SmallContainer: Story = {
|
|
79
|
+
args: {
|
|
80
|
+
size: "sm",
|
|
81
|
+
},
|
|
82
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
83
|
+
render: ({ withLayer, layer, ...args }: any) => (
|
|
84
|
+
<div style={{ backgroundColor: "#f0f0f0", padding: "16px" }}>
|
|
85
|
+
<Container
|
|
86
|
+
{...args}
|
|
87
|
+
style={{
|
|
88
|
+
backgroundColor: "white",
|
|
89
|
+
padding: "16px",
|
|
90
|
+
border: "1px solid #ccc",
|
|
91
|
+
}}
|
|
92
|
+
>
|
|
93
|
+
<Text>Small Container Layout</Text>
|
|
94
|
+
</Container>
|
|
95
|
+
</div>
|
|
96
|
+
),
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export const FluidContainer: Story = {
|
|
100
|
+
args: {
|
|
101
|
+
fluid: true,
|
|
102
|
+
},
|
|
103
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
104
|
+
render: ({ withLayer, layer, ...args }: any) => (
|
|
105
|
+
<div style={{ backgroundColor: "#f0f0f0", padding: "16px" }}>
|
|
106
|
+
<Container
|
|
107
|
+
{...args}
|
|
108
|
+
style={{
|
|
109
|
+
backgroundColor: "white",
|
|
110
|
+
padding: "16px",
|
|
111
|
+
border: "1px solid #ccc",
|
|
112
|
+
}}
|
|
113
|
+
>
|
|
114
|
+
<Text>Fluid Container Layout</Text>
|
|
115
|
+
</Container>
|
|
116
|
+
</div>
|
|
117
|
+
),
|
|
118
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Placeholder for future Container component tests. Add tests here if/when needed.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { forwardRef } from "react";
|
|
2
|
+
import {
|
|
3
|
+
Container as MantineContainer,
|
|
4
|
+
type ContainerProps as MantineContainerProps,
|
|
5
|
+
} from "@mantine/core";
|
|
6
|
+
import styles from "./Container.module.css";
|
|
7
|
+
|
|
8
|
+
import { type WithRecursicaSpacing } from "../../utils/filterStylingProps";
|
|
9
|
+
import { type RecursicaContainerProps } from "@recursica/adapter-common";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Container layout wrapper.
|
|
13
|
+
*
|
|
14
|
+
* Note: Unlike complex UI components, primitive layout components (Flex, Stack, Group, Container)
|
|
15
|
+
* DO NOT use the `RecursicaOverStyled` gatekeeper. Developers must be able to freely pass
|
|
16
|
+
* width, height, padding, margins, and flexbox alignment props to construct structural layouts.
|
|
17
|
+
*/
|
|
18
|
+
export type ContainerProps = WithRecursicaSpacing<
|
|
19
|
+
Omit<MantineContainerProps, "size"> & RecursicaContainerProps
|
|
20
|
+
>;
|
|
21
|
+
|
|
22
|
+
export const Container = forwardRef<HTMLDivElement, ContainerProps>(
|
|
23
|
+
function Container({ children, size, ...rest }, ref) {
|
|
24
|
+
const mapSize: Record<string, string> = {
|
|
25
|
+
"rec-sm": "sm",
|
|
26
|
+
"rec-default": "md",
|
|
27
|
+
"rec-md": "md",
|
|
28
|
+
"rec-lg": "lg",
|
|
29
|
+
"rec-xl": "xl",
|
|
30
|
+
"rec-2xl": "xl",
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const resolvedSize =
|
|
34
|
+
typeof size === "string" && mapSize[size] ? mapSize[size] : size;
|
|
35
|
+
|
|
36
|
+
const mergedClassNames: Partial<Record<string, string>> = {
|
|
37
|
+
root: styles.root,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const classNamesProp = rest.classNames;
|
|
41
|
+
if (
|
|
42
|
+
classNamesProp &&
|
|
43
|
+
typeof classNamesProp === "object" &&
|
|
44
|
+
!Array.isArray(classNamesProp)
|
|
45
|
+
) {
|
|
46
|
+
const o = classNamesProp as Partial<Record<string, string>>;
|
|
47
|
+
mergedClassNames.root = o.root ? `${styles.root} ${o.root}` : styles.root;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const classNameProp = rest.className as string | undefined;
|
|
51
|
+
const finalClass = classNameProp
|
|
52
|
+
? `${styles.root} ${classNameProp}`
|
|
53
|
+
: styles.root;
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<MantineContainer
|
|
57
|
+
ref={ref}
|
|
58
|
+
size={resolvedSize}
|
|
59
|
+
className={finalClass}
|
|
60
|
+
classNames={mergedClassNames}
|
|
61
|
+
{...rest}
|
|
62
|
+
>
|
|
63
|
+
{children}
|
|
64
|
+
</MantineContainer>
|
|
65
|
+
);
|
|
66
|
+
},
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
Container.displayName = "Container";
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Container - Usage Guide
|
|
2
|
+
|
|
3
|
+
This document describes how to integrate and use the `Container` component in your projects using `@recursica/adapter-mantine-v8`.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Import Reference
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { Container } from "@recursica/adapter-mantine-v8";
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 2. Basic Example
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import React from "react";
|
|
19
|
+
import { Container } from "@recursica/adapter-mantine-v8";
|
|
20
|
+
|
|
21
|
+
export default function Demo() {
|
|
22
|
+
return (
|
|
23
|
+
<Container size="lg">
|
|
24
|
+
<Text>Centered content container constrained by maximum width.</Text>
|
|
25
|
+
</Container>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 3. Design System Integration
|
|
33
|
+
|
|
34
|
+
All Recursica components in the `@recursica/adapter-mantine-v8` package adhere strictly to design system spacing, scaling, and behavior patterns.
|
|
35
|
+
|
|
36
|
+
> [!IMPORTANT]
|
|
37
|
+
>
|
|
38
|
+
> - **Anti-override protection**: Rogues style injections (like inline `style` or arbitrary `className`) are automatically blocked by our prop layer unless `overStyled={true}` is explicitly provided.
|
|
39
|
+
> - **No Direct Layers**: Do not pass a `layer` prop to this component. To place it on a specific visual layer, wrap it in a `<Layer layer={0|1|2|3}>` component natively.
|
|
40
|
+
> - **Variables and Theming**: Styling is entirely determined by local CSS variables defined in `recursica_variables_scoped.css` and mapped in the component's CSS module.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 4. Key Integration Features & Constraints
|
|
45
|
+
|
|
46
|
+
The `Container` component is a generic layout wrapper mapped directly to Mantine's `Container`.
|
|
47
|
+
It serves to provide standardized centered max-width bounds around content. Mantine handles the width boundaries inherently based on size properties.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# DatePicker Implementation Notes
|
|
2
|
+
|
|
3
|
+
## Architecture Overview
|
|
4
|
+
|
|
5
|
+
The `DatePicker` component is a wrapper around the `@mantine/dates` `DatePickerInput` component, implementing the `FormControlWrapper` macro structure for Recursica. This ensures that the component visually and structurally aligns with standard Recursica input primitives.
|
|
6
|
+
|
|
7
|
+
## Structural Constraints
|
|
8
|
+
|
|
9
|
+
1. **Naked Input Usage**: We intentionally pass `label={undefined}`, `description={undefined}`, and `error={undefined}` to the Mantine `DatePickerInput` component. This suppresses Mantine's internal macro form wrapping and ensures that only our `WithReadOnlyWrapper` > `FormControlWrapper` orchestrates labels, description text, and ARIA state error boundaries.
|
|
10
|
+
2. **Read-Only Implementation**: `readOnlyValue` is formatted via `@mantine/dates`' own `getFormattedDate` helper using the same `valueFormat` the editable `DatePickerInput` renders with — so a read-only date reads identically to that same value while editable (`05/20/26`, not a raw JS `Date.toString()`). Developers can still pass a custom `readOnlyComponent` to fully replace this rendering.
|
|
11
|
+
3. **Calendar Portal/Dropdown (Figma Token Issue)**: The Recursica UI Kit's `date-picker` component in Figma fails to export any explicit structural or color properties for the calendar popover itself (e.g. elevation, surface background, selected day colors, hover, today, in-range). To solve this organically within the framework without breaking strict token adherence, we manually map every calendar state to the closest existing Recursica token instead of leaving any of it on Mantine's own un-tokenized defaults:
|
|
12
|
+
- **Surface** (`.dropdown`) & **selected day** (`.day[data-selected]`): `--recursica_ui-kit_components_hover-card-popover` tokens for elevation/padding/surface, `--recursica_ui-kit_components_button_variants_styles_solid` tokens for the selected day fill (unchanged from before).
|
|
13
|
+
- **Header content, weekday row** (`.calendarHeader`, `.weekday`): the hover-card-popover content-color token — previously unmapped, so these leaked Mantine's own text colors.
|
|
14
|
+
- **Header nav controls & month/year label** (`.calendarHeaderControl`, `.calendarHeaderLevel`, `.calendarHeaderControlIcon`): these are functionally buttons, so they're now styled with `--recursica_ui-kit_components_button_variants_styles_text` tokens (border/background/color/elevation) plus small-size `Button` sizing tokens (height, icon-only vs. label-content border-radius/padding/min-width, icon size, typography) — the same tokens `Button`'s `data-variant="text"` uses. Disabled opacity/elevation and the focus-visible ring also mirror `Button`'s own treatment instead of the generic brand tokens used elsewhere in this file.
|
|
15
|
+
- **Hover** (any day cell, header nav, header level button): the generic `--recursica_brand_states_hover_color`/`_hover_opacity` pair, via the same `::after`-overlay technique used by `Button`/`Menu` — the standard convention for components with no dedicated hover token. Unlike `Button`, the day number is a bare text node with no wrapping span to `z-index` above the overlay, so here the overlay sits at `z-index: -1` instead of the text getting `z-index: 1` — same visual effect, opposite side of the layering. Also unlike `Button` (a plain button with no library-native hover CSS), Mantine's `Day`/`CalendarHeaderControl`/`CalendarHeaderLevel` all ship their own native `:hover { background-color: ... }` rule — an explicit `background-color: transparent` reset on `:hover` was needed first, or the overlay would just layer on top of Mantine's own gray-0/dark-5 fill instead of replacing it. (Caught in review: the first pass added the overlay without this reset, and the visible hover color was indistinguishable from Mantine's plain default — confirmed via computed-style diffing, not just eyeballing the screenshot.)
|
|
16
|
+
- **Disabled / outside-month days**: the generic `--recursica_brand_states_disabled` opacity token — the same one used repo-wide (Button, Chip, Tree, Pagination, Accordion) for elements with no dedicated disabled token. **Disabled header nav/label controls** use `Button`'s own text-variant disabled opacity/elevation tokens instead, since they're now styled as `Button`.
|
|
17
|
+
- **Today marker**: no dedicated token exists, so it reuses the hover-card-popover border-size/color tokens already used for the dropdown surface's own border (previously hardcoded `1px`). `highlightToday` is now defaulted to `true` in `DatePicker.tsx` (Mantine ships it `false`, meaning today was never marked at all before this pass).
|
|
18
|
+
- **Weekend days**: Mantine's default colors these red; the UI Kit has no such concept, so weekend text is explicitly forced back to the same color as any other day rather than left on that unrelated default.
|
|
19
|
+
- **Range selection** (`.day[data-in-range]`/`[data-first-in-range]`/`[data-last-in-range]`): styled with the generic `--recursica_brand_states_overlay_color`/`_overlay_opacity` pair — previously unused anywhere in the codebase, but its name and shape (a translucent tint token) is exactly this use case. **Not currently reachable through our public API**: `RecursicaDatePickerProps` doesn't discriminate on `type`, so `value`/`defaultValue` are typed for single-date selection only — `type="range"` fails typecheck for consumers. This CSS is forward-compatible groundwork, not a demoed feature; proper range-mode typing would be a separate, larger follow-up. Also flagged as a judgment call on the token pairing itself: first usage anywhere, no prior precedent or design-team confirmation.
|
|
20
|
+
|
|
21
|
+
## Styling Quirks
|
|
22
|
+
|
|
23
|
+
- The `DatePickerInput` mimics Mantine's `Input` structure natively (`.input`, `.wrapper`, `.section`). We attach our `styles.input` and `styles.root` classes exactly like `TextField`.
|
|
24
|
+
- The global layout margin override (`.layoutOverride`) utilizes `--form-control-margin-bottom` driven by specific stacked/side-by-side design tokens.
|
|
25
|
+
- **Popover `classNames` gotcha (bug fix)**: `.dropdown` was previously passed via the top-level `classNames` prop alongside `wrapper`/`input`/`section`/`day`/etc., which silently did nothing — the calendar surface is rendered by Mantine's internal `Popover`, whose style API is a separate namespace only reachable via `popoverProps.classNames` (`PickerInputBaseProps.popoverProps: Partial<Omit<PopoverProps, 'children'>>`). The `.dropdown` CSS (background/border/border-radius/box-shadow/padding/font-family, matching `Popover`'s own `.dropdown` rules 1:1) was never actually applied until this was fixed — confirmed via computed styles before/after (`box-shadow: none` → the real elevation token). `DatePicker.tsx` now merges any consumer-supplied `popoverProps`/`popoverProps.classNames` with our default instead of overwriting them.
|
|
26
|
+
- **Default value format**: `valueFormat="MM/DD/YY"` (a `dayjs` format string, Mantine's default is `"MMMM D, YYYY"`), set before the `sanitizedProps` spread so consumers can still override via their own `valueFormat` prop.
|
|
27
|
+
- **Default leading icon**: `leftSection={<CalendarIcon />}` (new `DatePicker.icons.tsx`, following the existing local-inline-SVG convention used by `Pagination.icons.tsx` — no icon library is a dependency of either adapter) is set the same way, overridable via `leftSection`.
|
|
28
|
+
- **Default placeholder**: `placeholder="MM / DD / YY"`, set the same way (before `sanitizedProps`, so consumers can override).
|
|
29
|
+
- **Single-line enforcement (bug fix)**: `DatePickerInput` renders its value/placeholder as a `<button>`'s text content, not a native `<input>` — it wraps like any other block text by default. A long placeholder (e.g. the original story's `"Select a deadline..."`) wrapped to two lines, inflating the field's height well past its `min-height` token and making the field visually look narrower than its actual `width` token value even though the box itself was always the right size. Fixed with `white-space: nowrap`/`text-overflow: ellipsis`/`overflow-x: clip`/`overflow-y: visible` on `.input`, the same convention `FileInput.module.css`'s `.value` uses.
|
|
30
|
+
- **Day focus ring (bug fix)**: Mantine's `Day` ships no built-in `:focus-visible` style of its own (unlike `.calendarHeaderControl`/`.calendarHeaderLevel`, which are styled as `Button` and inherited a focus ring from that treatment), so a focused day — e.g. the auto-focused selected/today day when the calendar opens — fell through to the browser's native blue outline instead of a Recursica token. Fixed by adding `.day:focus-visible` with the same generic `--recursica_brand_states_focus_*` box-shadow ring already used by `.input` and `.calendarHeaderControl`/`.calendarHeaderLevel`. mui-adapter's `.MuiPickerDay-root.Mui-focusVisible` already had this — only the adapter-mantine-v8 side was missing it.
|
|
31
|
+
- **Read-only value format (bug fix, 2026-08-30)**: `readOnlyValue` used to be a bare `String(value)`/`String(defaultValue)` cast — `Date`'s own `toString()`, e.g. `"Wed May 20 2026 17:00:00 GMT-0700 (Pacific Daylight Time)"` — completely ignoring `valueFormat`, so `ui-kit-datepicker--static-read-only` rendered a totally different (and far less usable) date string than the same value shown editable, or than mui-adapter's equivalent (which already formats its read-only text via dayjs). Fixed by running the value through `@mantine/dates`' exported `getFormattedDate({ type: "default", date, locale: "en", format: valueFormat, labelSeparator: "" })` — the same formatter `DatePickerInput` uses internally — so read-only and editable rendering of the same value always agree.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Default leading icon for DatePicker's left section. Consumers can override it by passing
|
|
5
|
+
* their own `leftSection` prop (see DatePicker.tsx). Sized/colored entirely via the generic
|
|
6
|
+
* `.section :global(svg)` rule in DatePicker.module.css, same as the icon in the
|
|
7
|
+
* WithLeadingIcon story — no width/height/color hardcoded here on purpose.
|
|
8
|
+
*/
|
|
9
|
+
export function CalendarIcon(props: React.SVGProps<SVGSVGElement>) {
|
|
10
|
+
return (
|
|
11
|
+
<svg
|
|
12
|
+
viewBox="0 0 24 24"
|
|
13
|
+
fill="none"
|
|
14
|
+
stroke="currentColor"
|
|
15
|
+
strokeWidth="2"
|
|
16
|
+
strokeLinecap="round"
|
|
17
|
+
strokeLinejoin="round"
|
|
18
|
+
aria-hidden
|
|
19
|
+
{...props}
|
|
20
|
+
>
|
|
21
|
+
<rect x="3" y="4" width="18" height="18" rx="2" ry="2" />
|
|
22
|
+
<line x1="16" y1="2" x2="16" y2="6" />
|
|
23
|
+
<line x1="8" y1="2" x2="8" y2="6" />
|
|
24
|
+
<line x1="3" y1="10" x2="21" y2="10" />
|
|
25
|
+
</svg>
|
|
26
|
+
);
|
|
27
|
+
}
|