@recursica/mui-adapter 0.6.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 (164) hide show
  1. package/ARCHITECTURE.md +15 -0
  2. package/CHANGELOG.md +6 -0
  3. package/SETUP.md +77 -0
  4. package/USAGE.md +55 -0
  5. package/dist/mui-adapter.cjs +26 -26
  6. package/dist/mui-adapter.cjs.map +1 -1
  7. package/dist/mui-adapter.css +1 -1
  8. package/dist/mui-adapter.js +3721 -3511
  9. package/dist/mui-adapter.js.map +1 -1
  10. package/dist/src/components/Accordion/Accordion.d.ts +9 -29
  11. package/dist/src/components/AssistiveElement/AssistiveElement.d.ts +2 -5
  12. package/dist/src/components/Autocomplete/Autocomplete.d.ts +4 -8
  13. package/dist/src/components/Avatar/Avatar.d.ts +1 -6
  14. package/dist/src/components/Badge/Badge.d.ts +1 -4
  15. package/dist/src/components/Breadcrumb/Breadcrumb.d.ts +2 -3
  16. package/dist/src/components/Button/Button.d.ts +2 -17
  17. package/dist/src/components/Card/Card.d.ts +2 -4
  18. package/dist/src/components/Checkbox/Checkbox.d.ts +4 -6
  19. package/dist/src/components/Checkbox/CheckboxGroup.d.ts +8 -6
  20. package/dist/src/components/Chip/Chip.d.ts +2 -11
  21. package/dist/src/components/Container/Container.d.ts +1 -5
  22. package/dist/src/components/DatePicker/DatePicker.d.ts +2 -1
  23. package/dist/src/components/Dropdown/Dropdown.d.ts +4 -14
  24. package/dist/src/components/Flex/Flex.d.ts +2 -22
  25. package/dist/src/components/FormControlLayout/FormControlLayout.d.ts +2 -7
  26. package/dist/src/components/FormControlWrapper/FormControlWrapper.d.ts +3 -18
  27. package/dist/src/components/Group/Group.d.ts +2 -7
  28. package/dist/src/components/HoverCard/HoverCard.d.ts +13 -39
  29. package/dist/src/components/Label/Label.d.ts +2 -9
  30. package/dist/src/components/Link/Link.d.ts +2 -6
  31. package/dist/src/components/Loader/Loader.d.ts +2 -7
  32. package/dist/src/components/Menu/Menu.d.ts +24 -98
  33. package/dist/src/components/Modal/Modal.d.ts +32 -31
  34. package/dist/src/components/NumberInput/NumberInput.d.ts +3 -5
  35. package/dist/src/components/Pagination/Pagination.d.ts +8 -41
  36. package/dist/src/components/Panel/Panel.d.ts +5 -18
  37. package/dist/src/components/Radio/Radio.d.ts +4 -4
  38. package/dist/src/components/Radio/RadioGroup.d.ts +3 -7
  39. package/dist/src/components/ReadOnlyField/ReadOnlyField.d.ts +2 -5
  40. package/dist/src/components/SegmentedControl/SegmentedControl.d.ts +5 -15
  41. package/dist/src/components/Slider/Slider.d.ts +4 -14
  42. package/dist/src/components/Stack/Stack.d.ts +2 -5
  43. package/dist/src/components/Stepper/Stepper.d.ts +36 -16
  44. package/dist/src/components/Switch/Switch.d.ts +4 -4
  45. package/dist/src/components/Switch/SwitchGroup.d.ts +4 -4
  46. package/dist/src/components/Table/Table.d.ts +2 -1
  47. package/dist/src/components/Tabs/Tabs.d.ts +11 -26
  48. package/dist/src/components/Text/Text.d.ts +2 -16
  49. package/dist/src/components/TextArea/TextArea.d.ts +3 -9
  50. package/dist/src/components/TextField/TextField.d.ts +3 -7
  51. package/dist/src/components/TimePicker/TimePicker.d.ts +2 -1
  52. package/dist/src/components/Timeline/Timeline.d.ts +2 -1
  53. package/dist/src/components/Timeline/TimelineItem.d.ts +2 -13
  54. package/dist/src/components/Title/Title.d.ts +2 -15
  55. package/dist/src/components/Toast/Toast.d.ts +11 -16
  56. package/dist/src/components/Tooltip/Tooltip.d.ts +7 -21
  57. package/dist/src/components/TransferList/TransferList.d.ts +2 -1
  58. package/dist/src/components/Typography/Typography.d.ts +1 -1
  59. package/dist/src/utils/RequireAccessibleLabel.d.ts +1 -18
  60. package/dist/src/utils/filterStylingProps.d.ts +1 -11
  61. package/llms.txt +16 -0
  62. package/package.json +6 -2
  63. package/src/components/Accordion/Accordion.module.css +1 -2
  64. package/src/components/Accordion/Accordion.stories.tsx +0 -18
  65. package/src/components/Accordion/Accordion.tsx +19 -23
  66. package/src/components/AssistiveElement/AssistiveElement.module.css +32 -29
  67. package/src/components/AssistiveElement/AssistiveElement.stories.tsx +10 -27
  68. package/src/components/AssistiveElement/AssistiveElement.tsx +11 -15
  69. package/src/components/Autocomplete/Autocomplete.module.css +17 -18
  70. package/src/components/Autocomplete/Autocomplete.stories.tsx +7 -16
  71. package/src/components/Autocomplete/Autocomplete.tsx +27 -45
  72. package/src/components/Avatar/Avatar.tsx +2 -13
  73. package/src/components/Badge/Badge.tsx +2 -5
  74. package/src/components/Breadcrumb/Breadcrumb.tsx +1 -4
  75. package/src/components/Button/Button.module.css +19 -61
  76. package/src/components/Button/Button.stories.tsx +24 -23
  77. package/src/components/Button/Button.tsx +7 -18
  78. package/src/components/Card/Card.module.css +36 -0
  79. package/src/components/Card/Card.tsx +6 -4
  80. package/src/components/Checkbox/Checkbox.module.css +27 -10
  81. package/src/components/Checkbox/Checkbox.tsx +124 -24
  82. package/src/components/Checkbox/CheckboxGroup.stories.tsx +139 -0
  83. package/src/components/Checkbox/CheckboxGroup.tsx +43 -23
  84. package/src/components/Chip/Chip.module.css +52 -34
  85. package/src/components/Chip/Chip.tsx +45 -47
  86. package/src/components/Container/Container.stories.tsx +103 -20
  87. package/src/components/Container/Container.tsx +1 -13
  88. package/src/components/DatePicker/DatePicker.stories.tsx +125 -19
  89. package/src/components/DatePicker/DatePicker.tsx +3 -1
  90. package/src/components/Dropdown/Dropdown.tsx +7 -9
  91. package/src/components/FileInput/FileInput.stories.tsx +2 -19
  92. package/src/components/FileUpload/FileUpload.stories.tsx +2 -19
  93. package/src/components/Flex/Flex.stories.tsx +113 -20
  94. package/src/components/Flex/Flex.tsx +16 -26
  95. package/src/components/FormControlLayout/FormControlLayout.stories.tsx +0 -8
  96. package/src/components/FormControlLayout/FormControlLayout.tsx +18 -7
  97. package/src/components/FormControlWrapper/FormControlWrapper.module.css +1 -10
  98. package/src/components/FormControlWrapper/FormControlWrapper.stories.tsx +12 -21
  99. package/src/components/FormControlWrapper/FormControlWrapper.tsx +11 -30
  100. package/src/components/Group/Group.stories.tsx +6 -30
  101. package/src/components/Group/Group.tsx +14 -9
  102. package/src/components/HoverCard/HoverCard.tsx +72 -75
  103. package/src/components/Label/Label.module.css +4 -0
  104. package/src/components/Label/Label.stories.tsx +18 -12
  105. package/src/components/Label/Label.tsx +3 -9
  106. package/src/components/Link/Link.module.css +4 -3
  107. package/src/components/Link/Link.stories.tsx +2 -8
  108. package/src/components/Link/Link.tsx +1 -5
  109. package/src/components/Loader/Loader.module.css +1 -2
  110. package/src/components/Loader/Loader.tsx +1 -7
  111. package/src/components/Menu/IMPLEMENTATION_NOTES.md +4 -0
  112. package/src/components/Menu/Menu.stories.tsx +106 -188
  113. package/src/components/Menu/Menu.tsx +34 -280
  114. package/src/components/Modal/Modal.tsx +158 -160
  115. package/src/components/NumberInput/NumberInput.tsx +6 -18
  116. package/src/components/Pagination/IMPLEMENTATION_NOTES.md +3 -0
  117. package/src/components/Pagination/Pagination.module.css +12 -24
  118. package/src/components/Pagination/Pagination.stories.tsx +0 -8
  119. package/src/components/Pagination/Pagination.tsx +20 -140
  120. package/src/components/Panel/Panel.tsx +7 -30
  121. package/src/components/Radio/Radio.module.css +25 -10
  122. package/src/components/Radio/Radio.tsx +51 -19
  123. package/src/components/Radio/RadioGroup.stories.tsx +117 -0
  124. package/src/components/Radio/RadioGroup.tsx +26 -12
  125. package/src/components/ReadOnlyField/ReadOnlyField.module.css +6 -6
  126. package/src/components/ReadOnlyField/ReadOnlyField.stories.tsx +5 -36
  127. package/src/components/ReadOnlyField/ReadOnlyField.tsx +9 -13
  128. package/src/components/SegmentedControl/SegmentedControl.module.css +23 -47
  129. package/src/components/SegmentedControl/SegmentedControl.tsx +44 -14
  130. package/src/components/Slider/Slider.module.css +1 -4
  131. package/src/components/Slider/Slider.stories.tsx +3 -3
  132. package/src/components/Slider/Slider.tsx +26 -25
  133. package/src/components/Stack/Stack.stories.tsx +4 -25
  134. package/src/components/Stack/Stack.tsx +1 -5
  135. package/src/components/Stepper/IMPLEMENTATION_NOTES.md +4 -0
  136. package/src/components/Stepper/Stepper.stories.tsx +56 -43
  137. package/src/components/Stepper/Stepper.tsx +89 -87
  138. package/src/components/Switch/Switch.module.css +21 -0
  139. package/src/components/Switch/Switch.tsx +63 -16
  140. package/src/components/Switch/SwitchGroup.stories.tsx +132 -0
  141. package/src/components/Switch/SwitchGroup.tsx +27 -18
  142. package/src/components/Table/Table.stories.tsx +1 -19
  143. package/src/components/Table/Table.tsx +3 -1
  144. package/src/components/Tabs/IMPLEMENTATION_NOTES.md +4 -0
  145. package/src/components/Tabs/Tabs.stories.tsx +41 -24
  146. package/src/components/Tabs/Tabs.tsx +49 -66
  147. package/src/components/Text/Text.stories.tsx +5 -17
  148. package/src/components/Text/Text.tsx +1 -15
  149. package/src/components/TextArea/TextArea.tsx +7 -17
  150. package/src/components/TextField/TextField.stories.tsx +1 -27
  151. package/src/components/TextField/TextField.tsx +4 -6
  152. package/src/components/TimePicker/TimePicker.stories.tsx +2 -19
  153. package/src/components/TimePicker/TimePicker.tsx +3 -1
  154. package/src/components/Timeline/Timeline.tsx +4 -1
  155. package/src/components/Timeline/TimelineItem.tsx +1 -12
  156. package/src/components/Title/Title.stories.tsx +0 -18
  157. package/src/components/Title/Title.tsx +1 -7
  158. package/src/components/Toast/Toast.stories.tsx +1 -1
  159. package/src/components/Toast/Toast.tsx +62 -28
  160. package/src/components/Tooltip/Tooltip.tsx +11 -37
  161. package/src/components/TransferList/TransferList.stories.tsx +1 -19
  162. package/src/components/TransferList/TransferList.tsx +3 -1
  163. package/src/utils/RequireAccessibleLabel.ts +1 -12
  164. package/src/utils/filterStylingProps.ts +7 -20
@@ -4,25 +4,28 @@ import {
4
4
  type StackProps as MUIStackProps,
5
5
  } from "@mui/material";
6
6
  import {
7
- type RecursicaSpacing,
8
7
  SPACING_MAP,
9
8
  type OmitSx,
10
9
  filterSxProp,
11
10
  } from "../../utils/filterStylingProps";
12
11
 
13
- export interface RecursicaGroupProps {
14
- children?: React.ReactNode;
15
- gap?: MUIStackProps["spacing"] | RecursicaSpacing;
16
- rowGap?: MUIStackProps["spacing"] | RecursicaSpacing;
17
- columnGap?: MUIStackProps["spacing"] | RecursicaSpacing;
18
- }
12
+ import { type RecursicaGroupProps } from "@recursica/adapter-common";
19
13
 
20
14
  export type GroupProps = OmitSx<
21
15
  Omit<MUIStackProps, "spacing" | "direction"> & RecursicaGroupProps
22
16
  >;
23
17
 
24
18
  export const Group = forwardRef<HTMLDivElement, GroupProps>(function Group(
25
- { children, gap = "rec-default", rowGap, columnGap, ...rest },
19
+ {
20
+ children,
21
+ gap = "rec-default",
22
+ rowGap,
23
+ columnGap,
24
+ justify,
25
+ align,
26
+ wrap,
27
+ ...rest
28
+ },
26
29
  ref,
27
30
  ) {
28
31
  const safeProps = filterSxProp(rest as Record<string, unknown>);
@@ -43,7 +46,9 @@ export const Group = forwardRef<HTMLDivElement, GroupProps>(function Group(
43
46
  <MUIStack
44
47
  ref={ref}
45
48
  direction="row"
46
- flexWrap="wrap"
49
+ flexWrap={wrap || "wrap"}
50
+ justifyContent={justify}
51
+ alignItems={align}
47
52
  spacing={resolvedGap}
48
53
  sx={{
49
54
  ...(resolvedRowGap ? { rowGap: resolvedRowGap } : {}),
@@ -1,6 +1,7 @@
1
+ import React, { isValidElement } from "react";
1
2
  import {
2
- Popover as MuiHoverCard,
3
- type PopoverProps as MuiHoverCardProps,
3
+ Tooltip as MuiTooltip,
4
+ type TooltipProps as MuiTooltipProps,
4
5
  } from "@mui/material";
5
6
  import {
6
7
  filterStylingProps,
@@ -12,48 +13,31 @@ import styles from "./HoverCard.module.css";
12
13
  // HOVERCARD ROOT
13
14
  // ============================================================
14
15
 
15
- /**
16
- * Recursica-specific props for HoverCard.
17
- */
18
- export interface RecursicaHoverCardProps {
19
- /**
20
- * Whether to display a beak (arrow) pointing from the dropdown to the target.
21
- * This is the Recursica equivalent of Mui's `withArrow`.
22
- * When both `withBeak` and `withArrow` are provided, `withBeak` takes precedence.
23
- */
24
- withBeak?: boolean;
25
- }
26
-
27
- /**
28
- * Recursica HoverCard component wrapping Mui's composable HoverCard.
29
- *
30
- * Displays a dropdown panel when the user hovers over a target element.
31
- * Uses the composable dot-notation pattern:
32
- * ```tsx
33
- * <HoverCard withBeak>
34
- * <HoverCard.Target>
35
- * <Button>Hover me</Button>
36
- * </HoverCard.Target>
37
- * <HoverCard.Dropdown>
38
- * Content displayed on hover
39
- * </HoverCard.Dropdown>
40
- * </HoverCard>
41
- * ```
42
- */
16
+ import { type RecursicaHoverCardProps } from "@recursica/adapter-common";
17
+
43
18
  export type HoverCardProps = RecursicaOverStyled<
44
- MuiHoverCardProps & RecursicaHoverCardProps
19
+ Omit<MuiTooltipProps, "title" | "children"> & RecursicaHoverCardProps
45
20
  >;
46
21
 
47
22
  const HoverCardBase = function HoverCard({
48
23
  overStyled = false,
49
24
  withBeak = true,
25
+ position = "top",
26
+ openDelay = 0,
27
+ closeDelay = 150,
28
+ disabled = false,
29
+ offset = 5,
30
+ children,
50
31
  ...rest
51
32
  }: HoverCardProps) {
52
- const sanitizedProps = filterStylingProps(rest, overStyled);
33
+ const sanitizedProps = filterStylingProps(
34
+ rest as Record<string, unknown>,
35
+ overStyled,
36
+ );
53
37
 
54
38
  // Bind CSS module classes to Mui's internal classNames API
55
39
  const mergedClassNames: Partial<Record<string, string>> = {
56
- dropdown: styles.dropdown,
40
+ tooltip: styles.dropdown,
57
41
  arrow: styles.arrow,
58
42
  };
59
43
 
@@ -73,29 +57,55 @@ const HoverCardBase = function HoverCard({
73
57
  });
74
58
  }
75
59
 
76
- // arrowSize must be a JS number prop — Mui uses it for inline width/height
77
- // and positioning offset (-arrowSize/2) calculations that cannot be CSS-driven.
78
- // Default to 16 to match the Recursica beak-size token (16px).
79
- const arrowSize =
80
- ((sanitizedProps as Record<string, unknown>).arrowSize as
81
- | number
82
- | undefined) ?? 16;
83
-
84
- // Resolve withBeak (Recursica) vs withArrow (Mui).
85
- // withBeak takes precedence when both are provided.
86
- const withArrow = (sanitizedProps as Record<string, unknown>).withArrow as
87
- | boolean
88
- | undefined;
89
- const resolvedWithArrow = withBeak ?? withArrow;
60
+ // Find Target and Dropdown children
61
+ let targetNode: React.ReactNode = null;
62
+ let dropdownNode: React.ReactNode = null;
63
+
64
+ React.Children.forEach(children, (child) => {
65
+ if (isValidElement(child)) {
66
+ const childElement = child as any;
67
+ if (childElement.type?.displayName === "HoverCardTarget") {
68
+ targetNode = childElement.props.children;
69
+ } else if (childElement.type?.displayName === "HoverCardDropdown") {
70
+ dropdownNode = childElement.props.children;
71
+ }
72
+ }
73
+ });
74
+
75
+ if (!targetNode) {
76
+ // Fallback if structure is wrong
77
+ targetNode = <div />;
78
+ }
79
+ if (!dropdownNode) {
80
+ dropdownNode = <div />;
81
+ }
90
82
 
91
83
  return (
92
- <MuiHoverCard
93
- position="top" /* Recursica default; Mui defaults to "bottom" */
94
- arrowSize={arrowSize}
95
- withArrow={resolvedWithArrow}
96
- classes={mergedClassNames}
97
- {...(sanitizedProps as unknown as MuiHoverCardProps)}
98
- />
84
+ <MuiTooltip
85
+ title={dropdownNode}
86
+ placement={position as any}
87
+ arrow={withBeak}
88
+ enterDelay={openDelay}
89
+ leaveDelay={closeDelay}
90
+ disableHoverListener={disabled}
91
+ slotProps={{
92
+ popper: {
93
+ modifiers: [
94
+ {
95
+ name: "offset",
96
+ options: {
97
+ offset: [0, offset],
98
+ },
99
+ },
100
+ ],
101
+ },
102
+ }}
103
+ classes={mergedClassNames as any}
104
+ {...(sanitizedProps as any)}
105
+ >
106
+ {/* Tooltip requires a single valid React element child that accepts a ref */}
107
+ {isValidElement(targetNode) ? targetNode : <span>{targetNode}</span>}
108
+ </MuiTooltip>
99
109
  );
100
110
  };
101
111
  HoverCardBase.displayName = "HoverCard";
@@ -104,14 +114,12 @@ HoverCardBase.displayName = "HoverCard";
104
114
  // HOVERCARD TARGET
105
115
  // ============================================================
106
116
 
107
- /**
108
- * Wrapper for the element that triggers the hover card.
109
- * Requires a single child element that supports ref forwarding.
110
- */
111
- export type HoverCardTargetProps = any;
117
+ export type HoverCardTargetProps = { children?: React.ReactNode };
112
118
 
113
- const HoverCardTarget = function HoverCardTarget(props: HoverCardTargetProps) {
114
- return <div {...props} />;
119
+ const HoverCardTarget = function HoverCardTarget({
120
+ children,
121
+ }: HoverCardTargetProps) {
122
+ return <>{children}</>;
115
123
  };
116
124
  HoverCardTarget.displayName = "HoverCardTarget";
117
125
 
@@ -119,23 +127,12 @@ HoverCardTarget.displayName = "HoverCardTarget";
119
127
  // HOVERCARD DROPDOWN
120
128
  // ============================================================
121
129
 
122
- /** The dropdown panel displayed when hovering over the target. */
123
- export type HoverCardDropdownProps = RecursicaOverStyled<any>;
130
+ export type HoverCardDropdownProps = { children?: React.ReactNode };
124
131
 
125
132
  const HoverCardDropdown = function HoverCardDropdown({
126
- overStyled = false,
127
- ...rest
133
+ children,
128
134
  }: HoverCardDropdownProps) {
129
- const sanitizedProps = filterStylingProps(rest, overStyled);
130
- const classNameProp = (sanitizedProps as Record<string, unknown>)
131
- .className as string | undefined;
132
-
133
- return (
134
- <div
135
- className={classNameProp}
136
- {...(sanitizedProps as unknown as MuiHoverCardDropdownProps)}
137
- />
138
- );
135
+ return <>{children}</>;
139
136
  };
140
137
  HoverCardDropdown.displayName = "HoverCardDropdown";
141
138
 
@@ -62,6 +62,10 @@
62
62
  );
63
63
  }
64
64
 
65
+ .root :global(.MuiFormLabel-asterisk) {
66
+ display: none !important;
67
+ }
68
+
65
69
  /* MUI propagates .Mui-error to the label automatically on FormControl error.
66
70
  We explicitly override this bleed to prevent the main label text from turning red,
67
71
  while allowing the asterisk to take the error color! */
@@ -15,19 +15,9 @@ const meta: Meta<LabelStoryProps> = {
15
15
  docs: {
16
16
  description: {
17
17
  component:
18
- "The `Label` component is a strict Recursica-styled wrapper around MUI's native `InputLabel`. It serves as the primary compositional primitive for all form fields, preserving MUI'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 MUI's native required asterisk mechanisms.",
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
19
  },
20
20
  },
21
- controls: {
22
- include: [
23
- "labelSize",
24
- "labelAlignment",
25
- "required",
26
- "labelOptionalText",
27
- "labelWithEditIcon",
28
- "children",
29
- ],
30
- },
31
21
  },
32
22
  argTypes: {
33
23
  ...formControlArgTypes,
@@ -39,7 +29,7 @@ export default meta;
39
29
  type Story = StoryObj<LabelStoryProps>;
40
30
 
41
31
  // Utility mapping to pipe raw Label args structurally into TextField accurately
42
- const renderWithTextField = ({ children, ...args }: any) => (
32
+ const renderWithTextField = ({ children, ...args }: LabelStoryProps) => (
43
33
  <TextField
44
34
  label={children as React.ReactNode}
45
35
  placeholder="Form Control primitive mapped..."
@@ -50,6 +40,7 @@ const renderWithTextField = ({ children, ...args }: any) => (
50
40
  export const Default: Story = {
51
41
  args: {
52
42
  children: "Dynamic Label (Controls)",
43
+
53
44
  labelSize: "default",
54
45
  labelAlignment: "left",
55
46
  required: false,
@@ -69,6 +60,7 @@ export const StackedDefault: Story = {
69
60
  export const StackedRequired: Story = {
70
61
  args: {
71
62
  children: "Primary Network Node",
63
+
72
64
  required: true,
73
65
  },
74
66
  render: renderWithTextField,
@@ -77,6 +69,7 @@ export const StackedRequired: Story = {
77
69
  export const StackedWithEditIcon: Story = {
78
70
  args: {
79
71
  children: "Environment Variables",
72
+
80
73
  labelWithEditIcon: true,
81
74
  },
82
75
  render: renderWithTextField,
@@ -85,6 +78,7 @@ export const StackedWithEditIcon: Story = {
85
78
  export const SideBySideDefault: Story = {
86
79
  args: {
87
80
  children: "Status",
81
+
88
82
  labelSize: "default",
89
83
  },
90
84
  render: renderWithTextField,
@@ -93,6 +87,7 @@ export const SideBySideDefault: Story = {
93
87
  export const RequiredSuppressesOptionalText: Story = {
94
88
  args: {
95
89
  children: "Full Name",
90
+
96
91
  required: true,
97
92
  labelOptionalText: "This should not render",
98
93
  },
@@ -102,6 +97,7 @@ export const RequiredSuppressesOptionalText: Story = {
102
97
  export const BooleanOptionalText: Story = {
103
98
  args: {
104
99
  children: "Middle Initial",
100
+
105
101
  labelOptionalText: true,
106
102
  },
107
103
  render: renderWithTextField,
@@ -110,6 +106,16 @@ export const BooleanOptionalText: Story = {
110
106
  export const WithEditIcon: Story = {
111
107
  args: {
112
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
+
113
119
  labelWithEditIcon: true,
114
120
  },
115
121
  render: renderWithTextField,
@@ -3,16 +3,10 @@ import { InputLabel, type InputLabelProps } from "@mui/material";
3
3
  import { filterStylingProps } from "../../utils/filterStylingProps";
4
4
  import styles from "./Label.module.css";
5
5
 
6
- export interface LabelProps extends InputLabelProps {
6
+ import { type RecursicaLabelProps } from "@recursica/adapter-common";
7
+
8
+ export interface LabelProps extends InputLabelProps, RecursicaLabelProps {
7
9
  overStyled?: boolean;
8
- /** Explicit optional text to render safely mapping alongside the label. Hidden natively if 'required' is flagged true. */
9
- labelOptionalText?: React.ReactNode | true;
10
- /** Triggers the inline edit action icon native layout hook beside the label element. */
11
- labelWithEditIcon?: boolean;
12
- /** Fires specifically on icon click natively. */
13
- onLabelEditClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;
14
- /** Replaces the right side optional text block natively with any custom React node (e.g. actions, toggles). */
15
- labelActionArea?: React.ReactNode;
16
10
  }
17
11
 
18
12
  export const Label = React.forwardRef<HTMLLabelElement, LabelProps>(
@@ -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.