@recursica/mui-adapter 0.34.0 → 0.34.1
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/package.json
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"url": "git+https://github.com/borderux/recursica.git",
|
|
14
14
|
"directory": "packages/mui-adapter"
|
|
15
15
|
},
|
|
16
|
-
"version": "0.34.
|
|
16
|
+
"version": "0.34.1",
|
|
17
17
|
"publishConfig": {
|
|
18
18
|
"access": "public"
|
|
19
19
|
},
|
|
@@ -59,7 +59,9 @@
|
|
|
59
59
|
"lint": "eslint .",
|
|
60
60
|
"storybook": "storybook dev -p 6012",
|
|
61
61
|
"analyze-tokens": "analyze-tokens --css @recursica/official-release/recursica_variables_scoped.css --dir src/components --output token-analysis.json",
|
|
62
|
-
"prebuild": "npm run analyze-tokens"
|
|
62
|
+
"prebuild": "npm run analyze-tokens",
|
|
63
|
+
"adapter-tester": "adapter-tester --serve",
|
|
64
|
+
"adapter-tester:automated": "adapter-tester"
|
|
63
65
|
},
|
|
64
66
|
"devDependencies": {
|
|
65
67
|
"@chromatic-com/storybook": "^5.1.1",
|
|
@@ -67,6 +69,8 @@
|
|
|
67
69
|
"@mui/lab": "^7.0.1-beta.25",
|
|
68
70
|
"@mui/x-date-pickers": "^9.11.0",
|
|
69
71
|
"@mui/x-tree-view": "^9.11.0",
|
|
72
|
+
"@playwright/test": "^1.53.0",
|
|
73
|
+
"@recursica/adapter-tester": "*",
|
|
70
74
|
"@recursica/recursica-postcss-vars": "*",
|
|
71
75
|
"@recursica/storybook-template": "*",
|
|
72
76
|
"@recursica/token-analyzer": "*",
|
|
@@ -120,6 +120,31 @@ export const ErrorState: Story = {
|
|
|
120
120
|
},
|
|
121
121
|
};
|
|
122
122
|
|
|
123
|
+
export const OpenedCalendar: Story = {
|
|
124
|
+
args: {
|
|
125
|
+
label: "Meeting Date",
|
|
126
|
+
assistiveText: "Calendar rendered open by default for styling review.",
|
|
127
|
+
// MUI X's DatePicker supports a controlled `open` prop directly; pairing it with a
|
|
128
|
+
// no-op `onClose` keeps the calendar open with no click interaction needed — same
|
|
129
|
+
// intent as the mantine-adapter's `OpenedCalendar` story.
|
|
130
|
+
open: true,
|
|
131
|
+
onClose: () => {},
|
|
132
|
+
// Fixed (not computed) so the selected-day fill is visible on load, alongside the
|
|
133
|
+
// today marker, for styling review. Local-component constructor, not an ISO date
|
|
134
|
+
// string — `new Date("2026-08-26")` parses as UTC midnight, which renders as the
|
|
135
|
+
// 25th in any timezone behind UTC.
|
|
136
|
+
defaultValue: new Date(2026, 7, 26),
|
|
137
|
+
},
|
|
138
|
+
parameters: {
|
|
139
|
+
docs: {
|
|
140
|
+
description: {
|
|
141
|
+
story:
|
|
142
|
+
"The calendar dropdown renders open by default so its styling can be reviewed without a click interaction.",
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
|
|
123
148
|
export const StaticReadOnly: Story = {
|
|
124
149
|
args: {
|
|
125
150
|
label: "Static ReadOnly Review",
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
/* Brand-layer exemptions (recursica-allow-brand) — see recursica-token-analyzer README.md.
|
|
2
|
+
* Close button is styled to match the Button component's text/icon-only variant, so it reuses
|
|
3
|
+
* the same global hover/focus state tokens Button.module.css exempts.
|
|
4
|
+
* recursica-allow-brand: --recursica_brand_states_focus_blur
|
|
5
|
+
* recursica-allow-brand: --recursica_brand_states_focus_border-size
|
|
6
|
+
* recursica-allow-brand: --recursica_brand_states_focus_color
|
|
7
|
+
* recursica-allow-brand: --recursica_brand_states_focus_margin
|
|
8
|
+
* recursica-allow-brand: --recursica_brand_states_hover_color
|
|
9
|
+
* recursica-allow-brand: --recursica_brand_states_hover_opacity
|
|
10
|
+
*/
|
|
11
|
+
|
|
1
12
|
.root {
|
|
2
13
|
}
|
|
3
14
|
|
|
@@ -40,6 +51,9 @@
|
|
|
40
51
|
}
|
|
41
52
|
|
|
42
53
|
.header {
|
|
54
|
+
display: flex; /* HARDCODE: puts the title and close button side-by-side so the title has a bounded width to truncate against */
|
|
55
|
+
align-items: center;
|
|
56
|
+
justify-content: space-between;
|
|
43
57
|
padding: var(
|
|
44
58
|
--recursica_ui-kit_components_modal_properties_header-footer-vertical-padding
|
|
45
59
|
)
|
|
@@ -50,6 +64,12 @@
|
|
|
50
64
|
}
|
|
51
65
|
|
|
52
66
|
.title {
|
|
67
|
+
flex: 1 1 auto; /* HARDCODE: let the title claim the space between the header edge and the close button */
|
|
68
|
+
min-width: 0; /* HARDCODE: required for text-overflow ellipsis to take effect on a flex child */
|
|
69
|
+
overflow: hidden;
|
|
70
|
+
white-space: nowrap;
|
|
71
|
+
text-overflow: ellipsis;
|
|
72
|
+
|
|
53
73
|
color: var(--recursica_ui-kit_components_modal_properties_colors_title);
|
|
54
74
|
|
|
55
75
|
/* Direct Figma Typography Mapping */
|
|
@@ -173,5 +193,87 @@
|
|
|
173
193
|
}
|
|
174
194
|
|
|
175
195
|
.close {
|
|
176
|
-
/*
|
|
196
|
+
/* Matches the Button component's text-variant, icon-only, small-size visual treatment
|
|
197
|
+
(see Button.module.css) so the modal close control looks like a Recursica Button
|
|
198
|
+
rather than MUI's native IconButton. */
|
|
199
|
+
box-sizing: border-box;
|
|
200
|
+
display: flex;
|
|
201
|
+
align-items: center;
|
|
202
|
+
justify-content: center;
|
|
203
|
+
position: relative;
|
|
204
|
+
overflow: hidden;
|
|
205
|
+
transition: all 0.2s ease;
|
|
206
|
+
|
|
207
|
+
height: var(
|
|
208
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_height
|
|
209
|
+
);
|
|
210
|
+
min-width: var(
|
|
211
|
+
--recursica_ui-kit_components_button_variants_content_icon-only_variants_sizes_small_properties_min-width
|
|
212
|
+
);
|
|
213
|
+
padding: 0
|
|
214
|
+
var(
|
|
215
|
+
--recursica_ui-kit_components_button_variants_content_icon-only_variants_sizes_small_properties_horizontal-padding
|
|
216
|
+
);
|
|
217
|
+
border-radius: var(
|
|
218
|
+
--recursica_ui-kit_components_button_variants_content_icon-only_variants_sizes_small_properties_border-radius
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
border-style: solid;
|
|
222
|
+
border-width: var(
|
|
223
|
+
--recursica_ui-kit_components_button_variants_styles_text_properties_border-size
|
|
224
|
+
);
|
|
225
|
+
border-color: var(
|
|
226
|
+
--recursica_ui-kit_components_button_variants_styles_text_properties_colors_border-color
|
|
227
|
+
);
|
|
228
|
+
background-color: var(
|
|
229
|
+
--recursica_ui-kit_components_button_variants_styles_text_properties_colors_background-color
|
|
230
|
+
);
|
|
231
|
+
color: var(
|
|
232
|
+
--recursica_ui-kit_components_button_variants_styles_text_properties_colors_icon-color
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.close svg {
|
|
237
|
+
position: relative;
|
|
238
|
+
z-index: 1;
|
|
239
|
+
width: var(
|
|
240
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_icon
|
|
241
|
+
);
|
|
242
|
+
height: var(
|
|
243
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_icon
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
.close::after {
|
|
248
|
+
content: "";
|
|
249
|
+
position: absolute;
|
|
250
|
+
inset: 0;
|
|
251
|
+
border-radius: inherit;
|
|
252
|
+
z-index: 0;
|
|
253
|
+
pointer-events: none;
|
|
254
|
+
transition: opacity 150ms ease;
|
|
255
|
+
opacity: 0;
|
|
256
|
+
background-color: var(--recursica_brand_states_hover_color);
|
|
257
|
+
}
|
|
258
|
+
.close:hover:not(:disabled)::after {
|
|
259
|
+
opacity: var(--recursica_brand_states_hover_opacity);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/* MuiIconButton injects its own `:hover` background via emotion at render time, which lands in
|
|
263
|
+
the DOM after this stylesheet and wins the tie at equal specificity — same class of conflict
|
|
264
|
+
documented in DatePicker.module.css's error/disabled state overrides. `!important` keeps the
|
|
265
|
+
button's own background transparent so only the `::after` overlay above renders the hover
|
|
266
|
+
feedback, matching Button's single-overlay hover treatment exactly. */
|
|
267
|
+
.close:hover {
|
|
268
|
+
background-color: transparent !important;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.close:focus-visible {
|
|
272
|
+
outline: none;
|
|
273
|
+
box-shadow:
|
|
274
|
+
0 0 0 var(--recursica_brand_states_focus_border-size)
|
|
275
|
+
var(--recursica_brand_states_focus_color),
|
|
276
|
+
0 0 var(--recursica_brand_states_focus_blur)
|
|
277
|
+
var(--recursica_brand_states_focus_margin)
|
|
278
|
+
var(--recursica_brand_states_focus_color);
|
|
177
279
|
}
|
|
@@ -19,7 +19,8 @@ export default meta;
|
|
|
19
19
|
type Story = StoryObj<typeof Modal>;
|
|
20
20
|
|
|
21
21
|
const DefaultWrapper = (args: ModalProps) => {
|
|
22
|
-
|
|
22
|
+
// Starts opened so the modal is visible without pressing a button first.
|
|
23
|
+
const [opened, setOpened] = useState(true);
|
|
23
24
|
return (
|
|
24
25
|
<>
|
|
25
26
|
<Modal {...args} opened={opened} onClose={() => setOpened(false)}>
|
|
@@ -43,8 +44,33 @@ export const Default: Story = {
|
|
|
43
44
|
render: (args) => <DefaultWrapper {...args} />,
|
|
44
45
|
};
|
|
45
46
|
|
|
47
|
+
const LongTitleWrapper = (args: ModalProps) => {
|
|
48
|
+
const [opened, setOpened] = useState(true);
|
|
49
|
+
return (
|
|
50
|
+
<>
|
|
51
|
+
<Modal {...args} opened={opened} onClose={() => setOpened(false)}>
|
|
52
|
+
The title above is longer than the header can display, so it truncates
|
|
53
|
+
with an ellipsis instead of wrapping onto a second line.
|
|
54
|
+
<Modal.Footer>
|
|
55
|
+
<Button onClick={() => setOpened(false)}>Got it</Button>
|
|
56
|
+
</Modal.Footer>
|
|
57
|
+
</Modal>
|
|
58
|
+
<Button onClick={() => setOpened(true)}>Open Modal</Button>
|
|
59
|
+
</>
|
|
60
|
+
);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export const LongTitle: Story = {
|
|
64
|
+
args: {
|
|
65
|
+
title:
|
|
66
|
+
"This Modal Title Is Deliberately Long Enough To Exceed The Available Header Width",
|
|
67
|
+
},
|
|
68
|
+
render: (args) => <LongTitleWrapper {...args} />,
|
|
69
|
+
};
|
|
70
|
+
|
|
46
71
|
const ScrollingWrapper = (args: ModalProps) => {
|
|
47
|
-
|
|
72
|
+
// Starts opened so the modal is visible without pressing a button first.
|
|
73
|
+
const [opened, setOpened] = useState(true);
|
|
48
74
|
return (
|
|
49
75
|
<>
|
|
50
76
|
<Modal {...args} opened={opened} onClose={() => setOpened(false)}>
|