@recursica/mantine-adapter 0.21.0 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/dist/mantine-adapter.cjs +1 -1
- package/dist/mantine-adapter.cjs.map +1 -1
- package/dist/mantine-adapter.css +1 -1
- package/dist/mantine-adapter.js +2017 -1630
- package/dist/mantine-adapter.js.map +1 -1
- package/dist/src/components/AutoComplete/AutoComplete.d.ts +9 -0
- package/dist/src/components/Avatar/Avatar.d.ts +1 -1
- package/dist/src/components/Badge/Badge.d.ts +1 -1
- package/dist/src/components/Button/Button.d.ts +1 -1
- package/dist/src/components/Card/Card.d.ts +1 -1
- package/dist/src/components/DatePicker/DatePicker.d.ts +8 -2
- package/dist/src/components/Flex/Flex.d.ts +1 -1
- package/dist/src/components/Link/Link.d.ts +1 -1
- package/dist/src/components/SegmentedControl/SegmentedControl.d.ts +6 -1
- package/dist/src/components/Slider/Slider.d.ts +24 -2
- package/dist/src/components/Text/Text.d.ts +1 -1
- package/dist/src/components/Toast/Toast.d.ts +1 -1
- package/dist/src/components/index.d.ts +1 -0
- package/dist/test.html +1 -0
- package/package.json +5 -2
- package/src/GlobalExemptions.modules.css +13 -0
- package/src/components/AutoComplete/AUTOCOMPLETE_IMPLEMENTATION_NOTES.md +21 -0
- package/src/components/AutoComplete/AutoComplete.module.css +311 -0
- package/src/components/AutoComplete/AutoComplete.stories.tsx +187 -0
- package/src/components/AutoComplete/AutoComplete.tsx +154 -0
- package/src/components/Avatar/Avatar.module.css +40 -36
- package/src/components/Badge/Badge.module.css +4 -1
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +3 -10
- package/src/components/Button/Button.module.css +215 -56
- package/src/components/Button/Button.stories.tsx +27 -0
- package/src/components/Button/Button.tsx +11 -4
- package/src/components/Card/Card.module.css +58 -1
- package/src/components/Card/Card.stories.tsx +4 -2
- package/src/components/Checkbox/Checkbox.module.css +74 -46
- package/src/components/Checkbox/Checkbox.stories.tsx +3 -0
- package/src/components/Checkbox/CheckboxGroup.tsx +1 -9
- package/src/components/Chip/Chip.module.css +19 -1
- package/src/components/DatePicker/DATEPICKER_IMPLEMENTATION_NOTES.md +16 -0
- package/src/components/DatePicker/DatePicker.module.css +286 -0
- package/src/components/DatePicker/DatePicker.stories.tsx +127 -4
- package/src/components/DatePicker/DatePicker.tsx +166 -5
- package/src/components/Dropdown/Dropdown.module.css +42 -15
- package/src/components/Dropdown/Dropdown.stories.tsx +3 -0
- package/src/components/Dropdown/Dropdown.tsx +5 -1
- package/src/components/FileInput/FileInput.module.css +50 -0
- package/src/components/FileUpload/FileUpload.module.css +43 -0
- package/src/components/FormControlLayout/FormControlLayout.module.css +12 -2
- package/src/components/FormControlWrapper/FormControlWrapper.module.css +67 -0
- package/src/components/HoverCard/HoverCard.module.css +12 -5
- package/src/components/Label/Label.module.css +11 -3
- package/src/components/Link/Link.module.css +8 -0
- package/src/components/Loader/LOADER_IMPLEMENTATION_NOTES.md +1 -2
- package/src/components/Loader/Loader.module.css +3 -9
- package/src/components/Menu/Menu.module.css +73 -30
- package/src/components/Modal/Modal.module.css +92 -47
- package/src/components/NumberInput/NumberInput.module.css +46 -15
- package/src/components/NumberInput/NumberInput.tsx +5 -1
- package/src/components/Pagination/Pagination.module.css +123 -41
- package/src/components/Panel/Panel.module.css +55 -3
- package/src/components/Popover/Popover.module.css +6 -4
- package/src/components/Radio/Radio.module.css +72 -59
- package/src/components/Radio/Radio.stories.tsx +3 -0
- package/src/components/Radio/RadioGroup.tsx +1 -8
- package/src/components/ReadOnlyField/ReadOnlyField.module.css +14 -0
- package/src/components/ReadOnlyField/ReadOnlyField.tsx +16 -1
- package/src/components/SegmentedControl/SegmentedControl.module.css +106 -41
- package/src/components/SegmentedControl/SegmentedControl.stories.tsx +1 -4
- package/src/components/SegmentedControl/SegmentedControl.tsx +18 -4
- package/src/components/Slider/IMPLEMENTATION_NOTES.md +49 -0
- package/src/components/Slider/Slider.module.css +498 -0
- package/src/components/Slider/Slider.stories.tsx +159 -4
- package/src/components/Slider/Slider.tsx +283 -4
- package/src/components/Stepper/Stepper.module.css +53 -2
- package/src/components/Switch/Switch.module.css +62 -23
- package/src/components/Switch/Switch.stories.tsx +3 -0
- package/src/components/Switch/Switch.tsx +1 -0
- package/src/components/Switch/SwitchGroup.tsx +3 -10
- package/src/components/Tabs/Tabs.module.css +33 -12
- package/src/components/TextArea/TextArea.module.css +58 -120
- package/src/components/TextArea/TextArea.stories.tsx +3 -0
- package/src/components/TextArea/TextArea.tsx +7 -3
- package/src/components/TextField/TextField.module.css +46 -15
- package/src/components/TextField/TextField.tsx +5 -1
- package/src/components/TimePicker/TimePicker.module.css +44 -0
- package/src/components/Timeline/Timeline.module.css +6 -0
- package/src/components/Toast/Toast.module.css +56 -1
- package/src/components/Toast/Toast.tsx +1 -1
- package/src/components/Tooltip/Tooltip.module.css +9 -0
- package/src/components/TransferList/TransferList.module.css +41 -0
- package/src/components/index.ts +1 -0
|
@@ -99,14 +99,7 @@ export const RadioGroup = forwardRef<HTMLDivElement, RadioGroupProps>(
|
|
|
99
99
|
defaultValue={defaultValue}
|
|
100
100
|
>
|
|
101
101
|
<div className={styles.groupRoot} data-layout={formLayout}>
|
|
102
|
-
{
|
|
103
|
-
if (React.isValidElement(child)) {
|
|
104
|
-
return React.cloneElement(child as React.ReactElement<any>, {
|
|
105
|
-
disabled: readOnly || (child.props as any).disabled,
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
return child;
|
|
109
|
-
})}
|
|
102
|
+
{children}
|
|
110
103
|
</div>
|
|
111
104
|
</MantineRadio.Group>
|
|
112
105
|
}
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
/* LAYOUT SPACING OVERRIDES:
|
|
2
|
+
- Sets the --form-control-margin-bottom spacing hook to map component-specific layout tokens. */
|
|
3
|
+
.layoutOverride {
|
|
4
|
+
--form-control-margin-bottom: var(
|
|
5
|
+
--recursica_ui-kit_components_read-only-field_variants_layouts_stacked_properties_top-bottom-margin
|
|
6
|
+
);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.layoutOverride[data-form-layout="side-by-side"] {
|
|
10
|
+
--form-control-margin-bottom: var(
|
|
11
|
+
--recursica_ui-kit_components_read-only-field_variants_layouts_side-by-side_properties_top-bottom-margin
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
1
15
|
/* HARDCODED VALUES:
|
|
2
16
|
- margin: 0; padding: overrides native paragraph margins mapping back to form element flows.
|
|
3
17
|
*/
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
FormControlWrapper,
|
|
15
15
|
} from "../FormControlWrapper/FormControlWrapper";
|
|
16
16
|
import { ReadOnlyTextField } from "./ReadOnlyTextField";
|
|
17
|
+
import styles from "./ReadOnlyField.module.css";
|
|
17
18
|
|
|
18
19
|
export interface RecursicaReadOnlyFieldProps
|
|
19
20
|
extends Omit<
|
|
@@ -40,7 +41,15 @@ export type ReadOnlyFieldProps =
|
|
|
40
41
|
*/
|
|
41
42
|
export const ReadOnlyField = forwardRef<HTMLDivElement, ReadOnlyFieldProps>(
|
|
42
43
|
function ReadOnlyField(
|
|
43
|
-
{
|
|
44
|
+
{
|
|
45
|
+
value,
|
|
46
|
+
type = "text",
|
|
47
|
+
emptyValueComponent,
|
|
48
|
+
overStyled = false,
|
|
49
|
+
className,
|
|
50
|
+
style,
|
|
51
|
+
...rest
|
|
52
|
+
},
|
|
44
53
|
ref,
|
|
45
54
|
) {
|
|
46
55
|
let content: React.ReactNode = null;
|
|
@@ -87,10 +96,16 @@ export const ReadOnlyField = forwardRef<HTMLDivElement, ReadOnlyFieldProps>(
|
|
|
87
96
|
break;
|
|
88
97
|
}
|
|
89
98
|
|
|
99
|
+
const wrapperClass = className
|
|
100
|
+
? `${styles.layoutOverride} ${className}`
|
|
101
|
+
: styles.layoutOverride;
|
|
102
|
+
|
|
90
103
|
return (
|
|
91
104
|
<FormControlWrapper
|
|
92
105
|
ref={ref}
|
|
93
106
|
overStyled={overStyled as true}
|
|
107
|
+
className={wrapperClass}
|
|
108
|
+
style={style}
|
|
94
109
|
{...(sanitizedProps as any)}
|
|
95
110
|
>
|
|
96
111
|
{content}
|
|
@@ -1,77 +1,104 @@
|
|
|
1
1
|
/* HARDCODED VALUES:
|
|
2
2
|
- border-style: solid; on container and indicator
|
|
3
3
|
- background-color: transparent; on label hover (overriding Mantine)
|
|
4
|
-
-
|
|
4
|
+
- Scope prefix .root to enforce Figma tokens over Mantine's inline calculation without using !important
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
.root {
|
|
8
8
|
background-color: var(
|
|
9
|
-
--recursica_ui-kit_components_segmented-
|
|
10
|
-
)
|
|
9
|
+
--recursica_ui-kit_components_segmented-control_properties_colors_background
|
|
10
|
+
);
|
|
11
11
|
border: var(
|
|
12
|
-
--recursica_ui-kit_components_segmented-
|
|
12
|
+
--recursica_ui-kit_components_segmented-control_properties_border-size
|
|
13
13
|
)
|
|
14
14
|
solid
|
|
15
15
|
var(
|
|
16
|
-
--recursica_ui-kit_components_segmented-
|
|
16
|
+
--recursica_ui-kit_components_segmented-control_properties_colors_border-color
|
|
17
17
|
);
|
|
18
18
|
border-radius: var(
|
|
19
|
-
--recursica_ui-kit_components_segmented-
|
|
20
|
-
)
|
|
19
|
+
--recursica_ui-kit_components_segmented-control_properties_border-radius
|
|
20
|
+
);
|
|
21
21
|
padding: var(
|
|
22
|
-
--recursica_ui-kit_components_segmented-
|
|
22
|
+
--recursica_ui-kit_components_segmented-control_properties_padding-vertical
|
|
23
23
|
)
|
|
24
24
|
var(
|
|
25
|
-
--recursica_ui-kit_components_segmented-
|
|
26
|
-
)
|
|
25
|
+
--recursica_ui-kit_components_segmented-control_properties_padding-horizontal
|
|
26
|
+
);
|
|
27
27
|
box-shadow: var(
|
|
28
|
-
--recursica_ui-kit_components_segmented-
|
|
28
|
+
--recursica_ui-kit_components_segmented-control_properties_elevation,
|
|
29
|
+
none
|
|
29
30
|
);
|
|
30
31
|
gap: var(--recursica_ui-kit_components_segmented-control_properties_item-gap);
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
.label {
|
|
34
|
+
.root .label {
|
|
34
35
|
padding-left: var(
|
|
35
36
|
--recursica_ui-kit_components_segmented-control-item_properties_item_padding-horizontal
|
|
36
|
-
)
|
|
37
|
+
);
|
|
37
38
|
padding-right: var(
|
|
38
39
|
--recursica_ui-kit_components_segmented-control-item_properties_item_padding-horizontal
|
|
39
|
-
)
|
|
40
|
+
);
|
|
40
41
|
height: var(
|
|
41
42
|
--recursica_ui-kit_components_segmented-control-item_properties_item_height
|
|
42
|
-
)
|
|
43
|
+
);
|
|
43
44
|
border-radius: var(
|
|
44
|
-
--recursica_ui-kit_components_segmented-control-
|
|
45
|
-
|
|
45
|
+
--recursica_ui-kit_components_segmented-control-item_properties_unselected_border-radius,
|
|
46
|
+
var(
|
|
47
|
+
--recursica_ui-kit_components_segmented-control-item_properties_item_border-radius
|
|
48
|
+
)
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
border: var(
|
|
52
|
+
--recursica_ui-kit_components_segmented-control-item_properties_unselected_border-size
|
|
53
|
+
)
|
|
54
|
+
solid
|
|
55
|
+
var(
|
|
56
|
+
--recursica_ui-kit_components_segmented-control-item_properties_unselected_colors_border-color
|
|
57
|
+
);
|
|
58
|
+
background-color: var(
|
|
59
|
+
--recursica_ui-kit_components_segmented-control-item_properties_unselected_colors_background
|
|
60
|
+
);
|
|
61
|
+
box-shadow: var(
|
|
62
|
+
--recursica_ui-kit_components_segmented-control-item_properties_unselected_elevation
|
|
63
|
+
);
|
|
46
64
|
|
|
47
65
|
font-family: var(
|
|
48
|
-
--recursica_ui-kit_components_segmented-control-
|
|
66
|
+
--recursica_ui-kit_components_segmented-control-item_properties_unselected-text_font-family,
|
|
67
|
+
inherit
|
|
49
68
|
);
|
|
50
69
|
font-size: var(
|
|
51
|
-
--recursica_ui-kit_components_segmented-control-
|
|
70
|
+
--recursica_ui-kit_components_segmented-control-item_properties_unselected-text_font-size,
|
|
71
|
+
inherit
|
|
52
72
|
);
|
|
53
73
|
font-style: var(
|
|
54
|
-
--recursica_ui-kit_components_segmented-control-
|
|
74
|
+
--recursica_ui-kit_components_segmented-control-item_properties_unselected-text_font-style,
|
|
75
|
+
inherit
|
|
55
76
|
);
|
|
56
77
|
font-weight: var(
|
|
57
|
-
--recursica_ui-kit_components_segmented-control-
|
|
78
|
+
--recursica_ui-kit_components_segmented-control-item_properties_unselected-text_font-weight,
|
|
79
|
+
inherit
|
|
58
80
|
);
|
|
59
81
|
letter-spacing: var(
|
|
60
|
-
--recursica_ui-kit_components_segmented-control-
|
|
82
|
+
--recursica_ui-kit_components_segmented-control-item_properties_unselected-text_letter-spacing,
|
|
83
|
+
inherit
|
|
61
84
|
);
|
|
62
85
|
line-height: var(
|
|
63
|
-
--recursica_ui-kit_components_segmented-control-
|
|
86
|
+
--recursica_ui-kit_components_segmented-control-item_properties_unselected-text_line-height,
|
|
87
|
+
inherit
|
|
64
88
|
);
|
|
65
89
|
text-decoration: var(
|
|
66
|
-
--recursica_ui-kit_components_segmented-control-
|
|
90
|
+
--recursica_ui-kit_components_segmented-control-item_properties_unselected-text_text-decoration,
|
|
91
|
+
inherit
|
|
67
92
|
);
|
|
68
93
|
text-transform: var(
|
|
69
|
-
--recursica_ui-kit_components_segmented-control-
|
|
94
|
+
--recursica_ui-kit_components_segmented-control-item_properties_unselected-text_text-transform,
|
|
95
|
+
inherit
|
|
70
96
|
);
|
|
71
97
|
|
|
72
98
|
color: var(
|
|
73
|
-
--recursica_ui-kit_components_segmented-
|
|
74
|
-
|
|
99
|
+
--recursica_ui-kit_components_segmented-control-item_properties_unselected_colors_text-color,
|
|
100
|
+
inherit
|
|
101
|
+
);
|
|
75
102
|
|
|
76
103
|
display: flex;
|
|
77
104
|
align-items: center;
|
|
@@ -79,7 +106,7 @@
|
|
|
79
106
|
}
|
|
80
107
|
|
|
81
108
|
/* Mantine natively wraps label contents in an innerLabel span */
|
|
82
|
-
.label :global(.mantine-SegmentedControl-innerLabel) {
|
|
109
|
+
.root .label :global(.mantine-SegmentedControl-innerLabel) {
|
|
83
110
|
display: flex;
|
|
84
111
|
align-items: center;
|
|
85
112
|
justify-content: center;
|
|
@@ -88,7 +115,7 @@
|
|
|
88
115
|
);
|
|
89
116
|
}
|
|
90
117
|
|
|
91
|
-
.label svg {
|
|
118
|
+
.root .label svg {
|
|
92
119
|
width: var(
|
|
93
120
|
--recursica_ui-kit_components_segmented-control-item_properties_item_icon-size
|
|
94
121
|
);
|
|
@@ -99,40 +126,78 @@
|
|
|
99
126
|
}
|
|
100
127
|
|
|
101
128
|
/* Mantine adds a background on hover, we must strictly strip it */
|
|
102
|
-
.label:hover {
|
|
103
|
-
background-color: transparent
|
|
129
|
+
.root .label:hover {
|
|
130
|
+
background-color: transparent;
|
|
104
131
|
}
|
|
105
132
|
|
|
106
133
|
/* Mantine adds separators via ::before on the .control */
|
|
107
|
-
.control::before {
|
|
134
|
+
.root .control::before {
|
|
108
135
|
background-color: var(
|
|
109
136
|
--recursica_ui-kit_components_segmented-control_properties_colors_divider-color
|
|
110
|
-
)
|
|
137
|
+
);
|
|
138
|
+
width: var(
|
|
139
|
+
--recursica_ui-kit_components_segmented-control_properties_divider-size
|
|
140
|
+
);
|
|
111
141
|
}
|
|
112
142
|
|
|
113
143
|
/* Indicator (the moving selected block) */
|
|
114
|
-
.indicator {
|
|
144
|
+
.root .indicator {
|
|
115
145
|
background-color: var(
|
|
116
146
|
--recursica_ui-kit_components_segmented-control-item_properties_selected_colors_background
|
|
117
|
-
)
|
|
147
|
+
);
|
|
118
148
|
border: var(
|
|
119
149
|
--recursica_ui-kit_components_segmented-control-item_properties_selected_border-size
|
|
120
150
|
)
|
|
121
151
|
solid
|
|
122
152
|
var(
|
|
123
153
|
--recursica_ui-kit_components_segmented-control-item_properties_selected_colors_border-color
|
|
124
|
-
)
|
|
154
|
+
);
|
|
125
155
|
box-shadow: var(
|
|
126
156
|
--recursica_ui-kit_components_segmented-control-item_properties_selected_elevation
|
|
127
|
-
)
|
|
157
|
+
);
|
|
128
158
|
border-radius: var(
|
|
129
|
-
--recursica_ui-kit_components_segmented-control-
|
|
130
|
-
|
|
159
|
+
--recursica_ui-kit_components_segmented-control-item_properties_selected_border-radius,
|
|
160
|
+
var(
|
|
161
|
+
--recursica_ui-kit_components_segmented-control-item_properties_item_border-radius
|
|
162
|
+
)
|
|
163
|
+
);
|
|
131
164
|
}
|
|
132
165
|
|
|
133
166
|
/* Selected label text color override */
|
|
134
|
-
.control[data-active] .label {
|
|
167
|
+
.root .control[data-active] .label {
|
|
135
168
|
color: var(
|
|
136
169
|
--recursica_ui-kit_components_segmented-control-item_properties_selected_colors_text-color
|
|
137
|
-
)
|
|
170
|
+
);
|
|
171
|
+
font-family: var(
|
|
172
|
+
--recursica_ui-kit_components_segmented-control-item_properties_selected-text_font-family,
|
|
173
|
+
inherit
|
|
174
|
+
);
|
|
175
|
+
font-size: var(
|
|
176
|
+
--recursica_ui-kit_components_segmented-control-item_properties_selected-text_font-size,
|
|
177
|
+
inherit
|
|
178
|
+
);
|
|
179
|
+
font-style: var(
|
|
180
|
+
--recursica_ui-kit_components_segmented-control-item_properties_selected-text_font-style,
|
|
181
|
+
inherit
|
|
182
|
+
);
|
|
183
|
+
font-weight: var(
|
|
184
|
+
--recursica_ui-kit_components_segmented-control-item_properties_selected-text_font-weight,
|
|
185
|
+
inherit
|
|
186
|
+
);
|
|
187
|
+
letter-spacing: var(
|
|
188
|
+
--recursica_ui-kit_components_segmented-control-item_properties_selected-text_letter-spacing,
|
|
189
|
+
inherit
|
|
190
|
+
);
|
|
191
|
+
line-height: var(
|
|
192
|
+
--recursica_ui-kit_components_segmented-control-item_properties_selected-text_line-height,
|
|
193
|
+
inherit
|
|
194
|
+
);
|
|
195
|
+
text-decoration: var(
|
|
196
|
+
--recursica_ui-kit_components_segmented-control-item_properties_selected-text_text-decoration,
|
|
197
|
+
inherit
|
|
198
|
+
);
|
|
199
|
+
text-transform: var(
|
|
200
|
+
--recursica_ui-kit_components_segmented-control-item_properties_selected-text_text-transform,
|
|
201
|
+
inherit
|
|
202
|
+
);
|
|
138
203
|
}
|
|
@@ -21,9 +21,7 @@ const meta: Meta<typeof SegmentedControl> = {
|
|
|
21
21
|
fullWidth: {
|
|
22
22
|
control: "boolean",
|
|
23
23
|
},
|
|
24
|
-
disabled: {
|
|
25
|
-
control: "boolean",
|
|
26
|
-
},
|
|
24
|
+
disabled: { table: { disable: true } },
|
|
27
25
|
data: { table: { disable: true } },
|
|
28
26
|
defaultChecked: { table: { disable: true } },
|
|
29
27
|
},
|
|
@@ -37,7 +35,6 @@ export const Default: Story = {
|
|
|
37
35
|
data: ["React", "Angular", "Vue", "Svelte"],
|
|
38
36
|
orientation: "horizontal",
|
|
39
37
|
fullWidth: false,
|
|
40
|
-
disabled: false,
|
|
41
38
|
},
|
|
42
39
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
|
|
43
40
|
render: ({ withLayer, layer, ...args }: any) => {
|
|
@@ -14,12 +14,23 @@ export interface RecursicaSegmentedControlProps {
|
|
|
14
14
|
orientation?: "horizontal" | "vertical";
|
|
15
15
|
/** If true, the control will take up the full width of its container */
|
|
16
16
|
fullWidth?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* SegmentedControl should NOT be allowed to be disabled by design.
|
|
19
|
+
* This component explicitly disables the `disabled` prop.
|
|
20
|
+
*/
|
|
21
|
+
disabled?: never;
|
|
17
22
|
}
|
|
18
23
|
|
|
19
24
|
export type SegmentedControlProps = RecursicaOverStyled<
|
|
20
25
|
Omit<
|
|
21
26
|
MantineSegmentedControlProps,
|
|
22
|
-
|
|
27
|
+
| "variant"
|
|
28
|
+
| "size"
|
|
29
|
+
| "radius"
|
|
30
|
+
| "color"
|
|
31
|
+
| "classNames"
|
|
32
|
+
| "className"
|
|
33
|
+
| "disabled"
|
|
23
34
|
> & {
|
|
24
35
|
className?: string;
|
|
25
36
|
classNames?: Partial<Record<string, string>>;
|
|
@@ -70,9 +81,12 @@ const _SegmentedControl = forwardRef<HTMLDivElement, SegmentedControlProps>(
|
|
|
70
81
|
ref,
|
|
71
82
|
) {
|
|
72
83
|
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
84
|
+
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
85
|
+
|
|
86
|
+
// Explicitly prevent consumers from bypassing the disabled restriction
|
|
87
|
+
delete restRecord["disabled"];
|
|
88
|
+
|
|
89
|
+
const stylingParams = useSegmentedControlClassNames(restRecord);
|
|
76
90
|
|
|
77
91
|
return (
|
|
78
92
|
<MantineSegmentedControl
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Slider Implementation Notes
|
|
2
|
+
|
|
3
|
+
This document contains specific design decisions, architectural constraints, and hacks required to bridge the Recursica design system with Mantine's underlying `Slider` primitive.
|
|
4
|
+
|
|
5
|
+
## 1. Bidirectional State Synchronization
|
|
6
|
+
|
|
7
|
+
**Decision:** Maintain a highly responsive, bidirectional connection between the sliding track value and the adjacent numeric text input.
|
|
8
|
+
**Implementation:**
|
|
9
|
+
|
|
10
|
+
- The slider track requires a clean `number` state, whereas the text box requires a `string` state (`inputValue`) to allow typing intermediate characters like decimals (`2.`), negative signs (`-`), or empty text without breaking standard React input binding.
|
|
11
|
+
- A `useEffect` hook continuously feeds the outer numeric state changes back into the text input value as a string representation.
|
|
12
|
+
- Input changes instantly parsed as float clamp bounds securely. On blur (`onBlur`), the input state is automatically sanitized and reset to the clean, clamped string representation of the final track value.
|
|
13
|
+
|
|
14
|
+
## 2. Outer Form Control Wrapper Integration
|
|
15
|
+
|
|
16
|
+
**Decision:** Bypass Mantine's native `Input.Wrapper` and `label` properties.
|
|
17
|
+
**Implementation:**
|
|
18
|
+
|
|
19
|
+
- Universal form wrappers like `<FormControlWrapper>` and `<WithReadOnlyWrapper>` handle the outer layout architecture, including labels, assistive text, error states, and optional edit-triggering fields.
|
|
20
|
+
- Therefore, we map the outer form label directly to the `label` property of the `Slider` (delegated to the wrapper), and rename Mantine's internal dragging tooltip label property to `tooltipLabel`.
|
|
21
|
+
|
|
22
|
+
## 3. Custom Min-Max Labels and Step Indicators
|
|
23
|
+
|
|
24
|
+
**Decision:** Enforce rigid typography tokens on lower bounds and custom mark indicators.
|
|
25
|
+
**Implementation:**
|
|
26
|
+
|
|
27
|
+
- Mantine's native mark and step structures are fully styles-mapped back to our scoped variables in `Slider.module.css`.
|
|
28
|
+
- Min and Max numeric guides are rendered directly to the left and right of the slider track, centered vertically and spaced automatically using standard input gaps, while dynamically fetching custom typography tokens for min-max labels to avoid hardcoded formatting constraints.
|
|
29
|
+
|
|
30
|
+
## 4. Visual Overrides for Stacked and Side-by-Side Spacing
|
|
31
|
+
|
|
32
|
+
**Decision:** Enforce layout margins dynamically based on container orientation parameters.
|
|
33
|
+
**Implementation:**
|
|
34
|
+
|
|
35
|
+
- Using custom layouts (e.g. `stacked` and `side-by-side`), we override the margins by assigning the component-specific Figma spacing variables to the unified `--form-control-margin-bottom` property.
|
|
36
|
+
|
|
37
|
+
## 5. Right-Aligned Floating Current Value
|
|
38
|
+
|
|
39
|
+
**Decision:** Position the current active value of the slider directly above the max guide (or right-side element) on the right side of the track.
|
|
40
|
+
**Implementation:**
|
|
41
|
+
|
|
42
|
+
- Wrap the max guide element in a relative layout container (`.rightGuideContainer`) to provide a positioning anchor.
|
|
43
|
+
- Place the active value element (`.currentValue`) inside `.rightGuideContainer` and position it absolutely (`bottom: calc(100% + var(--recursica_ui-kit_globals_form_properties_label-field-gap-vertical, 8px))`, `right: 0`).
|
|
44
|
+
- This absolute positioning strategy guarantees that the active value floats cleanly above the track's right side, while aligning it vertically on the Y-axis to sit in perfect baseline alignment with the component's left-aligned form label.
|
|
45
|
+
- Set typography using the Figma-aligned component-specific read-only value variables (`--recursica_ui-kit_components_slider_properties_read-only-value_...`).
|
|
46
|
+
- Allow the text color of both the floating current value (`.currentValue`) and the component's read-only value (`.readOnlyValue`) to naturally inherit from their parent states/form globals, automatically supporting default (`--form-field-text-valued`), disabled (`--form-field-disabled-text`), and error colors without explicit color overrides, matching the min/max guides.
|
|
47
|
+
- If `showInput` is enabled, the floating `.currentValue` is hidden since the active value is already displayed and editable within the adjacent numeric text input, avoiding visual redundancy.
|
|
48
|
+
- In `side-by-side` form layouts, the `.currentValue` is positioned inline (static positioning) to the right of the max label rather than floating above it, centered vertically with the max label and aligned right to the container. This uses CSS flexbox ordering (`order: 2` for `.currentValue` and `order: 1` for `.minMaxGuide`) to visually swap their positions while preserving clean, semantic DOM ordering.
|
|
49
|
+
- To ensure perfect, pixel-perfect vertical track alignment between sliders that show numeric text inputs (`showInput={true}`) and sliders that display the active inline value (`showInput={false}`), the `.currentValue` element is globally given a width equal to the input width (`var(--recursica_ui-kit_components_slider_properties_input-width)`) and right-aligned (`text-align: right`). In `side-by-side` layouts, `.rightGuideContainer`'s flex gap is also matched to the horizontal input-to-track gap (`var(--recursica_ui-kit_components_slider_properties_input-gap)`), making the horizontal space occupied by the rightmost elements exactly identical in both component modes.
|