@recursica/mantine-adapter 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.storybook/commonArgTypes.ts +148 -0
- package/CHANGELOG.md +69 -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 +1076 -266
- package/dist/mantine-adapter.js.map +1 -1
- package/dist/src/components/Accordion/Accordion.d.ts +13 -28
- package/dist/src/components/AssistiveElement/AssistiveElement.d.ts +10 -0
- package/dist/src/components/Avatar/Avatar.d.ts +1 -1
- package/dist/src/components/Breadcrumb/Breadcrumb.d.ts +6 -3
- package/dist/src/components/Button/Button.d.ts +1 -1
- package/dist/src/components/Card/Card.d.ts +38 -3
- package/dist/src/components/Checkbox/Checkbox.d.ts +11 -3
- package/dist/src/components/Checkbox/CheckboxGroup.d.ts +9 -0
- package/dist/src/components/Chip/Chip.d.ts +14 -2
- package/dist/src/components/FormControlWrapper/FormControlWrapper.d.ts +18 -0
- package/dist/src/components/Label/Label.d.ts +21 -0
- package/dist/src/components/Label/index.d.ts +1 -0
- package/dist/src/components/ReadOnlyField/ReadOnlyField.d.ts +19 -2
- package/dist/src/components/ReadOnlyField/ReadOnlyTextField.d.ts +8 -0
- package/dist/src/components/ReadOnlyField/WithReadOnlyWrapper.d.ts +22 -0
- package/dist/src/components/ReadOnlyField/index.d.ts +3 -0
- package/dist/src/components/Text/Text.d.ts +17 -0
- package/dist/src/components/TextField/TextField.d.ts +8 -2
- package/dist/src/components/Title/Title.d.ts +13 -0
- package/dist/src/components/index.d.ts +3 -1
- package/dist/src/utils/ColorSchemeWrapper.d.ts +3 -0
- package/dist/src/utils/filterStylingProps.d.ts +6 -2
- package/package.json +9 -5
- package/src/OverStyling.stories.tsx +174 -0
- package/src/Version.stories.tsx +56 -0
- package/src/components/Accordion/ACCORDION_IMPLEMENTATION_NOTES.md +48 -0
- package/src/components/Accordion/Accordion.module.css +261 -0
- package/src/components/Accordion/Accordion.stories.tsx +145 -0
- package/src/components/Accordion/Accordion.tsx +200 -0
- package/src/components/Accordion/index.ts +1 -0
- package/src/components/AssistiveElement/AssistiveElement.module.css +111 -0
- package/src/components/AssistiveElement/AssistiveElement.stories.tsx +73 -0
- package/src/components/AssistiveElement/AssistiveElement.tsx +91 -0
- package/src/components/Avatar/AVATAR_IMPLEMENTATION_NOTES.md +24 -0
- package/src/components/Avatar/Avatar.module.css +340 -0
- package/src/components/Avatar/Avatar.stories.tsx +102 -0
- package/src/components/Avatar/Avatar.tsx +100 -0
- package/src/components/Avatar/index.ts +1 -0
- package/src/components/Badge/BADGE_IMPLEMENTATION_NOTES.md +18 -0
- package/src/components/Badge/Badge.module.css +124 -0
- package/src/components/Badge/Badge.stories.tsx +77 -0
- package/src/components/Badge/Badge.tsx +66 -0
- package/src/components/Breadcrumb/BREADCRUMB_IMPLEMENTATION_NOTES.md +14 -0
- package/src/components/Breadcrumb/Breadcrumb.module.css +26 -0
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +77 -0
- package/src/components/Breadcrumb/Breadcrumb.tsx +64 -0
- package/src/components/Button/Button.module.css +275 -0
- package/src/components/Button/Button.stories.tsx +105 -0
- package/src/components/Button/Button.tsx +122 -0
- package/src/components/Button/IMPLEMENTATION_NOTES.md +45 -0
- package/src/components/Button/index.ts +1 -0
- package/src/components/Card/CARD_IMPLEMENTATION_NOTES.md +10 -0
- package/src/components/Card/Card.module.css +60 -0
- package/src/components/Card/Card.stories.tsx +141 -0
- package/src/components/Card/Card.tsx +176 -0
- package/src/components/Checkbox/CHECKBOX_IMPLEMENTATION_NOTES.md +25 -0
- package/src/components/Checkbox/Checkbox.module.css +204 -0
- package/src/components/Checkbox/Checkbox.stories.tsx +73 -0
- package/src/components/Checkbox/Checkbox.tsx +111 -0
- package/src/components/Checkbox/CheckboxGroup.stories.tsx +138 -0
- package/src/components/Checkbox/CheckboxGroup.tsx +140 -0
- package/src/components/Chip/CHIP_IMPLEMENTATION_NOTES.md +35 -0
- package/src/components/Chip/Chip.module.css +218 -0
- package/src/components/Chip/Chip.stories.tsx +115 -0
- package/src/components/Chip/Chip.tsx +143 -0
- package/src/components/DatePicker/DatePicker.stories.tsx +22 -0
- package/src/components/DatePicker/DatePicker.tsx +7 -0
- package/src/components/Dropdown/Dropdown.stories.tsx +22 -0
- package/src/components/Dropdown/Dropdown.tsx +7 -0
- package/src/components/FileInput/FileInput.stories.tsx +22 -0
- package/src/components/FileInput/FileInput.tsx +7 -0
- package/src/components/FileUpload/FileUpload.stories.tsx +22 -0
- package/src/components/FileUpload/FileUpload.tsx +7 -0
- package/src/components/FormControlWrapper/FORMCONTROLWRAPPER_IMPLEMENTATION_NOTES.md +32 -0
- package/src/components/FormControlWrapper/FormControlWrapper.module.css +46 -0
- package/src/components/FormControlWrapper/FormControlWrapper.stories.tsx +116 -0
- package/src/components/FormControlWrapper/FormControlWrapper.tsx +170 -0
- package/src/components/HoverCard/HoverCard.stories.tsx +17 -0
- package/src/components/HoverCard/HoverCard.tsx +7 -0
- package/src/components/Label/LABEL_IMPLEMENTATION_NOTES.md +48 -0
- package/src/components/Label/Label.module.css +177 -0
- package/src/components/Label/Label.stories.tsx +123 -0
- package/src/components/Label/Label.tsx +132 -0
- package/src/components/Label/index.ts +1 -0
- package/src/components/Link/Link.stories.tsx +17 -0
- package/src/components/Link/Link.tsx +7 -0
- package/src/components/Loader/Loader.stories.tsx +17 -0
- package/src/components/Loader/Loader.tsx +7 -0
- package/src/components/Menu/Menu.stories.tsx +17 -0
- package/src/components/Menu/Menu.tsx +7 -0
- package/src/components/Modal/Modal.stories.tsx +17 -0
- package/src/components/Modal/Modal.tsx +7 -0
- package/src/components/NumberInput/NumberInput.stories.tsx +22 -0
- package/src/components/NumberInput/NumberInput.tsx +7 -0
- package/src/components/Pagination/Pagination.stories.tsx +17 -0
- package/src/components/Pagination/Pagination.tsx +7 -0
- package/src/components/Panel/Panel.stories.tsx +17 -0
- package/src/components/Panel/Panel.tsx +7 -0
- package/src/components/Popover/Popover.stories.tsx +17 -0
- package/src/components/Popover/Popover.tsx +7 -0
- package/src/components/Radio/Radio.stories.tsx +22 -0
- package/src/components/Radio/Radio.tsx +7 -0
- package/src/components/ReadOnlyField/READ_ONLY_FIELD_IMPLEMENTATION_NOTES.md +15 -0
- package/src/components/ReadOnlyField/ReadOnlyField.module.css +49 -0
- package/src/components/ReadOnlyField/ReadOnlyField.stories.tsx +120 -0
- package/src/components/ReadOnlyField/ReadOnlyField.tsx +75 -0
- package/src/components/ReadOnlyField/ReadOnlyTextField.tsx +46 -0
- package/src/components/ReadOnlyField/WithReadOnlyWrapper.tsx +85 -0
- package/src/components/ReadOnlyField/index.ts +3 -0
- package/src/components/Search/Search.stories.tsx +17 -0
- package/src/components/Search/Search.tsx +7 -0
- package/src/components/SegmentedControl/SegmentedControl.stories.tsx +22 -0
- package/src/components/SegmentedControl/SegmentedControl.tsx +7 -0
- package/src/components/Slider/Slider.stories.tsx +22 -0
- package/src/components/Slider/Slider.tsx +7 -0
- package/src/components/Stepper/Stepper.stories.tsx +17 -0
- package/src/components/Stepper/Stepper.tsx +7 -0
- package/src/components/Switch/Switch.stories.tsx +22 -0
- package/src/components/Switch/Switch.tsx +7 -0
- package/src/components/Table/Table.stories.tsx +17 -0
- package/src/components/Table/Table.tsx +7 -0
- package/src/components/Tabs/Tabs.stories.tsx +17 -0
- package/src/components/Tabs/Tabs.tsx +7 -0
- package/src/components/Text/Text.stories.tsx +88 -0
- package/src/components/Text/Text.tsx +54 -0
- package/src/components/TextArea/TextArea.stories.tsx +22 -0
- package/src/components/TextArea/TextArea.tsx +7 -0
- package/src/components/TextField/TEXTFIELD_IMPLEMENTATION_NOTES.md +19 -0
- package/src/components/TextField/TextField.module.css +225 -0
- package/src/components/TextField/TextField.stories.tsx +162 -0
- package/src/components/TextField/TextField.tsx +138 -0
- package/src/components/TimePicker/TimePicker.stories.tsx +22 -0
- package/src/components/TimePicker/TimePicker.tsx +7 -0
- package/src/components/Timeline/Timeline.stories.tsx +17 -0
- package/src/components/Timeline/Timeline.tsx +7 -0
- package/src/components/Title/Title.stories.tsx +63 -0
- package/src/components/Title/Title.tsx +45 -0
- package/src/components/Toast/Toast.stories.tsx +17 -0
- package/src/components/Toast/Toast.tsx +7 -0
- package/src/components/Tooltip/Tooltip.stories.tsx +17 -0
- package/src/components/Tooltip/Tooltip.tsx +7 -0
- package/src/components/TransferList/TransferList.stories.tsx +17 -0
- package/src/components/TransferList/TransferList.tsx +7 -0
- package/src/components/index.ts +39 -0
- package/src/env.d.ts +7 -0
- package/src/index.ts +3 -0
- package/src/types/index.ts +9 -0
- package/src/types/mantine.d.ts +7 -0
- package/src/types/scss-modules.d.ts +9 -0
- package/src/utils/ColorSchemeWrapper.tsx +27 -0
- package/src/utils/copyToClipboard.ts +36 -0
- package/src/utils/filterStylingProps.ts +139 -0
- package/src/utils/index.ts +1 -0
|
@@ -0,0 +1,275 @@
|
|
|
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
|
+
|
|
10
|
+
/* Shared Defaults */
|
|
11
|
+
font-family: var(
|
|
12
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_text_font-family
|
|
13
|
+
);
|
|
14
|
+
font-size: var(
|
|
15
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_text_font-size
|
|
16
|
+
);
|
|
17
|
+
font-style: var(
|
|
18
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_text_font-style
|
|
19
|
+
);
|
|
20
|
+
font-weight: var(
|
|
21
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_text_font-weight
|
|
22
|
+
);
|
|
23
|
+
letter-spacing: var(
|
|
24
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_text_letter-spacing
|
|
25
|
+
);
|
|
26
|
+
line-height: var(
|
|
27
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_text_line-height
|
|
28
|
+
);
|
|
29
|
+
text-decoration: var(
|
|
30
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_text_text-decoration
|
|
31
|
+
);
|
|
32
|
+
text-transform: var(
|
|
33
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_text_text-transform
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/* Internal Mantine reset & layout logic for Truncation */
|
|
38
|
+
.root > * {
|
|
39
|
+
min-width: 0;
|
|
40
|
+
width: 100%;
|
|
41
|
+
position: relative;
|
|
42
|
+
z-index: 1;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.label {
|
|
46
|
+
display: flex;
|
|
47
|
+
align-items: center;
|
|
48
|
+
min-width: 0;
|
|
49
|
+
flex: 1 1 0;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.labelText {
|
|
53
|
+
display: block;
|
|
54
|
+
min-width: 0;
|
|
55
|
+
width: 100%;
|
|
56
|
+
overflow: hidden;
|
|
57
|
+
text-overflow: ellipsis;
|
|
58
|
+
white-space: nowrap;
|
|
59
|
+
font-size: inherit;
|
|
60
|
+
line-height: inherit;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* ==== SIZES ==== */
|
|
64
|
+
.root[data-size="default"] {
|
|
65
|
+
border-radius: var(
|
|
66
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_border-radius
|
|
67
|
+
);
|
|
68
|
+
height: var(
|
|
69
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_height
|
|
70
|
+
);
|
|
71
|
+
min-width: var(
|
|
72
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_min-width
|
|
73
|
+
);
|
|
74
|
+
padding: 0
|
|
75
|
+
var(
|
|
76
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_horizontal-padding
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
.root[data-size="small"] {
|
|
80
|
+
border-radius: var(
|
|
81
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_border-radius
|
|
82
|
+
);
|
|
83
|
+
height: var(
|
|
84
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_height
|
|
85
|
+
);
|
|
86
|
+
min-width: var(
|
|
87
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_min-width
|
|
88
|
+
);
|
|
89
|
+
padding: 0
|
|
90
|
+
var(
|
|
91
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_horizontal-padding
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
/* Override specific typography for small */
|
|
95
|
+
font-family: var(
|
|
96
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_text_font-family,
|
|
97
|
+
var(
|
|
98
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_text_font-family
|
|
99
|
+
)
|
|
100
|
+
);
|
|
101
|
+
font-size: var(
|
|
102
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_text_font-size,
|
|
103
|
+
var(
|
|
104
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_text_font-size
|
|
105
|
+
)
|
|
106
|
+
);
|
|
107
|
+
font-weight: var(
|
|
108
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_text_font-weight,
|
|
109
|
+
var(
|
|
110
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_text_font-weight
|
|
111
|
+
)
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/* Icon Resets */
|
|
116
|
+
.iconWrapper {
|
|
117
|
+
display: flex;
|
|
118
|
+
align-items: center;
|
|
119
|
+
justify-content: center;
|
|
120
|
+
flex-shrink: 0;
|
|
121
|
+
}
|
|
122
|
+
.iconWrapper > * {
|
|
123
|
+
width: 100%;
|
|
124
|
+
height: 100%;
|
|
125
|
+
object-fit: contain;
|
|
126
|
+
}
|
|
127
|
+
.root[data-size="default"] .iconWrapper {
|
|
128
|
+
width: var(
|
|
129
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_icon
|
|
130
|
+
);
|
|
131
|
+
height: var(
|
|
132
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_icon
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
.root[data-size="small"] .iconWrapper {
|
|
136
|
+
width: var(
|
|
137
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_icon
|
|
138
|
+
);
|
|
139
|
+
height: var(
|
|
140
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_icon
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.section {
|
|
145
|
+
min-width: 0;
|
|
146
|
+
}
|
|
147
|
+
.root[data-size="default"] .section {
|
|
148
|
+
gap: var(
|
|
149
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_icon-text-gap
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
.root[data-size="small"] .section {
|
|
153
|
+
gap: var(
|
|
154
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_icon-text-gap
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/* Icon-only logic overrides */
|
|
159
|
+
.root[data-icon-only] .section {
|
|
160
|
+
gap: 0;
|
|
161
|
+
}
|
|
162
|
+
.root[data-icon-only] .section[data-position="left"] {
|
|
163
|
+
margin-inline-end: 0;
|
|
164
|
+
}
|
|
165
|
+
.root[data-icon-only] .section[data-position="right"] {
|
|
166
|
+
margin-inline-start: 0;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/* Disabled */
|
|
170
|
+
.root:disabled {
|
|
171
|
+
opacity: var(--recursica_brand_states_disabled);
|
|
172
|
+
cursor: not-allowed;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/* Global Hover Hack Overlay */
|
|
176
|
+
.root::after {
|
|
177
|
+
content: "";
|
|
178
|
+
position: absolute;
|
|
179
|
+
inset: 0;
|
|
180
|
+
border-radius: inherit;
|
|
181
|
+
z-index: 0;
|
|
182
|
+
pointer-events: none;
|
|
183
|
+
transition: opacity 150ms ease;
|
|
184
|
+
opacity: 0;
|
|
185
|
+
}
|
|
186
|
+
.root[data-size="default"]::after {
|
|
187
|
+
background-color: var(
|
|
188
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_hover-color
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
.root[data-size="small"]::after {
|
|
192
|
+
background-color: var(
|
|
193
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_hover-color
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
.root:hover:not(:disabled)::after {
|
|
197
|
+
opacity: var(
|
|
198
|
+
--recursica_ui-kit_components_button_variants_sizes_default_properties_hover-opacity,
|
|
199
|
+
0.1
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/* ==== VARIANTS ==== */
|
|
204
|
+
|
|
205
|
+
/* SOLID */
|
|
206
|
+
.root[data-variant="solid"] {
|
|
207
|
+
border-width: var(
|
|
208
|
+
--recursica_ui-kit_components_button_variants_styles_solid_properties_border-size
|
|
209
|
+
);
|
|
210
|
+
box-shadow: var(
|
|
211
|
+
--recursica_ui-kit_components_button_variants_styles_solid_properties_elevation
|
|
212
|
+
);
|
|
213
|
+
background-color: var(
|
|
214
|
+
--recursica_ui-kit_components_button_variants_styles_solid_properties_colors_background
|
|
215
|
+
);
|
|
216
|
+
border-color: var(
|
|
217
|
+
--recursica_ui-kit_components_button_variants_styles_solid_properties_colors_border-color
|
|
218
|
+
);
|
|
219
|
+
color: var(
|
|
220
|
+
--recursica_ui-kit_components_button_variants_styles_solid_properties_colors_text
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
.root[data-variant="solid"]:hover:not(:disabled) {
|
|
224
|
+
color: var(
|
|
225
|
+
--recursica_ui-kit_components_button_variants_styles_solid_properties_colors_text-hover
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/* OUTLINE */
|
|
230
|
+
.root[data-variant="outline"] {
|
|
231
|
+
border-width: var(
|
|
232
|
+
--recursica_ui-kit_components_button_variants_styles_outline_properties_border-size
|
|
233
|
+
);
|
|
234
|
+
box-shadow: var(
|
|
235
|
+
--recursica_ui-kit_components_button_variants_styles_outline_properties_elevation
|
|
236
|
+
);
|
|
237
|
+
background-color: var(
|
|
238
|
+
--recursica_ui-kit_components_button_variants_styles_outline_properties_colors_background
|
|
239
|
+
);
|
|
240
|
+
border-color: var(
|
|
241
|
+
--recursica_ui-kit_components_button_variants_styles_outline_properties_colors_border-color
|
|
242
|
+
);
|
|
243
|
+
color: var(
|
|
244
|
+
--recursica_ui-kit_components_button_variants_styles_outline_properties_colors_text
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
.root[data-variant="outline"]:hover:not(:disabled) {
|
|
248
|
+
color: var(
|
|
249
|
+
--recursica_ui-kit_components_button_variants_styles_outline_properties_colors_text-hover
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/* TEXT */
|
|
254
|
+
.root[data-variant="text"] {
|
|
255
|
+
border-width: var(
|
|
256
|
+
--recursica_ui-kit_components_button_variants_styles_text_properties_border-size
|
|
257
|
+
);
|
|
258
|
+
box-shadow: var(
|
|
259
|
+
--recursica_ui-kit_components_button_variants_styles_text_properties_elevation
|
|
260
|
+
);
|
|
261
|
+
background-color: var(
|
|
262
|
+
--recursica_ui-kit_components_button_variants_styles_text_properties_colors_background
|
|
263
|
+
);
|
|
264
|
+
border-color: var(
|
|
265
|
+
--recursica_ui-kit_components_button_variants_styles_text_properties_colors_border-color
|
|
266
|
+
);
|
|
267
|
+
color: var(
|
|
268
|
+
--recursica_ui-kit_components_button_variants_styles_text_properties_colors_text
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
.root[data-variant="text"]:hover:not(:disabled) {
|
|
272
|
+
color: var(
|
|
273
|
+
--recursica_ui-kit_components_button_variants_styles_text_properties_colors_text-hover
|
|
274
|
+
);
|
|
275
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
|
+
import { Button } from "./Button";
|
|
4
|
+
import { Layer } from "@recursica/adapter-common";
|
|
5
|
+
|
|
6
|
+
type ButtonStoryProps = React.ComponentProps<typeof Button>;
|
|
7
|
+
|
|
8
|
+
const meta: Meta<ButtonStoryProps> = {
|
|
9
|
+
title: "UI-Kit/Button",
|
|
10
|
+
component: Button,
|
|
11
|
+
tags: ["autodocs"],
|
|
12
|
+
argTypes: {
|
|
13
|
+
variant: {
|
|
14
|
+
control: "select",
|
|
15
|
+
options: ["solid", "outline", "text"],
|
|
16
|
+
description: "The visual variant of the button",
|
|
17
|
+
},
|
|
18
|
+
size: {
|
|
19
|
+
control: "radio",
|
|
20
|
+
options: ["default", "small"],
|
|
21
|
+
description: "The size of the button",
|
|
22
|
+
},
|
|
23
|
+
disabled: {
|
|
24
|
+
control: "boolean",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default meta;
|
|
30
|
+
|
|
31
|
+
type Story = StoryObj<ButtonStoryProps>;
|
|
32
|
+
|
|
33
|
+
export const Default: Story = {
|
|
34
|
+
args: {
|
|
35
|
+
children: "Explore Button",
|
|
36
|
+
variant: "solid",
|
|
37
|
+
size: "default",
|
|
38
|
+
disabled: false,
|
|
39
|
+
},
|
|
40
|
+
render: (args) => {
|
|
41
|
+
return <Button {...args} />;
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const SolidDefault: Story = {
|
|
46
|
+
args: {
|
|
47
|
+
children: "Solid Default",
|
|
48
|
+
variant: "solid",
|
|
49
|
+
size: "default",
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const OutlineSmall: Story = {
|
|
54
|
+
args: {
|
|
55
|
+
children: "Outline Small",
|
|
56
|
+
variant: "outline",
|
|
57
|
+
size: "small",
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export const TextWithIcon: Story = {
|
|
62
|
+
args: {
|
|
63
|
+
children: "Text With Icon",
|
|
64
|
+
variant: "text",
|
|
65
|
+
size: "default",
|
|
66
|
+
icon: (
|
|
67
|
+
<svg
|
|
68
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
69
|
+
width="24"
|
|
70
|
+
height="24"
|
|
71
|
+
viewBox="0 0 24 24"
|
|
72
|
+
fill="none"
|
|
73
|
+
stroke="currentColor"
|
|
74
|
+
strokeWidth="2"
|
|
75
|
+
strokeLinecap="round"
|
|
76
|
+
strokeLinejoin="round"
|
|
77
|
+
>
|
|
78
|
+
<circle cx="11" cy="11" r="8"></circle>
|
|
79
|
+
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
|
|
80
|
+
</svg>
|
|
81
|
+
),
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export const LayerOneSolid: Story = {
|
|
86
|
+
args: {
|
|
87
|
+
children: "Layer 1 Solid",
|
|
88
|
+
variant: "solid",
|
|
89
|
+
size: "default",
|
|
90
|
+
},
|
|
91
|
+
render: (args: ButtonStoryProps) => (
|
|
92
|
+
<Layer layer={1} style={{ padding: "24px" }}>
|
|
93
|
+
<Button {...args} />
|
|
94
|
+
</Layer>
|
|
95
|
+
),
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export const DisabledSolid: Story = {
|
|
99
|
+
args: {
|
|
100
|
+
children: "Disabled Solid",
|
|
101
|
+
variant: "solid",
|
|
102
|
+
size: "default",
|
|
103
|
+
disabled: true,
|
|
104
|
+
},
|
|
105
|
+
};
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import React, { forwardRef } from "react";
|
|
2
|
+
import {
|
|
3
|
+
Button as MantineButton,
|
|
4
|
+
type ButtonProps as MantineButtonProps,
|
|
5
|
+
} from "@mantine/core";
|
|
6
|
+
import {
|
|
7
|
+
filterStylingProps,
|
|
8
|
+
type RecursicaOverStyled,
|
|
9
|
+
} from "../../utils/filterStylingProps";
|
|
10
|
+
import styles from "./Button.module.css";
|
|
11
|
+
|
|
12
|
+
export interface RecursicaButtonProps {
|
|
13
|
+
variant?: "solid" | "outline" | "text";
|
|
14
|
+
size?: "default" | "small";
|
|
15
|
+
icon?: React.ReactNode;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type ButtonProps = RecursicaOverStyled<
|
|
19
|
+
Omit<MantineButtonProps, "variant" | "size" | "leftSection" | "fullWidth"> &
|
|
20
|
+
RecursicaButtonProps
|
|
21
|
+
>;
|
|
22
|
+
|
|
23
|
+
function hasVisibleChildren(children: React.ReactNode): boolean {
|
|
24
|
+
if (children == null || children === "") return false;
|
|
25
|
+
if (typeof children === "string") return children.trim() !== "";
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
|
30
|
+
function Button(
|
|
31
|
+
{
|
|
32
|
+
variant = "solid",
|
|
33
|
+
size = "default",
|
|
34
|
+
icon,
|
|
35
|
+
children,
|
|
36
|
+
overStyled = false,
|
|
37
|
+
...rest
|
|
38
|
+
},
|
|
39
|
+
ref,
|
|
40
|
+
) {
|
|
41
|
+
const mapVariant = {
|
|
42
|
+
solid: "filled",
|
|
43
|
+
outline: "outline",
|
|
44
|
+
text: "subtle",
|
|
45
|
+
} as const;
|
|
46
|
+
|
|
47
|
+
const mapSize = {
|
|
48
|
+
default: "md",
|
|
49
|
+
small: "sm",
|
|
50
|
+
} as const;
|
|
51
|
+
|
|
52
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
53
|
+
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
54
|
+
|
|
55
|
+
// Explicitly delete blocked semantic expansion dimension props
|
|
56
|
+
delete restRecord["fullWidth"];
|
|
57
|
+
|
|
58
|
+
const hasLeftSection = !!icon || !!restRecord["leftSection"];
|
|
59
|
+
const hasRightSection = !!restRecord["rightSection"];
|
|
60
|
+
const isIconOnly =
|
|
61
|
+
(hasLeftSection || hasRightSection) && !hasVisibleChildren(children);
|
|
62
|
+
|
|
63
|
+
if (
|
|
64
|
+
typeof process !== "undefined" &&
|
|
65
|
+
process.env.NODE_ENV !== "production" &&
|
|
66
|
+
isIconOnly &&
|
|
67
|
+
!restRecord["aria-label"]
|
|
68
|
+
) {
|
|
69
|
+
console.warn(
|
|
70
|
+
'[Recursica Button] Icon-only buttons must provide an accessible name. Pass aria-label (e.g. aria-label="Submit").',
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const mergedClassNames: Partial<Record<string, string>> = {
|
|
75
|
+
root: styles.root,
|
|
76
|
+
section: styles.section,
|
|
77
|
+
label: styles.label,
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const classNamesProp = restRecord.classNames;
|
|
81
|
+
if (
|
|
82
|
+
classNamesProp &&
|
|
83
|
+
typeof classNamesProp === "object" &&
|
|
84
|
+
!Array.isArray(classNamesProp)
|
|
85
|
+
) {
|
|
86
|
+
const o = classNamesProp as Partial<Record<string, string>>;
|
|
87
|
+
mergedClassNames.root = o.root ? `${styles.root} ${o.root}` : styles.root;
|
|
88
|
+
mergedClassNames.section = o.section ?? styles.section;
|
|
89
|
+
mergedClassNames.label = o.label ?? styles.label;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const classNameProp = restRecord.className as string | undefined;
|
|
93
|
+
const finalClass = classNameProp
|
|
94
|
+
? `${styles.root} ${classNameProp}`
|
|
95
|
+
: styles.root;
|
|
96
|
+
|
|
97
|
+
return (
|
|
98
|
+
<MantineButton
|
|
99
|
+
ref={ref}
|
|
100
|
+
className={finalClass}
|
|
101
|
+
classNames={mergedClassNames}
|
|
102
|
+
variant={mapVariant[variant]}
|
|
103
|
+
size={mapSize[size]}
|
|
104
|
+
leftSection={
|
|
105
|
+
icon != null ? (
|
|
106
|
+
<span className={styles.iconWrapper} aria-hidden>
|
|
107
|
+
{icon}
|
|
108
|
+
</span>
|
|
109
|
+
) : undefined
|
|
110
|
+
}
|
|
111
|
+
data-variant={variant}
|
|
112
|
+
data-size={size}
|
|
113
|
+
{...(isIconOnly ? { "data-icon-only": "" } : {})}
|
|
114
|
+
{...sanitizedProps}
|
|
115
|
+
>
|
|
116
|
+
<span className={styles.labelText}>{children}</span>
|
|
117
|
+
</MantineButton>
|
|
118
|
+
);
|
|
119
|
+
},
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
Button.displayName = "Button";
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Button – implementation notes
|
|
2
|
+
|
|
3
|
+
Decisions and design tweaks for the Recursica Button that go beyond the Component Development Guide. Use this when maintaining the Button or when adding similar behavior to other components.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Icon size: Recursica defines it
|
|
8
|
+
|
|
9
|
+
**Decision:** Icon size is **not** left to the developer. Recursica defines it via the design tokens; the Button enforces it so callers cannot pass an arbitrarily sized icon.
|
|
10
|
+
|
|
11
|
+
**Implementation:**
|
|
12
|
+
|
|
13
|
+
- When `icon` is provided, the Button wraps it in a single element with class `iconWrapper` before passing it to Mantine’s `leftSection`.
|
|
14
|
+
- In `Button.module.css`, `.iconWrapper` has explicit `width` and `height` from the Recursica tokens mapping natively based on `data-size`.
|
|
15
|
+
- The rule `.iconWrapper > *` sets `width: 100%`, `height: 100%`, and `object-fit: contain` so whatever the caller passes scales cleanly with the token constraints.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Icon-only buttons: accessibility and width
|
|
20
|
+
|
|
21
|
+
**Decision:** When the button has an icon and no visible label (icon-only), callers must provide an accessible name, and the button must not show extra space to the right of the icon.
|
|
22
|
+
|
|
23
|
+
**Accessibility:** We document that icon-only buttons must pass `aria-label` (e.g. `aria-label="Submit"`). In development we log a console warning if `icon` is set, `children` is empty, and `aria-label` is missing.
|
|
24
|
+
|
|
25
|
+
**Width:** Mantine’s layout natively applies structural section gaps. We detect icon-only and set a `data-icon-only` hook so that `Button.module.css` zeros out the sections spacing allowing the button to precisely hit `min-width` perfectly centered.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Label truncation at max-width
|
|
30
|
+
|
|
31
|
+
**Decision:** When the button hits its Recursica max-width (500px), the label truncates with an ellipsis instead of wrapping.
|
|
32
|
+
|
|
33
|
+
**Implementation:**
|
|
34
|
+
Mantine's `.mantine-Button-label` flex centering breaks primitive truncation logic. To combat this:
|
|
35
|
+
|
|
36
|
+
- **`.root`** has `overflow: hidden`.
|
|
37
|
+
- **`.root > *`** forces `min-width: 0`.
|
|
38
|
+
- The structural children wrap into `<span className={styles.labelText}>`.
|
|
39
|
+
- **`.labelText`** binds `overflow: hidden; text-overflow: ellipsis; white-space: nowrap;` creating flawless string cutoffs strictly at exact UI constraints.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Disabled state: brand theme opacity (implicit)
|
|
44
|
+
|
|
45
|
+
**Decision:** The UI kit enforces global brand theme disabled opacities. The `.root:disabled` logic implicitly overrides visibility locally via `var(--recursica_brand_states_disabled)`.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./Button";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Card Implementation Notes
|
|
2
|
+
|
|
3
|
+
## Architecture Overrides
|
|
4
|
+
|
|
5
|
+
Because Mantine natively constructs `Card` bounding boxes with generic inner `<Card.Section>` elements that depend on explicit user styling (and lack implicit native designations for "Header" vs "Footer"), we implemented an explicit component wrapper departure:
|
|
6
|
+
|
|
7
|
+
- `<Card.Header>` explicitly hooks `--recursica_ui-kit_components_card_properties_header-background` and corresponding padding variables.
|
|
8
|
+
- `<Card.Footer>` explicitly hooks `--recursica_ui-kit_components_card_properties_footer-background` and corresponding padding variables.
|
|
9
|
+
|
|
10
|
+
Mantine's generic `<Card.Section>` calculates negative margins implicitly. Because of this, it is crucial that our local CSS module declares `--card-padding: var(--recursica_ui-kit_components_card_properties_padding)` directly on `.root` so that all generic or explicit section wrappers natively stretch across the bounding box properly.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
.root {
|
|
2
|
+
/* HARDCODE: Map Recursica explicitly into Mantine's variable format so internal components know the margins */
|
|
3
|
+
--card-padding: var(--recursica_ui-kit_components_card_properties_padding);
|
|
4
|
+
|
|
5
|
+
background-color: var(
|
|
6
|
+
--recursica_ui-kit_components_card_properties_colors_background
|
|
7
|
+
);
|
|
8
|
+
border-radius: var(
|
|
9
|
+
--recursica_ui-kit_components_card_properties_borders_border-radius
|
|
10
|
+
);
|
|
11
|
+
border: var(--recursica_ui-kit_components_card_properties_borders_border-size)
|
|
12
|
+
solid var(--recursica_ui-kit_components_card_properties_colors_border-color);
|
|
13
|
+
box-shadow: var(
|
|
14
|
+
--recursica_ui-kit_components_card_properties_elevations_elevation
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
padding: var(--card-padding);
|
|
18
|
+
min-width: var(--recursica_ui-kit_components_card_properties_min-width);
|
|
19
|
+
max-width: var(--recursica_ui-kit_components_card_properties_max-width);
|
|
20
|
+
color: var(--recursica_ui-kit_components_card_properties_colors_content);
|
|
21
|
+
|
|
22
|
+
display: flex;
|
|
23
|
+
flex-direction: column;
|
|
24
|
+
gap: var(--recursica_ui-kit_components_card_properties_section-gap);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.header {
|
|
28
|
+
background-color: var(
|
|
29
|
+
--recursica_ui-kit_components_card_properties_colors_header-background
|
|
30
|
+
);
|
|
31
|
+
padding: var(--recursica_ui-kit_components_card_properties_header-padding);
|
|
32
|
+
color: var(--recursica_ui-kit_components_card_properties_colors_title);
|
|
33
|
+
border-bottom: var(--recursica_ui-kit_components_card_properties_divider-size)
|
|
34
|
+
solid
|
|
35
|
+
var(--recursica_ui-kit_components_card_properties_colors_divider-color);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.footer {
|
|
39
|
+
background-color: var(
|
|
40
|
+
--recursica_ui-kit_components_card_properties_colors_footer-background
|
|
41
|
+
);
|
|
42
|
+
padding: var(--recursica_ui-kit_components_card_properties_footer-padding);
|
|
43
|
+
border-top: var(--recursica_ui-kit_components_card_properties_divider-size)
|
|
44
|
+
solid
|
|
45
|
+
var(--recursica_ui-kit_components_card_properties_colors_divider-color);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.section {
|
|
49
|
+
/* Just maps standard section spacing overrides if passed explicitly */
|
|
50
|
+
margin-top: var(
|
|
51
|
+
--recursica_ui-kit_components_card_properties_vertical-gutter
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.content {
|
|
56
|
+
display: flex;
|
|
57
|
+
flex-direction: column;
|
|
58
|
+
gap: var(--recursica_ui-kit_components_card_properties_vertical-gutter);
|
|
59
|
+
padding: 0;
|
|
60
|
+
}
|