@recursica/adapter-mantine-v8 1.3.0 → 1.3.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
@@ -12,7 +12,7 @@
12
12
  "type": "git",
13
13
  "url": "git+https://github.com/borderux/recursica-adapter-mantine-v8.git"
14
14
  },
15
- "version": "1.3.0",
15
+ "version": "1.3.1",
16
16
  "publishConfig": {
17
17
  "access": "public"
18
18
  },
@@ -78,15 +78,15 @@
78
78
  "release": "changeset publish"
79
79
  },
80
80
  "dependencies": {
81
- "@recursica/adapter-common": "^1.1.0"
81
+ "@recursica/adapter-common": "^1.1.1"
82
82
  },
83
83
  "devDependencies": {
84
84
  "@changesets/cli": "^2.29.7",
85
85
  "@eslint/js": "^9.25.0",
86
86
  "@playwright/test": "^1.62.1",
87
- "@recursica/adapter-tester": "^5.3.0",
87
+ "@recursica/adapter-tester": "^5.3.1",
88
88
  "@recursica/recursica-postcss-vars": "^1.5.0",
89
- "@recursica/storybook-template": "^0.7.11",
89
+ "@recursica/storybook-template": "^0.7.15",
90
90
  "@recursica/token-analyzer": "^1.8.0",
91
91
  "@storybook/addon-a11y": "^10.3.3",
92
92
  "@storybook/addon-docs": "^10.3.3",
@@ -21,7 +21,7 @@
21
21
  /* SideBySide Variant */
22
22
  .groupRoot[data-layout="side-by-side"] {
23
23
  flex-direction: column;
24
- flex-wrap: wrap;
24
+ flex-wrap: nowrap;
25
25
  padding-top: var(
26
26
  --recursica_ui-kit_components_checkbox-group_variants_layouts_side-by-side_properties_vertical-padding
27
27
  );
@@ -259,8 +259,6 @@
259
259
  );
260
260
  }
261
261
  .groupRoot[data-layout="side-by-side"] {
262
- flex-direction: row;
263
- flex-wrap: wrap;
264
262
  gap: var(
265
263
  --recursica_ui-kit_components_checkbox-group_variants_layouts_side-by-side_properties_gutter
266
264
  );
@@ -58,6 +58,14 @@
58
58
  min-height: var(
59
59
  --recursica_ui-kit_components_file-input_properties_min-height
60
60
  );
61
+ /* Fixed height (icon + padding + border) so the nested clear Button overflows the row instead of growing the control. */
62
+ height: calc(
63
+ var(--recursica_ui-kit_components_file-input_properties_icon-size) + 2 *
64
+ var(
65
+ --recursica_ui-kit_components_file-input_properties_vertical-padding
66
+ ) +
67
+ 2 * var(--recursica_ui-kit_components_file-input_properties_border-size)
68
+ );
61
69
  gap: var(--recursica_ui-kit_components_file-input_properties_icon-text-gap);
62
70
  padding-top: var(
63
71
  --recursica_ui-kit_components_file-input_properties_vertical-padding
@@ -35,6 +35,7 @@
35
35
  display: flex;
36
36
  flex-direction: column;
37
37
  width: 100%;
38
+ max-width: var(--recursica_ui-kit_globals_form_field_size_max-width);
38
39
  gap: var(--recursica_ui-kit_components_file-upload_properties_list-spacing);
39
40
  }
40
41
 
@@ -265,6 +265,7 @@ export const FileUpload = forwardRef<HTMLDivElement, FileUploadProps>(
265
265
  required={required}
266
266
  withAsterisk={withAsterisk}
267
267
  id={id}
268
+ controlMaxWidth="var(--recursica_ui-kit_globals_form_field_size_max-width)"
268
269
  >
269
270
  <div
270
271
  ref={ref}
@@ -267,7 +267,6 @@ export const WithDisabledItems: Story = {
267
267
  export const WithSubmenus: Story = {
268
268
  args: {
269
269
  position: "bottom-start",
270
- width: 200,
271
270
  // Rendered open by default so this story is diffable against the MUI adapter
272
271
  // without an interaction step.
273
272
  opened: true,
@@ -114,3 +114,11 @@ clips descenders (e.g. the "g" in a long title) whenever `text_line-height` is t
114
114
  font's natural ascent+descent. Switched to `overflow: clip; overflow-clip-margin: 0.35em;` — same
115
115
  truncation, but ink can bleed slightly past the line box before it's actually clipped.
116
116
  Project-wide fix; see Chip's `CHIP_IMPLEMENTATION_NOTES.md` for the original discovery.
117
+
118
+ ---
119
+
120
+ ## 9. Placement-aware border radius (Matt Massey, 2026-10-05)
121
+
122
+ **Decision:** The `border-radius` token is applied only to the corners on the edge that faces the page, not all four.
123
+
124
+ **Implementation:** A panel with `placement="right"` (the default) rounds its upper-left and lower-left corners only; its right corners are square against the screen edge. A panel with `placement="left"` rounds its upper-right and lower-right corners only. `Panel.tsx` adds `.contentRight` / `.contentLeft` to the `content` class, and those zero the two outer corners. `top` and `bottom` placements are unchanged (all four corners rounded).
@@ -1,6 +1,16 @@
1
1
  /* HARDCODED VALUES:
2
2
  - border-style: solid: Structural rendering rule for the panel border.
3
- - .inner { left: 0 }: Prevents the fixed Drawer portal from being pushed off-screen in centered flex environments (like Storybook Canvas).
3
+ - .contentTop {
4
+ border-top-left-radius: 0;
5
+ border-top-right-radius: 0;
6
+ }
7
+
8
+ .contentBottom {
9
+ border-bottom-left-radius: 0;
10
+ border-bottom-right-radius: 0;
11
+ }
12
+
13
+ .inner { left: 0 }: Prevents the fixed Drawer portal from being pushed off-screen in centered flex environments (like Storybook Canvas).
4
14
  - flexbox layout on .content & .body: Required to create a vertical flex context that pushes the footer to the bottom.
5
15
  - position: sticky & negative margins on .footer: A CSS technique used to break the footer out of the .body padding constraints so it stretches edge-to-edge, while remaining fixed at the bottom of the scroll container.
6
16
  - z-index: 10 on .footer: Ensures the footer covers the body content as it scrolls underneath.
@@ -24,13 +34,28 @@
24
34
  );
25
35
  box-shadow: var(--recursica_ui-kit_components_panel_properties_elevation);
26
36
  min-width: var(--recursica_ui-kit_components_panel_properties_min-width);
27
- max-width: var(--recursica_ui-kit_components_panel_properties_max-width);
37
+ max-width: min(
38
+ var(--recursica_ui-kit_components_panel_properties_max-width),
39
+ 100vw
40
+ );
28
41
 
29
42
  display: flex;
30
43
  flex-direction: column;
31
44
  height: 100%;
32
45
  }
33
46
 
47
+ /* Round only the edge facing the page: a panel sliding in from the right rounds
48
+ its left corners; from the left, its right corners. */
49
+ .contentRight {
50
+ border-top-right-radius: 0;
51
+ border-bottom-right-radius: 0;
52
+ }
53
+
54
+ .contentLeft {
55
+ border-top-left-radius: 0;
56
+ border-bottom-left-radius: 0;
57
+ }
58
+
34
59
  .inner {
35
60
  /* Forces the Drawer Inner container to the left edge, preventing it from inheriting
36
61
  a centered static position in flex environments like Storybook's Canvas wrapper */
@@ -86,7 +86,7 @@ export const Default: Story = {
86
86
  },
87
87
  render: ({ wrapHeaderText, ...args }: PanelStoryArgs) => {
88
88
  // eslint-disable-next-line react-hooks/rules-of-hooks
89
- const [opened, setOpened] = useState(false);
89
+ const [opened, setOpened] = useState(true);
90
90
 
91
91
  return (
92
92
  <>
@@ -129,7 +129,7 @@ export const LeftPlacement: Story = {
129
129
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
130
130
  render: ({ withLayer, layer, ...args }: PanelStoryArgs) => {
131
131
  // eslint-disable-next-line react-hooks/rules-of-hooks
132
- const [opened, setOpened] = useState(false);
132
+ const [opened, setOpened] = useState(true);
133
133
 
134
134
  return (
135
135
  <>
@@ -162,7 +162,7 @@ export const ScrollableContent: Story = {
162
162
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
163
163
  render: ({ withLayer, layer, ...args }: PanelStoryArgs) => {
164
164
  // eslint-disable-next-line react-hooks/rules-of-hooks
165
- const [opened, setOpened] = useState(false);
165
+ const [opened, setOpened] = useState(true);
166
166
 
167
167
  return (
168
168
  <>
@@ -204,7 +204,7 @@ export const LongTitle: Story = {
204
204
  },
205
205
  render: ({ ...args }: PanelStoryArgs) => {
206
206
  // eslint-disable-next-line react-hooks/rules-of-hooks
207
- const [opened, setOpened] = useState(false);
207
+ const [opened, setOpened] = useState(true);
208
208
 
209
209
  return (
210
210
  <>
@@ -75,7 +75,15 @@ const PanelBase = function Panel({
75
75
  // Bind CSS module classes to Mantine's internal classNames API
76
76
  const mergedClassNames = mergeClassNames(
77
77
  {
78
- content: styles.content,
78
+ content: `${styles.content} ${
79
+ placement === "right"
80
+ ? styles.contentRight
81
+ : placement === "left"
82
+ ? styles.contentLeft
83
+ : placement === "top"
84
+ ? styles.contentTop
85
+ : styles.contentBottom
86
+ }`,
79
87
  header: styles.header,
80
88
  title: wrapHeaderText ? styles.titleTruncate : styles.title,
81
89
  body: styles.body,
@@ -87,6 +95,7 @@ const PanelBase = function Panel({
87
95
  return (
88
96
  <MantineDrawer
89
97
  {...(sanitizedProps as unknown as MantineDrawerProps)}
98
+ size="var(--recursica_ui-kit_components_panel_properties_max-width)"
90
99
  position={placement} /* Recursica default: right; Mantine default: left */
91
100
  keepMounted={keepMounted}
92
101
  closeOnClickOutside={withCallerOverride(
@@ -24,8 +24,8 @@
24
24
 
25
25
  /* SideBySide Variant */
26
26
  .groupRoot[data-layout="side-by-side"] {
27
- flex-direction: row;
28
- flex-wrap: wrap;
27
+ flex-direction: column;
28
+ flex-wrap: nowrap;
29
29
  gap: var(
30
30
  --recursica_ui-kit_components_radio-button-group_variants_layouts_side-by-side_properties_gutter
31
31
  );
@@ -133,6 +133,32 @@
133
133
  );
134
134
  }
135
135
 
136
+ /* Vertical: Mantine's separator is a horizontal line across the item, so the divider token
137
+ sets its height; and the container radius is capped to stay concentric with the pill items. */
138
+ .root[data-orientation="vertical"] .control::before {
139
+ width: auto;
140
+ height: var(
141
+ --recursica_ui-kit_components_segmented-control_properties_divider-size
142
+ );
143
+ }
144
+
145
+ .root[data-orientation="vertical"] {
146
+ border-radius: min(
147
+ var(
148
+ --recursica_ui-kit_components_segmented-control_properties_border-radius
149
+ ),
150
+ calc(
151
+ var(
152
+ --recursica_ui-kit_components_segmented-control-item_properties_item_height
153
+ ) /
154
+ 2 +
155
+ var(
156
+ --recursica_ui-kit_components_segmented-control_properties_padding-vertical
157
+ )
158
+ )
159
+ );
160
+ }
161
+
136
162
  /* Indicator (the moving selected block) */
137
163
  .root .indicator {
138
164
  background-color: var(
@@ -84,6 +84,21 @@
84
84
  ); /* Move gap inside the step so the separator line can stretch through it */
85
85
  }
86
86
 
87
+ /* Mantine core adds a min-height, step-body inline margin and description margins on top of the
88
+ step-gap / indicator-label-gap tokens; zero them so spacing comes only from Recursica tokens. */
89
+ .root.vertical .step {
90
+ min-height: 0;
91
+ }
92
+
93
+ .root.vertical .stepBody {
94
+ margin-inline: 0;
95
+ }
96
+
97
+ .root.vertical .stepDescription {
98
+ margin-top: 0;
99
+ margin-bottom: 0;
100
+ }
101
+
87
102
  .root.vertical .step:last-of-type {
88
103
  padding-bottom: 0;
89
104
  }
@@ -185,6 +185,11 @@
185
185
  cursor: inherit;
186
186
  }
187
187
 
188
+ /* Mantine's InlineInput adds label-offset padding on top of the label-gap token. */
189
+ .root .label {
190
+ padding-inline: 0;
191
+ }
192
+
188
193
  .root:has(input:disabled) .label {
189
194
  color: var(
190
195
  --recursica_ui-kit_components_switch-item_properties_colors_disabled-text
@@ -265,6 +265,11 @@
265
265
  }
266
266
 
267
267
  /* Icon support */
268
+ /* Mantine core adds an xs margin between the section and label on top of the element-gap token. */
269
+ .root .tabSection {
270
+ margin-inline: 0;
271
+ }
272
+
268
273
  .root .tab svg {
269
274
  width: var(--tabs-icon-size);
270
275
  height: var(--tabs-icon-size);
@@ -37,6 +37,7 @@ const _Tabs = forwardRef<HTMLDivElement, TabsProps>(function Tabs(props, ref) {
37
37
  {
38
38
  list: styles.list,
39
39
  tab: styles.tab,
40
+ tabSection: styles.tabSection,
40
41
  panel: styles.panel,
41
42
  },
42
43
  restRecord.classNames as Partial<Record<string, string>> | undefined,