@recursica/mui-adapter 0.34.4 → 0.35.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/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.4",
16
+ "version": "0.35.0",
17
17
  "publishConfig": {
18
18
  "access": "public"
19
19
  },
@@ -10,7 +10,12 @@ New CSS classes (`.optionContent`/`.optionIcon`/`.optionText`/`.optionSupporting
10
10
 
11
11
  ## `wrapItemText`
12
12
 
13
- `label`/`supportingText` default to single-line truncation with an ellipsis (`.optionText > *` — `overflow: hidden; text-overflow: ellipsis; white-space: nowrap`). Passing `wrapItemText` adds `.optionTextWrap` alongside `.optionText`, re-enabling wrapping (`white-space: normal; overflow-wrap: anywhere`) for both children — later-cascade-wins, equal specificity. `renderRichOptionContent` takes `wrapItemText` as a third parameter and combines the two class names when it's true.
13
+ `label`/`supportingText` default to single-line truncation with an ellipsis (`.optionText > *` — `overflow: clip; overflow-clip-margin: 0.35em; text-overflow: ellipsis; white-space: nowrap`). Passing `wrapItemText` adds `.optionTextWrap` alongside `.optionText`, re-enabling wrapping (`white-space: normal; overflow-wrap: anywhere`) for both children — later-cascade-wins, equal specificity. `renderRichOptionContent` takes `wrapItemText` as a third parameter and combines the two class names when it's true.
14
+
15
+ `.optionText > *` used plain `overflow: hidden` until 2026-08-28 (Matt Massey) — it clipped
16
+ descenders (e.g. "g") whenever `text_line-height` is tighter than the font's natural
17
+ ascent+descent. `overflow-clip-margin` gives ink a small bleed allowance while still clipping
18
+ genuinely overflowing text; same project-wide fix as Chip's `CHIP_IMPLEMENTATION_NOTES.md`.
14
19
 
15
20
  ## Selected Option Highlight (bug fix)
16
21
 
@@ -323,7 +323,10 @@
323
323
 
324
324
  /* Default: label/supportingText each truncate to a single line with an ellipsis. */
325
325
  .optionText > * {
326
- overflow: hidden;
326
+ overflow: clip; /* HARDCODE: `hidden` clips descenders (e.g. "g") when text_line-height is
327
+ tighter than the font's natural ascent+descent; overflow-clip-margin gives ink a small bleed
328
+ allowance while still clipping genuinely overflowing text (see Chip's IMPLEMENTATION_NOTES.md). */
329
+ overflow-clip-margin: 0.35em;
327
330
  text-overflow: ellipsis;
328
331
  white-space: nowrap;
329
332
  }
@@ -75,3 +75,15 @@ We explicitly pass `disableRipple` and `disableElevation` to block MUI's dynamic
75
75
  **Root cause:** `.root` has `width: fit-content` (to hug its own content instead of stretching in flex columns) but no `max-width`. Verified via Playwright: the wrapper measured exactly 250px, but `fit-content` on `.root` still resolved to its 534px `max-content` size — it doesn't reliably clamp against a narrower containing block on its own. Same root cause and identical fix in mantine-adapter.
76
76
 
77
77
  **Fix:** added `max-width: 100%` to `.root`. It's a no-op when the parent is wide enough (confirmed no change to `Default`/`IconOnly`/`TextWithIcon` story widths), and clamps the button to the parent's resolved width when the parent is narrower — at which point the existing `overflow: hidden` (`.root`) + `text-overflow: ellipsis`/`white-space: nowrap` (`.labelText`) take over, exactly as already documented above.
78
+
79
+ ---
80
+
81
+ ## `.labelText` descender clipping (Matt Massey, 2026-08-28)
82
+
83
+ `.labelText` used plain `overflow: hidden` to make `text-overflow: ellipsis` work, which also
84
+ clips descenders (e.g. the "g" in a long label) whenever `text_line-height` is tighter than the
85
+ font's natural ascent+descent. Switched to `overflow: clip; overflow-clip-margin: 0.35em;` — same
86
+ truncation, but ink can bleed slightly past the line box before it's actually clipped. `.root`'s
87
+ own `overflow: hidden` (the max-width truncation bounding box, above) is untouched — it has
88
+ padding around the label so it isn't tight against the glyphs the way `.labelText` is.
89
+ Project-wide fix; see Chip's `CHIP_IMPLEMENTATION_NOTES.md` for the original discovery.
@@ -68,7 +68,10 @@
68
68
  .labelText {
69
69
  display: block;
70
70
  min-width: 0;
71
- overflow: hidden;
71
+ overflow: clip; /* HARDCODE: `hidden` clips descenders (e.g. "g") when text_line-height is
72
+ tighter than the font's natural ascent+descent; overflow-clip-margin gives ink a small bleed
73
+ allowance while still clipping genuinely overflowing text (see Chip's IMPLEMENTATION_NOTES.md). */
74
+ overflow-clip-margin: 0.35em;
72
75
  text-overflow: ellipsis;
73
76
  white-space: nowrap;
74
77
  font-size: inherit;
@@ -12,4 +12,9 @@ New CSS classes (`.optionContent`/`.optionIcon`/`.optionText`/`.optionSupporting
12
12
 
13
13
  ## `wrapItemText`
14
14
 
15
- `label`/`supportingText` default to single-line truncation with an ellipsis (`.optionText > *` — `overflow: hidden; text-overflow: ellipsis; white-space: nowrap`). Passing `wrapItemText` adds `.optionTextWrap` alongside `.optionText`, re-enabling wrapping (`white-space: normal; overflow-wrap: anywhere`) for both children — later-cascade-wins, equal specificity. `renderRichOptionContent` takes `wrapItemText` as a third parameter and combines the two class names when it's true. `Dropdown.tsx` exposes this as a public prop; `BareDropdown.tsx` (internal-only, not part of the public `Dropdown`/`AutoComplete` API this was requested for) doesn't take the prop and always truncates.
15
+ `label`/`supportingText` default to single-line truncation with an ellipsis (`.optionText > *` — `overflow: clip; overflow-clip-margin: 0.35em; text-overflow: ellipsis; white-space: nowrap`). Passing `wrapItemText` adds `.optionTextWrap` alongside `.optionText`, re-enabling wrapping (`white-space: normal; overflow-wrap: anywhere`) for both children — later-cascade-wins, equal specificity. `renderRichOptionContent` takes `wrapItemText` as a third parameter and combines the two class names when it's true. `Dropdown.tsx` exposes this as a public prop; `BareDropdown.tsx` (internal-only, not part of the public `Dropdown`/`AutoComplete` API this was requested for) doesn't take the prop and always truncates.
16
+
17
+ `.optionText > *` used plain `overflow: hidden` until 2026-08-28 (Matt Massey) — it clipped
18
+ descenders (e.g. "g") whenever `text_line-height` is tighter than the font's natural
19
+ ascent+descent. `overflow-clip-margin` gives ink a small bleed allowance while still clipping
20
+ genuinely overflowing text; same project-wide fix as Chip's `CHIP_IMPLEMENTATION_NOTES.md`.
@@ -454,7 +454,10 @@
454
454
 
455
455
  /* Default: label/supportingText each truncate to a single line with an ellipsis. */
456
456
  .optionText > * {
457
- overflow: hidden;
457
+ overflow: clip; /* HARDCODE: `hidden` clips descenders (e.g. "g") when text_line-height is
458
+ tighter than the font's natural ascent+descent; overflow-clip-margin gives ink a small bleed
459
+ allowance while still clipping genuinely overflowing text (see Chip's IMPLEMENTATION_NOTES.md). */
460
+ overflow-clip-margin: 0.35em;
458
461
  text-overflow: ellipsis;
459
462
  white-space: nowrap;
460
463
  }
@@ -0,0 +1,12 @@
1
+ # Modal Implementation Notes
2
+
3
+ ## `.title` descender clipping (Matt Massey, 2026-08-28)
4
+
5
+ `.title` truncates with an ellipsis (`white-space: nowrap; text-overflow: ellipsis`) rather than
6
+ wrapping, needing `flex: 1 1 auto; min-width: 0;` since it's a flex child of `.header` alongside
7
+ the close button. It used plain `overflow: hidden` to make the ellipsis work, which also clips
8
+ descenders (e.g. the "g" in a long title) whenever `text_line-height` is tighter than the font's
9
+ natural ascent+descent. Switched to `overflow: clip; overflow-clip-margin: 0.35em;` — same
10
+ truncation, but ink can bleed slightly past the line box before it's actually clipped.
11
+ Project-wide fix; see Chip's `CHIP_IMPLEMENTATION_NOTES.md` for the original discovery. Matches
12
+ mantine-adapter's equivalent `.title` rule (see its own `MODAL_IMPLEMENTATION_NOTES.md`).
@@ -66,7 +66,10 @@
66
66
  .title {
67
67
  flex: 1 1 auto; /* HARDCODE: let the title claim the space between the header edge and the close button */
68
68
  min-width: 0; /* HARDCODE: required for text-overflow ellipsis to take effect on a flex child */
69
- overflow: hidden;
69
+ overflow: clip; /* HARDCODE: `hidden` clips descenders (e.g. "g") when text_line-height is
70
+ tighter than the font's natural ascent+descent; overflow-clip-margin gives ink a small bleed
71
+ allowance while still clipping genuinely overflowing text (see Chip's IMPLEMENTATION_NOTES.md). */
72
+ overflow-clip-margin: 0.35em;
70
73
  white-space: nowrap;
71
74
  text-overflow: ellipsis;
72
75
 
@@ -62,3 +62,13 @@ No tokens from other component namespaces are referenced.
62
62
  **Decision:** Accept `opened` prop to match the standard Recursica component API.
63
63
 
64
64
  **Implementation:** MUI Drawer natively expects the `open` boolean prop. The wrapper maps the incoming framework-agnostic `opened` prop to MUI's `open={Boolean(opened)}`, allowing consistent usage across both adapter implementations.
65
+
66
+ ---
67
+
68
+ ## `.titleTruncate` descender clipping (Matt Massey, 2026-08-28)
69
+
70
+ `.titleTruncate` used plain `overflow: hidden` to make `text-overflow: ellipsis` work, which also
71
+ clips descenders (e.g. the "g" in a long title) whenever `text_line-height` is tighter than the
72
+ font's natural ascent+descent. Switched to `overflow: clip; overflow-clip-margin: 0.35em;` — same
73
+ truncation, but ink can bleed slightly past the line box before it's actually clipped.
74
+ Project-wide fix; see Chip's `CHIP_IMPLEMENTATION_NOTES.md` for the original discovery.
@@ -96,7 +96,10 @@
96
96
  .titleTruncate {
97
97
  composes: title;
98
98
  white-space: nowrap;
99
- overflow: hidden;
99
+ overflow: clip; /* HARDCODE: `hidden` clips descenders (e.g. "g") when text_line-height is
100
+ tighter than the font's natural ascent+descent; overflow-clip-margin gives ink a small bleed
101
+ allowance while still clipping genuinely overflowing text (see Chip's IMPLEMENTATION_NOTES.md). */
102
+ overflow-clip-margin: 0.35em;
100
103
  text-overflow: ellipsis;
101
104
  display: block;
102
105
  flex: 1;
@@ -0,0 +1,17 @@
1
+ # Typography – Implementation Notes
2
+
3
+ `Typography` is the shared rendering base for both `Text` and `Title` in mui-adapter — anything
4
+ applied here reaches both components.
5
+
6
+ ## `.root` `text-wrap: balance` (Matt Massey, 2026-08-28)
7
+
8
+ **Decision:** Added `text-wrap: balance` via a new `Typography.module.css` `.root` class, merged
9
+ onto the typography class alongside the caller's own `className`. Since both `Text` and `Title`
10
+ render through this component, it covers all `order` heading levels (h1–h6) and paragraph text in
11
+ one place.
12
+
13
+ **Implementation:** UX asked for more evenly balanced multi-line wrapping instead of a ragged last
14
+ line. Not a design token — it's a layout algorithm choice, so it's hardcoded rather than pulled
15
+ from `recursica_variables_scoped.css`. Most effective on short text (headings); Chromium/Firefox
16
+ only balance up to ~6 lines, so long paragraphs silently fall back to normal wrapping past that
17
+ point. No fallback needed — browsers that don't support the value just ignore the declaration.
@@ -0,0 +1,13 @@
1
+ /*
2
+ * HARDCODED VALUES
3
+ * - `.root` `text-wrap: balance` — not a design token; a layout algorithm choice requested by
4
+ * UX (Matt Massey, 2026-08-28) to even out wrapped line lengths. See TEXT_IMPLEMENTATION_NOTES.md.
5
+ */
6
+
7
+ .root {
8
+ /* HARDCODE: balances wrapped line lengths instead of leaving a ragged short last line. Most
9
+ effective on short text; browsers cap balancing at ~6 lines, so long paragraphs silently
10
+ fall back to normal wrapping past that point — no fallback needed, unsupported browsers
11
+ just ignore the declaration. */
12
+ text-wrap: balance;
13
+ }
@@ -7,6 +7,7 @@ import {
7
7
  filterStylingProps,
8
8
  type RecursicaOverStyled,
9
9
  } from "../../utils/filterStylingProps";
10
+ import styles from "./Typography.module.css";
10
11
 
11
12
  export type TypographyProps = RecursicaOverStyled<
12
13
  Omit<MuiTypographyProps, "variant"> & {
@@ -24,9 +25,9 @@ export const Typography = forwardRef<HTMLElement, TypographyProps>(
24
25
  const restRecord = sanitizedProps as Record<string, unknown>;
25
26
 
26
27
  const classNameProp = restRecord.className as string | undefined;
27
- const finalClass = classNameProp
28
- ? `${typographyClass} ${classNameProp}`
29
- : typographyClass;
28
+ const finalClass = [typographyClass, styles.root, classNameProp]
29
+ .filter(Boolean)
30
+ .join(" ");
30
31
 
31
32
  return (
32
33
  <MuiTypography