@trading-game/design-intelligence-layer 1.0.7 → 1.1.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/AGENTS.md +3 -3
- package/dist/index.cjs +30 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +30 -7
- package/dist/index.js.map +1 -1
- package/docs/components/badge.md +21 -4
- package/docs/components/item.md +25 -7
- package/docs/foundations/colors.md +3 -3
- package/docs/foundations/shape-layout.md +2 -2
- package/guides/brand-voice/trading-game-brand-voice.md +10 -11
- package/package.json +1 -1
- package/guides/rules/design-system-consuming-project.mdc +0 -366
package/AGENTS.md
CHANGED
|
@@ -14,7 +14,7 @@ Rules of engagement for AI agents building with `@trading-game/design-intelligen
|
|
|
14
14
|
8. **Dark is not a mirror.** Never build a light-theme construction and assume it inverts. If a token pair doesn't exist for what you need, stop and ask — don't improvise per-theme values in a component.
|
|
15
15
|
9. **Typography via type classes.** Component text uses its `.type-<component>-*` class (backed by private `--<component>-*` tokens). No `text-sm`, no `text-[13px]`, no `font-bold`.
|
|
16
16
|
10. **`.type-*` classes are plain CSS, not utilities**: variants can't gate them (`data-[x]:type-foo` does nothing — pick the class in JSX or write a CSS data-attribute rule), and they beat layered `font-*` utilities.
|
|
17
|
-
11. **Radius encodes element class** — buttons/chips `rounded-full`, icon buttons circles, cards/dialogs `rounded-2xl`, menus `rounded-lg`, menu rows `rounded-md`, inputs `rounded-xs` (deliberate, don't "fix" it).
|
|
17
|
+
11. **Radius encodes element class** — buttons/chips `rounded-full`, icon buttons circles, cards/dialogs **and Item** `rounded-2xl`, menus `rounded-lg`, menu rows `rounded-md`, inputs `rounded-xs` (deliberate, don't "fix" it). `rounded-md` means a row *inside* a menu or list panel (menu items, Tabs triggers, Sidebar rows, Numpad keys). An `Item` is a content shell in its own right, so it takes the card corner — don't "correct" it back to 8px.
|
|
18
18
|
12. **Sizes sit on the 32/40/48 rail**, default `md` (40px). Button padding-x = height/2 − 4, gap 8, and padding never changes when icons are hidden.
|
|
19
19
|
13. **Disabled is chosen per variant and per theme.** There is no single rule; each cell is a deliberate decision and changing one must not disturb the others. The default construction is the token trio — `text-disabled-default` for ink, `background-disabled-default` for the surface, `border-disabled-default` for the edge — where the background token is a **glaze**, laid on `background-image` (`[background-image:linear-gradient(var(--background-disabled-default),var(--background-disabled-default))]`) so the variant's own fill stays underneath and each variant keeps its identity. Fill-less variants (`tertiary`, ghost rows, menu items) take the ink only. On-brand surfaces stay on the static white ladder with `text-on-brand-disabled-default`. **Sanctioned `opacity` exceptions**, by explicit decision (2026-09-09): Button `primary` in both themes and Button `secondary` in light take `opacity-(--opacity-disabled)` (24%); Button `secondary` in dark keeps full opacity and takes a black-24% glaze instead; Button `frosted` fades to `opacity-(--opacity-disabled-frosted)` (40%) in both themes, keeping its brand ink — 24% left almost nothing visible on a fill that is already only a 10–24% brand tint, so the strength is per-variant and lives in its own token. Button's `loading` also stays on `opacity-24`. Be aware of what element `opacity` costs: it dims a fill and the ink on top of it by the same factor, so their relationship collapses — the light disabled `primary` label lands at 1.14:1 on its own washed fill and is not readable. WCAG 1.4.3 exempts inactive controls, so this is a legibility trade accepted on purpose, not a compliance break. Do not extend `opacity` to other components without the same explicit decision.
|
|
20
20
|
14. **Focus** = `focus-visible:ring-[3px] focus-visible:ring-ring-focus-strong` (controls) or `ring-ring-focus-soft` (text fields). Error ring = `ring-ring-error-soft`. Every colour must be a plain named token — no alpha-modified constructions, no colour primitives outside the sanctioned glass-ladder set; `npm run check:tokens` enforces both and diffs the Colors page against styles.css.
|
|
@@ -48,7 +48,7 @@ Docs: `docs/components/<kebab-name>.md` for every entry.
|
|
|
48
48
|
| Alert Dialog | Blocking confirm/cancel decisions (destructive actions) |
|
|
49
49
|
| Aspect Ratio | Fixed-ratio media containers |
|
|
50
50
|
| Avatar | User images with fallback initials, groups, count overflow |
|
|
51
|
-
| Badge | Small status/category markers (solid
|
|
51
|
+
| Badge | Small status/category markers (`solid` / `tint` families, meaning as the suffix; status = 600 fills). `size="count"` is the 18px numeric disc — circle at one digit, pill beyond; caller owns zero-hiding, the 99+ cap and any knockout ring |
|
|
52
52
|
| Banner | Editorial gradient promo panel with art, copy, white pill CTA |
|
|
53
53
|
| Bottom Navigation | Mobile bottom nav, max 4 destinations (3 is the norm) — chrome frost bar, liquid selection bubble; the phone counterpart of Sidebar |
|
|
54
54
|
| Breadcrumb | Hierarchical location trail |
|
|
@@ -69,7 +69,7 @@ Docs: `docs/components/<kebab-name>.md` for every entry.
|
|
|
69
69
|
| Input | Single-line text field; sizes sm/md/lg; `on-brand` variant |
|
|
70
70
|
| Input Group | Things inside a field: prefix/suffix text, icons, pill buttons |
|
|
71
71
|
| Input OTP | Segmented one-time-code entry |
|
|
72
|
-
| Item | List rows with media/title/description/actions
|
|
72
|
+
| Item | List rows with media/title/description/actions. `default` transparent, `outline` hairline only, `fill` hairline + solid surface (the ledger pattern — use it on the page canvas, where `outline` lets the canvas through), `muted` secondary surface |
|
|
73
73
|
| Label | Form label (14/medium); colour inherits so Field error ink flows through |
|
|
74
74
|
| Link | Inline/standalone links — quiet at rest, underline + darker ink on hover; `tone="on-brand"` |
|
|
75
75
|
| Menubar | Horizontal app menu bar (menu family) |
|
package/dist/index.cjs
CHANGED
|
@@ -1269,9 +1269,11 @@ var badgeVariants = (0, import_class_variance_authority4.cva)(
|
|
|
1269
1269
|
"solid-fail": "bg-background-error-solid text-text-on-status-static",
|
|
1270
1270
|
"solid-warning": "bg-background-warning-solid text-text-on-status-static",
|
|
1271
1271
|
// Tint — the Section Message surface tokens, coloured foreground.
|
|
1272
|
-
// Brand tint
|
|
1273
|
-
//
|
|
1274
|
-
|
|
1272
|
+
// Brand tint rides `brand-selected`, the theme-aware selection
|
|
1273
|
+
// family, for the same reason Calendar's range band does: the
|
|
1274
|
+
// static `brand-container` is one value in both themes and sits
|
|
1275
|
+
// near-white on a dark surface.
|
|
1276
|
+
tint: "bg-background-brand-selected border-transparent text-text-brand-selected",
|
|
1275
1277
|
"tint-demo": "bg-background-demo-default border-transparent text-text-demo-default",
|
|
1276
1278
|
"tint-neutral": "bg-background-secondary-surface border-transparent text-text-prominent-default",
|
|
1277
1279
|
"tint-success": "bg-background-success-default border-transparent text-text-success-default",
|
|
@@ -1282,7 +1284,18 @@ var badgeVariants = (0, import_class_variance_authority4.cva)(
|
|
|
1282
1284
|
xs: "type-badge-xs h-5 px-2 py-0.5",
|
|
1283
1285
|
sm: "type-badge-sm h-6 px-2.5 py-0.5",
|
|
1284
1286
|
md: "type-badge-md h-8 px-3 py-1",
|
|
1285
|
-
lg: "type-badge-lg h-10 px-4 py-1.5"
|
|
1287
|
+
lg: "type-badge-lg h-10 px-4 py-1.5",
|
|
1288
|
+
/* `count` is a shape, not a step on the xs/sm/md/lg rail: an
|
|
1289
|
+
18px disc that grows into a pill as digits are added. The
|
|
1290
|
+
padding is deliberately tight (`px-1`): one digit then
|
|
1291
|
+
measures under the 18px min-width, so min-width wins and the
|
|
1292
|
+
disc is a true circle. Widen the padding and a single digit
|
|
1293
|
+
overshoots 18px, turning it back into an oval. `tabular-nums` keeps every digit
|
|
1294
|
+
the same width, so a ticking count only resizes when the
|
|
1295
|
+
digit count changes, not on every update. Callers that pin
|
|
1296
|
+
it over other chrome add their own knockout ring — Badge
|
|
1297
|
+
cannot know what sits behind it. */
|
|
1298
|
+
count: "type-badge-xs min-w-[1.125rem] h-[1.125rem] px-1 tabular-nums"
|
|
1286
1299
|
}
|
|
1287
1300
|
},
|
|
1288
1301
|
defaultVariants: {
|
|
@@ -4604,12 +4617,21 @@ function ItemSeparator(_a) {
|
|
|
4604
4617
|
);
|
|
4605
4618
|
}
|
|
4606
4619
|
var itemVariants = (0, import_class_variance_authority10.cva)(
|
|
4607
|
-
"group/item type-item-description flex flex-wrap items-center rounded-
|
|
4620
|
+
"group/item type-item-description flex flex-wrap items-center rounded-2xl border border-transparent transition-colors duration-instant outline-none focus-visible:border-ring-focus-default focus-visible:ring-[3px] focus-visible:ring-ring-focus-strong [a]:transition-colors [a]:hover:bg-background-hover-default",
|
|
4608
4621
|
{
|
|
4609
4622
|
variants: {
|
|
4610
4623
|
variant: {
|
|
4611
4624
|
default: "bg-transparent",
|
|
4612
4625
|
outline: "border-border-default-default text-text-prominent-default hover:bg-background-hover-default",
|
|
4626
|
+
/* `fill` is `outline` plus a solid surface: a bordered card that reads
|
|
4627
|
+
as its own plane on the page canvas, the wallet-ledger pattern.
|
|
4628
|
+
Its hover steps primary -> secondary surface like the default Chip,
|
|
4629
|
+
because the shared `background-hover-default` glaze is translucent —
|
|
4630
|
+
laid over a filled row it would let the canvas show through instead
|
|
4631
|
+
of darkening the fill. The `[a]:` rule repeats for the same reason:
|
|
4632
|
+
the base link hover is that same glaze and outranks a plain
|
|
4633
|
+
`hover:` on an anchor. */
|
|
4634
|
+
fill: "bg-background-primary-surface border-border-default-default text-text-prominent-default hover:bg-background-secondary-surface [a]:hover:bg-background-secondary-surface",
|
|
4613
4635
|
muted: "bg-background-secondary-surface"
|
|
4614
4636
|
},
|
|
4615
4637
|
size: {
|
|
@@ -8168,10 +8190,11 @@ function HistoryButton({
|
|
|
8168
8190
|
return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "relative inline-flex", children: [
|
|
8169
8191
|
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)(NavigationButton, { type: "button", size: "md", "aria-label": ariaLabel, onClick, children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(import_lucide_react30.History, { className: "size-5" }) }),
|
|
8170
8192
|
show && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
|
|
8171
|
-
|
|
8193
|
+
Badge,
|
|
8172
8194
|
{
|
|
8173
8195
|
"aria-hidden": true,
|
|
8174
|
-
|
|
8196
|
+
size: "count",
|
|
8197
|
+
className: "pointer-events-none absolute -top-0.5 -right-0.5 ring-2 ring-background-primary-canvas",
|
|
8175
8198
|
children: label
|
|
8176
8199
|
}
|
|
8177
8200
|
)
|