@ai-matrx/design-system 0.3.1 → 0.4.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 +86 -0
- package/README.md +43 -4
- package/dist/index.cjs +18 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +18 -18
- package/dist/index.js.map +1 -1
- package/dist/styles.css +175 -0
- package/dist/theme.css +56 -0
- package/dist/tokens.css +156 -0
- package/package.json +7 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,91 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.0 — 2026-08-30
|
|
4
|
+
|
|
5
|
+
**The package ships its CSS.** Closes the C26 clause of the all-inclusive
|
|
6
|
+
retrofit row: the package shipped ZERO stylesheets while three host-owned CSS
|
|
7
|
+
contracts were required for its components to render correctly. Any consumer
|
|
8
|
+
that was not matrx-frontend got a broken scroll cue, an unstyled glass control,
|
|
9
|
+
a flat input, and desktop-density text inside a phone sheet.
|
|
10
|
+
|
|
11
|
+
New exports:
|
|
12
|
+
|
|
13
|
+
- **`./styles.css` — REQUIRED structural CSS.** Extracted from matrx-frontend
|
|
14
|
+
`app/globals.css` (the tap-target precedent): the `.matrx-scroll-fade`
|
|
15
|
+
mask geometry (`useScrollFade`), the `.matrx-mobile-sheet` mobile density
|
|
16
|
+
restatement (`TabbedBottomSheet`), `.matrx-glass-thin-border` (BottomSheet
|
|
17
|
+
chrome), `.pb-safe`, `.shadow-input`. Zero hardcoded colour — every colour
|
|
18
|
+
resolves from a token, asserted by test and by the tarball canary.
|
|
19
|
+
- **`./tokens.css` — DEFAULT token values.** A neutral, sensible default for
|
|
20
|
+
every token the components and the structural CSS read, light and dark, so
|
|
21
|
+
the package renders correctly UNTHEMED in a fresh app. Not a brand: values
|
|
22
|
+
are host-owned and every default sits in the `matrx-design-system-tokens`
|
|
23
|
+
layer so any host declaration wins.
|
|
24
|
+
- **`./theme.css` — optional Tailwind v4 registration.** Maps the semantic
|
|
25
|
+
colour utilities onto the tokens and registers the package build as a
|
|
26
|
+
`@source`, so a fresh Tailwind app is one `@import` from drop-in.
|
|
27
|
+
|
|
28
|
+
Colour sweep (hardcoded colour in components is banned):
|
|
29
|
+
|
|
30
|
+
- `Input` — `text-black dark:text-white` → `text-foreground`;
|
|
31
|
+
`placeholder:text-neutral-400` → `placeholder:text-muted-foreground` (the
|
|
32
|
+
paired `dark:placeholder-text-neutral-600` was a typo'd class that never
|
|
33
|
+
existed and is gone); `focus-visible:ring-neutral-400/600` →
|
|
34
|
+
`focus-visible:ring-ring`; the dark autofill fill-colour now follows
|
|
35
|
+
`--foreground`. The dark elevation `shadow-[0px_0px_1px_1px_var(--neutral-700)]`
|
|
36
|
+
referenced a token defined nowhere, so it computed to no shadow — replaced by
|
|
37
|
+
an honest `dark:shadow-none`, which renders identically.
|
|
38
|
+
- `Badge` — `info` variant `border-blue-200 bg-blue-100 text-blue-800` →
|
|
39
|
+
`border-info/30 bg-info/15 text-info`; `error` variant → the same
|
|
40
|
+
`destructive` tokens its twin variant already used.
|
|
41
|
+
- `ScoreRing` — `scoreRingColorClasses` / `scoreAccentBgClasses` now return
|
|
42
|
+
`success` / `warning` / `destructive` token classes instead of
|
|
43
|
+
`green-500` / `orange-500` / `red-500`.
|
|
44
|
+
- Overlay scrims and the glass sheet divider are tokens
|
|
45
|
+
(`--matrx-overlay-scrim`, `--matrx-overlay-scrim-soft`,
|
|
46
|
+
`--matrx-overlay-scrim-drawer`, `--matrx-sheet-divider`) instead of
|
|
47
|
+
`bg-black/80`, `bg-black/20 dark:bg-black/30`, an inline `rgba(0,0,0,0.08)`,
|
|
48
|
+
and `border-white/[0.06]`.
|
|
49
|
+
|
|
50
|
+
Gate: the tarball canary now asserts all three sheets ship at the exact paths
|
|
51
|
+
their exports point to, that `styles.css` carries each contract rule and no
|
|
52
|
+
hardcoded colour, and that `tokens.css` defaults every token in both themes.
|
|
53
|
+
A new `styles.test.ts` fails the build if a component ever references a bare
|
|
54
|
+
class with no shipped rule, reads a token with no default, or reintroduces a
|
|
55
|
+
palette colour.
|
|
56
|
+
|
|
57
|
+
### Consumer action
|
|
58
|
+
|
|
59
|
+
1. **Import the two sheets at your app root** (`styles.css` is required —
|
|
60
|
+
without it the scroll fade, glass chrome, safe-area padding and input
|
|
61
|
+
elevation are missing):
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
import "@ai-matrx/design-system/tokens.css";
|
|
65
|
+
import "@ai-matrx/design-system/styles.css";
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
2. **Declare the layer order once**, as the first line of your Tailwind/CSS
|
|
69
|
+
entry, so the package's default token values stay below your own:
|
|
70
|
+
|
|
71
|
+
```css
|
|
72
|
+
@layer matrx-design-system-tokens, matrx-design-system;
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
3. **Delete your host copies of the moved rules** — `.matrx-scroll-fade[…]`,
|
|
76
|
+
the `.matrx-mobile-sheet` block, `.matrx-glass-thin-border` (+ its
|
|
77
|
+
`:hover` / `:active` / `:has(> a:…)` states). They now ship in the package;
|
|
78
|
+
keeping both means two sources of truth. Rules that are members of a host
|
|
79
|
+
utility family (`.pb-safe` beside `pt-safe`/`mb-safe`/`mt-safe`) and
|
|
80
|
+
Tailwind-generated `.shadow-input` legitimately stay host-side — the
|
|
81
|
+
package versions sit in a lower layer and lose to them by design.
|
|
82
|
+
4. **If you consumed the ScoreRing colour helpers' return strings**, they are
|
|
83
|
+
now `text-success` / `text-warning` / `text-destructive` (and the `bg-`
|
|
84
|
+
twins). Define those semantic colours in your theme, or map them.
|
|
85
|
+
5. **A host that already maps the semantic colour vocabulary in its own
|
|
86
|
+
`@theme` does not need `theme.css`** — importing it would duplicate the
|
|
87
|
+
mapping.
|
|
88
|
+
|
|
3
89
|
## 0.3.1 — 2026-08-30
|
|
4
90
|
|
|
5
91
|
- `@ai-matrx/kit` is now a REAL dependency (`^0.7.3`) instead of a peer
|
package/README.md
CHANGED
|
@@ -13,18 +13,57 @@ import { Badge, Button } from "@ai-matrx/design-system";
|
|
|
13
13
|
<Badge variant="success">Ready</Badge>
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
The package intentionally does not ship product colors. Hosts define the normal Tailwind semantic tokens (`primary`, `background`, `border`, `muted`, `success`, and `warning`), so one component follows each product's theme without forking behavior. A few ported components additionally reference host-owned CSS contracts and degrade gracefully without them: the glass tokens/utilities used by the BottomSheet family, the `.matrx-scroll-fade` styling for `useScrollFade`, and the `shadow-input` utility.
|
|
17
|
-
|
|
18
16
|
Host-shaped systems are injected, never imported: wrap subtrees in `PortalContainerProvider` to point nested Popover portals at a dialog or popout body, and hand `OverflowToolbar` your menu and tooltip systems through its `renderOverflowMenu` / `renderTooltip` props. `@ai-matrx/kit` is a real dependency (installed automatically).
|
|
19
17
|
|
|
20
|
-
|
|
18
|
+
## Styling — the package ships its CSS, the host owns the values
|
|
19
|
+
|
|
20
|
+
The package is **opinionated about the token contract and ships every rule its
|
|
21
|
+
components need to work**; it is **not** opinionated about your colours.
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
// app root, once
|
|
25
|
+
import "@ai-matrx/design-system/tokens.css"; // default token VALUES — override these
|
|
26
|
+
import "@ai-matrx/design-system/styles.css"; // structural CSS — required
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
```css
|
|
30
|
+
/* your Tailwind/CSS entry — FIRST line, before @import "tailwindcss" */
|
|
31
|
+
@layer matrx-design-system-tokens, matrx-design-system;
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
- **`styles.css` (required)** — every rule the components need to render right:
|
|
35
|
+
the `.matrx-scroll-fade` mask geometry behind `useScrollFade`, the
|
|
36
|
+
`.matrx-mobile-sheet` density restatement `TabbedBottomSheet` sets, the
|
|
37
|
+
`.matrx-glass-thin-border` chrome, `.pb-safe`, `.shadow-input`. It hardcodes
|
|
38
|
+
no colour: every colour resolves from a token.
|
|
39
|
+
- **`tokens.css` (default values)** — a neutral, sensible default for every
|
|
40
|
+
token the package reads, in both themes, so a fresh app renders correctly
|
|
41
|
+
**unthemed**. This is not a brand.
|
|
42
|
+
- **`theme.css` (Tailwind v4 hosts, optional)** —
|
|
43
|
+
`@import "@ai-matrx/design-system/theme.css";` from your Tailwind entry maps
|
|
44
|
+
the semantic colour utilities (`bg-background`, `text-muted-foreground`, …)
|
|
45
|
+
onto those tokens and registers the package build as a scan source. A host
|
|
46
|
+
that already maps this vocabulary (matrx-frontend does, as a branded
|
|
47
|
+
superset) skips this file and keeps its own.
|
|
48
|
+
|
|
49
|
+
**Overriding with your brand.** Redeclare any token — `--primary`,
|
|
50
|
+
`--background`, the `--matrx-glass-*` material, the overlay scrims — anywhere
|
|
51
|
+
in your own CSS. The package defaults live in the
|
|
52
|
+
`matrx-design-system-tokens` layer, and the one-line `@layer` declaration
|
|
53
|
+
above puts that layer at the bottom of the cascade, so **any** host
|
|
54
|
+
declaration wins: layered or unlayered, before or after, whatever the
|
|
55
|
+
specificity. Declare the layer order once and the question never arises.
|
|
56
|
+
|
|
57
|
+
Tailwind CSS v4 ignores `node_modules` by default, so a host that does not
|
|
58
|
+
import `theme.css` still registers the package build beside its Tailwind
|
|
59
|
+
import:
|
|
21
60
|
|
|
22
61
|
```css
|
|
23
62
|
@import "tailwindcss";
|
|
24
63
|
@source "../node_modules/@ai-matrx/design-system/dist";
|
|
25
64
|
```
|
|
26
65
|
|
|
27
|
-
Workspace consumers point `@source` at `apps/shared/design-system/src`.
|
|
66
|
+
Workspace consumers point `@source` at `apps/shared/design-system/src`.
|
|
28
67
|
|
|
29
68
|
## Release gate
|
|
30
69
|
|
package/dist/index.cjs
CHANGED
|
@@ -122,8 +122,8 @@ var badgeVariants = (0, import_class_variance_authority.cva)(
|
|
|
122
122
|
outline: "border-border text-foreground",
|
|
123
123
|
success: "border-transparent bg-success/15 text-success",
|
|
124
124
|
warning: "border-transparent bg-warning/15 text-warning",
|
|
125
|
-
info: "border-
|
|
126
|
-
error: "border-transparent bg-
|
|
125
|
+
info: "border-info/30 bg-info/15 text-info",
|
|
126
|
+
error: "border-transparent bg-destructive/15 text-destructive",
|
|
127
127
|
neutral: "border-border bg-muted text-muted-foreground"
|
|
128
128
|
}
|
|
129
129
|
},
|
|
@@ -328,8 +328,8 @@ function BottomSheet({
|
|
|
328
328
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
329
329
|
import_vaul.Drawer.Overlay,
|
|
330
330
|
{
|
|
331
|
-
className: cn("fixed inset-0 z-50 bg-
|
|
332
|
-
style: { background: "
|
|
331
|
+
className: cn("fixed inset-0 z-50 bg-[var(--matrx-overlay-scrim)]", "fixed inset-0 z-50"),
|
|
332
|
+
style: { background: "var(--matrx-overlay-scrim-drawer)" }
|
|
333
333
|
}
|
|
334
334
|
),
|
|
335
335
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
@@ -406,7 +406,7 @@ function BottomSheetFooter({
|
|
|
406
406
|
"div",
|
|
407
407
|
{
|
|
408
408
|
className: cn(
|
|
409
|
-
"flex-shrink-0 px-4 py-3 pb-safe border-t border-
|
|
409
|
+
"flex-shrink-0 px-4 py-3 pb-safe border-t border-[var(--matrx-sheet-divider)]",
|
|
410
410
|
className
|
|
411
411
|
),
|
|
412
412
|
children
|
|
@@ -530,7 +530,7 @@ var CommandDialogContent = React5.forwardRef(({ className, children, container,
|
|
|
530
530
|
isModal ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
531
531
|
DialogPrimitive.Overlay,
|
|
532
532
|
{
|
|
533
|
-
className: "fixed inset-0 z-[10000] bg-
|
|
533
|
+
className: "fixed inset-0 z-[10000] bg-[var(--matrx-overlay-scrim-soft)] data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0"
|
|
534
534
|
}
|
|
535
535
|
) : null,
|
|
536
536
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
@@ -1124,14 +1124,14 @@ function EditableLabel({
|
|
|
1124
1124
|
var React7 = __toESM(require("react"), 1);
|
|
1125
1125
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
1126
1126
|
var getVariantStyles = (variant = "default") => {
|
|
1127
|
-
const baseStyles = `flex h-10 w-full border border-border bg-background text-
|
|
1128
|
-
file:text-sm file:font-medium placeholder:text-
|
|
1129
|
-
focus-visible:outline-none focus-visible:ring-[2px] focus-visible:ring-
|
|
1127
|
+
const baseStyles = `flex h-10 w-full border border-border bg-background text-foreground shadow-input rounded-md px-3 py-2 text-sm file:border-0 file:bg-transparent
|
|
1128
|
+
file:text-sm file:font-medium placeholder:text-muted-foreground
|
|
1129
|
+
focus-visible:outline-none focus-visible:ring-[2px] focus-visible:ring-ring
|
|
1130
1130
|
disabled:cursor-not-allowed disabled:opacity-50
|
|
1131
|
-
dark:shadow-
|
|
1131
|
+
dark:shadow-none
|
|
1132
1132
|
transition duration-400
|
|
1133
1133
|
[&:-webkit-autofill]:bg-background [&:-webkit-autofill]:shadow-[0_0_0_1000px_hsl(var(--background))_inset] [&:-webkit-autofill]:[caret-color:currentColor]
|
|
1134
|
-
dark:[&:-webkit-autofill]:shadow-[0_0_0_1000px_hsl(var(--background))_inset] dark:[&:-webkit-autofill]:[-webkit-text-fill-color:
|
|
1134
|
+
dark:[&:-webkit-autofill]:shadow-[0_0_0_1000px_hsl(var(--background))_inset] dark:[&:-webkit-autofill]:[-webkit-text-fill-color:hsl(var(--foreground))]
|
|
1135
1135
|
[&:-webkit-autofill:hover]:shadow-[0_0_0_1000px_hsl(var(--background))_inset] [&:-webkit-autofill:focus]:shadow-[0_0_0_1000px_hsl(var(--background))_inset]`;
|
|
1136
1136
|
switch (variant) {
|
|
1137
1137
|
case "destructive":
|
|
@@ -1410,15 +1410,15 @@ var DEFAULT_SCORE_THRESHOLDS = {
|
|
|
1410
1410
|
};
|
|
1411
1411
|
function scoreRingColorClasses(pct, thresholds = DEFAULT_SCORE_THRESHOLDS) {
|
|
1412
1412
|
if (pct === null) return "text-muted-foreground";
|
|
1413
|
-
if (pct >= thresholds.good) return "text-
|
|
1414
|
-
if (pct >= thresholds.warning) return "text-
|
|
1415
|
-
return "text-
|
|
1413
|
+
if (pct >= thresholds.good) return "text-success";
|
|
1414
|
+
if (pct >= thresholds.warning) return "text-warning";
|
|
1415
|
+
return "text-destructive";
|
|
1416
1416
|
}
|
|
1417
1417
|
function scoreAccentBgClasses(pct, thresholds = DEFAULT_SCORE_THRESHOLDS) {
|
|
1418
1418
|
if (pct === null) return "bg-muted-foreground/30";
|
|
1419
|
-
if (pct >= thresholds.good) return "bg-
|
|
1420
|
-
if (pct >= thresholds.warning) return "bg-
|
|
1421
|
-
return "bg-
|
|
1419
|
+
if (pct >= thresholds.good) return "bg-success";
|
|
1420
|
+
if (pct >= thresholds.warning) return "bg-warning";
|
|
1421
|
+
return "bg-destructive";
|
|
1422
1422
|
}
|
|
1423
1423
|
function ScoreRing({
|
|
1424
1424
|
pct,
|
|
@@ -1725,7 +1725,7 @@ var SheetOverlay = React12.forwardRef(({ className, ...props }, ref) => /* @__PU
|
|
|
1725
1725
|
SheetPrimitive.Overlay,
|
|
1726
1726
|
{
|
|
1727
1727
|
className: cn(
|
|
1728
|
-
"fixed inset-0 z-50 bg-
|
|
1728
|
+
"fixed inset-0 z-50 bg-[var(--matrx-overlay-scrim)] data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
1729
1729
|
className
|
|
1730
1730
|
),
|
|
1731
1731
|
...props,
|