@ai-matrx/design-system 0.11.1 → 0.11.3
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 +84 -0
- package/dist/index.cjs +19 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -3
- package/dist/index.d.ts +17 -3
- package/dist/index.js +19 -8
- package/dist/index.js.map +1 -1
- package/dist/styles.css +70 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,89 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.11.3 — 2026-09-07
|
|
4
|
+
|
|
5
|
+
**THE STICKY FOOTER STOPPED PAINTING OVER THE CONSEQUENCE.** `ConfirmDialog`'s
|
|
6
|
+
opaque footer covered the last ~8px of a multi-line consequence description —
|
|
7
|
+
the exact copy the platform's destructive-and-expensive-actions law requires
|
|
8
|
+
authors to write. Feedback `bf8fb00b`.
|
|
9
|
+
|
|
10
|
+
Measured in Chrome at 1280x800 on matrx-frontend, 0.11.2, with a real 3-line
|
|
11
|
+
folder-delete consequence:
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
description.bottom = 429.3 footer.top = 421.7 overlap = 7.6px
|
|
15
|
+
scrollHeight === clientHeight === 228
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The second line is what made it a defect rather than a nuisance: **the card did
|
|
19
|
+
not scroll**, so the occluded pixels could never be revealed by any user
|
|
20
|
+
action. And the overlap was not a long-copy edge case — it was a constant 8px
|
|
21
|
+
at EVERY description length, in both themes, on `Dialog` as well as
|
|
22
|
+
`AlertDialog` and therefore on `ConfirmDialog`.
|
|
23
|
+
|
|
24
|
+
**Root cause.** Both footers bled over the card's bottom padding with
|
|
25
|
+
`mb-[calc(var(--dialog-pad,0px)*-1)]`. A negative bottom margin makes an
|
|
26
|
+
element's border box taller than the grid area (or flex line) its parent
|
|
27
|
+
allocated it, and `position: sticky` **clamps a box to its containing block** —
|
|
28
|
+
so the browser yanked the whole footer UP by `--dialog-pad` (24px) against a
|
|
29
|
+
`gap-4` (16px). 24 − 16 = the 8px of occlusion. Statically positioned, the same
|
|
30
|
+
negative margin renders exactly as intended; it is the interaction with
|
|
31
|
+
`sticky` that breaks it, which is why it survived review.
|
|
32
|
+
|
|
33
|
+
**The fix.** The bleed is bought without a negative block margin. The card hands
|
|
34
|
+
its bottom padding to the footer, and the footer reproduces it — so the footer's
|
|
35
|
+
box is exactly the space it was given, sticky has nothing to clamp, and the
|
|
36
|
+
opaque background still reaches the card's bottom edge with nothing scrolling
|
|
37
|
+
through beneath the actions. Two rules now ship in `styles.css`:
|
|
38
|
+
|
|
39
|
+
- `.matrx-dialog-footer` — the whole footer geometry (`position: sticky;
|
|
40
|
+
bottom: 0`, the top pad, the INLINE bleed, and
|
|
41
|
+
`padding-bottom: var(--dialog-pad-bottom, var(--dialog-pad, 0px))`). Sticky
|
|
42
|
+
clamps the block axis only, so the inline bleed stays a negative margin.
|
|
43
|
+
- `.matrx-dialog-card:has(> .matrx-dialog-footer) { padding-bottom: 0 }` — the
|
|
44
|
+
reservation, **unlayered on purpose** so it beats the card's own `p-6` /
|
|
45
|
+
`p-4 pb-safe` utilities. Layered, it would lose and the fix would be silently
|
|
46
|
+
absent in every consumer. It is conditional on `:has()`, so a `DialogContent`
|
|
47
|
+
with no footer keeps its full padding.
|
|
48
|
+
|
|
49
|
+
The mobile sheet's home-indicator clearance moved with the padding:
|
|
50
|
+
`.matrx-mobile-sheet` sets `--dialog-pad-bottom: max(0.75rem,
|
|
51
|
+
env(safe-area-inset-bottom, 0px))`, the same floor `pb-safe` had.
|
|
52
|
+
|
|
53
|
+
**Guards.** `src/sticky-footer-geometry.test.tsx` — proven failing on the
|
|
54
|
+
pre-fix sources (7 of its 8 assertions fail there) and passing here. It bans
|
|
55
|
+
the MECHANISM by census, not the two known sites: nothing `sticky` anywhere in
|
|
56
|
+
this package may carry a negative block margin. It also asserts the shipped
|
|
57
|
+
rules exist, that the reservation is unlayered, and that every card and footer
|
|
58
|
+
is wired to them. jsdom has no layout engine, so the paint itself is proven in
|
|
59
|
+
a real browser and that proof is permanent, not a one-off: matrx-frontend
|
|
60
|
+
`/demos/confirm-geometry` exposes `window.__confirmGeometry.runAll()`, which
|
|
61
|
+
opens the real package `ConfirmDialog` at 1-, 2-, 3- and 6-line consequences
|
|
62
|
+
and returns `descriptionBottom`, `footerTop`, `overlapPx` and whether the card
|
|
63
|
+
scrolls. Invariant: `overlapPx <= 0` at every length, light and dark.
|
|
64
|
+
|
|
65
|
+
**Why the existing tests all passed.** `confirm-dialog.test.tsx` asserts the
|
|
66
|
+
consequence's DOM text, its `aria-describedby` wiring, and the absence of
|
|
67
|
+
`line-clamp`/`truncate`. Every one of those was true the whole time. A guard
|
|
68
|
+
that cannot see geometry cannot catch a geometry defect — recorded here because
|
|
69
|
+
that is the class, not this instance.
|
|
70
|
+
|
|
71
|
+
### Consumer action (C28)
|
|
72
|
+
|
|
73
|
+
**None** — no API change; the footer's rendered geometry is identical minus the
|
|
74
|
+
occlusion. Take the patch. Three assertions that spelled the footer contract as
|
|
75
|
+
the literal `sticky` utility now assert `matrx-dialog-footer`; no consumer
|
|
76
|
+
asserts on those class strings. Anything that overrode `DialogFooter`'s padding
|
|
77
|
+
through `className` still wins (the rule is layered); anything that set
|
|
78
|
+
`padding-bottom` on `DialogContent` itself while ALSO rendering a footer is now
|
|
79
|
+
overridden by the reservation, which is the point.
|
|
80
|
+
|
|
81
|
+
## 0.11.2
|
|
82
|
+
|
|
83
|
+
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
84
|
+
`git diff npm/design-system/v0.11.1..npm/design-system/v0.11.2 -- apps/shared/design-system`).
|
|
85
|
+
No source changes intended and no consumer action required.
|
|
86
|
+
|
|
3
87
|
## 0.11.1 — 2026-09-07
|
|
4
88
|
|
|
5
89
|
**The 0.10.1 dialog-centring fix, on the current line.** 0.11.0 was cut and
|
package/dist/index.cjs
CHANGED
|
@@ -1060,9 +1060,13 @@ var AlertDialogContent = React7.forwardRef(({ className, children, container, an
|
|
|
1060
1060
|
ref,
|
|
1061
1061
|
"data-slot": "alert-dialog-content",
|
|
1062
1062
|
className: cn(
|
|
1063
|
-
`fixed left-[50%] top-[50%] z-[10000] grid min-w-0 w-full max-w-lg ${CENTERED_DIALOG} gap-4 border bg-background p-6 shadow-lg`,
|
|
1063
|
+
`matrx-dialog-card fixed left-[50%] top-[50%] z-[10000] grid min-w-0 w-full max-w-lg ${CENTERED_DIALOG} gap-4 border bg-background p-6 shadow-lg`,
|
|
1064
1064
|
// Ruling 3 — never taller than the viewport, always scrollable, and
|
|
1065
1065
|
// the footer stays reachable via --dialog-pad like Dialog's.
|
|
1066
|
+
// Ruling 5 (0.11.3) — `matrx-dialog-card` hands the bottom padding to
|
|
1067
|
+
// a sticky footer when there is one, so the footer's box matches the
|
|
1068
|
+
// space the grid gave it and sticky never clamps it up over the
|
|
1069
|
+
// consequence copy.
|
|
1066
1070
|
"max-h-[85dvh] overflow-y-auto overscroll-contain [--dialog-pad:1.5rem] overflow-x-clip [overflow-wrap:anywhere] [&>*]:min-w-0 [&>*]:max-w-full",
|
|
1067
1071
|
"sm:rounded-lg",
|
|
1068
1072
|
animated && MOTION_DIALOG,
|
|
@@ -1100,9 +1104,12 @@ var AlertDialogFooter = ({
|
|
|
1100
1104
|
className: cn(
|
|
1101
1105
|
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
|
|
1102
1106
|
// Ruling 3/4 — sticky to the card edges so a scrolled body never shows
|
|
1103
|
-
// through under the actions, and safe-area padded on a phone.
|
|
1104
|
-
|
|
1105
|
-
|
|
1107
|
+
// through under the actions, and safe-area padded on a phone. ALL of
|
|
1108
|
+
// that geometry is `matrx-dialog-footer`, a rule this package SHIPS
|
|
1109
|
+
// (styles.css), because the utility spelling of it carried a negative
|
|
1110
|
+
// block margin that sticky clamped — painting the footer over the last
|
|
1111
|
+
// 8px of the consequence at every description length (0.11.3).
|
|
1112
|
+
"matrx-dialog-footer bg-background",
|
|
1106
1113
|
className
|
|
1107
1114
|
),
|
|
1108
1115
|
...props
|
|
@@ -2123,8 +2130,8 @@ var DialogContentPrimitive = React17.forwardRef((props, ref) => {
|
|
|
2123
2130
|
);
|
|
2124
2131
|
});
|
|
2125
2132
|
DialogContentPrimitive.displayName = "DialogContentPrimitive";
|
|
2126
|
-
var DIALOG_DESKTOP_CLASSES2 = `fixed left-[50%] top-[50%] z-[10000] grid min-w-0 w-full max-w-lg ${CENTERED_DIALOG} gap-4 max-h-[85dvh] overflow-y-auto overscroll-contain [--dialog-pad:1.5rem] overflow-x-clip border bg-background p-6 shadow-lg [overflow-wrap:anywhere] [&>*]:min-w-0 [&>*]:max-w-full sm:rounded-lg`;
|
|
2127
|
-
var DIALOG_MOBILE_SHEET_CLASSES2 = "matrx-mobile-sheet fixed inset-x-0 bottom-0 left-0 right-0 top-auto z-[10000] flex min-w-0 flex-col w-full max-w-full max-h-[90dvh] translate-x-0 translate-y-0 gap-4 [--dialog-pad:1rem] overflow-x-clip border-t bg-background p-4 pb-safe shadow-lg [overflow-wrap:anywhere] [&>*]:min-w-0 [&>*]:max-w-full rounded-t-2xl rounded-b-none overflow-y-auto overscroll-contain";
|
|
2133
|
+
var DIALOG_DESKTOP_CLASSES2 = `matrx-dialog-card fixed left-[50%] top-[50%] z-[10000] grid min-w-0 w-full max-w-lg ${CENTERED_DIALOG} gap-4 max-h-[85dvh] overflow-y-auto overscroll-contain [--dialog-pad:1.5rem] overflow-x-clip border bg-background p-6 shadow-lg [overflow-wrap:anywhere] [&>*]:min-w-0 [&>*]:max-w-full sm:rounded-lg`;
|
|
2134
|
+
var DIALOG_MOBILE_SHEET_CLASSES2 = "matrx-mobile-sheet matrx-dialog-card fixed inset-x-0 bottom-0 left-0 right-0 top-auto z-[10000] flex min-w-0 flex-col w-full max-w-full max-h-[90dvh] translate-x-0 translate-y-0 gap-4 [--dialog-pad:1rem] overflow-x-clip border-t bg-background p-4 pb-safe shadow-lg [overflow-wrap:anywhere] [&>*]:min-w-0 [&>*]:max-w-full rounded-t-2xl rounded-b-none overflow-y-auto overscroll-contain";
|
|
2128
2135
|
var DIALOG_MOBILE_SHEET_OVERRIDE2 = "inset-x-0 bottom-0 left-0 right-0 top-auto translate-x-0 translate-y-0 w-full max-w-full max-h-[90dvh] rounded-b-none rounded-t-2xl overflow-y-auto";
|
|
2129
2136
|
var DialogContent = React17.forwardRef(
|
|
2130
2137
|
({
|
|
@@ -2228,8 +2235,12 @@ var DialogFooter = ({
|
|
|
2228
2235
|
"data-slot": "dialog-footer",
|
|
2229
2236
|
className: cn(
|
|
2230
2237
|
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
|
|
2231
|
-
|
|
2232
|
-
|
|
2238
|
+
// Ruling 3 — the geometry is `matrx-dialog-footer`, a rule this package
|
|
2239
|
+
// SHIPS (styles.css). It used to be utilities, one of which was a
|
|
2240
|
+
// negative block margin that `position: sticky` clamps — the footer was
|
|
2241
|
+
// yanked up over the row above it by `--dialog-pad` minus the card gap
|
|
2242
|
+
// (0.11.3). The card gives the footer its bottom padding instead.
|
|
2243
|
+
"matrx-dialog-footer bg-background",
|
|
2233
2244
|
className
|
|
2234
2245
|
),
|
|
2235
2246
|
...props
|