@ai-matrx/design-system 0.5.2 → 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/CHANGELOG.md CHANGED
@@ -1,5 +1,152 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.7.0 — 2026-09-07
4
+
5
+ **GROWTH WAVE 2 (C18).** Wave 1 (0.5.0) deleted 34 forked primitives but had
6
+ to KEEP every primitive this package did not ship. A fresh import-site census
7
+ of matrx-frontend `components/ui/` ranked what was left; this release ships all
8
+ of it, so those forks die too.
9
+
10
+ Ten new primitive families, ordered by the host fan-out they close:
11
+ `Tooltip` (182 sites), `Drawer` (121), `AlertDialog` (78), `Alert` (76),
12
+ `Slider` (46), `Resizable` (38), `RadioGroup` (30), `HoverCard` (16),
13
+ `ToggleGroup` + `Toggle` (10). Each was built from EVERY host variant, not from
14
+ one repo's copy.
15
+
16
+ ### The tooltip collapse
17
+
18
+ `@ai-matrx/tap-target` shipped a Tooltip family that four repos adopted — and
19
+ its own file header said what it was: an inlined PORT of matrx-frontend's
20
+ `components/ui/tooltip.tsx`. So the fleet ran TWO copies, and a
21
+ button-geometry package was the accidental owner of a design-system surface.
22
+ A tooltip is a design-system surface: it lives here now. `tap-target@0.2.0`
23
+ takes this package as an ordinary sibling dependency, imports the Tooltip from
24
+ it, deletes its own copy, and **re-exports nothing** — one implementation, one
25
+ import path. The sibling DAG already ordered design-system before tap-target,
26
+ so no cycle is introduced.
27
+
28
+ The port also restores the seam tap-target's copy had dropped: tooltips resolve
29
+ their portal target through `PortalContainerProvider`, so a tooltip inside a
30
+ popped-out panel lands in the right document instead of always `document.body`.
31
+
32
+ ### Real defects fixed in the port (never "preserved")
33
+
34
+ - **`AlertDialogContent` was not clamped to the viewport.** A confirm dialog
35
+ listing what is about to be deleted pushed Cancel/Continue below the fold on
36
+ a short viewport — and Radix does NOT dismiss an ALERT dialog on backdrop
37
+ click, so the surface was a genuine dead end. It is now
38
+ `max-h-[85dvh] overflow-y-auto` with a sticky, edge-bleeding footer, matching
39
+ `Dialog`.
40
+ - **`Slider` rendered exactly one thumb.** The host copy hardcoded a single
41
+ `Thumb`, so any two-value range silently lost its upper handle. One thumb is
42
+ now rendered per value.
43
+ - **`HoverCard` rendered inline instead of portalling**, so a card inside an
44
+ `overflow-hidden` ancestor was clipped and one inside a popped-out panel could
45
+ not exist. It now portals through the same seam — which is why its layer moved
46
+ from `z-50` to `z-[10001]`: at the body it would otherwise sit UNDER a modal.
47
+ - **`ResizableHandle` always said `cursor: col-resize`**, inline, including on
48
+ the horizontal separator of a vertical group, which wants `row-resize`. The
49
+ cursor is now orientation-aware.
50
+ - **Every touch target under 44px** on `Slider`, `RadioGroup`, `ResizableHandle`
51
+ and the `Drawer` grab handle. The visible control keeps its size; an invisible
52
+ pseudo-target expands the hit area on coarse pointers only, so desktop density
53
+ is untouched.
54
+
55
+ ### Density is a prop, not a fork (C18), on four more primitives
56
+
57
+ `Slider size`, `RadioGroup size` (declared on the root, inherited by items),
58
+ `Toggle`/`ToggleGroup size`, `ResizableHandle size`. That last one collapses
59
+ TWO host files: matrx-frontend shipped `components/ui/resizable.tsx` AND
60
+ `components/ui/matrx/resizable.tsx`, whose only difference was an eight-step
61
+ handle-thickness scale.
62
+
63
+ ### The Drawer owns the mobile-first rules
64
+
65
+ matrx-frontend's doctrine is "Drawer, not Dialog, on mobile", so the Drawer is
66
+ where most of the platform's mobile UX lands. It now owns those rules so no
67
+ host re-derives them: `dvh` never `vh`; `pb-safe` / `pt-safe` safe-area padding
68
+ (`pt-safe` is new in `styles.css`); a 44px grab-handle target around the 4px
69
+ pill; `DrawerBody` as the `flex-1 min-h-0` scroll shard with a `mt-auto` footer;
70
+ and `direction` as a prop, so a side or top drawer is not a fork.
71
+
72
+ It also closes the last CONTEXT twin: `RadixDialogModalProvider` still had a
73
+ host copy at `components/ui/radix-dialog-modal-context.tsx`, and a host copy of
74
+ a React context is the quiet twin — `useContext` matches by object identity, so
75
+ the host Drawer's provider and this package's Sheet consumer were two different
76
+ contexts that merely looked alike. `BottomSheet` now composes `Drawer` too, so
77
+ there is ONE vaul wrapper in the package instead of two.
78
+
79
+ ### Alert ships the whole status vocabulary
80
+
81
+ `default | destructive | warning | success | info`, all token-driven. The host
82
+ copy had only two variants, which is why the census found dozens of hand-rolled
83
+ amber/emerald banners with literal palette classes across four repos.
84
+
85
+ ### Consumer action (C28)
86
+
87
+ Install `@ai-matrx/design-system@0.7.0` (and `@ai-matrx/tap-target@0.2.0`), then:
88
+
89
+ 1. **Tooltip imports move.** Anything importing `Tooltip`, `TooltipTrigger`,
90
+ `TooltipContent` or `TooltipProvider` from `@ai-matrx/tap-target` must import
91
+ them from `@ai-matrx/design-system` instead — tap-target no longer exports
92
+ them. Affected today: aidream `apps/dashboard` (10 files), aidream
93
+ `apps/workflow-studio` (18 files), matrx-extend (1), matrx-frontend (1).
94
+ 2. **Delete these host forks** and re-point or shim their imports:
95
+ - matrx-frontend `components/ui/tooltip.tsx`, `drawer.tsx`,
96
+ `alert-dialog.tsx`, `alert.tsx`, `slider.tsx`, `resizable.tsx`,
97
+ `matrx/resizable.tsx`, `radio-group.tsx`, `hover-card.tsx`,
98
+ `toggle-group.tsx`, `toggle.tsx`, `radix-dialog-modal-context.tsx`.
99
+ - No other consumer repo carries a fork of these — verified by census on
100
+ 2026-09-07 across matrx-extend, matrx-games, aidream `apps/dashboard` and
101
+ `apps/workflow-studio`.
102
+ 3. **`matrx/resizable.tsx` callers keep their `size` prop** — it is the same
103
+ eight-step scale, now on the one component. Callers of the plain
104
+ `resizable.tsx` get the identical 2px default (`size="sm"`).
105
+ 4. **Check any `z-50` assumption around HoverCard**; it now portals to the body
106
+ at `z-[10001]`.
107
+ 5. **`react-resizable-panels` v4 overwrites `data-testid`** with its own
108
+ generated id. Tests that query a handle by test id must query
109
+ `role="separator"` instead.
110
+ 6. Register the new names in each repo's `package-twins.json`.
111
+
112
+ ## 0.6.0 — 2026-09-07
113
+
114
+ **THE BUTTON SCALE.** matrx-frontend carried a 127-line CVA button fork
115
+ (`components/ui/ButtonMine.tsx`, 17 call sites) alongside the package `Button`.
116
+ It existed for one reason: the package scale stopped at `sm`/`lg`, so a dense
117
+ toolbar had nowhere to go. Per C22 the gap moves into the package rather than
118
+ being papered over in a host shim, and the fork is deleted in the same session.
119
+
120
+ - **`Button` gains six size rungs** — `xs`, `md`, `xl`, `2xl`, `3xl`, and
121
+ `roundIcon` (a circular icon box) — completing one scale from `xs` to `3xl`
122
+ beside the existing `icon` / `icon-sm`. `md` is a deliberate alias of
123
+ `default`; the fork's middle rung was spelled that way at its call sites.
124
+ - **`Button` gains two variants** — `primary` (an explicit spelling of
125
+ `default`, identical by construction, because ~17 sites say it) and
126
+ `success`, the affirmative twin of `destructive`, painted from the
127
+ `--success` / `--success-foreground` token pair the theme already shipped.
128
+ - **`src/button.test.tsx` makes the scale a contract**: every rung resolves,
129
+ every rung is distinct (except the declared `md` alias), heights ascend, and
130
+ NO variant reaches a raw palette colour. Proven failing-then-passing by
131
+ deleting the `xs` rung. A missing rung is how the fork came back the first
132
+ time.
133
+
134
+ Two names the fork spelled differently now resolve to the package's geometry,
135
+ and the ~17 adopted sites move with them: `sm` is `h-8` (the fork's was `h-7`)
136
+ and `icon` is `h-9 w-9` (the fork's was `h-10 w-10`). This is the convergence,
137
+ not a regression — the fork also painted hardcoded `blue-600`/`gray-700`
138
+ palettes, so those sites now follow the host's own tokens in light and dark.
139
+
140
+ Not carried: the fork's `m` / `l` legacy size aliases (no call site used
141
+ either) and its runtime `isValidOption` variant/size validation, which guarded
142
+ against values TypeScript already refuses.
143
+
144
+ ### Consumer action (C28)
145
+
146
+ None required — every existing `variant`/`size` value keeps its meaning. If
147
+ your repo has its own button fork with extra sizes, it can now be deleted:
148
+ adopt `@ai-matrx/design-system`'s `Button` and re-point the call sites.
149
+
3
150
  ## 0.5.2 — 2026-09-07
4
151
 
5
152
  Two real source corrections, found by adopting 0.5.0 in the first two consumers
@@ -121,7 +268,7 @@ copy of something this version now ships:
121
268
  - **matrx-frontend** — `components/ui/{avatar,card,checkbox,collapsible,dialog,dropdown-menu,progress,scroll-area,switch,table,tabs,textarea}.tsx`
122
269
  and `components/ui/context-menu/context-menu.tsx`. High-fanout files become
123
270
  re-export shims that bind this repo's historical variant (`Card size="sm"`,
124
- `Switch size="sm"`, `Table size="sm"`), matching what the 08-30 swap
271
+ `Switch size="sm"`, `Checkbox size="sm"`, `Table size="sm"`), matching what the 08-30 swap
125
272
  established for `button` / `badge` / `label` / `separator`. The
126
273
  clipboard/motion variants (`CopyInput`, `FancyInput`, `DeleteInput`,
127
274
  `CopyTextarea`, `FancyTextarea`) stay host-owned under the C8 split-out law.
package/README.md CHANGED
@@ -2,13 +2,17 @@
2
2
 
3
3
  The small, semantic UI foundation shared by AI Matrx React applications — primitives whose behavior and variants are identical across Vite and Next.js hosts.
4
4
 
5
- **Controls:** Button, Badge, Label, Separator, the Input family, the Textarea family, Checkbox, Switch, Avatar, Progress.
6
- **Surfaces:** Card, Table, Tabs, Collapsible, ScrollArea, Popover, Sheet, Dialog, BottomSheet + TabbedBottomSheet, Skeleton.
5
+ **Controls:** Button, Badge, Label, Separator, the Input family, the Textarea family, Checkbox, Switch, RadioGroup, Slider, Toggle + ToggleGroup, Avatar, Progress.
6
+ **Surfaces:** Card, Table, Tabs, Collapsible, ScrollArea, Popover, Tooltip, HoverCard, Sheet, Dialog, AlertDialog, Drawer, BottomSheet + TabbedBottomSheet, Alert, Resizable, Skeleton.
7
7
  **Menus:** DropdownMenu, ContextMenu, Command / CommandDialog, Select, CreatablePicker.
8
8
  **Composed:** EditableLabel, SegmentedControl, ScoreRing, OverflowToolbar.
9
- **Hooks + utilities:** `useScrollFade`, `useIsMobile`, `usePortalContainer`, `useDialogContainer`, `cn`.
9
+ **Hooks + utilities:** `useScrollFade`, `useIsMobile`, `usePortalContainer`, `useDialogContainer`, `useDrawerDirection`, `cn`.
10
10
 
11
- Where hosts had forked a primitive over DENSITY, density is a prop, not a fork: `Card size="sm|md|lg"`, `Table size="sm|md"`, `Switch`/`Avatar`/`Checkbox` `size`. It is declared once on the root and every section reads it from context, so a card cannot mix paddings.
11
+ **The Tooltip lives here, and only here.** `@ai-matrx/tap-target` used to ship its own copy; since design-system 0.7.0 / tap-target 0.2.0 it consumes this one and re-exports nothing.
12
+
13
+ Where hosts had forked a primitive over DENSITY, density is a prop, not a fork: `Card size="sm|md|lg"`, `Table size="sm|md"`, `Switch`/`Avatar`/`Checkbox`/`Slider`/`RadioGroup`/`Toggle` `size`, `ResizableHandle size="xs".."4xl"`. It is declared once on the root and every item reads it from context, so a card cannot mix paddings and a radio group cannot mix control sizes.
14
+
15
+ **Mobile is the Drawer's job.** `Drawer` owns the iOS rules every host was re-deriving — `dvh` never `vh`, `pb-safe`/`pt-safe` safe-area padding, a 44px grab-handle target, `DrawerBody` as the `flex-1 min-h-0` scroll shard — and `direction` makes a top/side drawer a prop rather than a fork. Every touch control (`Slider`, `RadioGroup`, `ResizableHandle`) carries an invisible 44px target on coarse pointers, with desktop density untouched.
12
16
 
13
17
  ```bash
14
18
  pnpm add @ai-matrx/design-system