@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,172 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { HoverCard } from "./HoverCard";
|
|
3
|
+
import { Button } from "../Button";
|
|
4
|
+
import { Text } from "../Text/Text";
|
|
5
|
+
import { Group } from "../Group/Group";
|
|
6
|
+
import { Stack } from "../Stack/Stack";
|
|
7
|
+
import { Avatar } from "../Avatar";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* HoverCard story axes:
|
|
11
|
+
* - position: dropdown alignment relative to target
|
|
12
|
+
* - withArrow: arrow indicator on the dropdown
|
|
13
|
+
* - openDelay / closeDelay: hover timing controls
|
|
14
|
+
* - content variations: plain text, rich content (avatar + text + actions)
|
|
15
|
+
* - layer: tested via the global Layer decorator (withLayer/layer args)
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
19
|
+
type HoverCardStoryArgs = Record<string, any>;
|
|
20
|
+
|
|
21
|
+
const meta: Meta = {
|
|
22
|
+
title: "UI-Kit/HoverCard",
|
|
23
|
+
component: HoverCard,
|
|
24
|
+
tags: ["autodocs"],
|
|
25
|
+
argTypes: {
|
|
26
|
+
position: {
|
|
27
|
+
control: "select",
|
|
28
|
+
options: [
|
|
29
|
+
"bottom",
|
|
30
|
+
"bottom-start",
|
|
31
|
+
"bottom-end",
|
|
32
|
+
"top",
|
|
33
|
+
"top-start",
|
|
34
|
+
"top-end",
|
|
35
|
+
"left",
|
|
36
|
+
"left-start",
|
|
37
|
+
"left-end",
|
|
38
|
+
"right",
|
|
39
|
+
"right-start",
|
|
40
|
+
"right-end",
|
|
41
|
+
],
|
|
42
|
+
description: "The position of the dropdown relative to the target.",
|
|
43
|
+
},
|
|
44
|
+
withBeak: {
|
|
45
|
+
control: "boolean",
|
|
46
|
+
description:
|
|
47
|
+
"Whether to display a beak (arrow) pointing to the target. Recursica equivalent of Mantine's withArrow.",
|
|
48
|
+
},
|
|
49
|
+
offset: {
|
|
50
|
+
control: "number",
|
|
51
|
+
description:
|
|
52
|
+
"Distance in px between the dropdown and the target element.",
|
|
53
|
+
},
|
|
54
|
+
openDelay: {
|
|
55
|
+
control: "number",
|
|
56
|
+
description: "Delay in ms before the dropdown opens on hover.",
|
|
57
|
+
},
|
|
58
|
+
closeDelay: {
|
|
59
|
+
control: "number",
|
|
60
|
+
description: "Delay in ms before the dropdown closes when hover ends.",
|
|
61
|
+
},
|
|
62
|
+
disabled: {
|
|
63
|
+
control: "boolean",
|
|
64
|
+
description: "If set, the hover card dropdown will not be rendered.",
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
parameters: {
|
|
68
|
+
layout: "centered",
|
|
69
|
+
docs: {
|
|
70
|
+
description: {
|
|
71
|
+
component: `
|
|
72
|
+
The \`HoverCard\` component displays a popover-style dropdown when the user hovers over a target element. It wraps Mantine's composable \`HoverCard\` while enforcing strict Recursica design token styling.
|
|
73
|
+
|
|
74
|
+
### Composable API
|
|
75
|
+
|
|
76
|
+
HoverCard uses a dot-notation composition pattern:
|
|
77
|
+
- \`<HoverCard>\` — Root container managing open/close state on hover
|
|
78
|
+
- \`<HoverCard.Target>\` — Wrapper for the trigger element (must be a single element supporting ref)
|
|
79
|
+
- \`<HoverCard.Dropdown>\` — The popup panel displaying content on hover
|
|
80
|
+
|
|
81
|
+
### Key Behaviors
|
|
82
|
+
- The dropdown opens when the user hovers over the target and closes when they move away
|
|
83
|
+
- \`openDelay\` and \`closeDelay\` control the timing of open/close transitions
|
|
84
|
+
- The dropdown stays open while the user hovers over it, allowing interaction with its content
|
|
85
|
+
`,
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export default meta;
|
|
92
|
+
|
|
93
|
+
type Story = StoryObj<HoverCardStoryArgs>;
|
|
94
|
+
|
|
95
|
+
export const Default: Story = {
|
|
96
|
+
args: {
|
|
97
|
+
position: "top",
|
|
98
|
+
withBeak: true,
|
|
99
|
+
offset: 5,
|
|
100
|
+
openDelay: 0,
|
|
101
|
+
closeDelay: 150,
|
|
102
|
+
},
|
|
103
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
104
|
+
render: ({ withLayer, layer, ...args }: HoverCardStoryArgs) => {
|
|
105
|
+
return (
|
|
106
|
+
<HoverCard {...args}>
|
|
107
|
+
<HoverCard.Target>
|
|
108
|
+
<Button variant="solid">Hover me</Button>
|
|
109
|
+
</HoverCard.Target>
|
|
110
|
+
|
|
111
|
+
<HoverCard.Dropdown>
|
|
112
|
+
<Text>
|
|
113
|
+
This is a hover card with informational content that appears when
|
|
114
|
+
you hover over the target element.
|
|
115
|
+
</Text>
|
|
116
|
+
</HoverCard.Dropdown>
|
|
117
|
+
</HoverCard>
|
|
118
|
+
);
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
export const WithoutBeak: Story = {
|
|
123
|
+
args: {
|
|
124
|
+
position: "top",
|
|
125
|
+
withBeak: false,
|
|
126
|
+
offset: 5,
|
|
127
|
+
},
|
|
128
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
129
|
+
render: ({ withLayer, layer, ...args }: HoverCardStoryArgs) => {
|
|
130
|
+
return (
|
|
131
|
+
<HoverCard {...args}>
|
|
132
|
+
<HoverCard.Target>
|
|
133
|
+
<Button variant="outline">Without Beak</Button>
|
|
134
|
+
</HoverCard.Target>
|
|
135
|
+
|
|
136
|
+
<HoverCard.Dropdown>
|
|
137
|
+
<Text>
|
|
138
|
+
This hover card has the beak disabled, showing a clean dropdown
|
|
139
|
+
without the pointing indicator.
|
|
140
|
+
</Text>
|
|
141
|
+
</HoverCard.Dropdown>
|
|
142
|
+
</HoverCard>
|
|
143
|
+
);
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
export const RichContent: Story = {
|
|
148
|
+
args: {
|
|
149
|
+
position: "top",
|
|
150
|
+
offset: 5,
|
|
151
|
+
},
|
|
152
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
153
|
+
render: ({ withLayer, layer, ...args }: HoverCardStoryArgs) => {
|
|
154
|
+
return (
|
|
155
|
+
<HoverCard {...args}>
|
|
156
|
+
<HoverCard.Target>
|
|
157
|
+
<Button variant="solid">User Profile</Button>
|
|
158
|
+
</HoverCard.Target>
|
|
159
|
+
|
|
160
|
+
<HoverCard.Dropdown>
|
|
161
|
+
<Group>
|
|
162
|
+
<Avatar src={null} alt="User avatar" />
|
|
163
|
+
<Stack>
|
|
164
|
+
<Text>Jane Doe</Text>
|
|
165
|
+
<Text>Software Engineer at Recursica</Text>
|
|
166
|
+
</Stack>
|
|
167
|
+
</Group>
|
|
168
|
+
</HoverCard.Dropdown>
|
|
169
|
+
</HoverCard>
|
|
170
|
+
);
|
|
171
|
+
},
|
|
172
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Placeholder for future HoverCard component tests. Add tests here if/when needed.
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import {
|
|
2
|
+
HoverCard as MantineHoverCard,
|
|
3
|
+
type HoverCardProps as MantineHoverCardProps,
|
|
4
|
+
type HoverCardTargetProps as MantineHoverCardTargetProps,
|
|
5
|
+
type HoverCardDropdownProps as MantineHoverCardDropdownProps,
|
|
6
|
+
} from "@mantine/core";
|
|
7
|
+
import {
|
|
8
|
+
filterStylingProps,
|
|
9
|
+
mergeClassNames,
|
|
10
|
+
type RecursicaOverStyled,
|
|
11
|
+
} from "../../utils/filterStylingProps";
|
|
12
|
+
import styles from "./HoverCard.module.css";
|
|
13
|
+
|
|
14
|
+
// ============================================================
|
|
15
|
+
// HOVERCARD ROOT
|
|
16
|
+
// ============================================================
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Recursica-specific props for HoverCard.
|
|
20
|
+
*/
|
|
21
|
+
import { type RecursicaHoverCardProps } from "@recursica/adapter-common";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Recursica HoverCard component wrapping Mantine's composable HoverCard.
|
|
25
|
+
*
|
|
26
|
+
* Displays a dropdown panel when the user hovers over a target element.
|
|
27
|
+
* Uses the composable dot-notation pattern:
|
|
28
|
+
* ```tsx
|
|
29
|
+
* <HoverCard withBeak>
|
|
30
|
+
* <HoverCard.Target>
|
|
31
|
+
* <Button>Hover me</Button>
|
|
32
|
+
* </HoverCard.Target>
|
|
33
|
+
* <HoverCard.Dropdown>
|
|
34
|
+
* Content displayed on hover
|
|
35
|
+
* </HoverCard.Dropdown>
|
|
36
|
+
* </HoverCard>
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export type HoverCardProps = RecursicaOverStyled<
|
|
40
|
+
MantineHoverCardProps & RecursicaHoverCardProps
|
|
41
|
+
>;
|
|
42
|
+
|
|
43
|
+
const HoverCardBase = function HoverCard({
|
|
44
|
+
overStyled = false,
|
|
45
|
+
withBeak = true,
|
|
46
|
+
position = "top", // Recursica default; Mantine defaults to "bottom". Consumers can still override.
|
|
47
|
+
// arrowSize must be a JS number prop — Mantine uses it for inline width/height
|
|
48
|
+
// and positioning offset (-arrowSize/2) calculations that cannot be CSS-driven.
|
|
49
|
+
// Default to 16 to match the Recursica beak-size token (16px). Consumers can still override.
|
|
50
|
+
arrowSize = 16,
|
|
51
|
+
withArrow,
|
|
52
|
+
...rest
|
|
53
|
+
}: HoverCardProps) {
|
|
54
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
55
|
+
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
56
|
+
|
|
57
|
+
// Bind CSS module classes to Mantine's internal classNames API
|
|
58
|
+
const mergedClassNames = mergeClassNames(
|
|
59
|
+
{
|
|
60
|
+
dropdown: styles.dropdown,
|
|
61
|
+
arrow: styles.arrow,
|
|
62
|
+
},
|
|
63
|
+
restRecord.classNames as Partial<Record<string, string>> | undefined,
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
// Resolve withBeak (Recursica) vs withArrow (Mantine).
|
|
67
|
+
// withBeak takes precedence when both are provided.
|
|
68
|
+
const resolvedWithArrow = withBeak ?? withArrow;
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<MantineHoverCard
|
|
72
|
+
{...(sanitizedProps as unknown as MantineHoverCardProps)}
|
|
73
|
+
position={position}
|
|
74
|
+
arrowSize={arrowSize}
|
|
75
|
+
withArrow={resolvedWithArrow}
|
|
76
|
+
classNames={mergedClassNames}
|
|
77
|
+
/>
|
|
78
|
+
);
|
|
79
|
+
};
|
|
80
|
+
HoverCardBase.displayName = "HoverCard";
|
|
81
|
+
|
|
82
|
+
// ============================================================
|
|
83
|
+
// HOVERCARD TARGET
|
|
84
|
+
// ============================================================
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Wrapper for the element that triggers the hover card.
|
|
88
|
+
* Requires a single child element that supports ref forwarding.
|
|
89
|
+
*/
|
|
90
|
+
export type HoverCardTargetProps = MantineHoverCardTargetProps;
|
|
91
|
+
|
|
92
|
+
const HoverCardTarget = function HoverCardTarget(props: HoverCardTargetProps) {
|
|
93
|
+
return <MantineHoverCard.Target {...props} />;
|
|
94
|
+
};
|
|
95
|
+
HoverCardTarget.displayName = "HoverCardTarget";
|
|
96
|
+
|
|
97
|
+
// ============================================================
|
|
98
|
+
// HOVERCARD DROPDOWN
|
|
99
|
+
// ============================================================
|
|
100
|
+
|
|
101
|
+
/** The dropdown panel displayed when hovering over the target. */
|
|
102
|
+
export type HoverCardDropdownProps =
|
|
103
|
+
RecursicaOverStyled<MantineHoverCardDropdownProps>;
|
|
104
|
+
|
|
105
|
+
const HoverCardDropdown = function HoverCardDropdown({
|
|
106
|
+
overStyled = false,
|
|
107
|
+
...rest
|
|
108
|
+
}: HoverCardDropdownProps) {
|
|
109
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
110
|
+
const classNameProp = (sanitizedProps as Record<string, unknown>)
|
|
111
|
+
.className as string | undefined;
|
|
112
|
+
|
|
113
|
+
return (
|
|
114
|
+
<MantineHoverCard.Dropdown
|
|
115
|
+
{...(sanitizedProps as unknown as MantineHoverCardDropdownProps)}
|
|
116
|
+
className={classNameProp}
|
|
117
|
+
/>
|
|
118
|
+
);
|
|
119
|
+
};
|
|
120
|
+
HoverCardDropdown.displayName = "HoverCardDropdown";
|
|
121
|
+
|
|
122
|
+
// ============================================================
|
|
123
|
+
// DOT NOTATION EXPORT
|
|
124
|
+
// ============================================================
|
|
125
|
+
|
|
126
|
+
type HoverCardComponent = typeof HoverCardBase & {
|
|
127
|
+
Target: typeof HoverCardTarget;
|
|
128
|
+
Dropdown: typeof HoverCardDropdown;
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
export const HoverCard = HoverCardBase as HoverCardComponent;
|
|
132
|
+
HoverCard.Target = HoverCardTarget;
|
|
133
|
+
HoverCard.Dropdown = HoverCardDropdown;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# HoverCard - Usage Guide
|
|
2
|
+
|
|
3
|
+
This document describes how to integrate and use the `HoverCard` component in your projects using `@recursica/adapter-mantine-v8`.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Import Reference
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { HoverCard } from "@recursica/adapter-mantine-v8";
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 2. Basic Example
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import React from "react";
|
|
19
|
+
import { HoverCard } from "@recursica/adapter-mantine-v8";
|
|
20
|
+
|
|
21
|
+
export default function Demo() {
|
|
22
|
+
return (
|
|
23
|
+
<HoverCard>
|
|
24
|
+
<HoverCard.Target>
|
|
25
|
+
<Text>Hover over me</Text>
|
|
26
|
+
</HoverCard.Target>
|
|
27
|
+
<HoverCard.Dropdown>
|
|
28
|
+
<Text size="sm">This is the hover card popup content.</Text>
|
|
29
|
+
</HoverCard.Dropdown>
|
|
30
|
+
</HoverCard>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 3. Design System Integration
|
|
38
|
+
|
|
39
|
+
All Recursica components in the `@recursica/adapter-mantine-v8` package adhere strictly to design system spacing, scaling, and behavior patterns.
|
|
40
|
+
|
|
41
|
+
> [!IMPORTANT]
|
|
42
|
+
>
|
|
43
|
+
> - **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.
|
|
44
|
+
> - **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.
|
|
45
|
+
> - **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.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 4. Notes
|
|
50
|
+
|
|
51
|
+
- Mantine calls the pointer indicator the "arrow"; Recursica calls it the "beak". Use the `withBeak` prop (default `true`) to show or hide it; `withArrow` is also accepted for compatibility, with `withBeak` taking precedence.
|
|
52
|
+
- The default `position` is `"top"` (Mantine's default is `"bottom"`); pass your own `position` prop to override it.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Label Implementation Notes
|
|
2
|
+
|
|
3
|
+
## Architecture Overview
|
|
4
|
+
|
|
5
|
+
The `Label` component is fundamentally built as a strict, localized wrapper around Mantine's native `Input.Label`. The core goal is to preserve context, ref-forwarding, and native accessibility links, while completely overriding visual behaviors via Recursica design variables in scoped CSS.
|
|
6
|
+
|
|
7
|
+
## Key Design Decisions
|
|
8
|
+
|
|
9
|
+
### **Layout Architecture**
|
|
10
|
+
|
|
11
|
+
- Because Recursica dictates complex alignments between primary label text, asterisks, edit icons, and optional strings, Mantine's rigid form label flow could not be used out-of-the-box.
|
|
12
|
+
- Implemented `display: flex; flex-wrap: wrap;` directly on `.root`.
|
|
13
|
+
- Injected strict integer-based flex `order` properties (e.g. `order: 1` for text, `order: 2` for `required`, `order: 5` for `optionalText`) to physically decouple DOM rendering from markup flow.
|
|
14
|
+
- Because `optionalText` often acts as secondary contextual detail, it forces `flex-basis: 100%`, securely wrapping to a secondary line underneath the primary label properties and transforming the horizontal gap spacing seamlessly into a `margin-top` vector.
|
|
15
|
+
|
|
16
|
+
### **Optional Text & Required Mutually Exclusive Parsing**
|
|
17
|
+
|
|
18
|
+
- By design standards, a component cannot logically be both "Required" and mapped as "Optional".
|
|
19
|
+
- To bulletproof implementations natively, the adapter forcibly suppresses rendering of the `resolvedOptionalText` strings if the parent wrapper invokes `required={true}`.
|
|
20
|
+
- `optionalText` can operate as dynamic data or specifically as a boolean `true`, which forces the adapter to natively render the formal `(Optional)` string map.
|
|
21
|
+
|
|
22
|
+
### **The "Edit Icon" Replacer Logic**
|
|
23
|
+
|
|
24
|
+
- Passing `withEditIcon={true}` evaluates it as fundamentally mutually exclusive to the standard required indicator asterisk.
|
|
25
|
+
- `required={required && !withEditIcon}` is passed to the underlying Mantine structure so the native `*` is entirely suppressed.
|
|
26
|
+
- Added localized styling via `data-replaces-asterisk={required ? "true" : undefined}` onto the `.editIconWrapper` element. If an editable instance is simultaneously designated as required, the edit icon functionally assumes the indicator role natively, overriding its default icon metrics explicitly to match `--recursica_ui-kit_components_label_properties_colors_asterisk`.
|
|
27
|
+
|
|
28
|
+
### **Bypassing `Input.Wrapper` Integrations**
|
|
29
|
+
|
|
30
|
+
- By decoupling from Mantine's standard `Input.Wrapper`, the `Label` component is exclusively mapped manually through `FormControlWrapper`. This grants us exact visual sync regarding where the label renders based on `formLayout="stacked"` or `formLayout="side-by-side"`, without fighting internal Mantine positional hooks that assume vertical stacking by default.
|
|
31
|
+
|
|
32
|
+
### **Label Size Container Constraints**
|
|
33
|
+
|
|
34
|
+
- The `labelSize` parameter (mapping values like `"small"`) internally **does not scale typographic font metrics**. Instead, it dynamically defines the explicit horizontal bounding width limit of the block container itself.
|
|
35
|
+
- **Architectural Rule:** `labelSize` modifications are strictly designed to execute exclusively when `formLayout="side-by-side"` is active. It acts as an optical grid threshold ensuring left-aligned string wrappers constrain correctly uniformly down a column without bleeding into the physical input arrays alongside them.
|
|
36
|
+
|
|
37
|
+
## Outstanding Technical Debt / Issues
|
|
38
|
+
|
|
39
|
+
### **Description Property Omission**
|
|
40
|
+
|
|
41
|
+
- **Issue:** Currently, the adapter `Label` does not natively parse or support a structured `description` node directly attached beneath it.
|
|
42
|
+
- **Context:** Standard forms often attach subtext beneath inputs, but mapping a description purely within the `<Label>` (distinct from an overall form-control description) is omitted structurally until subsequent UI Kit requirements mandate dedicated `description` styles locally on the label component itself.
|
|
43
|
+
|
|
44
|
+
### **Global Interactive Hover Mappings**
|
|
45
|
+
|
|
46
|
+
- **Issue:** Currently, the `editIconWrapper` lacks a dedicated hover background layer.
|
|
47
|
+
- **Context:** While the global theme abstracts interactive hover environments deeply using layered variable syntax (e.g., `--recursica_brand_layer_1_elements_interactive_hover-color`), Recursica's token generation framework natively fails to expose a universally generic placeholder token (e.g., `--recursica_elements_interactive_hover-color`) which downstream wrappers can map their `<Layer>` injections directly into safely.
|
|
48
|
+
- **Resolution Path:** We are explicitly ignoring the `.editIconWrapper:hover` background color assignment until the raw Figma token exports directly scaffold a generic token placeholder that we can interface cleanly with across arbitrary `<Layer>` contexts, avoiding manually mapping statically hardcoded depths (`layer-0`, `layer-1`).
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/* HARDCODED VALUES:
|
|
2
|
+
- display: flex helps us leverage flex 'order' to perfectly position Mantine's injected asterisk.
|
|
3
|
+
- align-items: baseline ensures text logic lines up nicely if font sizes differ slightly.
|
|
4
|
+
- margin/padding resets.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
.root {
|
|
8
|
+
display: flex;
|
|
9
|
+
flex-wrap: wrap;
|
|
10
|
+
align-items: baseline;
|
|
11
|
+
box-sizing: border-box;
|
|
12
|
+
margin: 0;
|
|
13
|
+
color: var(--recursica_ui-kit_components_label_properties_colors_text-color);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.root[data-alignment="left"] {
|
|
17
|
+
justify-content: flex-start;
|
|
18
|
+
text-align: left;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.root[data-alignment="right"] {
|
|
22
|
+
justify-content: flex-end;
|
|
23
|
+
text-align: right;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.labelText {
|
|
27
|
+
order: 1;
|
|
28
|
+
font-family: var(
|
|
29
|
+
--recursica_ui-kit_components_label_properties_label-text_font-family
|
|
30
|
+
);
|
|
31
|
+
font-size: var(
|
|
32
|
+
--recursica_ui-kit_components_label_properties_label-text_font-size
|
|
33
|
+
);
|
|
34
|
+
font-weight: var(
|
|
35
|
+
--recursica_ui-kit_components_label_properties_label-text_font-weight
|
|
36
|
+
);
|
|
37
|
+
letter-spacing: var(
|
|
38
|
+
--recursica_ui-kit_components_label_properties_label-text_letter-spacing
|
|
39
|
+
);
|
|
40
|
+
line-height: var(
|
|
41
|
+
--recursica_ui-kit_components_label_properties_label-text_line-height
|
|
42
|
+
);
|
|
43
|
+
font-style: var(
|
|
44
|
+
--recursica_ui-kit_components_label_properties_label-text_font-style
|
|
45
|
+
);
|
|
46
|
+
text-decoration: var(
|
|
47
|
+
--recursica_ui-kit_components_label_properties_label-text_text-decoration
|
|
48
|
+
);
|
|
49
|
+
text-transform: var(
|
|
50
|
+
--recursica_ui-kit_components_label_properties_label-text_text-transform
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.required {
|
|
55
|
+
order: 2;
|
|
56
|
+
margin-left: var(
|
|
57
|
+
--recursica_ui-kit_components_label_properties_required-indicator-gap
|
|
58
|
+
);
|
|
59
|
+
color: var(
|
|
60
|
+
--recursica_ui-kit_components_label_properties_colors_asterisk-color
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
/* Inherit identical typography bounds to prevent flex row line-height stretching */
|
|
64
|
+
font-family: var(
|
|
65
|
+
--recursica_ui-kit_components_label_properties_label-text_font-family
|
|
66
|
+
);
|
|
67
|
+
font-size: var(
|
|
68
|
+
--recursica_ui-kit_components_label_properties_label-text_font-size
|
|
69
|
+
);
|
|
70
|
+
line-height: var(
|
|
71
|
+
--recursica_ui-kit_components_label_properties_label-text_line-height
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.optionalText {
|
|
76
|
+
order: 5;
|
|
77
|
+
flex-basis: 100%;
|
|
78
|
+
margin-top: var(
|
|
79
|
+
--recursica_ui-kit_components_label_properties_label-optional-text-gap
|
|
80
|
+
);
|
|
81
|
+
margin-left: 0;
|
|
82
|
+
font-family: var(
|
|
83
|
+
--recursica_ui-kit_components_label_properties_optional-text_font-family
|
|
84
|
+
);
|
|
85
|
+
font-size: var(
|
|
86
|
+
--recursica_ui-kit_components_label_properties_optional-text_font-size
|
|
87
|
+
);
|
|
88
|
+
font-weight: var(
|
|
89
|
+
--recursica_ui-kit_components_label_properties_optional-text_font-weight
|
|
90
|
+
);
|
|
91
|
+
letter-spacing: var(
|
|
92
|
+
--recursica_ui-kit_components_label_properties_optional-text_letter-spacing
|
|
93
|
+
);
|
|
94
|
+
line-height: var(
|
|
95
|
+
--recursica_ui-kit_components_label_properties_optional-text_line-height
|
|
96
|
+
);
|
|
97
|
+
font-style: var(
|
|
98
|
+
--recursica_ui-kit_components_label_properties_optional-text_font-style
|
|
99
|
+
);
|
|
100
|
+
text-decoration: var(
|
|
101
|
+
--recursica_ui-kit_components_label_properties_optional-text_text-decoration
|
|
102
|
+
);
|
|
103
|
+
text-transform: var(
|
|
104
|
+
--recursica_ui-kit_components_label_properties_optional-text_text-transform
|
|
105
|
+
);
|
|
106
|
+
color: inherit;
|
|
107
|
+
opacity: var(
|
|
108
|
+
--recursica_ui-kit_components_label_properties_optional-text-opacity
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.actionAreaWrapper {
|
|
113
|
+
order: 4;
|
|
114
|
+
margin-left: var(
|
|
115
|
+
--recursica_ui-kit_components_label_properties_edit-icon-gap
|
|
116
|
+
);
|
|
117
|
+
display: inline-flex;
|
|
118
|
+
align-items: center;
|
|
119
|
+
justify-content: center;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.editIconWrapper {
|
|
123
|
+
order: 4;
|
|
124
|
+
margin-left: var(
|
|
125
|
+
--recursica_ui-kit_components_label_properties_edit-icon-gap
|
|
126
|
+
);
|
|
127
|
+
background: none;
|
|
128
|
+
border: none;
|
|
129
|
+
padding: 0;
|
|
130
|
+
cursor: pointer;
|
|
131
|
+
display: inline-flex;
|
|
132
|
+
align-items: center;
|
|
133
|
+
justify-content: center;
|
|
134
|
+
color: inherit;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.editIconWrapper[data-replaces-asterisk="true"] {
|
|
138
|
+
color: var(
|
|
139
|
+
--recursica_ui-kit_components_label_properties_colors_asterisk-color
|
|
140
|
+
);
|
|
141
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
|
+
import { Label } from "./Label";
|
|
4
|
+
import { Button } from "../Button/Button";
|
|
5
|
+
|
|
6
|
+
type LabelStoryProps = React.ComponentProps<typeof Label>;
|
|
7
|
+
|
|
8
|
+
const meta: Meta<LabelStoryProps> = {
|
|
9
|
+
title: "UI-Kit/Label",
|
|
10
|
+
component: Label,
|
|
11
|
+
tags: ["autodocs"],
|
|
12
|
+
parameters: {
|
|
13
|
+
docs: {
|
|
14
|
+
description: {
|
|
15
|
+
component:
|
|
16
|
+
"The `Label` component is a strict Recursica-styled wrapper around Mantine's native `Input.Label`. It serves as the primary compositional primitive for all form fields, preserving Mantine's accessibility associations and context while strictly enforcing the Recursica atomic design system.\n\n### Usage with Form Inputs\nThis component only renders the label itself — layout concerns like `stacked` vs `side-by-side` positioning relative to an input live on `FormControlLayout`/`FormControlWrapper`, not here. Render this `Label` in isolation to verify its own states, or see `UI-Kit/FormControlLayout` for how it composes into a full form field.",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
argTypes: {
|
|
21
|
+
labelSize: {
|
|
22
|
+
control: "inline-radio",
|
|
23
|
+
options: ["default", "small"],
|
|
24
|
+
description:
|
|
25
|
+
"Sizing metrics for the Label. Only visually distinguishable once composed inside a `side-by-side` FormControlLayout, which is where the resulting width constraint applies.",
|
|
26
|
+
},
|
|
27
|
+
labelAlignment: {
|
|
28
|
+
control: "inline-radio",
|
|
29
|
+
options: ["left", "right"],
|
|
30
|
+
description: "Text alignment of the label content.",
|
|
31
|
+
},
|
|
32
|
+
required: {
|
|
33
|
+
control: "boolean",
|
|
34
|
+
description:
|
|
35
|
+
"Renders the required asterisk (suppressed automatically when `labelWithEditIcon` is set, and mutually exclusive with `labelOptionalText`).",
|
|
36
|
+
},
|
|
37
|
+
labelOptionalText: {
|
|
38
|
+
control: "text",
|
|
39
|
+
description:
|
|
40
|
+
"Secondary text rendered beneath the label. Pass `true` for the default '(Optional)' string, or a custom node/string. Suppressed when `required` is true.",
|
|
41
|
+
},
|
|
42
|
+
labelWithEditIcon: {
|
|
43
|
+
control: "boolean",
|
|
44
|
+
description:
|
|
45
|
+
"Replaces the default edit icon slot with an interactive edit affordance; replaces the required asterisk visually when both are set.",
|
|
46
|
+
},
|
|
47
|
+
labelActionArea: {
|
|
48
|
+
table: { disable: true },
|
|
49
|
+
},
|
|
50
|
+
onLabelEditClick: {
|
|
51
|
+
table: { disable: true },
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export default meta;
|
|
57
|
+
|
|
58
|
+
type Story = StoryObj<LabelStoryProps>;
|
|
59
|
+
|
|
60
|
+
export const Default: Story = {
|
|
61
|
+
args: {
|
|
62
|
+
children: "Label",
|
|
63
|
+
labelSize: "default",
|
|
64
|
+
labelAlignment: "left",
|
|
65
|
+
required: false,
|
|
66
|
+
labelOptionalText: "",
|
|
67
|
+
labelWithEditIcon: false,
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export const Required: Story = {
|
|
72
|
+
args: {
|
|
73
|
+
children: "Required Field",
|
|
74
|
+
required: true,
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export const RequiredSuppressesOptionalText: Story = {
|
|
79
|
+
args: {
|
|
80
|
+
children: "Full Name",
|
|
81
|
+
required: true,
|
|
82
|
+
labelOptionalText: "This should not render",
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export const WithOptionalText: Story = {
|
|
87
|
+
args: {
|
|
88
|
+
children: "Bio",
|
|
89
|
+
labelOptionalText: "Max 100 characters",
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export const BooleanOptionalText: Story = {
|
|
94
|
+
args: {
|
|
95
|
+
children: "Middle Initial",
|
|
96
|
+
labelOptionalText: true,
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export const WithEditIcon: Story = {
|
|
101
|
+
args: {
|
|
102
|
+
children: "Shipping Address",
|
|
103
|
+
labelWithEditIcon: true,
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export const RequiredWithEditIcon: Story = {
|
|
108
|
+
args: {
|
|
109
|
+
children: "Primary Network Node",
|
|
110
|
+
required: true,
|
|
111
|
+
labelWithEditIcon: true,
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export const RightAligned: Story = {
|
|
116
|
+
args: {
|
|
117
|
+
children: "Status",
|
|
118
|
+
labelAlignment: "right",
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
export const WithActionArea: Story = {
|
|
123
|
+
args: {
|
|
124
|
+
children: "Configuration",
|
|
125
|
+
labelActionArea: (
|
|
126
|
+
<Button variant="text" size="small">
|
|
127
|
+
Edit
|
|
128
|
+
</Button>
|
|
129
|
+
),
|
|
130
|
+
},
|
|
131
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Placeholder for future Label component tests. Add tests here if/when needed.
|