@recursica/mui-adapter 0.2.0 → 0.4.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 (88) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/mui-adapter.cjs +1 -1
  3. package/dist/mui-adapter.cjs.map +1 -1
  4. package/dist/mui-adapter.css +1 -1
  5. package/dist/mui-adapter.js +286 -91
  6. package/dist/mui-adapter.js.map +1 -1
  7. package/dist/src/components/Box/Box.d.ts +2 -3
  8. package/dist/src/components/Button/Button.d.ts +40 -2
  9. package/dist/src/components/Container/Container.d.ts +8 -2
  10. package/dist/src/components/Flex/Flex.d.ts +25 -2
  11. package/dist/src/components/Group/Group.d.ts +10 -2
  12. package/dist/src/components/Link/Link.d.ts +13 -2
  13. package/dist/src/components/Loader/Loader.d.ts +9 -2
  14. package/dist/src/components/Stack/Stack.d.ts +8 -2
  15. package/dist/src/components/Text/Text.d.ts +18 -2
  16. package/dist/src/components/Title/Title.d.ts +17 -2
  17. package/dist/src/components/Typography/Typography.d.ts +27 -0
  18. package/dist/src/utils/filterStylingProps.d.ts +3 -0
  19. package/package.json +2 -1
  20. package/src/Introduction.stories.tsx +113 -110
  21. package/src/OverStyling.tsx +18 -23
  22. package/src/Version.tsx +14 -21
  23. package/src/components/Accordion/Accordion.stories.tsx +19 -0
  24. package/src/components/AssistiveElement/AssistiveElement.stories.tsx +19 -0
  25. package/src/components/Avatar/Avatar.stories.tsx +19 -0
  26. package/src/components/Badge/Badge.stories.tsx +19 -0
  27. package/src/components/Box/Box.stories.tsx +19 -10
  28. package/src/components/Box/Box.tsx +11 -14
  29. package/src/components/Box/IMPLEMENTATION_NOTES.md +5 -0
  30. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +19 -0
  31. package/src/components/Button/BUTTON_IMPLEMENTATION_NOTES.md +33 -0
  32. package/src/components/Button/Button.module.css +343 -0
  33. package/src/components/Button/Button.stories.tsx +181 -5
  34. package/src/components/Button/Button.tsx +141 -5
  35. package/src/components/Card/Card.stories.tsx +19 -0
  36. package/src/components/Checkbox/Checkbox.stories.tsx +19 -0
  37. package/src/components/Chip/Chip.stories.tsx +19 -0
  38. package/src/components/Container/Container.stories.tsx +19 -0
  39. package/src/components/Container/Container.tsx +56 -5
  40. package/src/components/Container/IMPLEMENTATION_NOTES.md +5 -0
  41. package/src/components/DatePicker/DatePicker.stories.tsx +19 -0
  42. package/src/components/Dropdown/Dropdown.stories.tsx +19 -0
  43. package/src/components/FileInput/FileInput.stories.tsx +19 -0
  44. package/src/components/FileUpload/FileUpload.stories.tsx +19 -0
  45. package/src/components/Flex/Flex.stories.tsx +19 -0
  46. package/src/components/Flex/Flex.tsx +77 -5
  47. package/src/components/FormControlLayout/FormControlLayout.stories.tsx +19 -0
  48. package/src/components/FormControlWrapper/FormControlWrapper.stories.tsx +19 -0
  49. package/src/components/Group/Group.stories.tsx +133 -5
  50. package/src/components/Group/Group.tsx +57 -5
  51. package/src/components/HoverCard/HoverCard.stories.tsx +19 -0
  52. package/src/components/Label/Label.stories.tsx +19 -0
  53. package/src/components/Link/Link.module.css +133 -0
  54. package/src/components/Link/Link.stories.tsx +52 -4
  55. package/src/components/Link/Link.tsx +47 -5
  56. package/src/components/Loader/LOADER_IMPLEMENTATION_NOTES.md +25 -0
  57. package/src/components/Loader/Loader.module.css +166 -0
  58. package/src/components/Loader/Loader.stories.tsx +93 -6
  59. package/src/components/Loader/Loader.tsx +69 -5
  60. package/src/components/Menu/Menu.stories.tsx +19 -0
  61. package/src/components/Modal/Modal.stories.tsx +19 -0
  62. package/src/components/NumberInput/NumberInput.stories.tsx +19 -0
  63. package/src/components/Pagination/Pagination.stories.tsx +19 -0
  64. package/src/components/Panel/Panel.stories.tsx +19 -0
  65. package/src/components/Radio/Radio.stories.tsx +19 -0
  66. package/src/components/ReadOnlyField/ReadOnlyField.stories.tsx +19 -0
  67. package/src/components/SegmentedControl/SegmentedControl.stories.tsx +19 -0
  68. package/src/components/Slider/Slider.stories.tsx +19 -0
  69. package/src/components/Stack/Stack.stories.tsx +118 -5
  70. package/src/components/Stack/Stack.tsx +37 -5
  71. package/src/components/Stepper/Stepper.stories.tsx +19 -0
  72. package/src/components/Switch/Switch.stories.tsx +19 -0
  73. package/src/components/Table/Table.stories.tsx +19 -0
  74. package/src/components/Tabs/Tabs.stories.tsx +19 -0
  75. package/src/components/Text/Text.stories.tsx +87 -3
  76. package/src/components/Text/Text.tsx +27 -4
  77. package/src/components/TextArea/TextArea.stories.tsx +19 -0
  78. package/src/components/TextField/TextField.stories.tsx +19 -0
  79. package/src/components/TimePicker/TimePicker.stories.tsx +19 -0
  80. package/src/components/Timeline/Timeline.stories.tsx +19 -0
  81. package/src/components/Title/Title.stories.tsx +68 -3
  82. package/src/components/Title/Title.tsx +29 -5
  83. package/src/components/Toast/Toast.stories.tsx +19 -0
  84. package/src/components/Tooltip/Tooltip.stories.tsx +19 -0
  85. package/src/components/TransferList/TransferList.stories.tsx +19 -0
  86. package/src/components/Typography/Typography.tsx +42 -0
  87. package/src/utils/ColorSchemeWrapper.tsx +1 -5
  88. package/src/utils/filterStylingProps.ts +13 -1
package/src/Version.tsx CHANGED
@@ -1,43 +1,36 @@
1
1
  import ReactMarkdown from "react-markdown";
2
- import {
3
- Container,
4
- Paper,
5
- Title,
6
- TypographyStylesProvider,
7
- Group,
8
- Anchor,
9
- Divider,
10
- } from "@mantine/core";
2
+ import { Paper, Divider } from "@mui/material";
3
+ import { Container, Title, Group, Link, Box } from "./components";
11
4
  import pkg from "../package.json";
12
5
  import changelog from "../CHANGELOG.md?raw";
13
6
 
14
7
  export const VersionInfo = () => {
15
8
  return (
16
- <Container size="md" py="xl">
17
- <Paper withBorder p="xl" radius="md">
18
- <Title order={1} mb="xs">
19
- Mantine Adapter v{pkg.version}
9
+ <Container size="md" style={{ padding: "32px 0" }}>
10
+ <Paper variant="outlined" sx={{ p: 4, borderRadius: 2 }}>
11
+ <Title order={1} mb={1}>
12
+ MUI Adapter v{pkg.version}
20
13
  </Title>
21
- <Group mb="xl" gap="md">
22
- <Anchor
14
+ <Group mb={4} gap="rec-md">
15
+ <Link
23
16
  href="https://github.com/borderux/recursica"
24
17
  target="_blank"
25
18
  rel="noopener noreferrer"
26
19
  >
27
20
  GitHub Repository
28
- </Anchor>
29
- <Anchor
21
+ </Link>
22
+ <Link
30
23
  href="https://recursica.com"
31
24
  target="_blank"
32
25
  rel="noopener noreferrer"
33
26
  >
34
27
  Documentation & Website
35
- </Anchor>
28
+ </Link>
36
29
  </Group>
37
- <Divider mb="xl" />
38
- <TypographyStylesProvider>
30
+ <Divider sx={{ mb: 4 }} />
31
+ <Box className="markdown-body">
39
32
  <ReactMarkdown>{changelog}</ReactMarkdown>
40
- </TypographyStylesProvider>
33
+ </Box>
41
34
  </Paper>
42
35
  </Container>
43
36
  );
@@ -6,6 +6,25 @@ const meta: Meta<typeof Accordion> = {
6
6
  title: "UI-Kit/🚧 Accordion",
7
7
  component: Accordion,
8
8
  tags: ["autodocs"],
9
+ 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
+ ],
26
+ },
27
+ },
9
28
  };
10
29
 
11
30
  export default meta;
@@ -6,6 +6,25 @@ const meta: Meta<typeof AssistiveElement> = {
6
6
  title: "UI-Kit/🚧 AssistiveElement",
7
7
  component: AssistiveElement,
8
8
  tags: ["autodocs"],
9
+ 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
+ ],
26
+ },
27
+ },
9
28
  };
10
29
 
11
30
  export default meta;
@@ -6,6 +6,25 @@ const meta: Meta<typeof Avatar> = {
6
6
  title: "UI-Kit/🚧 Avatar",
7
7
  component: Avatar,
8
8
  tags: ["autodocs"],
9
+ 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
+ ],
26
+ },
27
+ },
9
28
  };
10
29
 
11
30
  export default meta;
@@ -6,6 +6,25 @@ const meta: Meta<typeof Badge> = {
6
6
  title: "UI-Kit/🚧 Badge",
7
7
  component: Badge,
8
8
  tags: ["autodocs"],
9
+ 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
+ ],
26
+ },
27
+ },
9
28
  };
10
29
 
11
30
  export default meta;
@@ -12,6 +12,23 @@ const meta: Meta<typeof Box> = {
12
12
  "The `Box` component is the foundational layout primitive. It accepts all standard MUI layout properties (like `m`, `mt`, `p`, `px`, etc.), but natively intercepts **Recursica Spacing Tokens** (e.g., `rec-none`, `rec-sm`, `rec-default`, `rec-md`, `rec-lg`, `rec-xl`, `rec-2xl`). This allows developers to use Recursica's strict design tokens seamlessly alongside standard MUI spacing.",
13
13
  },
14
14
  },
15
+ controls: {
16
+ include: [
17
+ "layer",
18
+ "withLayer",
19
+ "children",
20
+ "component",
21
+ "variant",
22
+ "size",
23
+ "icon",
24
+ "disabled",
25
+ "href",
26
+ "onClick",
27
+ "onChange",
28
+ "value",
29
+ "checked",
30
+ ],
31
+ },
15
32
  },
16
33
  };
17
34
 
@@ -24,11 +41,7 @@ export const Default: Story = {
24
41
  m: "20px",
25
42
  },
26
43
  render: (args) => (
27
- <Box
28
- {...args}
29
- style={{ border: "1px solid gray", padding: "10px" }}
30
- overStyled={true}
31
- />
44
+ <Box {...args} style={{ border: "1px solid gray", padding: "10px" }} />
32
45
  ),
33
46
  };
34
47
 
@@ -40,11 +53,7 @@ export const WithRecursicaTokens: Story = {
40
53
  },
41
54
  render: (args) => (
42
55
  <div style={{ border: "1px dashed #ccc", display: "inline-block" }}>
43
- <Box
44
- {...args}
45
- style={{ backgroundColor: "rgba(0,0,0,0.1)" }}
46
- overStyled={true}
47
- />
56
+ <Box {...args} style={{ backgroundColor: "rgba(0,0,0,0.1)" }} />
48
57
  </div>
49
58
  ),
50
59
  };
@@ -1,26 +1,23 @@
1
+ /**
2
+ * Box layout wrapper.
3
+ *
4
+ * NOTE: Box is the lowest-level primitive layout component. It explicitly ALLOWS
5
+ * the `sx` prop as an escape hatch. It does not use the strict RecursicaOverStyled gatekeeper
6
+ * or any style stripping utilities.
7
+ */
1
8
  import React, { forwardRef } from "react";
2
9
  import { Box as MUIBox, type BoxProps as MUIBoxProps } from "@mui/material";
3
- import {
4
- filterStylingProps,
5
- type RecursicaOverStyled,
6
- } from "../../utils/filterStylingProps";
7
10
 
8
- export type BoxProps<C extends React.ElementType = "div"> = RecursicaOverStyled<
9
- MUIBoxProps<C, { component?: C }>
11
+ export type BoxProps<C extends React.ElementType = "div"> = MUIBoxProps<
12
+ C,
13
+ { component?: C }
10
14
  >;
11
15
 
12
16
  export const Box = forwardRef(function Box<C extends React.ElementType = "div">(
13
17
  props: BoxProps<C>,
14
18
  ref: React.Ref<Element>,
15
19
  ) {
16
- const { overStyled = false, ...rest } = props;
17
-
18
- const sanitizedProps = filterStylingProps(
19
- rest as Record<string, unknown>,
20
- overStyled,
21
- );
22
-
23
- return <MUIBox ref={ref} {...sanitizedProps} />;
20
+ return <MUIBox ref={ref} {...props} />;
24
21
  }) as <C extends React.ElementType = "div">(
25
22
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
26
23
  props: BoxProps<C> & { ref?: React.ForwardedRef<any> },
@@ -0,0 +1,5 @@
1
+ # Box Implementation Notes
2
+
3
+ ## `sx` Prop Exemption
4
+
5
+ By design, the `Box` component is the most permissive primitive in the UI kit. It explicitly allows the `sx` prop to pass through to the underlying MUI `Box`. It does not use any strict styling gatekeepers (`RecursicaOverStyled`, `filterSxProp`). It is intended to be used as a final escape hatch when the standard layout primitives or design system tokens cannot fulfill a unique layout requirement.
@@ -6,6 +6,25 @@ const meta: Meta<typeof Breadcrumb> = {
6
6
  title: "UI-Kit/🚧 Breadcrumb",
7
7
  component: Breadcrumb,
8
8
  tags: ["autodocs"],
9
+ 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
+ ],
26
+ },
27
+ },
9
28
  };
10
29
 
11
30
  export default meta;
@@ -0,0 +1,33 @@
1
+ # Button Component Implementation Notes
2
+
3
+ **Implementation Philosophy:**
4
+ The Button component serves as a foundational building block in Recursica. This implementation wraps the `@mui/material/Button` component but **disables its native visual heuristics entirely.**
5
+
6
+ We explicitly pass `disableRipple` and `disableElevation` to block MUI's dynamic behaviors. Furthermore, we intentionally **do not** map our `variant` or `size` properties to MUI's native `variant` or `size` props because doing so would trigger MUI's internal CSS engines to inject styles that clash with our strict design tokens.
7
+
8
+ **Styling Strategy:**
9
+
10
+ - We utilize `filterStylingProps` to prevent rogue injections of `sx`, `style`, or `className` properties that would violate the design system.
11
+ - All styling is controlled directly via CSS Modules, mapping DOM attributes like `data-variant` and `data-size` to pure CSS selectors.
12
+ - Hover states are managed with a standard `::after` pseudo-element overlay hack rather than relying on native hover psuedo-selectors modifying background-color directly. This allows a clean `opacity` overlay based on the provided design tokens, which guarantees identical visual feedback behavior across all underlying themes without overriding background hues manually.
13
+ - The polymorphic `component` prop natively supported by MUI is safely forwarded to allow correct semantics (e.g. rendering as an `<a>` tag or using a router `Link`).
14
+
15
+ **Accessibility:**
16
+
17
+ - We inject a development-time warning explicitly requiring `aria-label` when the component detects an icon-only configuration.
18
+
19
+ ---
20
+
21
+ ## Loader color contrast
22
+
23
+ **Decision:** When a Button is in a loading state, the `Recursica Loader` component is injected via the `loadingIndicator` prop. The `Loader` component strictly defines its own colors and styles per variant, meaning it does not automatically inherit the text color (`currentColor`) from the Button.
24
+
25
+ **Constraint:** This can lead to contrast issues (e.g., a blue dots loader inside a solid blue button). Design has explicitly decided not to address this at the moment. As such, developers using the `loading` prop must be aware that the loader's color is fixed by its internal tokens, not by the button's context.
26
+
27
+ ---
28
+
29
+ ## Loading state enforces disabled state
30
+
31
+ **Decision:** When `loading={true}` is passed to the Button, the component explicitly forces `disabled={true}` natively on the underlying element.
32
+
33
+ **Implementation:** This ensures that loading buttons automatically inherit the brand theme disabled opacities (via the `:disabled` CSS pseudo-class) rather than relying solely on MUI's internal loading opacity adjustments.
@@ -0,0 +1,343 @@
1
+ /* Baseline and Reset */
2
+ .root {
3
+ box-sizing: border-box;
4
+ margin: 0;
5
+ border-style: solid;
6
+ overflow: hidden; /* Truncation bounding box */
7
+ position: relative;
8
+ transition: all 0.2s ease;
9
+ width: fit-content; /* Prevent stretching in flex columns */
10
+
11
+ /* Shared Defaults */
12
+ font-family: var(
13
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_text_font-family
14
+ );
15
+ font-size: var(
16
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_text_font-size
17
+ );
18
+ font-style: var(
19
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_text_font-style
20
+ );
21
+ font-weight: var(
22
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_text_font-weight
23
+ );
24
+ letter-spacing: var(
25
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_text_letter-spacing
26
+ );
27
+ line-height: var(
28
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_text_line-height
29
+ );
30
+ text-decoration: var(
31
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_text_text-decoration
32
+ );
33
+ text-transform: var(
34
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_text_text-transform
35
+ );
36
+ }
37
+
38
+ /* Reset MUI native properties */
39
+ .root {
40
+ text-transform: none;
41
+ min-width: 0;
42
+ color: inherit;
43
+ background-color: transparent;
44
+ }
45
+
46
+ /* Internal layout logic for Truncation */
47
+ .root > *:not(:global(.MuiButton-loadingIndicator)) {
48
+ min-width: 0;
49
+ position: relative;
50
+ z-index: 1;
51
+ }
52
+
53
+ .label {
54
+ display: flex;
55
+ align-items: center;
56
+ min-width: 0;
57
+ flex: 1 1 0;
58
+ }
59
+
60
+ .labelText {
61
+ display: block;
62
+ min-width: 0;
63
+ overflow: hidden;
64
+ text-overflow: ellipsis;
65
+ white-space: nowrap;
66
+ font-size: inherit;
67
+ line-height: inherit;
68
+ }
69
+ .root[data-loading="true"] .labelText {
70
+ visibility: hidden;
71
+ }
72
+
73
+ /*
74
+ * Keep the loader fully opaque, but make the background transparent
75
+ * to create contrast for solid variants without changing the loader color.
76
+ */
77
+ .root[data-loading="true"] {
78
+ opacity: 1 !important;
79
+ }
80
+
81
+ .root[data-size="default"][data-variant="solid"][data-loading="true"] {
82
+ background-color: color-mix(
83
+ in srgb,
84
+ var(
85
+ --recursica_ui-kit_components_button_variants_styles_solid_properties_colors_background
86
+ )
87
+ calc(
88
+ var(
89
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_disabled-opacity
90
+ ) *
91
+ 100%
92
+ ),
93
+ transparent
94
+ ) !important;
95
+ }
96
+
97
+ .root[data-size="small"][data-variant="solid"][data-loading="true"] {
98
+ background-color: color-mix(
99
+ in srgb,
100
+ var(
101
+ --recursica_ui-kit_components_button_variants_styles_solid_properties_colors_background
102
+ )
103
+ calc(
104
+ var(
105
+ --recursica_ui-kit_components_button_variants_sizes_small_properties_disabled-opacity
106
+ ) *
107
+ 100%
108
+ ),
109
+ transparent
110
+ ) !important;
111
+ }
112
+
113
+ /* ==== SIZES ==== */
114
+ .root[data-size="default"] {
115
+ border-radius: var(
116
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_border-radius
117
+ );
118
+ height: var(
119
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_height
120
+ );
121
+ min-width: var(
122
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_min-width
123
+ );
124
+ padding: 0
125
+ var(
126
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_horizontal-padding
127
+ );
128
+ }
129
+ .root[data-size="default"] .labelText {
130
+ max-width: var(
131
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_max-label-width
132
+ );
133
+ }
134
+ .root[data-size="small"] {
135
+ border-radius: var(
136
+ --recursica_ui-kit_components_button_variants_sizes_small_properties_border-radius
137
+ );
138
+ height: var(
139
+ --recursica_ui-kit_components_button_variants_sizes_small_properties_height
140
+ );
141
+ min-width: var(
142
+ --recursica_ui-kit_components_button_variants_sizes_small_properties_min-width
143
+ );
144
+ padding: 0
145
+ var(
146
+ --recursica_ui-kit_components_button_variants_sizes_small_properties_horizontal-padding
147
+ );
148
+
149
+ /* Override specific typography for small */
150
+ font-family: var(
151
+ --recursica_ui-kit_components_button_variants_sizes_small_properties_text_font-family,
152
+ var(
153
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_text_font-family
154
+ )
155
+ );
156
+ font-size: var(
157
+ --recursica_ui-kit_components_button_variants_sizes_small_properties_text_font-size,
158
+ var(
159
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_text_font-size
160
+ )
161
+ );
162
+ font-weight: var(
163
+ --recursica_ui-kit_components_button_variants_sizes_small_properties_text_font-weight,
164
+ var(
165
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_text_font-weight
166
+ )
167
+ );
168
+ }
169
+ .root[data-size="small"] .labelText {
170
+ max-width: var(
171
+ --recursica_ui-kit_components_button_variants_sizes_small_properties_max-label-width
172
+ );
173
+ }
174
+
175
+ /* Icon Resets */
176
+ .iconWrapper {
177
+ display: flex;
178
+ align-items: center;
179
+ justify-content: center;
180
+ flex-shrink: 0;
181
+ }
182
+ .iconWrapper > * {
183
+ width: 100%;
184
+ height: 100%;
185
+ object-fit: contain;
186
+ }
187
+ .root[data-size="default"] .iconWrapper {
188
+ width: var(
189
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_icon
190
+ );
191
+ height: var(
192
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_icon
193
+ );
194
+ }
195
+ .root[data-size="small"] .iconWrapper {
196
+ width: var(
197
+ --recursica_ui-kit_components_button_variants_sizes_small_properties_icon
198
+ );
199
+ height: var(
200
+ --recursica_ui-kit_components_button_variants_sizes_small_properties_icon
201
+ );
202
+ }
203
+
204
+ /* MUI uses .MuiButton-startIcon and .MuiButton-endIcon */
205
+ .root[data-size="default"] .MuiButton-startIcon,
206
+ .root[data-size="default"] .MuiButton-endIcon {
207
+ margin-left: 0;
208
+ margin-right: var(
209
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_icon-text-gap
210
+ );
211
+ }
212
+ .root[data-size="small"] .MuiButton-startIcon,
213
+ .root[data-size="small"] .MuiButton-endIcon {
214
+ margin-left: 0;
215
+ margin-right: var(
216
+ --recursica_ui-kit_components_button_variants_sizes_small_properties_icon-text-gap
217
+ );
218
+ }
219
+
220
+ /* Icon-only logic overrides */
221
+ .root[data-icon-only] .MuiButton-startIcon,
222
+ .root[data-icon-only] .MuiButton-endIcon {
223
+ margin-right: 0;
224
+ margin-left: 0;
225
+ }
226
+
227
+ /* Disabled */
228
+ .root[data-size="default"]:disabled,
229
+ .root[data-size="default"]:global(.Mui-disabled) {
230
+ opacity: var(
231
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_disabled-opacity
232
+ );
233
+ cursor: not-allowed;
234
+ }
235
+ .root[data-size="small"]:disabled,
236
+ .root[data-size="small"]:global(.Mui-disabled) {
237
+ opacity: var(
238
+ --recursica_ui-kit_components_button_variants_sizes_small_properties_disabled-opacity
239
+ );
240
+ cursor: not-allowed;
241
+ }
242
+
243
+ /* Global Hover Hack Overlay */
244
+ .root::after {
245
+ content: "";
246
+ position: absolute;
247
+ inset: 0;
248
+ border-radius: inherit;
249
+ z-index: 0;
250
+ pointer-events: none;
251
+ transition: opacity 150ms ease;
252
+ opacity: 0;
253
+ }
254
+ .root[data-size="default"]::after {
255
+ background-color: var(
256
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_hover-color
257
+ );
258
+ }
259
+ .root[data-size="small"]::after {
260
+ background-color: var(
261
+ --recursica_ui-kit_components_button_variants_sizes_small_properties_hover-color
262
+ );
263
+ }
264
+ .root:hover:not(:disabled):not(:global(.Mui-disabled))::after {
265
+ opacity: var(
266
+ --recursica_ui-kit_components_button_variants_sizes_default_properties_hover-opacity,
267
+ 0.1
268
+ );
269
+ }
270
+
271
+ /* ==== VARIANTS ==== */
272
+
273
+ /* SOLID */
274
+ .root[data-variant="solid"] {
275
+ border-width: var(
276
+ --recursica_ui-kit_components_button_variants_styles_solid_properties_border-size
277
+ );
278
+ box-shadow: var(
279
+ --recursica_ui-kit_components_button_variants_styles_solid_properties_elevation
280
+ );
281
+ background-color: var(
282
+ --recursica_ui-kit_components_button_variants_styles_solid_properties_colors_background
283
+ );
284
+ border-color: var(
285
+ --recursica_ui-kit_components_button_variants_styles_solid_properties_colors_border-color
286
+ );
287
+ color: var(
288
+ --recursica_ui-kit_components_button_variants_styles_solid_properties_colors_text
289
+ );
290
+ }
291
+ .root[data-variant="solid"]:hover:not(:disabled):not(:global(.Mui-disabled)) {
292
+ color: var(
293
+ --recursica_ui-kit_components_button_variants_styles_solid_properties_colors_text-hover
294
+ );
295
+ }
296
+
297
+ /* OUTLINE */
298
+ .root[data-variant="outline"] {
299
+ border-width: var(
300
+ --recursica_ui-kit_components_button_variants_styles_outline_properties_border-size
301
+ );
302
+ box-shadow: var(
303
+ --recursica_ui-kit_components_button_variants_styles_outline_properties_elevation
304
+ );
305
+ background-color: var(
306
+ --recursica_ui-kit_components_button_variants_styles_outline_properties_colors_background
307
+ );
308
+ border-color: var(
309
+ --recursica_ui-kit_components_button_variants_styles_outline_properties_colors_border-color
310
+ );
311
+ color: var(
312
+ --recursica_ui-kit_components_button_variants_styles_outline_properties_colors_text
313
+ );
314
+ }
315
+ .root[data-variant="outline"]:hover:not(:disabled):not(:global(.Mui-disabled)) {
316
+ color: var(
317
+ --recursica_ui-kit_components_button_variants_styles_outline_properties_colors_text-hover
318
+ );
319
+ }
320
+
321
+ /* TEXT */
322
+ .root[data-variant="text"] {
323
+ border-width: var(
324
+ --recursica_ui-kit_components_button_variants_styles_text_properties_border-size
325
+ );
326
+ box-shadow: var(
327
+ --recursica_ui-kit_components_button_variants_styles_text_properties_elevation
328
+ );
329
+ background-color: var(
330
+ --recursica_ui-kit_components_button_variants_styles_text_properties_colors_background
331
+ );
332
+ border-color: var(
333
+ --recursica_ui-kit_components_button_variants_styles_text_properties_colors_border-color
334
+ );
335
+ color: var(
336
+ --recursica_ui-kit_components_button_variants_styles_text_properties_colors_text
337
+ );
338
+ }
339
+ .root[data-variant="text"]:hover:not(:disabled):not(:global(.Mui-disabled)) {
340
+ color: var(
341
+ --recursica_ui-kit_components_button_variants_styles_text_properties_colors_text-hover
342
+ );
343
+ }