@recursica/mui-adapter 0.5.0 → 0.7.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.
Files changed (212) hide show
  1. package/ARCHITECTURE.md +15 -0
  2. package/CHANGELOG.md +15 -0
  3. package/SETUP.md +77 -0
  4. package/USAGE.md +55 -0
  5. package/dist/mui-adapter.cjs +74 -1
  6. package/dist/mui-adapter.cjs.map +1 -1
  7. package/dist/mui-adapter.css +1 -1
  8. package/dist/mui-adapter.js +6863 -205
  9. package/dist/mui-adapter.js.map +1 -1
  10. package/dist/src/components/Accordion/Accordion.d.ts +43 -2
  11. package/dist/src/components/AssistiveElement/AssistiveElement.d.ts +6 -2
  12. package/dist/src/components/Autocomplete/Autocomplete.d.ts +12 -2
  13. package/dist/src/components/Avatar/Avatar.d.ts +10 -3
  14. package/dist/src/components/Badge/Badge.d.ts +10 -3
  15. package/dist/src/components/Breadcrumb/Breadcrumb.d.ts +9 -3
  16. package/dist/src/components/Button/Button.d.ts +2 -17
  17. package/dist/src/components/Card/Card.d.ts +38 -3
  18. package/dist/src/components/Checkbox/Checkbox.d.ts +13 -2
  19. package/dist/src/components/Checkbox/CheckboxGroup.d.ts +18 -0
  20. package/dist/src/components/Checkbox/index.d.ts +5 -1
  21. package/dist/src/components/Chip/Chip.d.ts +9 -2
  22. package/dist/src/components/Container/Container.d.ts +1 -5
  23. package/dist/src/components/DatePicker/DatePicker.d.ts +2 -1
  24. package/dist/src/components/Dropdown/Dropdown.d.ts +12 -2
  25. package/dist/src/components/Flex/Flex.d.ts +2 -22
  26. package/dist/src/components/FormControlLayout/FormControlLayout.d.ts +5 -2
  27. package/dist/src/components/FormControlWrapper/FormControlWrapper.d.ts +9 -2
  28. package/dist/src/components/Group/Group.d.ts +2 -7
  29. package/dist/src/components/HoverCard/HoverCard.d.ts +28 -2
  30. package/dist/src/components/Label/Label.d.ts +6 -2
  31. package/dist/src/components/Link/Link.d.ts +2 -6
  32. package/dist/src/components/Loader/Loader.d.ts +2 -7
  33. package/dist/src/components/Menu/Menu.d.ts +25 -3
  34. package/dist/src/components/Modal/Modal.d.ts +37 -2
  35. package/dist/src/components/NumberInput/NumberInput.d.ts +12 -2
  36. package/dist/src/components/Pagination/Pagination.d.ts +12 -3
  37. package/dist/src/components/Pagination/Pagination.icons.d.ts +8 -0
  38. package/dist/src/components/Panel/Panel.d.ts +52 -3
  39. package/dist/src/components/Radio/Radio.d.ts +13 -3
  40. package/dist/src/components/Radio/RadioGroup.d.ts +9 -0
  41. package/dist/src/components/ReadOnlyField/ReadOnlyBooleanField.d.ts +5 -0
  42. package/dist/src/components/ReadOnlyField/ReadOnlyField.d.ts +4 -2
  43. package/dist/src/components/ReadOnlyField/ReadOnlySwitchField.d.ts +5 -0
  44. package/dist/src/components/ReadOnlyField/ReadOnlyTextField.d.ts +8 -0
  45. package/dist/src/components/ReadOnlyField/WithReadOnlyWrapper.d.ts +28 -0
  46. package/dist/src/components/ReadOnlyField/index.d.ts +1 -0
  47. package/dist/src/components/SegmentedControl/SegmentedControl.d.ts +21 -3
  48. package/dist/src/components/Slider/Slider.d.ts +18 -2
  49. package/dist/src/components/Stack/Stack.d.ts +2 -5
  50. package/dist/src/components/Stepper/Stepper.d.ts +41 -2
  51. package/dist/src/components/Switch/Switch.d.ts +10 -3
  52. package/dist/src/components/Switch/SwitchGroup.d.ts +13 -0
  53. package/dist/src/components/Table/Table.d.ts +2 -1
  54. package/dist/src/components/Tabs/Tabs.d.ts +20 -3
  55. package/dist/src/components/Text/Text.d.ts +2 -16
  56. package/dist/src/components/TextArea/TextArea.d.ts +12 -2
  57. package/dist/src/components/TextField/TextField.d.ts +12 -2
  58. package/dist/src/components/TimePicker/TimePicker.d.ts +2 -1
  59. package/dist/src/components/Timeline/Timeline.d.ts +15 -2
  60. package/dist/src/components/Timeline/TimelineItem.d.ts +18 -0
  61. package/dist/src/components/Title/Title.d.ts +2 -15
  62. package/dist/src/components/Toast/Toast.d.ts +20 -2
  63. package/dist/src/components/Tooltip/Tooltip.d.ts +28 -3
  64. package/dist/src/components/TransferList/TransferList.d.ts +2 -1
  65. package/dist/src/components/Typography/Typography.d.ts +1 -1
  66. package/dist/src/utils/RequireAccessibleLabel.d.ts +1 -18
  67. package/dist/src/utils/filterStylingProps.d.ts +1 -11
  68. package/llms.txt +16 -0
  69. package/package.json +14 -3
  70. package/src/components/Accordion/Accordion.module.css +294 -56
  71. package/src/components/Accordion/Accordion.stories.tsx +131 -21
  72. package/src/components/Accordion/Accordion.tsx +260 -5
  73. package/src/components/AssistiveElement/AssistiveElement.module.css +114 -20
  74. package/src/components/AssistiveElement/AssistiveElement.stories.tsx +60 -20
  75. package/src/components/AssistiveElement/AssistiveElement.tsx +81 -5
  76. package/src/components/Autocomplete/Autocomplete.module.css +319 -42
  77. package/src/components/Autocomplete/Autocomplete.stories.tsx +175 -23
  78. package/src/components/Autocomplete/Autocomplete.tsx +181 -6
  79. package/src/components/Avatar/Avatar.module.css +343 -73
  80. package/src/components/Avatar/Avatar.stories.tsx +94 -22
  81. package/src/components/Avatar/Avatar.tsx +99 -6
  82. package/src/components/Badge/Badge.module.css +127 -29
  83. package/src/components/Badge/Badge.stories.tsx +65 -22
  84. package/src/components/Badge/Badge.tsx +67 -6
  85. package/src/components/Breadcrumb/Breadcrumb.module.css +25 -5
  86. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +57 -22
  87. package/src/components/Breadcrumb/Breadcrumb.tsx +59 -6
  88. package/src/components/Button/Button.module.css +19 -61
  89. package/src/components/Button/Button.stories.tsx +24 -23
  90. package/src/components/Button/Button.tsx +7 -18
  91. package/src/components/Card/Card.module.css +154 -38
  92. package/src/components/Card/Card.stories.tsx +117 -19
  93. package/src/components/Card/Card.tsx +181 -5
  94. package/src/components/Checkbox/Checkbox.module.css +249 -39
  95. package/src/components/Checkbox/Checkbox.stories.tsx +81 -19
  96. package/src/components/Checkbox/Checkbox.tsx +246 -5
  97. package/src/components/Checkbox/CheckboxGroup.stories.tsx +139 -0
  98. package/src/components/Checkbox/CheckboxGroup.tsx +137 -0
  99. package/src/components/Checkbox/index.ts +6 -1
  100. package/src/components/Chip/Chip.module.css +246 -43
  101. package/src/components/Chip/Chip.stories.tsx +101 -21
  102. package/src/components/Chip/Chip.tsx +136 -6
  103. package/src/components/Container/Container.stories.tsx +103 -20
  104. package/src/components/Container/Container.tsx +1 -13
  105. package/src/components/DatePicker/DatePicker.stories.tsx +125 -19
  106. package/src/components/DatePicker/DatePicker.tsx +3 -1
  107. package/src/components/Dropdown/Dropdown.module.css +291 -41
  108. package/src/components/Dropdown/Dropdown.stories.tsx +80 -21
  109. package/src/components/Dropdown/Dropdown.tsx +180 -6
  110. package/src/components/FileInput/FileInput.stories.tsx +2 -19
  111. package/src/components/FileUpload/FileUpload.stories.tsx +2 -19
  112. package/src/components/Flex/Flex.stories.tsx +113 -20
  113. package/src/components/Flex/Flex.tsx +16 -26
  114. package/src/components/FormControlLayout/FormControlLayout.module.css +92 -0
  115. package/src/components/FormControlLayout/FormControlLayout.stories.tsx +67 -20
  116. package/src/components/FormControlLayout/FormControlLayout.tsx +69 -4
  117. package/src/components/FormControlWrapper/FormControlWrapper.module.css +87 -0
  118. package/src/components/FormControlWrapper/FormControlWrapper.stories.tsx +116 -22
  119. package/src/components/FormControlWrapper/FormControlWrapper.tsx +126 -6
  120. package/src/components/Group/Group.stories.tsx +6 -30
  121. package/src/components/Group/Group.tsx +14 -9
  122. package/src/components/HoverCard/HoverCard.module.css +90 -22
  123. package/src/components/HoverCard/HoverCard.stories.tsx +158 -21
  124. package/src/components/HoverCard/HoverCard.tsx +147 -5
  125. package/src/components/Label/Label.module.css +140 -35
  126. package/src/components/Label/Label.stories.tsx +108 -21
  127. package/src/components/Label/Label.tsx +82 -5
  128. package/src/components/Link/Link.module.css +4 -3
  129. package/src/components/Link/Link.stories.tsx +2 -8
  130. package/src/components/Link/Link.tsx +1 -5
  131. package/src/components/Loader/Loader.module.css +1 -2
  132. package/src/components/Loader/Loader.tsx +1 -7
  133. package/src/components/Menu/IMPLEMENTATION_NOTES.md +4 -0
  134. package/src/components/Menu/Menu.module.css +285 -51
  135. package/src/components/Menu/Menu.stories.tsx +229 -25
  136. package/src/components/Menu/Menu.tsx +73 -6
  137. package/src/components/Modal/Modal.module.css +171 -35
  138. package/src/components/Modal/Modal.stories.tsx +66 -22
  139. package/src/components/Modal/Modal.tsx +215 -5
  140. package/src/components/NumberInput/NumberInput.module.css +276 -42
  141. package/src/components/NumberInput/NumberInput.stories.tsx +83 -20
  142. package/src/components/NumberInput/NumberInput.tsx +136 -6
  143. package/src/components/Pagination/IMPLEMENTATION_NOTES.md +3 -0
  144. package/src/components/Pagination/Pagination.icons.tsx +66 -0
  145. package/src/components/Pagination/Pagination.module.css +234 -20
  146. package/src/components/Pagination/Pagination.stories.tsx +34 -21
  147. package/src/components/Pagination/Pagination.tsx +74 -6
  148. package/src/components/Panel/Panel.module.css +206 -38
  149. package/src/components/Panel/Panel.stories.tsx +214 -22
  150. package/src/components/Panel/Panel.tsx +130 -5
  151. package/src/components/Radio/Radio.module.css +235 -37
  152. package/src/components/Radio/Radio.stories.tsx +77 -19
  153. package/src/components/Radio/Radio.tsx +210 -5
  154. package/src/components/Radio/RadioGroup.stories.tsx +117 -0
  155. package/src/components/Radio/RadioGroup.tsx +125 -0
  156. package/src/components/ReadOnlyField/ReadOnlyBooleanField.tsx +21 -0
  157. package/src/components/ReadOnlyField/ReadOnlyField.module.css +53 -15
  158. package/src/components/ReadOnlyField/ReadOnlyField.stories.tsx +147 -19
  159. package/src/components/ReadOnlyField/ReadOnlyField.tsx +105 -5
  160. package/src/components/ReadOnlyField/ReadOnlySwitchField.tsx +21 -0
  161. package/src/components/ReadOnlyField/ReadOnlyTextField.tsx +48 -0
  162. package/src/components/ReadOnlyField/WithReadOnlyWrapper.tsx +93 -0
  163. package/src/components/ReadOnlyField/index.ts +1 -0
  164. package/src/components/SegmentedControl/SegmentedControl.module.css +179 -47
  165. package/src/components/SegmentedControl/SegmentedControl.stories.tsx +102 -20
  166. package/src/components/SegmentedControl/SegmentedControl.tsx +140 -6
  167. package/src/components/Slider/Slider.module.css +539 -86
  168. package/src/components/Slider/Slider.stories.tsx +157 -19
  169. package/src/components/Slider/Slider.tsx +283 -5
  170. package/src/components/Stack/Stack.stories.tsx +4 -25
  171. package/src/components/Stack/Stack.tsx +1 -5
  172. package/src/components/Stepper/IMPLEMENTATION_NOTES.md +4 -0
  173. package/src/components/Stepper/Stepper.module.css +410 -71
  174. package/src/components/Stepper/Stepper.stories.tsx +146 -20
  175. package/src/components/Stepper/Stepper.tsx +147 -6
  176. package/src/components/Switch/Switch.module.css +259 -39
  177. package/src/components/Switch/Switch.stories.tsx +98 -19
  178. package/src/components/Switch/Switch.tsx +200 -6
  179. package/src/components/Switch/SwitchGroup.stories.tsx +132 -0
  180. package/src/components/Switch/SwitchGroup.tsx +120 -0
  181. package/src/components/Table/Table.stories.tsx +1 -19
  182. package/src/components/Table/Table.tsx +3 -1
  183. package/src/components/Tabs/IMPLEMENTATION_NOTES.md +4 -0
  184. package/src/components/Tabs/Tabs.module.css +422 -79
  185. package/src/components/Tabs/Tabs.stories.tsx +156 -20
  186. package/src/components/Tabs/Tabs.tsx +86 -6
  187. package/src/components/Text/Text.stories.tsx +5 -17
  188. package/src/components/Text/Text.tsx +1 -15
  189. package/src/components/TextArea/TextArea.module.css +155 -32
  190. package/src/components/TextArea/TextArea.stories.tsx +80 -21
  191. package/src/components/TextArea/TextArea.tsx +146 -6
  192. package/src/components/TextField/TextField.module.css +261 -42
  193. package/src/components/TextField/TextField.stories.tsx +147 -20
  194. package/src/components/TextField/TextField.tsx +169 -6
  195. package/src/components/TimePicker/TimePicker.stories.tsx +2 -19
  196. package/src/components/TimePicker/TimePicker.tsx +3 -1
  197. package/src/components/Timeline/Timeline.module.css +365 -76
  198. package/src/components/Timeline/Timeline.stories.tsx +114 -21
  199. package/src/components/Timeline/Timeline.tsx +83 -5
  200. package/src/components/Timeline/TimelineItem.tsx +90 -0
  201. package/src/components/Title/Title.stories.tsx +0 -18
  202. package/src/components/Title/Title.tsx +1 -7
  203. package/src/components/Toast/Toast.module.css +166 -28
  204. package/src/components/Toast/Toast.stories.tsx +54 -22
  205. package/src/components/Toast/Toast.tsx +124 -5
  206. package/src/components/Tooltip/Tooltip.module.css +89 -24
  207. package/src/components/Tooltip/Tooltip.stories.tsx +152 -22
  208. package/src/components/Tooltip/Tooltip.tsx +88 -5
  209. package/src/components/TransferList/TransferList.stories.tsx +1 -19
  210. package/src/components/TransferList/TransferList.tsx +3 -1
  211. package/src/utils/RequireAccessibleLabel.ts +1 -12
  212. package/src/utils/filterStylingProps.ts +7 -20
@@ -1,35 +1,122 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import React from "react";
1
3
  import type { Meta, StoryObj } from "@storybook/react";
2
4
  import { Label } from "./Label";
3
- import { ComingSoon } from "@recursica/storybook-template";
5
+ import { TextField } from "../TextField/TextField";
6
+ import { formControlArgTypes } from "../../../.storybook/commonArgTypes";
4
7
 
5
- const meta: Meta<typeof Label> = {
6
- title: "UI-Kit/🚧 Label",
8
+ type LabelStoryProps = React.ComponentProps<typeof Label>;
9
+
10
+ const meta: Meta<LabelStoryProps> = {
11
+ title: "UI-Kit/Label",
7
12
  component: Label,
8
13
  tags: ["autodocs"],
9
14
  parameters: {
10
- controls: {
11
- include: [
12
- "layer",
13
- "withLayer",
14
- "children",
15
- "component",
16
- "variant",
17
- "size",
18
- "icon",
19
- "disabled",
20
- "href",
21
- "onClick",
22
- "onChange",
23
- "value",
24
- "checked",
25
- ],
15
+ docs: {
16
+ description: {
17
+ component:
18
+ "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\nWhen working with form structures, render this `Label` component directly above your inputs or supply it to a component's overriding properties. The component automatically maps structural layout dimensions, dynamic alignment (`left` vs `right`), custom indicator gaps, and integrates a customized `optionalText` and `withEditIcon` flow that safely bypasses Mantine's native required asterisk mechanisms.",
19
+ },
26
20
  },
27
21
  },
22
+ argTypes: {
23
+ ...formControlArgTypes,
24
+ },
28
25
  };
29
26
 
30
27
  export default meta;
31
- type Story = StoryObj<typeof Label>;
28
+
29
+ type Story = StoryObj<LabelStoryProps>;
30
+
31
+ // Utility mapping to pipe raw Label args structurally into TextField accurately
32
+ const renderWithTextField = ({ children, ...args }: LabelStoryProps) => (
33
+ <TextField
34
+ label={children as React.ReactNode}
35
+ placeholder="Form Control primitive mapped..."
36
+ {...(args as any)}
37
+ />
38
+ );
32
39
 
33
40
  export const Default: Story = {
34
- render: () => <ComingSoon componentName="Label" />,
41
+ args: {
42
+ children: "Dynamic Label (Controls)",
43
+
44
+ labelSize: "default",
45
+ labelAlignment: "left",
46
+ required: false,
47
+ labelOptionalText: "",
48
+ labelWithEditIcon: false,
49
+ },
50
+ render: renderWithTextField,
51
+ };
52
+
53
+ export const StackedDefault: Story = {
54
+ args: {
55
+ children: "Email Address",
56
+ },
57
+ render: renderWithTextField,
58
+ };
59
+
60
+ export const StackedRequired: Story = {
61
+ args: {
62
+ children: "Primary Network Node",
63
+
64
+ required: true,
65
+ },
66
+ render: renderWithTextField,
67
+ };
68
+
69
+ export const StackedWithEditIcon: Story = {
70
+ args: {
71
+ children: "Environment Variables",
72
+
73
+ labelWithEditIcon: true,
74
+ },
75
+ render: renderWithTextField,
76
+ };
77
+
78
+ export const SideBySideDefault: Story = {
79
+ args: {
80
+ children: "Status",
81
+
82
+ labelSize: "default",
83
+ },
84
+ render: renderWithTextField,
85
+ };
86
+
87
+ export const RequiredSuppressesOptionalText: Story = {
88
+ args: {
89
+ children: "Full Name",
90
+
91
+ required: true,
92
+ labelOptionalText: "This should not render",
93
+ },
94
+ render: renderWithTextField,
95
+ };
96
+
97
+ export const BooleanOptionalText: Story = {
98
+ args: {
99
+ children: "Middle Initial",
100
+
101
+ labelOptionalText: true,
102
+ },
103
+ render: renderWithTextField,
104
+ };
105
+
106
+ export const WithEditIcon: Story = {
107
+ args: {
108
+ children: "Shipping Address",
109
+
110
+ labelWithEditIcon: true,
111
+ },
112
+ render: renderWithTextField,
113
+ };
114
+
115
+ export const LayerOneSideBySide: Story = {
116
+ args: {
117
+ children: "Configuration",
118
+
119
+ labelWithEditIcon: true,
120
+ },
121
+ render: renderWithTextField,
35
122
  };
@@ -1,8 +1,85 @@
1
1
  import React from "react";
2
- import "./Label.module.css";
2
+ import { InputLabel, type InputLabelProps } from "@mui/material";
3
+ import { filterStylingProps } from "../../utils/filterStylingProps";
4
+ import styles from "./Label.module.css";
3
5
 
4
- export type LabelProps = React.HTMLAttributes<HTMLDivElement>;
6
+ import { type RecursicaLabelProps } from "@recursica/adapter-common";
5
7
 
6
- export const Label: React.FC<LabelProps> = (props) => {
7
- return <div {...props}>Label</div>;
8
- };
8
+ export interface LabelProps extends InputLabelProps, RecursicaLabelProps {
9
+ overStyled?: boolean;
10
+ }
11
+
12
+ export const Label = React.forwardRef<HTMLLabelElement, LabelProps>(
13
+ function Label(props, ref) {
14
+ const {
15
+ overStyled = false,
16
+ required = false,
17
+ labelOptionalText = "",
18
+ labelWithEditIcon = false,
19
+ onLabelEditClick,
20
+ labelActionArea,
21
+ children,
22
+ className,
23
+ ...rest
24
+ } = props;
25
+
26
+ const sanitizedProps = filterStylingProps(rest, overStyled);
27
+
28
+ const PenIcon = () => (
29
+ <svg
30
+ xmlns="http://www.w3.org/2000/svg"
31
+ width="24"
32
+ height="24"
33
+ viewBox="0 0 24 24"
34
+ fill="none"
35
+ stroke="currentColor"
36
+ strokeWidth="2"
37
+ strokeLinecap="round"
38
+ strokeLinejoin="round"
39
+ >
40
+ <path d="M12 20h9"></path>
41
+ <path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"></path>
42
+ </svg>
43
+ );
44
+
45
+ // Bypassing MUI's floating functionality by forcing shrink=true to static inline positioning.
46
+ return (
47
+ <InputLabel
48
+ ref={ref}
49
+ shrink={true}
50
+ className={className ? `${styles.root} ${className}` : styles.root}
51
+ {...(sanitizedProps as InputLabelProps)}
52
+ >
53
+ <div className={styles.innerLayout}>
54
+ <span className={styles.textWrapper}>
55
+ <span className={styles.text}>{children}</span>
56
+ {required && <span className={styles.required}> *</span>}
57
+ </span>
58
+
59
+ <div className={styles.endNodes}>
60
+ {labelActionArea && (
61
+ <span className={styles.actionArea}>{labelActionArea}</span>
62
+ )}
63
+ {!required && labelOptionalText && !labelActionArea && (
64
+ <span className={styles.optionalText}>
65
+ {labelOptionalText === true ? "Optional" : labelOptionalText}
66
+ </span>
67
+ )}
68
+ {labelWithEditIcon && (
69
+ <button
70
+ type="button"
71
+ className={styles.editIcon}
72
+ onClick={onLabelEditClick}
73
+ aria-label="Edit label"
74
+ >
75
+ <PenIcon />
76
+ </button>
77
+ )}
78
+ </div>
79
+ </div>
80
+ </InputLabel>
81
+ );
82
+ },
83
+ );
84
+
85
+ Label.displayName = "Label";
@@ -8,9 +8,8 @@ HARDCODED VALUES:
8
8
  */
9
9
 
10
10
  .root {
11
- /* HARDCODE: base layout to support optional icon gaps */
12
- display: inline-flex;
13
- align-items: center;
11
+ /* HARDCODE: base layout */
12
+ display: inline;
14
13
  cursor: pointer;
15
14
 
16
15
  /* HARDCODE: Reset underline and color so we can explicitly use our tokens */
@@ -45,6 +44,8 @@ HARDCODED VALUES:
45
44
  }
46
45
 
47
46
  .root[data-has-icon] {
47
+ display: inline-flex;
48
+ align-items: center;
48
49
  gap: var(--recursica_ui-kit_components_link_properties_icon-text-gap);
49
50
  }
50
51
 
@@ -2,17 +2,11 @@
2
2
  /* eslint-disable @typescript-eslint/no-unused-vars */
3
3
  import type { Meta, StoryObj } from "@storybook/react";
4
4
  import { Link } from "./Link";
5
- import { Text } from "../Text/Text";
6
5
 
7
6
  const meta: Meta<typeof Link> = {
8
7
  title: "UI-Kit/Link",
9
8
  component: Link,
10
9
  tags: ["autodocs"],
11
- parameters: {
12
- controls: {
13
- include: ["children", "href", "icon", "component", "onClick"],
14
- },
15
- },
16
10
  args: {
17
11
  children: "Link text",
18
12
  href: "#",
@@ -57,8 +51,8 @@ export const Polymorphic: Story = {
57
51
 
58
52
  export const InlineText: Story = {
59
53
  render: () => (
60
- <Text>
54
+ <p>
61
55
  Here is some text with an <Link href="#">inline link</Link> inside it.
62
- </Text>
56
+ </p>
63
57
  ),
64
58
  };
@@ -6,11 +6,7 @@ import {
6
6
  } from "../../utils/filterStylingProps";
7
7
  import styles from "./Link.module.css";
8
8
 
9
- export interface RecursicaLinkProps {
10
- icon?: React.ReactNode;
11
- children?: React.ReactNode;
12
- component?: React.ElementType;
13
- }
9
+ import { type RecursicaLinkProps } from "@recursica/adapter-common";
14
10
 
15
11
  export type LinkProps = RecursicaOverStyled<
16
12
  Omit<MUILinkProps, "underline"> & RecursicaLinkProps
@@ -1,8 +1,7 @@
1
1
  .root {
2
2
  /* Default inheritance mapped from component variables if not explicitly overridden by variants */
3
3
  --loader-color: var(
4
- --recursica_ui-kit_components_loader_properties_indicator-color,
5
- currentColor
4
+ --recursica_ui-kit_components_loader_properties_indicator-color
6
5
  );
7
6
  box-sizing: border-box;
8
7
  }
@@ -2,16 +2,10 @@ import React, { forwardRef } from "react";
2
2
  import {
3
3
  filterStylingProps,
4
4
  type RecursicaOverStyled,
5
- type RecursicaSize,
6
5
  } from "../../utils/filterStylingProps";
7
6
  import styles from "./Loader.module.css";
8
7
 
9
- export interface RecursicaLoaderProps {
10
- /** Map to the component styles defined in variables */
11
- variant?: "oval" | "bars" | "dots";
12
- /** Map to Recursica sizes */
13
- size?: "sm" | "md" | "lg" | RecursicaSize;
14
- }
8
+ import { type RecursicaLoaderProps } from "@recursica/adapter-common";
15
9
 
16
10
  export type LoaderProps = RecursicaOverStyled<
17
11
  React.HTMLAttributes<HTMLSpanElement> & RecursicaLoaderProps
@@ -0,0 +1,4 @@
1
+ # Menu Implementation Notes
2
+
3
+ - **Compositional API Dropped:** Mantine uses `<Menu.Target>`, `<Menu.Dropdown>`, `<Menu.Item>`, etc., and manages state natively via React context within `<Menu>`. MUI's API is fully monolithic.
4
+ - **Monolithic API Adopted:** Following architectural review, we have abandoned the fabricated context wrappers for `mui-adapter`. We now natively export `Menu`, `MenuItem`, and `MenuDivider` wrapping their `@mui/material` counterparts. Developers are expected to manage `anchorEl` state themselves, just like native MUI. Storybook tests have been updated to simulate this open state so visual regressions still cover the dropdown menu visually.
@@ -1,53 +1,287 @@
1
1
  /* EXEMPTIONS:
2
- This component is a placeholder stub. Once fully implemented, its specific
3
- tokens will be fully wired up to direct styles. */
4
-
5
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_border-radius */
6
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_colors_selected-item_background */
7
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_colors_selected-item_hover-color */
8
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_colors_selected-item_hover-opacity */
9
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_colors_selected-item_leading-icon-color */
2
+ - colors_selected-item_supporting-text-color is ignored because selected menu items do not render
3
+ supporting secondary text, making selected state overrides for supporting text colors obsolete. */
10
4
  /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_colors_selected-item_supporting-text-color */
11
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_colors_selected-item_text */
12
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_colors_selected-item_trailing-icon-color */
13
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_background */
14
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_hover-color */
15
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_hover-opacity */
16
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_leading-icon-color */
17
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_supporting-text-color */
18
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_text */
19
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_trailing-icon-color */
20
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_disabled-opacity */
21
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_horizontal-padding */
22
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_icon-leading-size */
23
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_icon-text-gap */
24
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_icon-trailing-size */
25
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_supporting-text_font-family */
26
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_supporting-text_font-size */
27
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_supporting-text_font-style */
28
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_supporting-text_font-weight */
29
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_supporting-text_letter-spacing */
30
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_supporting-text_line-height */
31
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_supporting-text_text-decoration */
32
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_supporting-text_text-transform */
33
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_text-gap */
34
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_text_font-family */
35
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_text_font-size */
36
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_text_font-style */
37
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_text_font-weight */
38
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_text_letter-spacing */
39
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_text_line-height */
40
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_text_text-decoration */
41
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_text_text-transform */
42
- /* recursica-ignore: --recursica_ui-kit_components_menu-item_properties_vertical-padding */
43
- /* recursica-ignore: --recursica_ui-kit_components_menu_properties_border-radius */
44
- /* recursica-ignore: --recursica_ui-kit_components_menu_properties_border-size */
45
- /* recursica-ignore: --recursica_ui-kit_components_menu_properties_colors_background */
46
- /* recursica-ignore: --recursica_ui-kit_components_menu_properties_colors_border-color */
47
- /* recursica-ignore: --recursica_ui-kit_components_menu_properties_colors_divider-color */
48
- /* recursica-ignore: --recursica_ui-kit_components_menu_properties_divider-height */
49
- /* recursica-ignore: --recursica_ui-kit_components_menu_properties_divider-opacity */
50
- /* recursica-ignore: --recursica_ui-kit_components_menu_properties_elevation */
51
- /* recursica-ignore: --recursica_ui-kit_components_menu_properties_max-height */
52
- /* recursica-ignore: --recursica_ui-kit_components_menu_properties_max-width */
53
- /* recursica-ignore: --recursica_ui-kit_components_menu_properties_min-width */
5
+
6
+ /* HARDCODED VALUES:
7
+ - border-style: solid. Structural rendering rule for the dropdown border (Mantine uses Paper which may not set border natively).
8
+ - opacity: 0.5 on disabled items. Recursica has no dedicated disabled-opacity token for menu items.
9
+ - NOTE: overflow is intentionally NOT set on .dropdown. Mantine renders sub-menu dropdowns
10
+ inside the parent dropdown DOM tree using Floating UI absolute positioning. Setting
11
+ overflow: hidden clips sub-menus; overflow-y: auto causes unwanted scrollbars.
12
+ - All structural layout (flex, cursor, pointer-events on disabled) is deferred to Mantine's
13
+ native behavior. We only override visual design tokens (colors, typography, spacing, borders).
14
+ */
15
+
16
+ /* ======================================
17
+ DROPDOWN CONTAINER
18
+ ====================================== */
19
+
20
+ .dropdown {
21
+ background-color: var(
22
+ --recursica_ui-kit_components_menu_properties_colors_background
23
+ );
24
+ border-style: solid; /* HARDCODE: Mantine Paper does not set border-style natively */
25
+ border-width: var(--recursica_ui-kit_components_menu_properties_border-size);
26
+ border-color: var(
27
+ --recursica_ui-kit_components_menu_properties_colors_border-color
28
+ );
29
+ border-radius: var(
30
+ --recursica_ui-kit_components_menu_properties_border-radius
31
+ );
32
+ box-shadow: var(--recursica_ui-kit_components_menu_properties_elevation);
33
+
34
+ min-width: var(--recursica_ui-kit_components_menu_properties_min-width);
35
+ max-height: var(--recursica_ui-kit_components_menu_properties_max-height);
36
+ max-width: var(--recursica_ui-kit_components_menu_properties_max-width);
37
+
38
+ /* HARDCODE: Figma UI Kit does not export padding tokens for the Menu container itself.
39
+ If added in the future, it would be mapped here. */
40
+ padding: 8px;
41
+ }
42
+
43
+ /* ======================================
44
+ MENU ITEM
45
+ ====================================== */
46
+
47
+ .item {
48
+ position: relative;
49
+
50
+ /* Geometry */
51
+ padding: var(
52
+ --recursica_ui-kit_components_menu-item_properties_vertical-padding
53
+ )
54
+ var(--recursica_ui-kit_components_menu-item_properties_horizontal-padding);
55
+ border-radius: var(
56
+ --recursica_ui-kit_components_menu-item_properties_border-radius
57
+ );
58
+
59
+ /* Typography */
60
+ font-family: var(
61
+ --recursica_ui-kit_components_menu-item_properties_text_font-family
62
+ );
63
+ font-size: var(
64
+ --recursica_ui-kit_components_menu-item_properties_text_font-size
65
+ );
66
+ font-style: var(
67
+ --recursica_ui-kit_components_menu-item_properties_text_font-style
68
+ );
69
+ font-weight: var(
70
+ --recursica_ui-kit_components_menu-item_properties_text_font-weight
71
+ );
72
+ letter-spacing: var(
73
+ --recursica_ui-kit_components_menu-item_properties_text_letter-spacing
74
+ );
75
+ line-height: var(
76
+ --recursica_ui-kit_components_menu-item_properties_text_line-height
77
+ );
78
+ text-decoration: var(
79
+ --recursica_ui-kit_components_menu-item_properties_text_text-decoration
80
+ );
81
+ text-transform: var(
82
+ --recursica_ui-kit_components_menu-item_properties_text_text-transform
83
+ );
84
+
85
+ /* Default State: Unselected */
86
+ background-color: var(
87
+ --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_background
88
+ );
89
+ color: var(
90
+ --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_text
91
+ );
92
+ opacity: 1;
93
+ }
94
+
95
+ /* Override Mantine's native hover background to use our overlay technique */
96
+ .item:hover {
97
+ background-color: var(
98
+ --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_background
99
+ );
100
+ }
101
+
102
+ /* Hover overlay using ::after pseudo-element (same technique as Accordion) */
103
+ .item::after {
104
+ content: "";
105
+ position: absolute;
106
+ inset: 0;
107
+ border-radius: inherit;
108
+ z-index: 0;
109
+ pointer-events: none;
110
+ background-color: var(
111
+ --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_hover-color
112
+ );
113
+ opacity: 0;
114
+ transition: opacity 150ms ease;
115
+ }
116
+
117
+ .item:hover:not([data-disabled])::after {
118
+ opacity: var(
119
+ --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_hover-opacity
120
+ );
121
+ }
122
+
123
+ /* Selected item state */
124
+ .item[data-selected] {
125
+ background-color: var(
126
+ --recursica_ui-kit_components_menu-item_properties_colors_selected-item_background
127
+ );
128
+ color: var(
129
+ --recursica_ui-kit_components_menu-item_properties_colors_selected-item_text
130
+ );
131
+ opacity: 1;
132
+ }
133
+
134
+ .item[data-selected]::after {
135
+ background-color: var(
136
+ --recursica_ui-kit_components_menu-item_properties_colors_selected-item_hover-color
137
+ );
138
+ }
139
+
140
+ /* Hovered item state (keyboard navigation) */
141
+ .item[data-hovered] {
142
+ background-color: var(
143
+ --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_background
144
+ );
145
+ }
146
+ .item[data-hovered]::after {
147
+ opacity: var(
148
+ --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_hover-opacity
149
+ );
150
+ }
151
+
152
+ .item[data-hovered][data-selected]::after {
153
+ opacity: var(
154
+ --recursica_ui-kit_components_menu-item_properties_colors_selected-item_hover-opacity
155
+ );
156
+ }
157
+
158
+ /* Disabled item */
159
+ .item[data-disabled] {
160
+ opacity: var(
161
+ --recursica_ui-kit_components_menu-item_properties_disabled-opacity
162
+ );
163
+ }
164
+
165
+ /* ======================================
166
+ ITEM LABEL
167
+ ====================================== */
168
+
169
+ .itemLabel {
170
+ position: relative;
171
+ z-index: 1;
172
+ color: inherit;
173
+ }
174
+
175
+ /* ======================================
176
+ ITEM SECTION (LEFT / RIGHT ICONS)
177
+ ====================================== */
178
+
179
+ .itemSection {
180
+ position: relative;
181
+ z-index: 1;
182
+ }
183
+
184
+ .itemSection[data-position="left"] {
185
+ width: var(
186
+ --recursica_ui-kit_components_menu-item_properties_icon-leading-size
187
+ );
188
+ height: var(
189
+ --recursica_ui-kit_components_menu-item_properties_icon-leading-size
190
+ );
191
+ margin-right: var(
192
+ --recursica_ui-kit_components_menu-item_properties_icon-text-gap
193
+ );
194
+ color: var(
195
+ --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_leading-icon-color
196
+ );
197
+ }
198
+
199
+ .itemSection[data-position="right"] {
200
+ width: var(
201
+ --recursica_ui-kit_components_menu-item_properties_icon-trailing-size
202
+ );
203
+ height: var(
204
+ --recursica_ui-kit_components_menu-item_properties_icon-trailing-size
205
+ );
206
+ margin-left: var(--recursica_ui-kit_components_menu-item_properties_text-gap);
207
+ color: var(
208
+ --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_trailing-icon-color
209
+ );
210
+ }
211
+
212
+ .item[data-selected] .itemSection[data-position="left"] {
213
+ color: var(
214
+ --recursica_ui-kit_components_menu-item_properties_colors_selected-item_leading-icon-color
215
+ );
216
+ }
217
+
218
+ .item[data-selected] .itemSection[data-position="right"] {
219
+ color: var(
220
+ --recursica_ui-kit_components_menu-item_properties_colors_selected-item_trailing-icon-color
221
+ );
222
+ }
223
+
224
+ /* ======================================
225
+ DIVIDER
226
+ ====================================== */
227
+
228
+ .divider {
229
+ height: var(--recursica_ui-kit_components_menu_properties_divider-height);
230
+ background-color: var(
231
+ --recursica_ui-kit_components_menu_properties_colors_divider-color
232
+ );
233
+ opacity: var(--recursica_ui-kit_components_menu_properties_divider-opacity);
234
+ margin: 8px 0;
235
+ }
236
+
237
+ /* ======================================
238
+ SECTION LABEL
239
+ ====================================== */
240
+
241
+ .label {
242
+ padding: var(
243
+ --recursica_ui-kit_components_menu-item_properties_vertical-padding
244
+ )
245
+ var(--recursica_ui-kit_components_menu-item_properties_horizontal-padding);
246
+
247
+ /* Supporting Text Typography */
248
+ font-family: var(
249
+ --recursica_ui-kit_components_menu-item_properties_supporting-text_font-family
250
+ );
251
+ font-size: var(
252
+ --recursica_ui-kit_components_menu-item_properties_supporting-text_font-size
253
+ );
254
+ font-style: var(
255
+ --recursica_ui-kit_components_menu-item_properties_supporting-text_font-style
256
+ );
257
+ font-weight: var(
258
+ --recursica_ui-kit_components_menu-item_properties_supporting-text_font-weight
259
+ );
260
+ letter-spacing: var(
261
+ --recursica_ui-kit_components_menu-item_properties_supporting-text_letter-spacing
262
+ );
263
+ line-height: var(
264
+ --recursica_ui-kit_components_menu-item_properties_supporting-text_line-height
265
+ );
266
+ text-decoration: var(
267
+ --recursica_ui-kit_components_menu-item_properties_supporting-text_text-decoration
268
+ );
269
+ text-transform: var(
270
+ --recursica_ui-kit_components_menu-item_properties_supporting-text_text-transform
271
+ );
272
+
273
+ color: var(
274
+ --recursica_ui-kit_components_menu-item_properties_colors_unselected-item_supporting-text-color
275
+ );
276
+ opacity: 0.7;
277
+ }
278
+
279
+ /* ======================================
280
+ SUB-MENU CHEVRON
281
+ ====================================== */
282
+
283
+ .chevron {
284
+ position: relative;
285
+ z-index: 1;
286
+ color: inherit;
287
+ }