@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/docs/components/badge.md
CHANGED
|
@@ -21,7 +21,7 @@ Non-interactive status pill — emphasis (solid or tint) crossed with meaning (b
|
|
|
21
21
|
| Prop | Type | Default | Notes |
|
|
22
22
|
| --- | --- | --- | --- |
|
|
23
23
|
| `variant` | `"solid" \| "solid-demo" \| "solid-neutral" \| "solid-success" \| "solid-fail" \| "solid-warning" \| "tint" \| "tint-demo" \| "tint-neutral" \| "tint-success" \| "tint-fail" \| "tint-warning"` | `"solid"` | Emphasis + meaning grid; brand is the unsuffixed default. |
|
|
24
|
-
| `size` | `"xs" \| "sm" \| "md" \| "lg"` | `"md"` | Heights 20 / 24 / 32 / 40. |
|
|
24
|
+
| `size` | `"xs" \| "sm" \| "md" \| "lg" \| "count"` | `"md"` | Heights 20 / 24 / 32 / 40. |
|
|
25
25
|
| `asChild` | `boolean` | `false` | Render onto a caller element. Badges are read-only markers — no hover states exist (interactive pills are Chips). |
|
|
26
26
|
|
|
27
27
|
The `glass` variant was removed (breaking change); there is no replacement — use `tint` on imagery-free surfaces.
|
|
@@ -46,11 +46,29 @@ import { Badge } from "@trading-game/design-intelligence-layer"
|
|
|
46
46
|
| `md` | 32px | `px-3 py-1` | 14/20 |
|
|
47
47
|
| `lg` | 40px | `px-4 py-1.5` | 16/24 |
|
|
48
48
|
|
|
49
|
+
### `count`
|
|
50
|
+
|
|
51
|
+
`size="count"` is a shape, not a step on the xs/sm/md/lg rail: an 18px disc whose minimum
|
|
52
|
+
width equals its height, so one digit is a circle and more digits grow it into a pill at the
|
|
53
|
+
same height. `tabular-nums` fixes the digit width, so a ticking count only resizes when the
|
|
54
|
+
number of digits changes, not on every update.
|
|
55
|
+
|
|
56
|
+
Conventions the caller owns, not the component: hide the badge at zero, and cap above 99 as
|
|
57
|
+
`99+`. Pinning it over other chrome needs a knockout ring in the colour of whatever is
|
|
58
|
+
behind it — Badge cannot know that, so the caller adds it:
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
<Badge aria-hidden size="count"
|
|
62
|
+
className="absolute -top-0.5 -right-0.5 ring-2 ring-background-primary-canvas">
|
|
63
|
+
{count > 99 ? "99+" : count}
|
|
64
|
+
</Badge>
|
|
65
|
+
```
|
|
66
|
+
|
|
49
67
|
## Tokens
|
|
50
68
|
|
|
51
69
|
**Colour (semantic):**
|
|
52
70
|
- Solid: `background-brand-default` + `text-on-brand-static`; `background-demo-solid`; `background-inverse-surface` + `text-prominent-inverse`; `background-success-solid` / `background-error-solid` / `background-warning-solid`, all with `text-on-status-static`.
|
|
53
|
-
- Tint:
|
|
71
|
+
- Tint: `background-brand-selected` + `text-brand-selected` (the theme-aware selection family, same recipe as Calendar's range band); `background-demo-default` + `text-demo-default`; `background-secondary-surface` + `text-prominent-default`; `background-success/error/warning-default` + matching `text-*` status tokens. All tints are borderless — the tinted fill alone carries the meaning.
|
|
54
72
|
- The `tint-demo` / `tint-success` / `tint-fail` / `tint-warning` fills are one family by construction: a light `-50` step in light, and the hue's base step at **24% over the canvas** in dark. `tint-demo` gained its dark override so it stops reading as a light chip beside Won/Lost/Pending; note ember's base step is 500, not 600, because it is a game accent rather than a status colour.
|
|
55
73
|
- Focus: `ring-focus-strong`.
|
|
56
74
|
|
|
@@ -59,8 +77,7 @@ import { Badge } from "@trading-game/design-intelligence-layer"
|
|
|
59
77
|
## Behaviour
|
|
60
78
|
|
|
61
79
|
- Status solids use the bright 600 fills with shared static white ink (`text-on-status-static`) — deliberately below AA on green and amber; a style call, not an oversight.
|
|
62
|
-
- `tint` (brand)
|
|
63
|
-
- `tint` (brand) is the one tint that stays light in dark, because `--background-brand-container` is a deliberately static icy panel shared with Calendar's selection. It sits outside the status/demo tint family on purpose.
|
|
80
|
+
- `tint` (brand) flips with the theme like every other tint: `blue-600 @ 10%` over white in light, `blue-400 @ 24%` over the canvas in dark, with `blue-200` ink. It was the last variant on the static `--background-brand-container`; that token now has no consumers.
|
|
64
81
|
- No hover states — badges are read-only markers; if it needs to be clickable, it's a [Chip](./chip.md).
|
|
65
82
|
- `rounded-full`, `border-transparent` on every variant — no outlines, no shadow.
|
|
66
83
|
|
package/docs/components/item.md
CHANGED
|
@@ -13,7 +13,7 @@ Generic list row — media, title/description, and actions in one flex shell, wi
|
|
|
13
13
|
|
|
14
14
|
- `ItemGroup` — `role="list"` column; auto-divider mode on by default. `data-slot="item-group"`, `data-divider`.
|
|
15
15
|
- `ItemSeparator` — manual hairline (`Separator`). `data-slot="item-separator"`.
|
|
16
|
-
- `Item` — the row (`rounded-
|
|
16
|
+
- `Item` — the row (`rounded-2xl`, transparent hairline border for state changes). `data-slot="item"`, `data-variant`, `data-size`.
|
|
17
17
|
- `ItemMedia` — leading icon/image slot; top-aligns itself when a description is present. `data-slot="item-media"`, `data-variant`.
|
|
18
18
|
- `ItemContent` — flex-1 column for title + description. `data-slot="item-content"`.
|
|
19
19
|
- `ItemTitle` — 14/medium/20 prominent ink. `data-slot="item-title"`.
|
|
@@ -27,13 +27,13 @@ Generic list row — media, title/description, and actions in one flex shell, wi
|
|
|
27
27
|
|
|
28
28
|
| Prop | Type | Default | Notes |
|
|
29
29
|
| --- | --- | --- | --- |
|
|
30
|
-
| `divider` | `boolean` | `true` | Draws a 1px `border-default-default` line (inset `inset-x-4`) after each non-last **default-variant** Item, in a 4px gap. `outline`/`muted` items are skipped so borders don't double. Pass `false` for flush stacks or manual `ItemSeparator`. |
|
|
30
|
+
| `divider` | `boolean` | `true` | Draws a 1px `border-default-default` line (inset `inset-x-4`) after each non-last **default-variant** Item, in a 4px gap. `outline`/`fill`/`muted` items are skipped so borders don't double. Pass `false` for flush stacks or manual `ItemSeparator`. |
|
|
31
31
|
|
|
32
32
|
### Item
|
|
33
33
|
|
|
34
34
|
| Prop | Type | Default | Notes |
|
|
35
35
|
| --- | --- | --- | --- |
|
|
36
|
-
| `variant` | `"default" \| "outline" \| "muted"` | `"default"` | default transparent; outline = hairline `border-border-default-default` + hover fill; muted = `bg-background-secondary-surface
|
|
36
|
+
| `variant` | `"default" \| "outline" \| "fill" \| "muted"` | `"default"` | default transparent; outline = hairline `border-border-default-default` + hover glaze, no fill; **fill** = solid `bg-background-primary-surface` + the same hairline, hover steps to `background-secondary-surface`; muted = `bg-background-secondary-surface`, no border. |
|
|
37
37
|
| `size` | `"default" \| "sm"` | `"default"` | default `gap-4 p-4`; sm `gap-2.5 px-4 py-3`. |
|
|
38
38
|
| `asChild` | `boolean` | `false` | Render as link/button via Radix Slot; anchors get `hover:bg-background-hover-default`. |
|
|
39
39
|
|
|
@@ -73,11 +73,29 @@ import { BellIcon } from "lucide-react"
|
|
|
73
73
|
</ItemGroup>
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
+
### Picking between `outline` and `fill`
|
|
77
|
+
|
|
78
|
+
Both draw the same hairline. They differ only on a **non-white** background:
|
|
79
|
+
|
|
80
|
+
- On a Card, Sheet or Popover they are identical at rest — pick either.
|
|
81
|
+
- On `background-primary-canvas` (a game screen, a ledger page), `outline` lets the canvas
|
|
82
|
+
show through and the row reads as part of the page. `fill` gives the row its own solid
|
|
83
|
+
plane — the wallet-ledger pattern, and the right default for trade lists.
|
|
84
|
+
|
|
85
|
+
Every variant sits on `rounded-2xl` (18px) — the card radius Card, Dialog and Popover use.
|
|
86
|
+
An Item is a content shell, not a menu row, so it takes the card corner rather than the
|
|
87
|
+
tighter `rounded-md` it used previously.
|
|
88
|
+
|
|
89
|
+
`fill` hover steps `primary-surface` -> `secondary-surface` rather than using the shared
|
|
90
|
+
`background-hover-default` glaze, which is translucent and would let the canvas through a
|
|
91
|
+
filled row instead of darkening it. The same override is repeated for `[a]:` because the
|
|
92
|
+
base link hover uses that glaze and outranks a plain `hover:` on an anchor.
|
|
93
|
+
|
|
76
94
|
## Tokens
|
|
77
95
|
|
|
78
96
|
**Colour (semantic):**
|
|
79
97
|
- title `text-text-prominent-default`; description `text-text-subtle-default` (links underline, hover `text-text-brand-selected`)
|
|
80
|
-
- outline: `border-border-default-default`, hover `bg-background-hover-default`; muted: `bg-background-secondary-surface`
|
|
98
|
+
- outline: `border-border-default-default`, hover `bg-background-hover-default`; fill: `bg-background-primary-surface` + `border-border-default-default`, hover `bg-background-secondary-surface`; muted: `bg-background-secondary-surface`
|
|
81
99
|
- group divider: `bg-border-default-default`
|
|
82
100
|
- focus: `border-ring-focus-default` + 3px `ring-ring-focus-strong` (control ring)
|
|
83
101
|
- icon media: `bg-background-secondary-surface` + `text-icon-prominent-default`
|
|
@@ -96,10 +114,10 @@ import { BellIcon } from "lucide-react"
|
|
|
96
114
|
|
|
97
115
|
**Do**
|
|
98
116
|
- Let `ItemGroup` draw dividers; only reach for `ItemSeparator` with `divider={false}`.
|
|
99
|
-
-
|
|
117
|
+
- Leave the radius alone — Item is `rounded-2xl` (18px), the card tier, not the 8px row tier.
|
|
100
118
|
- Use `asChild` with a real `<a>`/`<button>` when the whole row navigates.
|
|
101
119
|
|
|
102
120
|
**Don't**
|
|
103
|
-
- Don't mix `variant="outline"` items into a dividered group expecting dividers — they are deliberately skipped.
|
|
121
|
+
- Don't mix `variant="outline"` or `variant="fill"` items into a dividered group expecting dividers — they are deliberately skipped.
|
|
104
122
|
- Don't push the title past medium 500; row titles never reach semibold, and bold does not exist in components.
|
|
105
|
-
- Don't add shadows to muted/outline rows; state is shown by fill and hairline only.
|
|
123
|
+
- Don't add shadows to muted/outline/fill rows; state is shown by fill and hairline only.
|
|
@@ -53,7 +53,7 @@ All scales run 50→1000 (mono 50→1200; blue adds 25 and 1000 as the two canva
|
|
|
53
53
|
| `background-brand-hover` | black 16% over brand | (same recipe, re-derives) | Primary button hover — a state layer, not a scale step |
|
|
54
54
|
| `background-brand-pressed` | black 32% over brand | (same recipe) | Primary button pressed |
|
|
55
55
|
| `background-brand-selected` | blue-600 10% over white ≈ `#E9E9FF` | blue-400 24% over canvas ≈ `#121A55` | Selected/active fills: active nav row, current page, checked choice card |
|
|
56
|
-
| `background-brand-container` | white 92% glaze over blue-600 (layered) | static — same | The icy brand panel
|
|
56
|
+
| `background-brand-container` | white 92% glaze over blue-600 (layered) | static — same | The icy brand panel. **No current consumers** — Calendar's range band and Badge `tint` both moved to `background-brand-selected` because a static value cannot carry dark. Retained for the v1.0 sweep. **Layered value — paint with `background:`, never `bg-*`** |
|
|
57
57
|
| `background-inverse-surface` | mono-1100 `#1C1C1C` | mono-50 `#FFFFFF` | The flipped surface (tooltips, toasts) |
|
|
58
58
|
| `background-overlay-default` | black-alpha-50 | black-alpha-64 | Modal scrims |
|
|
59
59
|
| `background-success-default` | green-50 | green-600 24% over canvas | Status tint surface (Section Message) |
|
|
@@ -80,7 +80,7 @@ All scales run 50→1000 (mono 50→1200; blue adds 25 and 1000 as the two canva
|
|
|
80
80
|
| `text-on-brand-static` | mono-50 | static | White text on brand fills — never flips |
|
|
81
81
|
| `text-on-brand-subtle-static` | white-alpha-64 | static | Secondary copy on a brand fill. On brand the ladder **inverts** — it descends from white through the alpha rungs instead of climbing the mono ramp (3.8:1 on blue-600, 2.7:1 on blue-400) |
|
|
82
82
|
| `text-on-brand-disabled-default` | white-alpha-32 | white-alpha-24 | Disabled ink on a brand fill — 1.8:1 over blue-600, 1.5:1 over blue-400. **Not static**, unlike the rest of the on-brand family: the fill itself flips blue-600 → blue-400, and blue-400 caps white at 4.3:1, so the rung comes down with it. Replaces the `opacity-24` wash on on-brand variants |
|
|
83
|
-
| `text-brand-container-static` | blue-600 | static |
|
|
83
|
+
| `text-brand-container-static` | blue-600 | static | Brand ink on a **static white** surface — Button `on-brand`, Toast's action button, Input selection. Still in use; do not retire with `background-brand-container` |
|
|
84
84
|
| `text-static-black` | mono-1100 | static | Ink on `background-static-white` |
|
|
85
85
|
| `text-success-default` / `-error-` / `-warning-` / `-information-` | status 600 | **static — same in both themes** (deliberate call) | Status text |
|
|
86
86
|
| `text-on-status-static` | mono-50 | static | White on solid status fills (below AA on green/amber — deliberate style call) |
|
|
@@ -109,7 +109,7 @@ Several values are **recipes, not scale steps** — a solid base with a fixed la
|
|
|
109
109
|
- **State layers**: hover = black 16% / pressed = black 32% mixed over the brand fill (`color-mix`), so any brand colour derives its own states.
|
|
110
110
|
- **Dark surfaces**: white 6% / 12% mixed over the dark canvas — solid results, no translucency.
|
|
111
111
|
- **Dark status tints**: status-600 at 24% mixed over the canvas — solid.
|
|
112
|
-
- **Brand container**: a real two-layer paint (white 92% glaze over blue-600) — consume via `background: var(--background-brand-container)`.
|
|
112
|
+
- **Brand container**: a real two-layer paint (white 92% glaze over blue-600) — consume via `background: var(--background-brand-container)`. Nothing consumes it today: it is static by construction, so anything needing a brand tint that survives dark takes `background-brand-selected` instead.
|
|
113
113
|
- **On-brand sunken fields** (Input/InputGroup `variant="on-brand"`): `black-alpha-32` glaze fill + `white-alpha-24` border over whatever brand colour the consumer painted.
|
|
114
114
|
- **Glass** (Button/NavigationButton `glass`, Card `glass`): `white-alpha-24` fill + border + `backdrop-blur-md`; hover 32, press 16. Theme-independent.
|
|
115
115
|
|
|
@@ -24,9 +24,9 @@ Radius encodes the element's *class*, not taste:
|
|
|
24
24
|
|---|---|---|
|
|
25
25
|
| Actions — buttons, chips, pills, toggle pills | `rounded-full` | Button, Chip, Pagination cells, Bottom Navigation, badges, glass circles |
|
|
26
26
|
| Icon buttons | circles (`rounded-full` on a square) | Navigation Button, Button icon sizes, Input Group icon buttons |
|
|
27
|
-
| Cards & panels | `rounded-2xl` = **18px** | Card, Dialog, Alert Dialog, Popover, Hover Card, Empty shell, Drawer's attached edge (`rounded-t-2xl`) |
|
|
27
|
+
| Cards & panels | `rounded-2xl` = **18px** | Card, Dialog, Alert Dialog, Popover, Hover Card, Empty shell, **Item** (every variant — a content shell, not a menu row), Drawer's attached edge (`rounded-t-2xl`) |
|
|
28
28
|
| Menus & floating lists | `rounded-lg` = **10px** | Dropdown/Context/Menubar/Select panels, Menubar bar, Navigation Menu viewport |
|
|
29
|
-
| Rows inside menus/lists | `rounded-md` = **8px** | Menu items,
|
|
29
|
+
| Rows inside menus/lists | `rounded-md` = **8px** | Menu items, Tabs triggers, Sidebar rows, Numpad keys |
|
|
30
30
|
| Form fields | `rounded-xs` = **4px** — deliberate, unchanged | Input, Textarea, Native Select, Input Group frame, OTP slot end caps — the whole text-entry family |
|
|
31
31
|
| Checkboxes | `rounded-2xs` | Checkbox |
|
|
32
32
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# trading.game — Brand voice
|
|
2
2
|
|
|
3
|
-
**Version:** 2.
|
|
3
|
+
**Version:** 2.1 · September 2026
|
|
4
4
|
**Adds:** Channel-specific voice application per persona mode; anti-AI writing rules for all copy
|
|
5
5
|
|
|
6
6
|
---
|
|
@@ -106,7 +106,7 @@ The tone is not the same for all three modes. Edge Seekers respond to validation
|
|
|
106
106
|
Give them something to be early on. Frame the product as a read, not a game.
|
|
107
107
|
|
|
108
108
|
> "Vol 100 has been oscillating inside a 12-point range for three sessions.
|
|
109
|
-
> Rise
|
|
109
|
+
> Rise-Fall is pricing that in. If you've been watching it, now's the time."
|
|
110
110
|
|
|
111
111
|
> "The fastest feedback loop on a market read.
|
|
112
112
|
> Five ticks. Real price data. No waiting for a daily close."
|
|
@@ -163,7 +163,7 @@ Subject lines that work are different by mode:
|
|
|
163
163
|
|
|
164
164
|
**Edge Seeker:**
|
|
165
165
|
- "Your read on V_100 paid out."
|
|
166
|
-
- "Rise
|
|
166
|
+
- "Rise-Fall is running on Vol 200. Your call."
|
|
167
167
|
- "The chart moved where you said it would."
|
|
168
168
|
|
|
169
169
|
**System Runner:**
|
|
@@ -228,7 +228,7 @@ State the thing. Then the implication for the player. Don't lead with your feeli
|
|
|
228
228
|
|
|
229
229
|
| ✅ | ❌ |
|
|
230
230
|
|---|---|
|
|
231
|
-
| "Rise
|
|
231
|
+
| "Rise-Fall now runs on V_200. Higher vol, wider payout range. Check the multiplier before you trade." | "We're excited to announce an exciting new instrument! Amazing opportunity for all traders!" |
|
|
232
232
|
| "Digits is live. Tick-based prediction on the last digit of a price feed. 1–10 ticks, six contract types." | "Introducing Digits, our innovative new game that revolutionises the prediction experience!" |
|
|
233
233
|
| "Withdrawal processing is now instant. Not 'faster.' Instant." | "We've made some improvements to our withdrawal process for a more seamless experience." |
|
|
234
234
|
|
|
@@ -266,9 +266,9 @@ The other difference: HyperSwap assumes DeFi fluency. We can't. Some players hav
|
|
|
266
266
|
|
|
267
267
|
| HyperSwap register | trading.game register |
|
|
268
268
|
|---|---|
|
|
269
|
-
| "SWAP Genesis is live. Early believers get rewarded 🔥" | "Rise
|
|
269
|
+
| "SWAP Genesis is live. Early believers get rewarded 🔥" | "Rise-Fall is live on V_100. Edge is 2%. The rest is skill." |
|
|
270
270
|
| "Swappies, the airdrop is coming 🚀" | "Your win rate this week: 54%. Baseline is 50%. You're ahead." |
|
|
271
|
-
| "Earn boosted rewards for LPs 💰" | "Transferred 20 USDT to
|
|
271
|
+
| "Earn boosted rewards for LPs 💰" | "Transferred 20 USDT to Box-O. Your capital, your call." |
|
|
272
272
|
|
|
273
273
|
---
|
|
274
274
|
|
|
@@ -292,11 +292,10 @@ The other difference: HyperSwap assumes DeFi fluency. We can't. Some players hav
|
|
|
292
292
|
|
|
293
293
|
| Correct | Not |
|
|
294
294
|
|---|---|
|
|
295
|
-
| Rise & Fall
|
|
296
|
-
|
|
|
297
|
-
| Swipe Cards
|
|
295
|
+
| Rise-Fall | Rise & Fall / Rise and Fall / Rise/Fall |
|
|
296
|
+
| Box-O | BoxO / Box O / GridRush |
|
|
297
|
+
| Swipe | Swipe Cards / Swipe-Cards / SwipeCards |
|
|
298
298
|
| Digits | The Digits game |
|
|
299
|
-
| Dice | The Dice game |
|
|
300
299
|
|
|
301
300
|
### Formatting
|
|
302
301
|
|
|
@@ -322,4 +321,4 @@ Before publishing anything:
|
|
|
322
321
|
|
|
323
322
|
---
|
|
324
323
|
|
|
325
|
-
*trading.game Brand Voice — v2.
|
|
324
|
+
*trading.game Brand Voice — v2.1*
|
package/package.json
CHANGED
|
@@ -1,366 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Enforce correct usage of the @trading-game/design-intelligence-layer npm package. Apply whenever building UI in a project that has the package installed — before writing any component, layout, or styled element.
|
|
3
|
-
globs: ["**/*.tsx", "**/*.jsx", "**/*.ts", "**/*.css"]
|
|
4
|
-
alwaysApply: true
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# @trading-game/design-intelligence-layer — AI Agent Usage Rules
|
|
8
|
-
|
|
9
|
-
## Rule 1 — Check the package before writing any custom UI
|
|
10
|
-
|
|
11
|
-
**BEFORE** writing any `<div>`, `<button>`, `<span>`, or other element styled with Tailwind classes, you MUST check if a component already exists in `@trading-game/design-intelligence-layer`.
|
|
12
|
-
|
|
13
|
-
### Available components (check this list first)
|
|
14
|
-
|
|
15
|
-
Accordion, Alert, AlertDialog, AspectRatio, Avatar, AvatarGroup, Badge, **Banner**, Breadcrumb, Button, Calendar, Card, Carousel, Chart, Checkbox, **Chip**, Collapsible, Combobox, Command, ContextMenu, Dialog, Direction, Drawer, DropdownMenu, Empty, Field, Form, HoverCard, Input, InputGroup, InputOTP, Item, Kbd, Label, **Link**, Menubar, NativeSelect, NavigationButton, NavigationMenu, Pagination, Popover, Progress, RadioGroup, Resizable, ScrollArea, Select, Separator, Sheet, Sidebar, Skeleton, Slider, Spinner, **Stepper**, Switch, Table, Tabs, Textarea, **TicketCard / CreditTicketCard**, Toast/Toaster, **ResultSnackbar**, Toggle, ToggleGroup, Tooltip
|
|
16
|
-
|
|
17
|
-
### Decision flow
|
|
18
|
-
|
|
19
|
-
```
|
|
20
|
-
Does a component exist in the list above?
|
|
21
|
-
YES → Import it from @trading-game/design-intelligence-layer. Do NOT re-implement it.
|
|
22
|
-
NO → STOP. Tell the user:
|
|
23
|
-
"The [ComponentName] component does not exist in @trading-game/design-intelligence-layer.
|
|
24
|
-
Options:
|
|
25
|
-
(a) Build a custom one using design system tokens only
|
|
26
|
-
(b) Use a different existing component
|
|
27
|
-
(c) Skip this component"
|
|
28
|
-
Wait for user to choose. Do NOT proceed without confirmation.
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
### Correct import pattern
|
|
32
|
-
|
|
33
|
-
```tsx
|
|
34
|
-
import { Button, Card, Badge } from "@trading-game/design-intelligence-layer"
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
---
|
|
38
|
-
|
|
39
|
-
## Rule 2 — Token-only rule (applies to ALL code, including approved custom builds)
|
|
40
|
-
|
|
41
|
-
### Never use
|
|
42
|
-
|
|
43
|
-
```
|
|
44
|
-
❌ Hardcoded hex: #2323FF, #000000, rgba(0,0,0,0.5)
|
|
45
|
-
❌ Raw Tailwind palette: bg-gray-100, text-zinc-500, text-slate-400, bg-black, bg-white
|
|
46
|
-
❌ Arbitrary color: bg-[#EEEEEE], text-[rgba(35,35,255,0.1)]
|
|
47
|
-
❌ Raw CSS var: bg-[var(--border-subtle)] ← NEVER do this
|
|
48
|
-
❌ hsl(var()) syntax: hsl(var(--primary)) ← this is Tailwind v3, not v4
|
|
49
|
-
❌ Raw opacity on non-tokens: bg-black/50
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
### Always use semantic token classes
|
|
53
|
-
|
|
54
|
-
#### Background tokens
|
|
55
|
-
```
|
|
56
|
-
✅ bg-prominent — page background (white #FFFFFF)
|
|
57
|
-
✅ bg-card — card/panel surface (white #FFFFFF)
|
|
58
|
-
✅ bg-popover — popover/dropdown surface (white #FFFFFF)
|
|
59
|
-
✅ bg-subtle — subtle tinted surface (#F5F5F5)
|
|
60
|
-
✅ bg-overlay — modal/dialog backdrop (black 50%) — ONLY for overlays
|
|
61
|
-
✅ bg-primary — brand blue #2323FF — CTAs and primary actions
|
|
62
|
-
✅ bg-primary-hover — darker blue #0B0BD2 — primary button hover
|
|
63
|
-
✅ bg-primary-inverse — white surface for use on dark/coloured areas
|
|
64
|
-
✅ bg-prominent-inverse — dark surface for use on light pages (toasts, etc.)
|
|
65
|
-
✅ bg-secondary-hover — light grey #EEEEEE — outline/secondary button hover
|
|
66
|
-
✅ bg-semantic-win — green — profit/positive
|
|
67
|
-
✅ bg-semantic-loss — red — loss/negative
|
|
68
|
-
✅ bg-semantic-warning — orange — warning/caution
|
|
69
|
-
✅ bg-semantic-boost — amber-orange #F9840F — boost/bonus badge (tinted: bg-semantic-boost/16)
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
#### Text tokens — paired with a surface
|
|
73
|
-
|
|
74
|
-
> Convention: `bg-<surface>` always has a paired `text-on-<surface>` foreground. Use them together for guaranteed legibility.
|
|
75
|
-
|
|
76
|
-
```
|
|
77
|
-
✅ text-on-prominent — paired with bg-prominent (black #000000) — default body text
|
|
78
|
-
✅ text-on-prominent-inverse — paired with bg-prominent-inverse (white) — toast text, etc.
|
|
79
|
-
✅ text-on-primary — paired with bg-primary (white) — primary button label, tooltip text
|
|
80
|
-
✅ text-on-primary-inverse — paired with bg-primary-inverse (blue) — primary-inverse button label
|
|
81
|
-
✅ text-on-semantic-win — paired with bg-semantic-win (white)
|
|
82
|
-
✅ text-on-semantic-loss — paired with bg-semantic-loss (white)
|
|
83
|
-
✅ text-on-semantic-warning — paired with bg-semantic-warning (white)
|
|
84
|
-
✅ text-on-semantic-boost — paired with bg-semantic-boost (dark amber #713813)
|
|
85
|
-
✅ text-on-subtle — secondary text (aliases text-subtle-default: mono-800 #717171 light / mono-600 #AAAAAA dark)
|
|
86
|
-
✅ text-on-disabled — disabled / inactive text (aliases text-disabled-default: mono-400 #C6C6C6 light / mono-900 #555555 dark)
|
|
87
|
-
|
|
88
|
-
✅ text-primary — brand blue #2323FF — inline brand text over neutral surfaces
|
|
89
|
-
✅ text-semantic-win — green — profit/positive inline text
|
|
90
|
-
✅ text-semantic-loss — red — loss/negative inline text
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
> ⚠️ **Deprecated:** `text-on-prominent-static-inverse` still works (aliased to `--on-prominent-inverse`) but new code should pick the explicit `text-on-<surface>` for whatever background sits behind the text.
|
|
94
|
-
|
|
95
|
-
#### Border tokens
|
|
96
|
-
```
|
|
97
|
-
✅ border-border-subtle — light grey #EEEEEE — default UI borders, dividers, cards
|
|
98
|
-
✅ border-border-prominent — pure black #000000 — outline variant components
|
|
99
|
-
✅ border-border — @deprecated alias for border-subtle (still works, prefer border-border-subtle)
|
|
100
|
-
✅ border-input — input field borders (same value as border-subtle)
|
|
101
|
-
✅ ring-ring — focus ring (blue #2323FF)
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
#### Opacity on a token is fine
|
|
105
|
-
```
|
|
106
|
-
✅ bg-primary/20, border-border-subtle/50, ring-ring/10
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
---
|
|
110
|
-
|
|
111
|
-
## Rule 3 — Layout utilities are exempt
|
|
112
|
-
|
|
113
|
-
Structural Tailwind utilities are freely usable without token rules:
|
|
114
|
-
|
|
115
|
-
```
|
|
116
|
-
✅ flex, grid, gap-4, p-6, m-2, w-full, h-screen, max-w-lg
|
|
117
|
-
✅ z-50, overflow-hidden, opacity-50, transition-all
|
|
118
|
-
✅ col-span-2, items-center, justify-between
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
Token rules apply **only** to: color (bg, text, border, ring, shadow color), border radius, and font family.
|
|
122
|
-
|
|
123
|
-
---
|
|
124
|
-
|
|
125
|
-
## Rule 3.5 — Typography: use the type scale, never hand-written sizes
|
|
126
|
-
|
|
127
|
-
**MANDATORY decision procedure for ANY text you render.** Do not choose font sizes. Every piece of text gets its size, line-height, and weight from one of the 13 scale classes below — this is what keeps every screen's hierarchy identical.
|
|
128
|
-
|
|
129
|
-
### Step 1 — Is there a component for it?
|
|
130
|
-
|
|
131
|
-
If the text lives in a component slot, USE THE COMPONENT — every component carries its own typography internally (via private component tokens or a built-in scale class):
|
|
132
|
-
`DialogTitle` / `AlertDialogTitle` / `SheetTitle` / `DrawerTitle` / `EmptyTitle`, `CardTitle`, every `*Description` slot, `Label` / `FieldLabel` / `FieldTitle` / `ItemTitle`, `AccordionTrigger` / `AccordionContent`, `Button` — never hand-style any component's text.
|
|
133
|
-
|
|
134
|
-
### Step 2 — Freeform text: pick from the scale
|
|
135
|
-
|
|
136
|
-
| Class | Size / line | Weight | Use for |
|
|
137
|
-
| ------------ | ----------- | ------------- | ------------------------------------------------------ |
|
|
138
|
-
| `display` | 36→56 fluid | ExtraBold 800 | Hero statement on a landing/marketing page |
|
|
139
|
-
| `h1` | 30→40 fluid | Bold 700 | The single main title of a page/screen (ONE per page) |
|
|
140
|
-
| `h2` | 26→32 fluid | Bold 700 | A major section heading |
|
|
141
|
-
| `h3` | 22→24 fluid | SemiBold 600 | A sub-group heading inside a section |
|
|
142
|
-
| `h4` | 20 / 28 | SemiBold 600 | A dashboard panel / large feature-card header |
|
|
143
|
-
| `h5` | 18 / 24 | SemiBold 600 | Dialog, sheet, and drawer titles (freeform) |
|
|
144
|
-
| `h6` | 16 / 24 | SemiBold 600 | A card / compact panel title (freeform) |
|
|
145
|
-
| `body-lg` | 18 / 28 | Regular 400 | Intro / lead paragraph |
|
|
146
|
-
| `body-md` | 16 / 24 | Regular 400 | Default body text |
|
|
147
|
-
| `body-sm` | 14 / 20 | Regular 400 | Description under a title, helper copy |
|
|
148
|
-
| `label-text` | 14 / 20 | Medium 500 | Form label, list-item title, table header (freeform) |
|
|
149
|
-
| `caption` | 12 / 16 | Medium 500 | Metadata, timestamps, fine print |
|
|
150
|
-
| `overline` | 12 / 16 | SemiBold 600 | Eyebrow above a heading, tag (uppercases itself) |
|
|
151
|
-
|
|
152
|
-
**`h1`–`h6` are STYLE names, not HTML tags.** Put the class on whatever element the document outline needs — `<h2 className="h4">` is correct and normal when heading level and visual size legitimately differ. Never let the class name pick the tag for you.
|
|
153
|
-
|
|
154
|
-
```tsx
|
|
155
|
-
✅ <h1 className="h1 text-on-prominent">Account settings</h1>
|
|
156
|
-
✅ <h2 className="h2 text-on-prominent">Security</h2>
|
|
157
|
-
✅ <p className="body-sm text-on-subtle">Manage your sign-in methods.</p>
|
|
158
|
-
✅ <span className="overline text-primary">New</span> {/* uppercases itself */}
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
### Hard rules
|
|
162
|
-
```
|
|
163
|
-
❌ NEVER hand-build titles/body from utilities (text-2xl font-bold tracking-tight, text-[13px]…)
|
|
164
|
-
❌ NEVER uppercase a heading — the system is sentence-case; only `overline` uppercases (automatically)
|
|
165
|
-
❌ NEVER add responsive size overrides (md:text-*, sm:text-*) to a scale class — display and
|
|
166
|
-
h1–h3 already scale desktop→mobile via their tokens. A class NEVER changes between
|
|
167
|
-
breakpoints: h2 on desktop is h2 on mobile.
|
|
168
|
-
❌ NEVER use more than one h1 per page; never skip more than one hierarchy level
|
|
169
|
-
❌ NEVER tweak a scale class with utilities (h5 font-medium does nothing — scale classes are
|
|
170
|
-
unlayered CSS and beat utilities). Need something different? Use a different class.
|
|
171
|
-
✅ Emphasis inside body text: <b>/<span> + font-semibold on that span — never a bigger size
|
|
172
|
-
✅ Numeric data displays (P&L, balances) are the accepted exception: bespoke size + tabular-nums
|
|
173
|
-
✅ A SMALLER class passed via className overrides a component's built-in one (stylesheet is
|
|
174
|
-
ordered largest→smallest), e.g. <EmptyTitle className="h6"> for compact contexts
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
> Naming notes: `overline` is also a Tailwind text-decoration utility — the package's class wins and clears the line. The label class is `label-text` (not `label`) to avoid confusion with the `Label` component.
|
|
178
|
-
|
|
179
|
-
---
|
|
180
|
-
|
|
181
|
-
## Rule 3.6 — Result Snackbar is for a settled game result, and nothing else
|
|
182
|
-
|
|
183
|
-
`ResultSnackbar` exists for exactly one thing: reporting a **settled contract the player was not watching** — a win or a loss, with its figure.
|
|
184
|
-
|
|
185
|
-
```
|
|
186
|
-
Did a contract just settle, win or loss, off-screen?
|
|
187
|
-
YES → ResultSnackbar
|
|
188
|
-
NO → toast(...) // everything else
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
Use `toast(...)` — never `ResultSnackbar` — for:
|
|
192
|
-
|
|
193
|
-
- **Refunds.** Nothing was won or lost, so there is no figure to report. A refund is a non-event.
|
|
194
|
-
- **Trade rejections, live payout warnings, connection problems**, and every other notification.
|
|
195
|
-
- Anything that needs an **action** from the player. `ResultSnackbar` is pointer-transparent by design: it is a report, not a control.
|
|
196
|
-
|
|
197
|
-
And do not use it for the contract the player **was** watching as it ended — that gets the full-screen result moment. `ResultSnackbar` deliberately does not take the board.
|
|
198
|
-
|
|
199
|
-
It is never the surface of record either. Every result also lands in positions and history, which is where a player goes to study terms.
|
|
200
|
-
|
|
201
|
-
**Why the two look nothing alike:** that difference is intentional, not drift. `toast` is transient system messaging on the inverse surface. `ResultSnackbar` reports money: floating-chrome glass, an illustration, a signed figure in outcome ink, and a visible dwell timer. Do not "unify" them.
|
|
202
|
-
|
|
203
|
-
```tsx
|
|
204
|
-
import { ResultSnackbar } from "@trading-game/design-intelligence-layer"
|
|
205
|
-
|
|
206
|
-
<ResultSnackbar
|
|
207
|
-
outcome="win" // "win" | "loss" — the only two states
|
|
208
|
-
amount="+8.40" // pre-signed; use a true Unicode minus for losses
|
|
209
|
-
amountValue={8.4} // optional count-up target
|
|
210
|
-
currency="USDT"
|
|
211
|
-
contractLabel="Rise"
|
|
212
|
-
duration="15 seconds"
|
|
213
|
-
icon={<img src="/thumbs-up.webp" alt="" aria-hidden className="size-8" />}
|
|
214
|
-
onDismiss={advanceQueue} // fires once, after the exit finishes
|
|
215
|
-
className="absolute top-3 right-3" // placement is yours; anchor it to something meaningful
|
|
216
|
-
/>
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
Placement and queueing are the consumer's: the meaningful anchor differs per game, and deciding what waits, what is stale, and what replays after an interruption is product logic. The component shows one settlement and reports when it is done.
|
|
220
|
-
|
|
221
|
-
---
|
|
222
|
-
|
|
223
|
-
## Rule 4 — Do NOT install or configure these separately
|
|
224
|
-
|
|
225
|
-
```
|
|
226
|
-
❌ Do NOT install lucide-react — it is already bundled in the package
|
|
227
|
-
❌ Do NOT install tailwindcss separately — the package ships its own Tailwind v4 setup
|
|
228
|
-
❌ Do NOT add a tailwind.config.js — configuration is handled by the package
|
|
229
|
-
❌ Do NOT use @apply with hsl(var(--token)) — Tailwind v4 uses CSS variables directly
|
|
230
|
-
❌ Do NOT override font-family manually in CSS — use font-display and font-body utility classes
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
### Correct CSS setup in the consuming project
|
|
234
|
-
|
|
235
|
-
```css
|
|
236
|
-
@import "@trading-game/design-intelligence-layer/styles";
|
|
237
|
-
@import "tailwindcss";
|
|
238
|
-
@source "../node_modules/@trading-game/design-intelligence-layer/dist";
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
### Vite projects — required plugin
|
|
242
|
-
|
|
243
|
-
If the project uses Vite, `@tailwindcss/vite` MUST be in `vite.config.js`:
|
|
244
|
-
|
|
245
|
-
```js
|
|
246
|
-
import tailwindcss from '@tailwindcss/vite'
|
|
247
|
-
// plugins: [react(), tailwindcss()]
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
Without this, Tailwind CSS will not process any styles. Next.js projects do NOT need this.
|
|
251
|
-
|
|
252
|
-
---
|
|
253
|
-
|
|
254
|
-
## Rule 5 — Button and Badge variants
|
|
255
|
-
|
|
256
|
-
### Button variants
|
|
257
|
-
```tsx
|
|
258
|
-
// Light surfaces
|
|
259
|
-
<Button variant="primary" /> // Blue filled — main CTA
|
|
260
|
-
<Button variant="secondary" /> // Black outline — secondary actions
|
|
261
|
-
<Button variant="tertiary" /> // Text only — minimal
|
|
262
|
-
|
|
263
|
-
// Dark / coloured surfaces
|
|
264
|
-
<Button variant="primary-inverse" /> // White filled + blue text — main CTA on dark bg
|
|
265
|
-
<Button variant="secondary-inverse" /> // White outline + white text — secondary on dark bg
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
All variants support icon sizes — use `size="icon-lg|icon-md|icon-sm|icon-xs"` for icon-only buttons on any variant:
|
|
269
|
-
```tsx
|
|
270
|
-
<Button variant="primary-inverse" size="icon-md"><Bell /></Button>
|
|
271
|
-
<Button variant="secondary-inverse" size="icon-sm"><X /></Button>
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
### Badge variants
|
|
275
|
-
```tsx
|
|
276
|
-
// Solid
|
|
277
|
-
<Badge variant="default" /> // Blue solid
|
|
278
|
-
<Badge variant="standard" /> // Subtle grey solid
|
|
279
|
-
<Badge variant="default-success" /> // Green solid
|
|
280
|
-
<Badge variant="default-fail" /> // Red solid
|
|
281
|
-
<Badge variant="default-warning" /> // Orange solid
|
|
282
|
-
|
|
283
|
-
// Tint
|
|
284
|
-
<Badge variant="fill" /> // Blue tint bg
|
|
285
|
-
<Badge variant="fill-success" /> // Green tint bg
|
|
286
|
-
<Badge variant="fill-fail" /> // Red tint bg
|
|
287
|
-
<Badge variant="fill-warning" /> // Orange tint bg
|
|
288
|
-
<Badge variant="fill-credit" /> // Deep peach (#FDCA8A) + bold amber text — credit/boost (Welcome credit, bonus)
|
|
289
|
-
<Badge variant="fill-demo" /> // Peach + red-orange text — demo / test-mode indicator
|
|
290
|
-
|
|
291
|
-
// Outline (black border, hover grey)
|
|
292
|
-
<Badge variant="outline" />
|
|
293
|
-
|
|
294
|
-
// Ghost (transparent bg)
|
|
295
|
-
<Badge variant="ghost" />
|
|
296
|
-
<Badge variant="ghost-success" />
|
|
297
|
-
<Badge variant="ghost-fail" />
|
|
298
|
-
<Badge variant="ghost-warning" />
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
---
|
|
302
|
-
|
|
303
|
-
## Rule 6 — If in doubt, stop and ask
|
|
304
|
-
|
|
305
|
-
If you cannot find a token for a value you need, do NOT fall back to a hardcoded value.
|
|
306
|
-
|
|
307
|
-
Stop and tell the user:
|
|
308
|
-
```
|
|
309
|
-
"I need [value] for [element]. No design token exists for this.
|
|
310
|
-
Should I: (a) use a hardcoded value, or (b) skip this styling?"
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
Wait for confirmation before proceeding.
|
|
314
|
-
|
|
315
|
-
---
|
|
316
|
-
|
|
317
|
-
## Rule 8 — Blocks are first-class exports (import them by name)
|
|
318
|
-
|
|
319
|
-
**Blocks** are opinionated, composed UI sections — exported from `@trading-game/design-intelligence-layer` the same as primitives. Import by name and pass data via props. Variants live as a `layout` / `mode` / `status` prop on a single block, not as separate components.
|
|
320
|
-
|
|
321
|
-
```
|
|
322
|
-
✅ Import blocks directly from the package — same pattern as primitives
|
|
323
|
-
✅ Pass data via props; variants are configured via a single variant prop
|
|
324
|
-
✅ Block names ARE valid component names (treat them like Rule 1 components)
|
|
325
|
-
❌ Do NOT re-implement a block by hand if a block export already covers it
|
|
326
|
-
❌ Do NOT split variants into separate blocks — use the variant prop
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
| Block | Variants | Importable? |
|
|
330
|
-
|-------|----------|-------------|
|
|
331
|
-
| `HeroBlock` | `layout: "centered" \| "split"` | Yes — `import { HeroBlock }` |
|
|
332
|
-
| `AuthBlock` | `mode: "sign-in" \| "sign-up"` | Yes — `import { AuthBlock }` |
|
|
333
|
-
| `FAQBlock` | `layout: "desktop" \| "mobile"` | Yes — `import { FAQBlock }` |
|
|
334
|
-
| `NavBarBlock` | — (internal mobile-menu state) | Yes — `import { NavBarBlock }` |
|
|
335
|
-
| `HeaderNavigationBlock` | — (optional `history.count` badge) | Yes — `import { HeaderNavigationBlock }` |
|
|
336
|
-
| `OpenPositionsBlock` | `Position` discriminated union | Yes — `import { OpenPositionsBlock, type Position }` |
|
|
337
|
-
| `ResultBlock` | `status` + `ctaMode` | Yes — `import { ResultBlock }` |
|
|
338
|
-
| `ResultDialog` | — | Yes — `import { ResultDialog }` |
|
|
339
|
-
|
|
340
|
-
See `guides/design-system-guide/trading-game-ds-guide.md` § 8.5 for full per-block API, used components, and used tokens.
|
|
341
|
-
|
|
342
|
-
---
|
|
343
|
-
|
|
344
|
-
## Rule 7 — Package version upgrades (stay aligned with the published design system)
|
|
345
|
-
|
|
346
|
-
When the user asks to **update**, **upgrade**, or **install the latest** `@trading-game/design-intelligence-layer`, or after the dependency version changes in `package.json`:
|
|
347
|
-
|
|
348
|
-
### How updates actually apply
|
|
349
|
-
|
|
350
|
-
- If the project **imports components only** from `@trading-game/design-intelligence-layer`, new styles and behavior come from **`node_modules/.../dist`** after **`npm install` / `npm ci` and a dev or production build**. The package is the source of truth — no AI step is required for those imports to change.
|
|
351
|
-
- If the repo **contains copied or forked** files that mirror package components (e.g. a local `components/ui/button.tsx` with full implementation), **`npm install` does not update those files.** They stay stale until someone reconciles them.
|
|
352
|
-
|
|
353
|
-
### What you MUST do after a design-system version bump
|
|
354
|
-
|
|
355
|
-
1. **Search for local duplication** — Look for UI files that re-implement package exports (`components/ui/`, `@/components/ui`, etc.). Flag any file that is not a **thin re-export** or **documented wrapper** around the package.
|
|
356
|
-
2. **Reconcile** — Prefer **removing** duplicate implementations and **importing from the package**. If a fork must stay, align it with the **exact** current implementation in the installed package (or tag on GitHub) and document why it diverges (file name + reason).
|
|
357
|
-
3. **Notify on replace** — If you **delete, replace, or substantially overwrite** local component code to match the package, **stop and tell the user clearly**, e.g.
|
|
358
|
-
`Aligned [ComponentName] with @trading-game/design-intelligence-layer@[version]. Previous local behavior or classes: [short summary]. Re-apply needs via package variants/props, tokens, or a thin wrapper only if product requires it.`
|
|
359
|
-
4. **Review `className` overrides** — Parent apps often pass `className` on DS components. Old overrides (radius, colors, shadows) can **hide** new defaults (e.g. pill buttons). After upgrade, scan for overrides on DS components and trim or adjust them when they conflict with the new design.
|
|
360
|
-
5. **Refresh Cursor rules** — The package ships `guides/rules/design-system-consuming-project.mdc`. Cursor does **not** read it from `node_modules` automatically. Tell the user to re-copy it (see README **AI Agent Setup → Cursor**) so agent instructions match the release.
|
|
361
|
-
6. **Tailwind** — Confirm `@source` still points at `node_modules/@trading-game/design-intelligence-layer/dist` so Tailwind v4 emits classes from the updated bundle.
|
|
362
|
-
|
|
363
|
-
### Do not assume
|
|
364
|
-
|
|
365
|
-
- Do **not** assume `npm update` alone fixed forked files in the app repo.
|
|
366
|
-
- Do **not** silently delete user customizations — always report what was removed or replaced and offer a token-safe way to re-apply if needed.
|