@recursica/mui-adapter 0.5.0 → 0.6.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 (159) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/mui-adapter.cjs +74 -1
  3. package/dist/mui-adapter.cjs.map +1 -1
  4. package/dist/mui-adapter.css +1 -1
  5. package/dist/mui-adapter.js +6652 -204
  6. package/dist/mui-adapter.js.map +1 -1
  7. package/dist/src/components/Accordion/Accordion.d.ts +63 -2
  8. package/dist/src/components/AssistiveElement/AssistiveElement.d.ts +9 -2
  9. package/dist/src/components/Autocomplete/Autocomplete.d.ts +16 -2
  10. package/dist/src/components/Avatar/Avatar.d.ts +14 -2
  11. package/dist/src/components/Badge/Badge.d.ts +13 -3
  12. package/dist/src/components/Breadcrumb/Breadcrumb.d.ts +10 -3
  13. package/dist/src/components/Button/Button.d.ts +1 -1
  14. package/dist/src/components/Card/Card.d.ts +40 -3
  15. package/dist/src/components/Checkbox/Checkbox.d.ts +15 -2
  16. package/dist/src/components/Checkbox/CheckboxGroup.d.ts +16 -0
  17. package/dist/src/components/Checkbox/index.d.ts +5 -1
  18. package/dist/src/components/Chip/Chip.d.ts +18 -2
  19. package/dist/src/components/Dropdown/Dropdown.d.ts +23 -3
  20. package/dist/src/components/FormControlLayout/FormControlLayout.d.ts +10 -2
  21. package/dist/src/components/FormControlWrapper/FormControlWrapper.d.ts +24 -2
  22. package/dist/src/components/HoverCard/HoverCard.d.ts +55 -3
  23. package/dist/src/components/Label/Label.d.ts +13 -2
  24. package/dist/src/components/Link/Link.d.ts +1 -1
  25. package/dist/src/components/Menu/Menu.d.ts +99 -3
  26. package/dist/src/components/Modal/Modal.d.ts +36 -2
  27. package/dist/src/components/NumberInput/NumberInput.d.ts +14 -2
  28. package/dist/src/components/Pagination/Pagination.d.ts +44 -2
  29. package/dist/src/components/Pagination/Pagination.icons.d.ts +8 -0
  30. package/dist/src/components/Panel/Panel.d.ts +65 -3
  31. package/dist/src/components/Radio/Radio.d.ts +13 -3
  32. package/dist/src/components/Radio/RadioGroup.d.ts +13 -0
  33. package/dist/src/components/ReadOnlyField/ReadOnlyBooleanField.d.ts +5 -0
  34. package/dist/src/components/ReadOnlyField/ReadOnlyField.d.ts +7 -2
  35. package/dist/src/components/ReadOnlyField/ReadOnlySwitchField.d.ts +5 -0
  36. package/dist/src/components/ReadOnlyField/ReadOnlyTextField.d.ts +8 -0
  37. package/dist/src/components/ReadOnlyField/WithReadOnlyWrapper.d.ts +28 -0
  38. package/dist/src/components/ReadOnlyField/index.d.ts +1 -0
  39. package/dist/src/components/SegmentedControl/SegmentedControl.d.ts +31 -3
  40. package/dist/src/components/Slider/Slider.d.ts +28 -2
  41. package/dist/src/components/Stepper/Stepper.d.ts +21 -2
  42. package/dist/src/components/Switch/Switch.d.ts +10 -3
  43. package/dist/src/components/Switch/SwitchGroup.d.ts +13 -0
  44. package/dist/src/components/Tabs/Tabs.d.ts +35 -3
  45. package/dist/src/components/Text/Text.d.ts +1 -1
  46. package/dist/src/components/TextArea/TextArea.d.ts +18 -2
  47. package/dist/src/components/TextField/TextField.d.ts +16 -2
  48. package/dist/src/components/Timeline/Timeline.d.ts +14 -2
  49. package/dist/src/components/Timeline/TimelineItem.d.ts +29 -0
  50. package/dist/src/components/Title/Title.d.ts +1 -1
  51. package/dist/src/components/Toast/Toast.d.ts +25 -2
  52. package/dist/src/components/Tooltip/Tooltip.d.ts +42 -3
  53. package/dist/src/components/Typography/Typography.d.ts +1 -1
  54. package/package.json +9 -2
  55. package/src/components/Accordion/Accordion.module.css +295 -56
  56. package/src/components/Accordion/Accordion.stories.tsx +149 -21
  57. package/src/components/Accordion/Accordion.tsx +264 -5
  58. package/src/components/AssistiveElement/AssistiveElement.module.css +111 -20
  59. package/src/components/AssistiveElement/AssistiveElement.stories.tsx +76 -19
  60. package/src/components/AssistiveElement/AssistiveElement.tsx +85 -5
  61. package/src/components/Autocomplete/Autocomplete.module.css +320 -42
  62. package/src/components/Autocomplete/Autocomplete.stories.tsx +180 -19
  63. package/src/components/Autocomplete/Autocomplete.tsx +199 -6
  64. package/src/components/Avatar/Avatar.module.css +343 -73
  65. package/src/components/Avatar/Avatar.stories.tsx +94 -22
  66. package/src/components/Avatar/Avatar.tsx +110 -6
  67. package/src/components/Badge/Badge.module.css +127 -29
  68. package/src/components/Badge/Badge.stories.tsx +65 -22
  69. package/src/components/Badge/Badge.tsx +70 -6
  70. package/src/components/Breadcrumb/Breadcrumb.module.css +25 -5
  71. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +57 -22
  72. package/src/components/Breadcrumb/Breadcrumb.tsx +62 -6
  73. package/src/components/Button/Button.module.css +3 -3
  74. package/src/components/Card/Card.module.css +118 -38
  75. package/src/components/Card/Card.stories.tsx +117 -19
  76. package/src/components/Card/Card.tsx +179 -5
  77. package/src/components/Checkbox/Checkbox.module.css +232 -39
  78. package/src/components/Checkbox/Checkbox.stories.tsx +81 -19
  79. package/src/components/Checkbox/Checkbox.tsx +146 -5
  80. package/src/components/Checkbox/CheckboxGroup.tsx +117 -0
  81. package/src/components/Checkbox/index.ts +6 -1
  82. package/src/components/Chip/Chip.module.css +228 -43
  83. package/src/components/Chip/Chip.stories.tsx +101 -21
  84. package/src/components/Chip/Chip.tsx +138 -6
  85. package/src/components/Dropdown/Dropdown.module.css +291 -41
  86. package/src/components/Dropdown/Dropdown.stories.tsx +80 -21
  87. package/src/components/Dropdown/Dropdown.tsx +182 -6
  88. package/src/components/FormControlLayout/FormControlLayout.module.css +92 -0
  89. package/src/components/FormControlLayout/FormControlLayout.stories.tsx +74 -19
  90. package/src/components/FormControlLayout/FormControlLayout.tsx +58 -4
  91. package/src/components/FormControlWrapper/FormControlWrapper.module.css +96 -0
  92. package/src/components/FormControlWrapper/FormControlWrapper.stories.tsx +122 -19
  93. package/src/components/FormControlWrapper/FormControlWrapper.tsx +145 -6
  94. package/src/components/HoverCard/HoverCard.module.css +90 -22
  95. package/src/components/HoverCard/HoverCard.stories.tsx +158 -21
  96. package/src/components/HoverCard/HoverCard.tsx +150 -5
  97. package/src/components/Label/Label.module.css +136 -35
  98. package/src/components/Label/Label.stories.tsx +98 -17
  99. package/src/components/Label/Label.tsx +88 -5
  100. package/src/components/Menu/Menu.module.css +285 -51
  101. package/src/components/Menu/Menu.stories.tsx +307 -21
  102. package/src/components/Menu/Menu.tsx +318 -5
  103. package/src/components/Modal/Modal.module.css +171 -35
  104. package/src/components/Modal/Modal.stories.tsx +66 -22
  105. package/src/components/Modal/Modal.tsx +216 -4
  106. package/src/components/NumberInput/NumberInput.module.css +276 -42
  107. package/src/components/NumberInput/NumberInput.stories.tsx +83 -20
  108. package/src/components/NumberInput/NumberInput.tsx +148 -6
  109. package/src/components/Pagination/Pagination.icons.tsx +66 -0
  110. package/src/components/Pagination/Pagination.module.css +246 -20
  111. package/src/components/Pagination/Pagination.stories.tsx +42 -21
  112. package/src/components/Pagination/Pagination.tsx +193 -5
  113. package/src/components/Panel/Panel.module.css +206 -38
  114. package/src/components/Panel/Panel.stories.tsx +214 -22
  115. package/src/components/Panel/Panel.tsx +153 -5
  116. package/src/components/Radio/Radio.module.css +220 -37
  117. package/src/components/Radio/Radio.stories.tsx +77 -19
  118. package/src/components/Radio/Radio.tsx +178 -5
  119. package/src/components/Radio/RadioGroup.tsx +111 -0
  120. package/src/components/ReadOnlyField/ReadOnlyBooleanField.tsx +21 -0
  121. package/src/components/ReadOnlyField/ReadOnlyField.module.css +53 -15
  122. package/src/components/ReadOnlyField/ReadOnlyField.stories.tsx +175 -16
  123. package/src/components/ReadOnlyField/ReadOnlyField.tsx +109 -5
  124. package/src/components/ReadOnlyField/ReadOnlySwitchField.tsx +21 -0
  125. package/src/components/ReadOnlyField/ReadOnlyTextField.tsx +48 -0
  126. package/src/components/ReadOnlyField/WithReadOnlyWrapper.tsx +93 -0
  127. package/src/components/ReadOnlyField/index.ts +1 -0
  128. package/src/components/SegmentedControl/SegmentedControl.module.css +203 -47
  129. package/src/components/SegmentedControl/SegmentedControl.stories.tsx +102 -20
  130. package/src/components/SegmentedControl/SegmentedControl.tsx +110 -6
  131. package/src/components/Slider/Slider.module.css +542 -86
  132. package/src/components/Slider/Slider.stories.tsx +157 -19
  133. package/src/components/Slider/Slider.tsx +282 -5
  134. package/src/components/Stepper/Stepper.module.css +410 -71
  135. package/src/components/Stepper/Stepper.stories.tsx +132 -19
  136. package/src/components/Stepper/Stepper.tsx +145 -6
  137. package/src/components/Switch/Switch.module.css +238 -39
  138. package/src/components/Switch/Switch.stories.tsx +98 -19
  139. package/src/components/Switch/Switch.tsx +153 -6
  140. package/src/components/Switch/SwitchGroup.tsx +111 -0
  141. package/src/components/Tabs/Tabs.module.css +422 -79
  142. package/src/components/Tabs/Tabs.stories.tsx +138 -19
  143. package/src/components/Tabs/Tabs.tsx +103 -6
  144. package/src/components/TextArea/TextArea.module.css +155 -32
  145. package/src/components/TextArea/TextArea.stories.tsx +80 -21
  146. package/src/components/TextArea/TextArea.tsx +156 -6
  147. package/src/components/TextField/TextField.module.css +261 -42
  148. package/src/components/TextField/TextField.stories.tsx +168 -15
  149. package/src/components/TextField/TextField.tsx +171 -6
  150. package/src/components/Timeline/Timeline.module.css +365 -76
  151. package/src/components/Timeline/Timeline.stories.tsx +114 -21
  152. package/src/components/Timeline/Timeline.tsx +80 -5
  153. package/src/components/Timeline/TimelineItem.tsx +101 -0
  154. package/src/components/Toast/Toast.module.css +166 -28
  155. package/src/components/Toast/Toast.stories.tsx +54 -22
  156. package/src/components/Toast/Toast.tsx +90 -5
  157. package/src/components/Tooltip/Tooltip.module.css +89 -24
  158. package/src/components/Tooltip/Tooltip.stories.tsx +152 -22
  159. package/src/components/Tooltip/Tooltip.tsx +114 -5
@@ -1,8 +1,147 @@
1
- import React from "react";
2
- import "./Stepper.module.css";
1
+ import React, { forwardRef, isValidElement } from "react";
2
+ import {
3
+ Stepper as MuiStepper,
4
+ Step as MuiStep,
5
+ StepLabel as MuiStepLabel,
6
+ StepButton as MuiStepButton,
7
+ StepConnector as MuiStepConnector,
8
+ type StepperProps as MuiStepperProps,
9
+ } from "@mui/material";
10
+ import {
11
+ filterStylingProps,
12
+ type RecursicaOverStyled,
13
+ } from "../../utils/filterStylingProps";
14
+ import styles from "./Stepper.module.css";
3
15
 
4
- export type StepperProps = React.HTMLAttributes<HTMLDivElement>;
16
+ export interface RecursicaStepperProps
17
+ extends Omit<
18
+ MuiStepperProps,
19
+ "size" | "color" | "radius" | "iconSize" | "contentPadding" | "activeStep"
20
+ > {
21
+ size?: "small" | "large";
22
+ active?: number;
23
+ onStepClick?: (stepIndex: number) => void;
24
+ orientation?: "horizontal" | "vertical";
25
+ }
5
26
 
6
- export const Stepper: React.FC<StepperProps> = (props) => {
7
- return <div {...props}>Stepper</div>;
8
- };
27
+ export type StepperProps = RecursicaOverStyled<RecursicaStepperProps>;
28
+
29
+ export const StepperStep: React.FC<any> = () => null;
30
+ export const StepperCompleted: React.FC<any> = () => null;
31
+
32
+ const _Stepper = forwardRef<HTMLDivElement, StepperProps>(
33
+ function Stepper(props, ref) {
34
+ const {
35
+ overStyled = false,
36
+ size = "large",
37
+ orientation = "horizontal",
38
+ className,
39
+ style,
40
+ active = 0,
41
+ onStepClick,
42
+ children,
43
+ ...rest
44
+ } = props;
45
+
46
+ const sanitizedProps = filterStylingProps(rest, overStyled);
47
+
48
+ const steps = React.Children.toArray(children).filter(
49
+ (child: any) =>
50
+ isValidElement(child) &&
51
+ (child.type === StepperStep ||
52
+ (child.type as any).displayName === "StepperStep"),
53
+ );
54
+ const completed = React.Children.toArray(children).find(
55
+ (child: any) =>
56
+ isValidElement(child) &&
57
+ (child.type === StepperCompleted ||
58
+ (child.type as any).displayName === "StepperCompleted"),
59
+ );
60
+
61
+ return (
62
+ <div
63
+ className={`${styles.root} ${orientation === "horizontal" ? styles.horizontal : styles.vertical} ${size === "large" ? styles.large : styles.small} ${className || ""}`}
64
+ style={style as React.CSSProperties}
65
+ data-size={size}
66
+ data-orientation={orientation}
67
+ >
68
+ <MuiStepper
69
+ ref={ref as any}
70
+ orientation={orientation}
71
+ activeStep={active}
72
+ connector={
73
+ <MuiStepConnector
74
+ classes={{
75
+ root:
76
+ orientation === "horizontal"
77
+ ? styles.separator
78
+ : styles.verticalSeparator,
79
+ }}
80
+ />
81
+ }
82
+ classes={{
83
+ root: styles.steps,
84
+ }}
85
+ {...(sanitizedProps as MuiStepperProps)}
86
+ >
87
+ {steps.map((step: any, index: number) => {
88
+ const stepProps = step.props;
89
+ const label = stepProps.label;
90
+ const description = stepProps.description;
91
+
92
+ return (
93
+ <MuiStep
94
+ key={index}
95
+ classes={{ root: styles.step }}
96
+ completed={active > index}
97
+ >
98
+ <MuiStepButton onClick={() => onStepClick?.(index)}>
99
+ <MuiStepLabel
100
+ optional={
101
+ description ? (
102
+ <div className={styles.stepDescription}>
103
+ {description}
104
+ </div>
105
+ ) : null
106
+ }
107
+ classes={{
108
+ label: styles.stepLabel,
109
+ iconContainer: styles.stepIcon,
110
+ }}
111
+ >
112
+ {label}
113
+ </MuiStepLabel>
114
+ </MuiStepButton>
115
+ </MuiStep>
116
+ );
117
+ })}
118
+ </MuiStepper>
119
+ {active >= steps.length && completed && (
120
+ <div className={styles.content}>
121
+ {(completed as React.ReactElement).props.children}
122
+ </div>
123
+ )}
124
+ {active < steps.length &&
125
+ steps[active] &&
126
+ (steps[active] as React.ReactElement).props.children && (
127
+ <div className={styles.content}>
128
+ {(steps[active] as React.ReactElement).props.children}
129
+ </div>
130
+ )}
131
+ </div>
132
+ );
133
+ },
134
+ );
135
+
136
+ StepperStep.displayName = "StepperStep";
137
+ StepperCompleted.displayName = "StepperCompleted";
138
+
139
+ export const Stepper: typeof _Stepper & {
140
+ Step: typeof StepperStep;
141
+ Completed: typeof StepperCompleted;
142
+ } = Object.assign(_Stepper, {
143
+ Step: StepperStep,
144
+ Completed: StepperCompleted,
145
+ });
146
+
147
+ _Stepper.displayName = "Stepper";
@@ -1,39 +1,238 @@
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_switch-group_properties_item-gap */
6
- /* recursica-ignore: --recursica_ui-kit_components_switch-group_properties_padding */
7
- /* recursica-ignore: --recursica_ui-kit_components_switch-group_variants_layouts_side-by-side_properties_gutter */
8
- /* recursica-ignore: --recursica_ui-kit_components_switch-group_variants_layouts_side-by-side_properties_top-bottom-margin */
9
- /* recursica-ignore: --recursica_ui-kit_components_switch-group_variants_layouts_side-by-side_properties_vertical-padding */
10
- /* recursica-ignore: --recursica_ui-kit_components_switch-group_variants_layouts_stacked_properties_label-field-gap */
11
- /* recursica-ignore: --recursica_ui-kit_components_switch-group_variants_layouts_stacked_properties_top-bottom-margin */
12
- /* recursica-ignore: --recursica_ui-kit_components_switch-item_properties_colors_disabled-text */
13
- /* recursica-ignore: --recursica_ui-kit_components_switch-item_properties_colors_text */
14
- /* recursica-ignore: --recursica_ui-kit_components_switch-item_properties_disabled-opacity */
15
- /* recursica-ignore: --recursica_ui-kit_components_switch-item_properties_label-gap */
16
- /* recursica-ignore: --recursica_ui-kit_components_switch-item_properties_label-max-width */
17
- /* recursica-ignore: --recursica_ui-kit_components_switch-item_properties_text_font-family */
18
- /* recursica-ignore: --recursica_ui-kit_components_switch-item_properties_text_font-size */
19
- /* recursica-ignore: --recursica_ui-kit_components_switch-item_properties_text_font-style */
20
- /* recursica-ignore: --recursica_ui-kit_components_switch-item_properties_text_font-weight */
21
- /* recursica-ignore: --recursica_ui-kit_components_switch-item_properties_text_letter-spacing */
22
- /* recursica-ignore: --recursica_ui-kit_components_switch-item_properties_text_line-height */
23
- /* recursica-ignore: --recursica_ui-kit_components_switch-item_properties_text_text-decoration */
24
- /* recursica-ignore: --recursica_ui-kit_components_switch-item_properties_text_text-transform */
25
- /* recursica-ignore: --recursica_ui-kit_components_switch_properties_colors_icon-selected */
26
- /* recursica-ignore: --recursica_ui-kit_components_switch_properties_colors_icon-unselected */
27
- /* recursica-ignore: --recursica_ui-kit_components_switch_properties_colors_thumb-selected */
28
- /* recursica-ignore: --recursica_ui-kit_components_switch_properties_colors_thumb-unselected */
29
- /* recursica-ignore: --recursica_ui-kit_components_switch_properties_colors_track-selected */
30
- /* recursica-ignore: --recursica_ui-kit_components_switch_properties_colors_track-unselected */
31
- /* recursica-ignore: --recursica_ui-kit_components_switch_properties_thumb-border-radius */
32
- /* recursica-ignore: --recursica_ui-kit_components_switch_properties_thumb-elevation */
33
- /* recursica-ignore: --recursica_ui-kit_components_switch_properties_thumb-height */
34
- /* recursica-ignore: --recursica_ui-kit_components_switch_properties_thumb-icon-size */
35
- /* recursica-ignore: --recursica_ui-kit_components_switch_properties_thumb-width */
36
- /* recursica-ignore: --recursica_ui-kit_components_switch_properties_track-border-radius */
37
- /* recursica-ignore: --recursica_ui-kit_components_switch_properties_track-elevation */
38
- /* recursica-ignore: --recursica_ui-kit_components_switch_properties_track-inner-padding */
39
- /* recursica-ignore: --recursica_ui-kit_components_switch_properties_track-width */
1
+ /* HARDCODED VALUES
2
+ *
3
+ * 1. track border: none; (we do not use border for the switch track)
4
+ * 2. thumb border: none; (we do not use border for the thumb)
5
+ * 3. outline: none; (focus rings handled internally by mantine)
6
+ */
7
+
8
+ .root {
9
+ /* Provide a stable cursor when not disabled */
10
+ cursor: pointer;
11
+
12
+ --switch-track-padding: var(
13
+ --recursica_ui-kit_components_switch_properties_track-inner-padding
14
+ );
15
+ --switch-thumb-width: var(
16
+ --recursica_ui-kit_components_switch_properties_thumb-width
17
+ );
18
+ --switch-thumb-height: var(
19
+ --recursica_ui-kit_components_switch_properties_thumb-height
20
+ );
21
+ --switch-track-width: var(
22
+ --recursica_ui-kit_components_switch_properties_track-width
23
+ );
24
+ }
25
+
26
+ .root:has(input:disabled) {
27
+ cursor: not-allowed;
28
+ opacity: var(
29
+ --recursica_ui-kit_components_switch-item_properties_disabled-opacity
30
+ );
31
+ }
32
+
33
+ .body {
34
+ display: flex;
35
+ align-items: center;
36
+ gap: var(--recursica_ui-kit_components_switch-item_properties_label-gap);
37
+ }
38
+
39
+ /* HARDCODE: disable native hover color transitions applied by Mantine */
40
+ .track:hover {
41
+ background-color: var(
42
+ --recursica_ui-kit_components_switch_properties_colors_track-unselected
43
+ );
44
+ }
45
+ .root input:checked + .track:hover {
46
+ background-color: var(
47
+ --recursica_ui-kit_components_switch_properties_colors_track-selected
48
+ );
49
+ }
50
+
51
+ .track {
52
+ width: var(--switch-track-width);
53
+ height: calc(var(--switch-thumb-height) + (var(--switch-track-padding) * 2));
54
+ border-radius: var(
55
+ --recursica_ui-kit_components_switch_properties_track-border-radius
56
+ );
57
+ background-color: var(
58
+ --recursica_ui-kit_components_switch_properties_colors_track-unselected
59
+ );
60
+ box-shadow: var(
61
+ --recursica_ui-kit_components_switch_properties_track-elevation
62
+ );
63
+ padding: var(--switch-track-padding);
64
+ border: none; /* HARDCODE */
65
+
66
+ /* Mantine uses variables internally for these, but we explicitly override the CSS to ensure our dimensions */
67
+ --switch-width: var(--switch-track-width);
68
+ --switch-height: calc(
69
+ var(--switch-thumb-height) + (var(--switch-track-padding) * 2)
70
+ );
71
+ --switch-thumb-size: var(--switch-thumb-width);
72
+
73
+ display: flex;
74
+ align-items: center;
75
+ box-sizing: border-box;
76
+ transition: background-color 150ms ease;
77
+ cursor: inherit;
78
+ }
79
+
80
+ .root input:checked + .track {
81
+ background-color: var(
82
+ --recursica_ui-kit_components_switch_properties_colors_track-selected
83
+ );
84
+ border-color: transparent;
85
+ }
86
+
87
+ .thumb {
88
+ width: var(--switch-thumb-width);
89
+ height: var(--switch-thumb-height);
90
+ border-radius: var(
91
+ --recursica_ui-kit_components_switch_properties_thumb-border-radius
92
+ );
93
+ background-color: var(
94
+ --recursica_ui-kit_components_switch_properties_colors_thumb-unselected
95
+ );
96
+ box-shadow: var(
97
+ --recursica_ui-kit_components_switch_properties_thumb-elevation
98
+ );
99
+ border: none; /* HARDCODE */
100
+
101
+ transition: background-color 150ms ease;
102
+ }
103
+
104
+ .root input:checked + .track .thumb {
105
+ background-color: var(
106
+ --recursica_ui-kit_components_switch_properties_colors_thumb-selected
107
+ );
108
+ }
109
+
110
+ .labelWrapper {
111
+ display: flex;
112
+ flex-direction: column;
113
+ max-width: var(
114
+ --recursica_ui-kit_components_switch-item_properties_label-max-width
115
+ );
116
+ }
117
+
118
+ .label {
119
+ font-family: var(
120
+ --recursica_ui-kit_components_switch-item_properties_text_font-family
121
+ );
122
+ font-size: var(
123
+ --recursica_ui-kit_components_switch-item_properties_text_font-size
124
+ );
125
+ font-weight: var(
126
+ --recursica_ui-kit_components_switch-item_properties_text_font-weight
127
+ );
128
+ font-style: var(
129
+ --recursica_ui-kit_components_switch-item_properties_text_font-style
130
+ );
131
+ line-height: var(
132
+ --recursica_ui-kit_components_switch-item_properties_text_line-height
133
+ );
134
+ letter-spacing: var(
135
+ --recursica_ui-kit_components_switch-item_properties_text_letter-spacing
136
+ );
137
+ text-transform: var(
138
+ --recursica_ui-kit_components_switch-item_properties_text_text-transform
139
+ );
140
+ text-decoration: var(
141
+ --recursica_ui-kit_components_switch-item_properties_text_text-decoration
142
+ );
143
+ color: var(--recursica_ui-kit_components_switch-item_properties_colors_text);
144
+ cursor: inherit;
145
+ }
146
+
147
+ .root:has(input:disabled) .label {
148
+ color: var(
149
+ --recursica_ui-kit_components_switch-item_properties_colors_disabled-text
150
+ );
151
+ }
152
+
153
+ .thumbIconWrapper {
154
+ display: flex;
155
+ align-items: center;
156
+ justify-content: center;
157
+ width: 100%;
158
+ height: 100%;
159
+ position: relative;
160
+ }
161
+
162
+ .checkIcon,
163
+ .closeIcon {
164
+ width: var(--recursica_ui-kit_components_switch_properties_thumb-icon-size);
165
+ height: var(--recursica_ui-kit_components_switch_properties_thumb-icon-size);
166
+ position: absolute;
167
+ transition:
168
+ opacity 150ms ease,
169
+ transform 150ms ease;
170
+ }
171
+
172
+ /* Unchecked state */
173
+ .checkIcon {
174
+ opacity: 0;
175
+ transform: scale(0.5);
176
+ color: var(
177
+ --recursica_ui-kit_components_switch_properties_colors_icon-selected
178
+ );
179
+ }
180
+
181
+ .closeIcon {
182
+ opacity: 1;
183
+ transform: scale(1);
184
+ color: var(
185
+ --recursica_ui-kit_components_switch_properties_colors_icon-unselected
186
+ );
187
+ }
188
+
189
+ /* Checked state */
190
+ .root input:checked + .track .thumb .checkIcon {
191
+ opacity: 1;
192
+ transform: scale(1);
193
+ }
194
+
195
+ .root input:checked + .track .thumb .closeIcon {
196
+ opacity: 0;
197
+ transform: scale(0.5);
198
+ }
199
+
200
+ /* --- GROUP STYLES --- */
201
+ .groupRoot {
202
+ display: flex;
203
+ flex-direction: column;
204
+ align-items: flex-start;
205
+ padding: var(--recursica_ui-kit_components_switch-group_properties_padding);
206
+ gap: var(--recursica_ui-kit_components_switch-group_properties_item-gap);
207
+ }
208
+
209
+ /* SideBySide Variant */
210
+ .groupRoot[data-layout="side-by-side"] {
211
+ flex-direction: column;
212
+ gap: var(
213
+ --recursica_ui-kit_components_switch-group_variants_layouts_side-by-side_properties_gutter
214
+ );
215
+ padding-top: var(
216
+ --recursica_ui-kit_components_switch-group_variants_layouts_side-by-side_properties_vertical-padding
217
+ );
218
+ padding-bottom: var(
219
+ --recursica_ui-kit_components_switch-group_variants_layouts_side-by-side_properties_vertical-padding
220
+ );
221
+ margin-top: var(
222
+ --recursica_ui-kit_components_switch-group_variants_layouts_side-by-side_properties_top-bottom-margin
223
+ );
224
+ margin-bottom: var(
225
+ --recursica_ui-kit_components_switch-group_variants_layouts_side-by-side_properties_top-bottom-margin
226
+ );
227
+ }
228
+
229
+ /* Stacked Variant */
230
+ .groupRoot[data-layout="stacked"] {
231
+ flex-direction: column;
232
+ margin-top: var(
233
+ --recursica_ui-kit_components_switch-group_variants_layouts_stacked_properties_label-field-gap
234
+ );
235
+ margin-bottom: var(
236
+ --recursica_ui-kit_components_switch-group_variants_layouts_stacked_properties_top-bottom-margin
237
+ );
238
+ }
@@ -1,35 +1,114 @@
1
1
  import type { Meta, StoryObj } from "@storybook/react";
2
2
  import { Switch } from "./Switch";
3
- import { ComingSoon } from "@recursica/storybook-template";
3
+ import { Stack } from "../Stack/Stack";
4
4
 
5
5
  const meta: Meta<typeof Switch> = {
6
- title: "UI-Kit/🚧 Switch",
6
+ title: "UI-Kit/Switch",
7
7
  component: Switch,
8
8
  tags: ["autodocs"],
9
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
- ],
10
+ docs: {
11
+ description: {
12
+ component: `
13
+ The \`Switch\` component is an atomic form primitive representing boolean states, natively aligned to the Recursica design system.
14
+
15
+ > [!IMPORTANT]
16
+ > Unlike \`Checkbox\`, the \`Switch\` is typically used for standalone settings toggles. It fully supports the universal \`ReadOnlyField\` boundaries when passed the \`readOnly\` attribute.
17
+
18
+ ### Usage
19
+ To render a standard switch:
20
+ \`\`\`tsx
21
+ <Switch label="Enable Notifications" defaultChecked />
22
+ \`\`\`
23
+ `,
24
+ },
26
25
  },
27
26
  },
27
+ argTypes: {
28
+ checked: {
29
+ control: "boolean",
30
+ },
31
+ disabled: {
32
+ control: "boolean",
33
+ },
34
+ required: {
35
+ control: "boolean",
36
+ },
37
+ error: {
38
+ control: "boolean",
39
+ },
40
+ defaultChecked: {
41
+ control: "boolean",
42
+ },
43
+ readOnly: {
44
+ control: "boolean",
45
+ description:
46
+ "Toggles structural read-only data presentation bypassing interaction boundaries completely.",
47
+ },
48
+ controlMaxWidth: { table: { disable: true } },
49
+ controlMinWidth: { table: { disable: true } },
50
+ emptyValueComponent: { table: { disable: true } },
51
+ },
28
52
  };
29
53
 
30
54
  export default meta;
55
+
31
56
  type Story = StoryObj<typeof Switch>;
32
57
 
33
58
  export const Default: Story = {
34
- render: () => <ComingSoon componentName="Switch" />,
59
+ args: {
60
+ disabled: false,
61
+ label: "Standard Switch",
62
+ },
63
+ // We explicitly destructure global Storybook injected arguments so they do not leak into the DOM natively.
64
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
65
+ render: ({ withLayer, layer, ...args }: any) => <Switch {...args} />,
66
+ };
67
+
68
+ export const SideBySideLayout: Story = {
69
+ args: {
70
+ label: "Opt-in form alignment",
71
+ formLayout: "side-by-side",
72
+ },
73
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
74
+ render: ({ withLayer, layer, ...args }: any) => <Switch {...args} />,
75
+ };
76
+
77
+ export const StaticVariations: Story = {
78
+ args: {},
79
+ render: () => (
80
+ <Stack gap="xl">
81
+ <Switch label="Default Unchecked State" />
82
+ <Switch label="Checked State" defaultChecked />
83
+ <Switch label="Disabled Unchecked" disabled />
84
+ <Switch label="Disabled Checked" defaultChecked disabled />
85
+ </Stack>
86
+ ),
87
+ };
88
+
89
+ export const ReadOnly: Story = {
90
+ args: {
91
+ ...Default.args,
92
+ readOnly: true,
93
+ },
94
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
95
+ render: ({ withLayer, layer, ...args }: any) => <Switch {...args} />,
96
+ };
97
+
98
+ export const CustomReadOnly: Story = {
99
+ args: {
100
+ ...Default.args,
101
+ readOnly: true,
102
+ },
103
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
104
+ render: ({ withLayer, layer, ...args }: any) => (
105
+ <Switch
106
+ {...args}
107
+ readOnlyComponent={({ checked, label }) => (
108
+ <span style={{ fontWeight: "bold", color: checked ? "green" : "red" }}>
109
+ {label} {checked ? "ENABLED" : "DISABLED"}
110
+ </span>
111
+ )}
112
+ />
113
+ ),
35
114
  };