@trading-game/design-intelligence-layer 0.17.4 → 1.0.1
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 +105 -231
- package/README.md +50 -746
- package/dist/index.cjs +2753 -2986
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +247 -261
- package/dist/index.d.ts +247 -261
- package/dist/index.js +2648 -2856
- package/dist/index.js.map +1 -1
- package/docs/components/accordion.md +85 -0
- package/docs/components/alert-dialog.md +98 -0
- package/docs/components/aspect-ratio.md +55 -0
- package/docs/components/avatar.md +88 -0
- package/docs/components/badge.md +75 -0
- package/docs/components/banner.md +84 -0
- package/docs/components/bottom-navigation.md +90 -0
- package/docs/components/breadcrumb.md +85 -0
- package/docs/components/button.md +94 -0
- package/docs/components/calendar.md +74 -0
- package/docs/components/card.md +79 -0
- package/docs/components/carousel.md +82 -0
- package/docs/components/checkbox.md +66 -0
- package/docs/components/chip.md +72 -0
- package/docs/components/command.md +86 -0
- package/docs/components/context-menu.md +90 -0
- package/docs/components/dialog.md +95 -0
- package/docs/components/drawer.md +97 -0
- package/docs/components/dropdown-menu.md +92 -0
- package/docs/components/empty.md +87 -0
- package/docs/components/field.md +117 -0
- package/docs/components/hover-card.md +77 -0
- package/docs/components/input-group.md +105 -0
- package/docs/components/input-otp.md +87 -0
- package/docs/components/input.md +71 -0
- package/docs/components/item.md +105 -0
- package/docs/components/label.md +56 -0
- package/docs/components/link.md +66 -0
- package/docs/components/menubar.md +102 -0
- package/docs/components/native-select.md +71 -0
- package/docs/components/navigation-button.md +68 -0
- package/docs/components/navigation-menu.md +99 -0
- package/docs/components/numpad.md +78 -0
- package/docs/components/pagination.md +84 -0
- package/docs/components/popover.md +89 -0
- package/docs/components/profile-photo.md +81 -0
- package/docs/components/progress.md +60 -0
- package/docs/components/radio-group.md +82 -0
- package/docs/components/resizable.md +79 -0
- package/docs/components/scroll-area.md +66 -0
- package/docs/components/section-message.md +99 -0
- package/docs/components/select.md +105 -0
- package/docs/components/separator.md +55 -0
- package/docs/components/sheet.md +91 -0
- package/docs/components/sidebar.md +125 -0
- package/docs/components/skeleton.md +51 -0
- package/docs/components/slider.md +61 -0
- package/docs/components/spinner.md +52 -0
- package/docs/components/stepper.md +68 -0
- package/docs/components/switch.md +57 -0
- package/docs/components/table.md +86 -0
- package/docs/components/tabs.md +95 -0
- package/docs/components/textarea.md +58 -0
- package/docs/components/toast.md +66 -0
- package/docs/components/toggle-group.md +77 -0
- package/docs/components/toggle.md +60 -0
- package/docs/components/tooltip.md +83 -0
- package/docs/foundations/colors.md +110 -0
- package/docs/foundations/motion.md +63 -0
- package/docs/foundations/shape-layout.md +56 -0
- package/docs/foundations/typography.md +83 -0
- package/docs/patterns/forms.md +70 -0
- package/docs/patterns/menus.md +50 -0
- package/docs/patterns/on-brand.md +43 -0
- package/guides/audits/design-system-audit-2026-07.md +135 -0
- package/guides/rules/design-system-consuming-project.mdc +56 -0
- package/package.json +5 -6
- package/src/styles.css +1634 -252
- package/guides/design-system-guide/trading-game-ds-guide.md +0 -933
|
@@ -1,933 +0,0 @@
|
|
|
1
|
-
# Trading Game Design System Guide
|
|
2
|
-
|
|
3
|
-
> **Package:** `@trading-game/design-intelligence-layer`
|
|
4
|
-
> **Audience:** AI agents and developers building UI for the Trading Game. This is the single source of truth for setting up and using the design system in any project.
|
|
5
|
-
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## MANDATORY RULES — READ FIRST
|
|
9
|
-
|
|
10
|
-
### Rule 1 — Component existence check
|
|
11
|
-
|
|
12
|
-
```
|
|
13
|
-
BEFORE using any component:
|
|
14
|
-
1. Check the Component Catalogue (Section 8). Does it exist?
|
|
15
|
-
YES → Import it from the npm package exactly as documented. Do NOT re-implement it.
|
|
16
|
-
NO → STOP. Tell the user:
|
|
17
|
-
"The [ComponentName] component does not exist in the Trading Game design system.
|
|
18
|
-
Options:
|
|
19
|
-
(a) Build a custom one using design system tokens only (no hardcoded colors or values)
|
|
20
|
-
(b) Use a different component that exists in the system
|
|
21
|
-
(c) Skip this component entirely"
|
|
22
|
-
Wait for the user to choose. Do NOT proceed without confirmation.
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
### Rule 2 — Token-only styling
|
|
26
|
-
|
|
27
|
-
```
|
|
28
|
-
NEVER use:
|
|
29
|
-
❌ Hardcoded hex: #2323FF, #FFFFFF, etc.
|
|
30
|
-
❌ Raw Tailwind palette: bg-gray-100, text-zinc-500, text-slate-400, bg-black, bg-white
|
|
31
|
-
❌ Raw opacity on non-tokens: bg-black/50 (use bg-overlay instead)
|
|
32
|
-
❌ Arbitrary color values: bg-[#FF6600], text-[rgba(0,0,0,0.5)]
|
|
33
|
-
❌ hsl(var(--token)) syntax — this is Tailwind v3. This project uses Tailwind v4.
|
|
34
|
-
❌ Non-existent tokens: bg-hover, bg-badge-rank, text-primary-foreground, text-on-decorative
|
|
35
|
-
❌ border-border — deprecated alias; use border-border-subtle or border-border-prominent
|
|
36
|
-
|
|
37
|
-
ALWAYS use semantic tokens:
|
|
38
|
-
✅ bg-prominent, bg-card, bg-popover, bg-subtle, bg-overlay
|
|
39
|
-
✅ text-on-prominent, text-on-subtle
|
|
40
|
-
✅ border-border-subtle, border-border-prominent, ring-ring
|
|
41
|
-
✅ bg-primary, bg-primary-hover, bg-secondary-hover
|
|
42
|
-
✅ text-semantic-win, text-semantic-loss, text-semantic-warning
|
|
43
|
-
✅ Opacity on a token IS allowed: bg-primary/20, border-border-subtle/50, ring-primary/10
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
### Rule 3 — Layout utilities are exempt
|
|
47
|
-
|
|
48
|
-
```
|
|
49
|
-
Tailwind layout/spacing utilities are freely usable for structural layout:
|
|
50
|
-
✅ flex, grid, gap-4, p-6, m-2, w-full, h-screen, max-w-lg, col-span-2, etc.
|
|
51
|
-
✅ z-50, overflow-hidden, transition-all, etc.
|
|
52
|
-
|
|
53
|
-
Token rules apply ONLY to:
|
|
54
|
-
- Color (background, text, border, ring, shadow color)
|
|
55
|
-
- Border radius (use the design system's radius scale — see Section 5)
|
|
56
|
-
- Typography (font family must use font-display or font-body, never raw font names)
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
### Rule 4 — Do NOT install or import these separately
|
|
60
|
-
|
|
61
|
-
```
|
|
62
|
-
❌ lucide-react — already bundled in the npm package
|
|
63
|
-
❌ tailwindcss — the package ships its own Tailwind v4 config
|
|
64
|
-
❌ @apply with hsl(var(--token)) — Tailwind v4 uses CSS variables directly
|
|
65
|
-
❌ tailwind.config.js — configuration is handled by the package via CSS
|
|
66
|
-
❌ Manual font-family in CSS — use font-display and font-body utility classes
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
### Rule 5 — Complexity-aware implementation
|
|
70
|
-
|
|
71
|
-
```
|
|
72
|
-
Each component in the catalogue is tagged:
|
|
73
|
-
[simple] → Drop in, one import, works immediately
|
|
74
|
-
[composed] → Has required sub-components; use the full pattern shown
|
|
75
|
-
[complex] → Has significant state or setup; ask clarifying questions first
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
---
|
|
79
|
-
|
|
80
|
-
## 1 — Quick Start
|
|
81
|
-
|
|
82
|
-
### Step 1 — Install the package
|
|
83
|
-
|
|
84
|
-
```bash
|
|
85
|
-
npm install @trading-game/design-intelligence-layer@latest --safe-chain-skip-minimum-package-age
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### Step 2 — Add CSS imports
|
|
89
|
-
|
|
90
|
-
In your main CSS file (e.g. `globals.css` or `index.css`):
|
|
91
|
-
|
|
92
|
-
```css
|
|
93
|
-
@import url("https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700;800&display=swap");
|
|
94
|
-
@import "tailwindcss";
|
|
95
|
-
@import "@trading-game/design-intelligence-layer/styles";
|
|
96
|
-
@source "../node_modules/@trading-game/design-intelligence-layer/dist";
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
> **Note:** Fonts are loaded via a direct Google Fonts `@import` URL. Do NOT use `next/font`.
|
|
100
|
-
|
|
101
|
-
### Step 3 — Set base HTML class
|
|
102
|
-
|
|
103
|
-
The design system is light-first. No extra class is required on `<html>` for the default light theme. A `.dark` class is reserved for future dark theme support but not yet styled.
|
|
104
|
-
|
|
105
|
-
### Step 4 — Import components
|
|
106
|
-
|
|
107
|
-
```tsx
|
|
108
|
-
import { Button, Card, Badge } from "@trading-game/design-intelligence-layer"
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
---
|
|
112
|
-
|
|
113
|
-
## 2 — Design Tokens
|
|
114
|
-
|
|
115
|
-
> This is the single authoritative token reference. All tokens are defined as CSS variables in the package and mapped to Tailwind utility classes automatically.
|
|
116
|
-
|
|
117
|
-
### 2.1 — Backgrounds
|
|
118
|
-
|
|
119
|
-
| CSS Variable | Tailwind Class | Usage |
|
|
120
|
-
| ---------------- | ---------------- | ------------------------- |
|
|
121
|
-
| `--prominent` | `bg-prominent` | Main page background |
|
|
122
|
-
| `--card` | `bg-card` | Cards, panels, modals |
|
|
123
|
-
| `--popover` | `bg-popover` | Popovers, elevated cards |
|
|
124
|
-
| `--subtle` | `bg-subtle` | Muted / secondary surfaces|
|
|
125
|
-
| `--overlay` | `bg-overlay` | Modal/dialog/drawer/sheet backdrop (semi-transparent) |
|
|
126
|
-
| `--tabs` | `bg-tabs` | Tab container / tab bar background (`variant="default"`) — 4% black alpha, adapts to any surface |
|
|
127
|
-
| `--tabs-active` | `bg-tabs-active` | Active / selected tab background — solid white |
|
|
128
|
-
|
|
129
|
-
### 2.2 — Primary (Brand Blue)
|
|
130
|
-
|
|
131
|
-
| CSS Variable | Tailwind Class | Usage |
|
|
132
|
-
| --------------------- | ------------------- | ------------------------- |
|
|
133
|
-
| `--primary` | `bg-primary` / `text-primary` | Primary CTA, brand color, interactive elements |
|
|
134
|
-
| `--on-primary` | `text-on-primary` | Text/icon color paired with `bg-primary` (always white) |
|
|
135
|
-
| `--primary-hover` | `bg-primary-hover` | Hover & pressed states on primary elements |
|
|
136
|
-
| `--primary-inverse` | `bg-primary-inverse` | Inverted primary surface — white bg for use on dark/coloured areas |
|
|
137
|
-
| `--on-primary-inverse`| `text-on-primary-inverse` | Text/icon color paired with `bg-primary-inverse` (always blue) |
|
|
138
|
-
|
|
139
|
-
### 2.3 — Semantic (Trading Status)
|
|
140
|
-
|
|
141
|
-
> **Naming convention:** every surface token has a paired `--on-<name>` foreground (text/icon) token. Use the pair together (`bg-semantic-X` + `text-on-semantic-X`) for guaranteed legibility on the saturated surface.
|
|
142
|
-
|
|
143
|
-
| CSS Variable | Tailwind Class | Usage |
|
|
144
|
-
| -------------------------- | ------------------------------------------- | --------------------------------------------- |
|
|
145
|
-
| `--semantic-win` | `bg-semantic-win` / `text-semantic-win` | Win / Profit / Positive outcomes |
|
|
146
|
-
| `--on-semantic-win` | `text-on-semantic-win` | Text/icon on `bg-semantic-win` surfaces (white) |
|
|
147
|
-
| `--semantic-loss` | `bg-semantic-loss` / `text-semantic-loss` | Loss / Negative outcomes |
|
|
148
|
-
| `--on-semantic-loss` | `text-on-semantic-loss` | Text/icon on `bg-semantic-loss` surfaces (white) |
|
|
149
|
-
| `--semantic-warning` | `bg-semantic-warning` / `text-semantic-warning` | Warning / Caution / Non-destructive alerts |
|
|
150
|
-
| `--on-semantic-warning` | `text-on-semantic-warning` | Text/icon on `bg-semantic-warning` surfaces (white) |
|
|
151
|
-
| `--semantic-info` | `bg-semantic-info` / `text-semantic-info` | Informational alerts |
|
|
152
|
-
| `--semantic-boost` | `bg-semantic-boost` | Boost / bonus badge background (`#F9840F` amber-orange) |
|
|
153
|
-
| `--on-semantic-boost` | `text-on-semantic-boost` | Boost / bonus badge foreground (`#713813` dark amber) |
|
|
154
|
-
|
|
155
|
-
> All semantic tokens support opacity variants (e.g. `bg-semantic-warning/10` for tinted backgrounds). For structured alpha surfaces, use the primitive alpha scales — see Section 2.10.
|
|
156
|
-
|
|
157
|
-
### 2.4 — Text & Icon Colors
|
|
158
|
-
|
|
159
|
-
The system follows a Material-style `<surface>` / `on-<surface>` pair convention: no prefix = surface/background, `on-` prefix = the foreground (text/icon) color paired with that surface.
|
|
160
|
-
|
|
161
|
-
| CSS Variable | Tailwind Class | Usage |
|
|
162
|
-
| ------------------------- | ----------------------------- | ------------------------- |
|
|
163
|
-
| `--prominent` | `bg-prominent` | Light surface (page chrome, cards) |
|
|
164
|
-
| `--on-prominent` | `text-on-prominent` | Text/icon on `bg-prominent` (black) |
|
|
165
|
-
| `--prominent-inverse` | `bg-prominent-inverse` | Dark surface for use on light pages (e.g. toasts) |
|
|
166
|
-
| `--on-prominent-inverse` | `text-on-prominent-inverse` | Text/icon on `bg-prominent-inverse` (white) |
|
|
167
|
-
| `--on-subtle` | `text-on-subtle` | Secondary text (descriptions, labels) — paired with `bg-subtle` |
|
|
168
|
-
| `--on-disabled` | `text-on-disabled` | Disabled text (inactive controls, placeholders) |
|
|
169
|
-
|
|
170
|
-
> **Deprecated aliases:** `--on-prominent-static-inverse` and `--surface-inverse-static` remain defined in CSS for backwards-compat with external consumers using raw `var()` references, but internal components no longer use them — prefer the explicit `on-<surface>` / `<surface>-inverse` pairs above.
|
|
171
|
-
|
|
172
|
-
### 2.5 — Borders & Inputs
|
|
173
|
-
|
|
174
|
-
| CSS Variable | Tailwind Class | Usage |
|
|
175
|
-
| ------------------- | ------------------------- | ------------------------- |
|
|
176
|
-
| `--border-subtle` | `border-border-subtle` | Default light border |
|
|
177
|
-
| `--border-prominent`| `border-border-prominent` | Strong / emphasized border|
|
|
178
|
-
| `--input` | `border-input` | Input resting state border|
|
|
179
|
-
| `--ring` | `ring-ring` / `border-ring` | Focus ring and focus border color |
|
|
180
|
-
|
|
181
|
-
### 2.6 — Supporting Colors
|
|
182
|
-
|
|
183
|
-
| CSS Variable | Tailwind Class | Usage |
|
|
184
|
-
| ------------------------ | -------------------- | ------------------------- |
|
|
185
|
-
| `--secondary-hover` | `bg-secondary-hover` | Hover bg on neutral elements (light gray) |
|
|
186
|
-
| `--slider-range` | `bg-slider-range` | Slider range fill (primary at 40%) |
|
|
187
|
-
| `--alert-info-text` | `text-alert-info-text` | Alert info text color |
|
|
188
|
-
| `--alert-info-border` | `border-alert-info-border` | Alert info border |
|
|
189
|
-
| `--alert-error-text` | `text-alert-error-text` | Alert error text color |
|
|
190
|
-
| `--alert-error-border` | `border-alert-error-border` | Alert error border |
|
|
191
|
-
|
|
192
|
-
> **Accent (orange) and Violet:** `--primitive-orange-500` and `--primitive-violet-500` are available as CSS variables only (no Tailwind utility class). Use `var(--primitive-orange-500)` directly for rank badges and special highlights.
|
|
193
|
-
|
|
194
|
-
### 2.7 — Opacity Patterns
|
|
195
|
-
|
|
196
|
-
| Usage | Tailwind Class |
|
|
197
|
-
| ------------------------------ | ---------------------- |
|
|
198
|
-
| Subtle hover tint | `bg-primary/[0.08]` |
|
|
199
|
-
| Medium highlight | `bg-primary/[0.16]` |
|
|
200
|
-
| Selected/active tint | `bg-primary/10` |
|
|
201
|
-
| Status badge tint backgrounds | `bg-semantic-win/10`, `bg-semantic-loss/10`, etc. |
|
|
202
|
-
|
|
203
|
-
### 2.8 — Interactive States
|
|
204
|
-
|
|
205
|
-
> **`bg-hover` does not exist.** Use `bg-secondary-hover` or `bg-primary/[0.08]` for hover states.
|
|
206
|
-
|
|
207
|
-
**Universal pattern for interactive list/row/chip elements** (except Button and Tabs which have their own):
|
|
208
|
-
|
|
209
|
-
| State | Background | Text |
|
|
210
|
-
| -------- | -------------------- | ---------------------------------- |
|
|
211
|
-
| Default | transparent | `text-on-prominent` or `text-on-subtle` |
|
|
212
|
-
| Hover | `bg-secondary-hover` | `text-primary` |
|
|
213
|
-
| Selected | `bg-secondary-hover` | `text-primary font-semibold` |
|
|
214
|
-
|
|
215
|
-
> **NEVER** use `bg-accent` or `text-accent-foreground`. Do NOT add borders to selected states.
|
|
216
|
-
|
|
217
|
-
### 2.9 — Transitions
|
|
218
|
-
|
|
219
|
-
**Duration tokens:**
|
|
220
|
-
|
|
221
|
-
| Tailwind Class | CSS Variable | Value | Usage |
|
|
222
|
-
| ----------------- | ------------------------------ | ------ | -------------------------------------- |
|
|
223
|
-
| `duration-instant`| `--primitive-duration-instant` | `50ms` | Focus rings, hover color tints |
|
|
224
|
-
| `duration-fast` | `--primitive-duration-fast` | `100ms`| Buttons, inputs, badges, checkboxes |
|
|
225
|
-
| `duration-base` | `--primitive-duration-base` | `200ms`| Dropdowns, popovers, accordions |
|
|
226
|
-
| `duration-slow` | `--primitive-duration-slow` | `300ms`| Dialogs, sheets, drawers closing |
|
|
227
|
-
| `duration-open` | `--primitive-duration-open` | `500ms`| Sheets, drawers entering |
|
|
228
|
-
|
|
229
|
-
**Easing tokens:**
|
|
230
|
-
|
|
231
|
-
| Tailwind Class | CSS Variable | Value | Usage |
|
|
232
|
-
| ---------------- | ----------------------------- | ------------------------------ | -------------------------------------- |
|
|
233
|
-
| `ease-standard` | `--primitive-ease-standard` | `cubic-bezier(0.2, 0, 0, 1)` | General UI — bidirectional state changes |
|
|
234
|
-
| `ease-enter` | `--primitive-ease-enter` | `cubic-bezier(0, 0, 0.2, 1)` | Overlays / surfaces entering |
|
|
235
|
-
| `ease-exit` | `--primitive-ease-exit` | `cubic-bezier(0.4, 0, 1, 1)` | Overlays / surfaces leaving |
|
|
236
|
-
| `ease-linear` | `--primitive-ease-linear` | `linear` | Sidebar width, progress bar |
|
|
237
|
-
|
|
238
|
-
**Usage pattern:**
|
|
239
|
-
|
|
240
|
-
```tsx
|
|
241
|
-
<div className="transition-colors duration-fast ease-standard">...</div>
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
### 2.10 — Primitive Alpha Scales
|
|
245
|
-
|
|
246
|
-
> Raw alpha (opacity) variants of the mono and blue primitives. These are **internal CSS variables only** — not exposed as Tailwind utility classes. Reference them only from semantic tokens, never directly in components.
|
|
247
|
-
|
|
248
|
-
**Naming convention:** `--primitive-[color]-alpha-[stop]`
|
|
249
|
-
|
|
250
|
-
**Mono alpha scale** (black — `oklch(0 0 0 / X%)`)
|
|
251
|
-
|
|
252
|
-
| CSS Variable | Opacity | Typical use |
|
|
253
|
-
| ----------------------------- | ------- | ---------------------------------------- |
|
|
254
|
-
| `--primitive-mono-alpha-4` | 4% | Tab container background (`--tabs`) |
|
|
255
|
-
| `--primitive-mono-alpha-8` | 8% | Subtle hover tint |
|
|
256
|
-
| `--primitive-mono-alpha-16` | 16% | Pressed / active surface tint |
|
|
257
|
-
| `--primitive-mono-alpha-24` | 24% | Medium-weight tinted surface |
|
|
258
|
-
| `--primitive-mono-alpha-32` | 32% | Disabled state overlay |
|
|
259
|
-
| `--primitive-mono-alpha-40` | 40% | Strong tint / scrim |
|
|
260
|
-
| `--primitive-mono-alpha-50` | 50% | Backdrop overlay (replaces `--primitive-black-50`) |
|
|
261
|
-
| `--primitive-mono-alpha-64` | 64% | Heavy overlay |
|
|
262
|
-
| `--primitive-mono-alpha-80` | 80% | Near-opaque overlay |
|
|
263
|
-
|
|
264
|
-
**Blue alpha scale** (brand blue — `oklch(0.476 0.297 267.4 / X%)`)
|
|
265
|
-
|
|
266
|
-
| CSS Variable | Opacity | Typical use |
|
|
267
|
-
| ----------------------------- | ------- | ---------------------------------------- |
|
|
268
|
-
| `--primitive-blue-alpha-4` | 4% | Extremely subtle brand tint |
|
|
269
|
-
| `--primitive-blue-alpha-8` | 8% | Hover tint on brand surfaces |
|
|
270
|
-
| `--primitive-blue-alpha-16` | 16% | Selected / active brand tint |
|
|
271
|
-
| `--primitive-blue-alpha-24` | 24% | Medium brand surface highlight |
|
|
272
|
-
| `--primitive-blue-alpha-32` | 32% | Strong brand tint |
|
|
273
|
-
| `--primitive-blue-alpha-40` | 40% | Slider range fill (via `--slider-range`) |
|
|
274
|
-
| `--primitive-blue-alpha-50` | 50% | Brand overlay |
|
|
275
|
-
| `--primitive-blue-alpha-64` | 64% | Heavy brand overlay |
|
|
276
|
-
| `--primitive-blue-alpha-80` | 80% | Near-opaque brand overlay |
|
|
277
|
-
|
|
278
|
-
> **`--primitive-black-50` is deprecated.** It now aliases `--primitive-mono-alpha-50`. The `--overlay` semantic token is unaffected — it still resolves to the same 50% black value.
|
|
279
|
-
|
|
280
|
-
---
|
|
281
|
-
|
|
282
|
-
## 3 — AI Agent Decision Rules
|
|
283
|
-
|
|
284
|
-
> Quick-lookup table: "If I need X, use Y, never Z."
|
|
285
|
-
|
|
286
|
-
| IF you need to... | THEN use | NEVER use |
|
|
287
|
-
| -------------------------------------- | --------------------------------- | -------------------------------------- |
|
|
288
|
-
| Pick a primary CTA button color | `bg-primary` | Green, or any other color for primary CTA |
|
|
289
|
-
| Show WIN / profit / positive | `text-semantic-win` | Primary blue for profit |
|
|
290
|
-
| Show LOSS / negative | `text-semantic-loss` | Any non-token red |
|
|
291
|
-
| Show WARNING / caution | `text-semantic-warning` | Raw orange hex or primary tint |
|
|
292
|
-
| Show a credit / boost / bonus badge | `<Badge variant="fill-credit">` (frosted glass — `bg-semantic-boost-surface` = `oklch(1 0 0 / 0.22)` + `backdrop-blur-md` + `text-on-primary`); place it on a coloured surface only — invisible on white | Hardcoded rgba/alpha |
|
|
293
|
-
| Color a tab container background | `bg-tabs` | `bg-subtle` for tabs |
|
|
294
|
-
| Color an active/selected tab | `bg-tabs-active` | `bg-prominent` for active tab |
|
|
295
|
-
| Color a page background | `bg-prominent` | `bg-white` directly |
|
|
296
|
-
| Color a modal/dialog backdrop | `bg-overlay` | `bg-black/50` or raw black opacity |
|
|
297
|
-
| Color a card or panel | `bg-card` | Arbitrary gray |
|
|
298
|
-
| Color an elevated surface (popover) | `bg-popover` | `bg-card` for popovers |
|
|
299
|
-
| Write primary heading text | `text-on-prominent` | Pure white, raw hex colors |
|
|
300
|
-
| Write body / description text | `text-on-subtle` | `text-on-prominent` for descriptions |
|
|
301
|
-
| Write a subtle label | `text-on-subtle` | Raw gray values |
|
|
302
|
-
| Write disabled / inactive text | `text-on-disabled` | `text-gray-300`, raw light hex values |
|
|
303
|
-
| Add a default border | `border-border-subtle` | Solid black borders, `border-border` |
|
|
304
|
-
| Add a strong border | `border-border-prominent` | — |
|
|
305
|
-
| Style an input (resting) | `border-input` | Solid colored backgrounds |
|
|
306
|
-
| Style an input (focused) | `border-ring` + `ring-[3px] ring-ring/50` | Generic shadows on inputs |
|
|
307
|
-
| Pick a heading font | `font-display` | System fonts, raw font-family names |
|
|
308
|
-
| Pick a body font | `font-body` | Raw font-family names |
|
|
309
|
-
| Style button text | `font-display font-bold`, sentence case | `uppercase` on buttons |
|
|
310
|
-
| Write text on a primary blue surface | `text-on-primary` | `text-white` or `text-on-prominent-static-inverse` |
|
|
311
|
-
| Write text on a dark inverse surface | `text-on-prominent-inverse` | `text-white` or raw white hex |
|
|
312
|
-
| Write text on a semantic surface | `text-on-semantic-win` / `-loss` / `-warning` / `-boost` | `text-white` (the surface may not always be dark) |
|
|
313
|
-
|
|
314
|
-
---
|
|
315
|
-
|
|
316
|
-
## 4 — Typography
|
|
317
|
-
|
|
318
|
-
### 4.1 — Font Setup
|
|
319
|
-
|
|
320
|
-
All text uses **Plus Jakarta Sans** (loaded weights: 300–800). Three Tailwind aliases are available — they all resolve to the same font:
|
|
321
|
-
|
|
322
|
-
| Tailwind Class | Purpose |
|
|
323
|
-
| --------------- | ------------------------------- |
|
|
324
|
-
| `font-display` | Headings, wordmark, buttons |
|
|
325
|
-
| `font-body` | Body text, UI elements |
|
|
326
|
-
| `font-sans` | Default sans-serif fallback |
|
|
327
|
-
|
|
328
|
-
### 4.2 — Pre-built Typography Classes
|
|
329
|
-
|
|
330
|
-
The npm package ships these ready-to-use CSS classes. All include `text-transform: uppercase`:
|
|
331
|
-
|
|
332
|
-
| Class | Size | Line Height | Weight | Letter Spacing |
|
|
333
|
-
| ------------- | ----- | ----------- | ------ | -------------- |
|
|
334
|
-
| `heading-h1` | 72px | 72px | 600 | 1.5px |
|
|
335
|
-
| `heading-h2` | 64px | 64px | 600 | 1.5px |
|
|
336
|
-
| `heading-h3` | 48px | 48px | 600 | 1.5px |
|
|
337
|
-
| `heading-h4` | 40px | 40px | 600 | 1.5px |
|
|
338
|
-
| `heading-xs` | 24px | 24px | 600 | 1.5px |
|
|
339
|
-
| `body-lg` | 18px | 28px | 600 | — |
|
|
340
|
-
| `body-md` | 16px | 24px | 600 | — |
|
|
341
|
-
| `body-sm` | 12px | 16px | 600 | — |
|
|
342
|
-
| `body-xs` | 8px | 12px | 600 | — |
|
|
343
|
-
|
|
344
|
-
**Responsive heading sizes** (headings scale down on mobile):
|
|
345
|
-
|
|
346
|
-
| Class | Desktop | Mobile |
|
|
347
|
-
| ------------ | ------- | ------ |
|
|
348
|
-
| `heading-h1` | 72px | 48px |
|
|
349
|
-
| `heading-h2` | 64px | 48px |
|
|
350
|
-
| `heading-h3` | 48px | 40px |
|
|
351
|
-
| `heading-h4` | 40px | 32px |
|
|
352
|
-
| `heading-xs` | 24px | 20px |
|
|
353
|
-
|
|
354
|
-
### 4.3 — Custom Text Size Overrides
|
|
355
|
-
|
|
356
|
-
These sizes differ from standard Tailwind defaults — use the design system values:
|
|
357
|
-
|
|
358
|
-
| Class | Size | Line Height | How it differs from Tailwind |
|
|
359
|
-
| ----------- | ------ | ----------- | ---------------------------- |
|
|
360
|
-
| `text-xxs` | 8px | 12px | Custom (not in standard TW) |
|
|
361
|
-
| `text-2xl` | 24px | **24px** | Line height differs (TW: 32px) |
|
|
362
|
-
| `text-3xl` | **32px** | **32px** | Size differs (TW: 30px) |
|
|
363
|
-
| `text-4xl` | **40px** | **40px** | Size differs (TW: 36px) |
|
|
364
|
-
| `text-6xl` | **64px** | **64px** | Size differs (TW: 60px) |
|
|
365
|
-
|
|
366
|
-
> All other `text-*` sizes (`xs`, `sm`, `base`, `lg`, `xl`, `5xl`, `7xl`, `8xl`, `9xl`) match standard Tailwind.
|
|
367
|
-
|
|
368
|
-
### 4.4 — Typography Usage Rules
|
|
369
|
-
|
|
370
|
-
| Context | Class | Weight |
|
|
371
|
-
| ------------------------ | -------------- | ------------------- |
|
|
372
|
-
| Page headings | `font-display` | `font-semibold` (600) |
|
|
373
|
-
| Button labels | `font-display` | `font-bold` (700), sentence case |
|
|
374
|
-
| Body text | `font-body` | `font-semibold` (600) |
|
|
375
|
-
| Tiny labels / decorative | `font-body` | `font-semibold` (600) at 8px |
|
|
376
|
-
|
|
377
|
-
### 4.5 — Letter Spacing Tokens
|
|
378
|
-
|
|
379
|
-
| Token value | Usage |
|
|
380
|
-
| ----------- | ------------------------ |
|
|
381
|
-
| 1.5px | Buttons, headings |
|
|
382
|
-
| -0.4px | Paragraphs, tight text |
|
|
383
|
-
| -0.8px | Tight display text |
|
|
384
|
-
|
|
385
|
-
---
|
|
386
|
-
|
|
387
|
-
## 5 — Border Radius
|
|
388
|
-
|
|
389
|
-
The design system uses a custom radius scale (base = 10px). Use these named tokens instead of arbitrary values:
|
|
390
|
-
|
|
391
|
-
| Tailwind Class | Value |
|
|
392
|
-
| -------------- | ------ |
|
|
393
|
-
| `rounded-2xs` | 2px |
|
|
394
|
-
| `rounded-xs` | 4px |
|
|
395
|
-
| `rounded-sm` | 6px |
|
|
396
|
-
| `rounded-md` | 8px |
|
|
397
|
-
| `rounded-lg` | 10px |
|
|
398
|
-
| `rounded-xl` | 14px |
|
|
399
|
-
| `rounded-2xl` | 18px |
|
|
400
|
-
| `rounded-3xl` | 22px |
|
|
401
|
-
| `rounded-4xl` | 26px |
|
|
402
|
-
| `rounded-full` | 9999px |
|
|
403
|
-
|
|
404
|
-
> **Important:** Do NOT use `rounded-[4px]` or `rounded-[2px]` — use `rounded-xs` and `rounded-2xs` instead. Arbitrary radius values should only be used for sizes not in this scale (e.g. `rounded-[24px]`, `rounded-[32px]`).
|
|
405
|
-
|
|
406
|
-
---
|
|
407
|
-
|
|
408
|
-
## 6 — Button System
|
|
409
|
-
|
|
410
|
-
### 6.1 — Variants
|
|
411
|
-
|
|
412
|
-
| Variant | Background | Text Color | Border | Hover | Use on |
|
|
413
|
-
| -------------------- | -------------------- | --------------------------- | ---------------------------------------- | --------------------------- | ---------------------- |
|
|
414
|
-
| `primary` | `bg-primary` | `text-on-primary` | none | `bg-primary-hover` | Light surfaces |
|
|
415
|
-
| `primary-inverse` | `bg-primary-inverse` | `text-on-primary-inverse` | none | `bg-primary-inverse/80` | Dark/coloured surfaces |
|
|
416
|
-
| `secondary` | transparent | `text-on-prominent` | `border-[1.5px] border-border-prominent` | `bg-secondary-hover` | Light surfaces |
|
|
417
|
-
| `secondary-inverse` | transparent | `text-on-prominent-inverse` | `border-[1.5px] border-primary-inverse` | `bg-primary-inverse/10` | Dark/coloured surfaces |
|
|
418
|
-
| `tertiary` | transparent | `text-on-prominent` | none | `bg-secondary-hover` | Light surfaces |
|
|
419
|
-
| `tertiary-inverse` | transparent | `text-on-primary` | none | `bg-on-primary/[0.10]` | Dark/coloured surfaces |
|
|
420
|
-
|
|
421
|
-
### 6.2 — Sizes
|
|
422
|
-
|
|
423
|
-
| Size | Height | Padding X | Font Size | Icon Size | Radius |
|
|
424
|
-
| --------- | ------ | --------- | --------- | --------- | ------ |
|
|
425
|
-
| `lg` | 48px | 24px | 16px | 16px | 4px |
|
|
426
|
-
| `md` | 40px | 16px | 14px | 16px | 4px |
|
|
427
|
-
| `sm` | 32px | 12px | 12px | 14px | 4px |
|
|
428
|
-
| `xs` | 24px | 8px | 12px | 12px | 4px |
|
|
429
|
-
|
|
430
|
-
**Icon-only sizes:**
|
|
431
|
-
|
|
432
|
-
| Size | Dimensions | Icon Size |
|
|
433
|
-
| ---------- | ---------- | --------- |
|
|
434
|
-
| `icon-lg` | 48×48px | 16px |
|
|
435
|
-
| `icon-md` | 40×40px | 16px |
|
|
436
|
-
| `icon-sm` | 28×28px | 16px |
|
|
437
|
-
| `icon-xs` | 24×24px | 12px |
|
|
438
|
-
|
|
439
|
-
### 6.3 — Button Typography & States
|
|
440
|
-
|
|
441
|
-
All buttons: `font-display font-bold`, sentence case (no `uppercase`, no `tracking-wide`).
|
|
442
|
-
|
|
443
|
-
| State | Behavior |
|
|
444
|
-
| -------- | ------------------------------------------------ |
|
|
445
|
-
| Default | Base styling per variant |
|
|
446
|
-
| Hover | Color shift per variant (see above) |
|
|
447
|
-
| Focus | 3px ring with `ring-ring/50` opacity |
|
|
448
|
-
| Pressed | `active:opacity-60` |
|
|
449
|
-
| Loading | `opacity-24`, `pointer-events-none`, `data-loading`, `aria-busy` — applies to all variants |
|
|
450
|
-
| Disabled | `opacity-24`, `pointer-events-none` — applies to all variants |
|
|
451
|
-
|
|
452
|
-
---
|
|
453
|
-
|
|
454
|
-
## 7 — Responsive Layout
|
|
455
|
-
|
|
456
|
-
### 7.1 — Layout Grid
|
|
457
|
-
|
|
458
|
-
| Breakpoint | Viewport | Columns | Gutter | Margin |
|
|
459
|
-
| ---------- | ---------- | ------- | ------ | ------ |
|
|
460
|
-
| Default | 0–319px | 1 | 0 | 16px |
|
|
461
|
-
| Small | 320–599px | 4 | 16px | 16px |
|
|
462
|
-
| Medium | 600–1135px | 8 | 36px | 36px |
|
|
463
|
-
| Large | 1136px+ | 12 | 36px | 64px |
|
|
464
|
-
|
|
465
|
-
**Tailwind utilities:** `gap-layout-gutter`, `px-layout-margin-inline`.
|
|
466
|
-
|
|
467
|
-
**CSS variables for custom grids:** `var(--semantic-layout-grid-columns)`, `var(--spacing-layout-gutter)`, `var(--spacing-layout-margin-inline)`.
|
|
468
|
-
|
|
469
|
-
### 7.2 — Responsive Spacing Tokens
|
|
470
|
-
|
|
471
|
-
| Token | Desktop | Mobile |
|
|
472
|
-
| -------------------- | ------- | ------ |
|
|
473
|
-
| container-padding-x | 24px | 16px |
|
|
474
|
-
| section-padding-y | 96px | 64px |
|
|
475
|
-
| section-title-gap-xl | 24px | 20px |
|
|
476
|
-
| section-title-gap-lg | 20px | 16px |
|
|
477
|
-
| section-title-gap-md | 20px | 16px |
|
|
478
|
-
| section-title-gap-sm | 16px | 16px |
|
|
479
|
-
|
|
480
|
-
---
|
|
481
|
-
|
|
482
|
-
## 8 — Available Components
|
|
483
|
-
|
|
484
|
-
> **All components below are exported from `@trading-game/design-intelligence-layer`.**
|
|
485
|
-
> - If a component is listed → import and use it. Do NOT re-implement.
|
|
486
|
-
> - If NOT listed → STOP and ask the user (see Rule 1).
|
|
487
|
-
> - For props, variants, sizes, and sub-components → inspect the package's TypeScript types after installation.
|
|
488
|
-
|
|
489
|
-
### Import pattern
|
|
490
|
-
|
|
491
|
-
All components use the same import path:
|
|
492
|
-
|
|
493
|
-
```tsx
|
|
494
|
-
import { Button, Card, Badge } from "@trading-game/design-intelligence-layer"
|
|
495
|
-
```
|
|
496
|
-
|
|
497
|
-
### Example — composed component with sub-components
|
|
498
|
-
|
|
499
|
-
```tsx
|
|
500
|
-
import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, DialogClose } from "@trading-game/design-intelligence-layer"
|
|
501
|
-
|
|
502
|
-
<Dialog>
|
|
503
|
-
<DialogTrigger asChild><Button>Open</Button></DialogTrigger>
|
|
504
|
-
<DialogContent showCloseButton>
|
|
505
|
-
<DialogHeader>
|
|
506
|
-
<DialogTitle>Title</DialogTitle>
|
|
507
|
-
<DialogDescription>Description text.</DialogDescription>
|
|
508
|
-
</DialogHeader>
|
|
509
|
-
<div>Content here</div>
|
|
510
|
-
<DialogFooter>
|
|
511
|
-
<Button variant="primary" size="md">Confirm</Button>
|
|
512
|
-
</DialogFooter>
|
|
513
|
-
</DialogContent>
|
|
514
|
-
</Dialog>
|
|
515
|
-
```
|
|
516
|
-
|
|
517
|
-
### Component list
|
|
518
|
-
|
|
519
|
-
> **Complexity tags:** `[simple]` = drop in, one import | `[composed]` = has required sub-components | `[complex]` = has significant state/setup, ask the user first
|
|
520
|
-
|
|
521
|
-
| Component | Tag | Sub-components |
|
|
522
|
-
|-----------|-----|----------------|
|
|
523
|
-
| Accordion | [composed] | AccordionItem, AccordionTrigger, AccordionContent |
|
|
524
|
-
| Alert | [simple] | — (flat-prop API: `variant`, `layout`, `title`, `description`, `icon`, `action`, `actions`, `onDismiss`, `dismissLabel`) — **status** notifications only; for promo use `Banner` |
|
|
525
|
-
| AlertDialog | [complex] | AlertDialogTrigger, AlertDialogContent, AlertDialogHeader, AlertDialogFooter, AlertDialogTitle, AlertDialogDescription, AlertDialogAction, AlertDialogCancel, AlertDialogMedia |
|
|
526
|
-
| AspectRatio | [simple] | — |
|
|
527
|
-
| Avatar | [composed] | AvatarImage, AvatarFallback, AvatarBadge, AvatarGroup, AvatarGroupCount |
|
|
528
|
-
| Badge | [simple] | — |
|
|
529
|
-
| Banner | [simple] | — (flat-prop API: `layout`, `title`, `description`, `icon`, `action`, `actions`, `onDismiss`, `dismissLabel`, `onClick`) |
|
|
530
|
-
| Breadcrumb | [composed] | BreadcrumbList, BreadcrumbItem, BreadcrumbLink, BreadcrumbPage, BreadcrumbSeparator, BreadcrumbEllipsis |
|
|
531
|
-
| Button | [simple] | — |
|
|
532
|
-
| Calendar | [complex] | — |
|
|
533
|
-
| Card | [composed] | CardHeader, CardTitle, CardDescription, CardContent, CardFooter, CardAction |
|
|
534
|
-
| Carousel | [complex] | CarouselContent, CarouselItem, CarouselPrevious, CarouselNext |
|
|
535
|
-
| Chart | [complex] | ChartContainer, ChartTooltip, ChartTooltipContent, ChartLegend, ChartLegendContent, ChartStyle |
|
|
536
|
-
| Checkbox | [simple] | — |
|
|
537
|
-
| Chip | [simple] | — (`selected`, `disabled`, `onClick`, standard button props) — pill-shaped toggle-able selection chip. Selected: `bg-primary/[0.08]` + `text-primary`. Unselected: outline + `text-on-prominent`. |
|
|
538
|
-
| Collapsible | [composed] | CollapsibleTrigger, CollapsibleContent |
|
|
539
|
-
| Combobox | [complex] | ComboboxInput, ComboboxContent, ComboboxList, ComboboxItem, ComboboxEmpty, ComboboxGroup, ComboboxLabel |
|
|
540
|
-
| Command | [complex] | CommandDialog, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem, CommandSeparator, CommandShortcut |
|
|
541
|
-
| ContextMenu | [composed] | ContextMenuTrigger, ContextMenuContent, ContextMenuItem, ContextMenuSeparator, ContextMenuLabel, ContextMenuCheckboxItem, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSub, ContextMenuSubTrigger, ContextMenuSubContent |
|
|
542
|
-
| Dialog | [complex] | DialogTrigger, DialogContent, DialogHeader, DialogFooter, DialogTitle, DialogDescription, DialogClose |
|
|
543
|
-
| DirectionProvider | [simple] | — |
|
|
544
|
-
| Drawer | [complex] | DrawerTrigger, DrawerContent, DrawerHeader, DrawerFooter, DrawerTitle, DrawerDescription, DrawerClose |
|
|
545
|
-
| DropdownMenu | [composed] | DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuCheckboxItem, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent, DropdownMenuShortcut |
|
|
546
|
-
| Empty | [composed] | EmptyHeader, EmptyMedia, EmptyTitle, EmptyDescription, EmptyContent |
|
|
547
|
-
| Field | [complex] | FieldLabel, FieldDescription, FieldError, FieldGroup, FieldLegend, FieldSet, FieldContent, FieldTitle, FieldSeparator |
|
|
548
|
-
| Form | [complex] | FormField, FormItem, FormLabel, FormControl, FormDescription, FormMessage |
|
|
549
|
-
| HoverCard | [composed] | HoverCardTrigger, HoverCardContent |
|
|
550
|
-
| Input | [simple] | — variants: `default`, `inverse` (dark sunken fill + white text, for use on `bg-primary` and other brand-coloured surfaces). |
|
|
551
|
-
| InputGroup | [composed] | InputGroupAddon, InputGroupInput, InputGroupButton, InputGroupText, InputGroupTextarea. Variants: `default`, `inverse` (propagates to nested controls via context — addon / text / input all swap to the inverse recipe automatically). |
|
|
552
|
-
| InputOTP | [composed] | InputOTPGroup, InputOTPSlot, InputOTPSeparator. Variants: OTP 4 digits, OTP 6 digits, OTP 6 split, OTP 8 digits, OTP 6 separated |
|
|
553
|
-
| Item | [composed] | ItemGroup, ItemContent, ItemTitle, ItemDescription, ItemMedia, ItemActions, ItemHeader, ItemFooter, ItemSeparator |
|
|
554
|
-
| Kbd | [simple] | KbdGroup |
|
|
555
|
-
| Label | [simple] | — |
|
|
556
|
-
| Link | [simple] | — |
|
|
557
|
-
| Menubar | [complex] | MenubarMenu, MenubarTrigger, MenubarContent, MenubarItem, MenubarSeparator, MenubarLabel, MenubarCheckboxItem, MenubarRadioGroup, MenubarRadioItem, MenubarSub, MenubarSubTrigger, MenubarSubContent, MenubarShortcut |
|
|
558
|
-
| NavigationButton | [simple] | — |
|
|
559
|
-
| NavigationMenu | [complex] | NavigationMenuList, NavigationMenuItem, NavigationMenuTrigger, NavigationMenuContent, NavigationMenuLink, NavigationMenuIndicator, NavigationMenuViewport, navigationMenuTriggerStyle |
|
|
560
|
-
| NativeSelect | [simple] | NativeSelectOption, NativeSelectOptGroup |
|
|
561
|
-
| Pagination | [composed] | PaginationContent, PaginationItem, PaginationLink, PaginationPrevious, PaginationNext, PaginationEllipsis |
|
|
562
|
-
| Popover | [composed] | PopoverTrigger, PopoverContent, PopoverHeader, PopoverTitle, PopoverDescription |
|
|
563
|
-
| Progress | [simple] | — |
|
|
564
|
-
| RadioGroup | [composed] | RadioGroupItem |
|
|
565
|
-
| Resizable | [complex] | ResizablePanelGroup, ResizablePanel, ResizableHandle |
|
|
566
|
-
| ScrollArea | [simple] | ScrollBar |
|
|
567
|
-
| Select | [composed] | SelectTrigger (`size`: sm/md/lg, default md), SelectValue, SelectContent, SelectGroup, SelectLabel, SelectItem, SelectSeparator |
|
|
568
|
-
| Separator | [simple] | — |
|
|
569
|
-
| Sheet | [complex] | SheetTrigger, SheetContent, SheetHeader, SheetFooter, SheetTitle, SheetDescription, SheetClose |
|
|
570
|
-
| Sidebar | [complex] | SidebarProvider, SidebarTrigger, SidebarInset, SidebarHeader, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupLabel, SidebarGroupContent, SidebarMenu, SidebarMenuItem, SidebarMenuButton, SidebarRail, useSidebar |
|
|
571
|
-
| Skeleton | [simple] | — |
|
|
572
|
-
| Slider | [simple] | — |
|
|
573
|
-
| Toast | [simple] | `Toaster`, `toast` — import both from `@trading-game/design-intelligence-layer` (the toaster wraps `sonner` internally; `toast` is re-exported so consumers don't need to import the underlying library) |
|
|
574
|
-
| Spinner | [simple] | — |
|
|
575
|
-
| Stepper | [simple] | — |
|
|
576
|
-
| Switch | [simple] | — |
|
|
577
|
-
| Table | [composed] | TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption |
|
|
578
|
-
| Tabs | [composed] | TabsList (`variant`: default/line, `size`: sm/md/lg), TabsTrigger (`iconPosition`: inline/top), TabsContent. Root accepts `orientation`: horizontal/vertical. |
|
|
579
|
-
| Textarea | [simple] | — |
|
|
580
|
-
| TicketCard | [composed] | — (`icon`, `label`, `value`, `currency`, `stubLabel`, `onStubClick`, `stubDisabled`, `compact`) |
|
|
581
|
-
| CreditTicketCard | [composed] | — (`icon`, `label`, `value`, `currency`, `stubLabel`, `onStubClick`, `stubDisabled`, `badgeIcon`, `badgeLabel`, `badgeValue`, `badgeCurrency`, `badgeInfo`, `badgeInfoSide`, `badgeInfoAlign`, `badgeInfoTitle`, `badgeInfoCloseLabel`, `compact`) — use when a Welcome credit / bonus badge must sit next to (or, on narrow widths in compact mode, below) the value |
|
|
582
|
-
| Toggle | [simple] | — |
|
|
583
|
-
| ToggleGroup | [composed] | ToggleGroupItem |
|
|
584
|
-
| Tooltip | [composed] | TooltipTrigger, TooltipContent, TooltipProvider |
|
|
585
|
-
|
|
586
|
-
### Component styling notes
|
|
587
|
-
|
|
588
|
-
These are styling behaviors you can't discover from TypeScript types alone:
|
|
589
|
-
|
|
590
|
-
| Component | Note |
|
|
591
|
-
|-----------|------|
|
|
592
|
-
| Button | `font-display font-bold`, sentence case (no `uppercase`). **Variants:** `primary` (blue fill, light surfaces), `primary-inverse` (white fill + blue text, dark/coloured surfaces), `secondary` (black outline, light surfaces), `secondary-inverse` (white outline + white text, dark/coloured surfaces), `tertiary` (text-only, black text, light surfaces — `text-on-prominent` hover `bg-secondary-hover`). **Loading state:** pass `loading` prop — button automatically renders a centred `Spinner`, hides children with `invisible` to preserve width. Do NOT manually place `<Spinner>` or "Loading" text inside the button. |
|
|
593
|
-
| Card | Flat by default (no shadow). Add elevation manually: `className="shadow-sm"` |
|
|
594
|
-
| Input | Resting: `border-input`. Focus: `border-ring` + `ring-[3px] ring-ring/50`. Radius: `rounded-sm` (6px). **Read-only:** pass the native `readOnly` prop — renders with `border-transparent bg-subtle/60`, `pointer-events-none` (non-interactive, non-focusable). Use to display a value that the user should not be able to edit. |
|
|
595
|
-
| InputGroup | Wraps `Input` with inline addons (icons, buttons, text). **Sizes:** `sm` (h-8) / `md` (h-10, default) / `lg` (h-12) — pass `size` to `InputGroup`, it flows to `InputGroupInput` via context. **Padding:** when any `inline-start` or `inline-end` addon is present, input text gets equal `pl-2 pr-2` (8px) on both sides for visual symmetry. Without addons, Input's default `px-3`/`px-4` applies. |
|
|
596
|
-
| InputOTP | **Variants:** OTP 4 digits (single group, 4 slots), OTP 6 digits (single group, 6 slots), OTP 6 split (two groups of 3 with `InputOTPSeparator`), OTP 8 digits (single group, 8 slots), OTP 6 separated (each slot in its own `InputOTPGroup` for individually spaced boxes). Slot: `h-9 w-9`, `border-border-subtle`, `rounded-sm` on first/last. Focus: `border-primary` + `ring-primary/[0.08]`. |
|
|
597
|
-
| NavigationButton | Icon-only tertiary button for navigation. `text-on-prominent` (black icons), `hover:bg-secondary-hover`. **Sizes (8-point grid):** `lg` 48px / 24px icon, `md` 40px / 20px icon, `sm` 32px / 20px icon, `xs` 24px / 16px icon. States: focus `ring-ring/50`, active `opacity-60`, disabled `opacity-24`. Supports `asChild`. |
|
|
598
|
-
| Tooltip | Bubble (default variant): `bg-prominent-inverse` + `text-on-prominent-inverse` (black surface, white text). `inverse` variant: `bg-prominent` + `text-on-prominent` (white surface for use over saturated coloured surfaces). Default primitive includes `max-w-xs` + `whitespace-normal` so consumers don't need to pass them. When a `Kbd` is detected inside via `:has([data-slot=kbd])`, padding bumps to `px-3.5 py-2` and siblings get `space-y-1.5` for breathing room. Always wrap in `<TooltipProvider>`. |
|
|
599
|
-
| Sidebar | `SidebarHeader` / `SidebarFooter` / `SidebarGroup` use `px-layout-margin-inline py-2` (16 px horizontal via `--semantic-layout-margin-inline`), with `group-data-[collapsible=icon]:px-2` so the icon-collapsed rail tightens to 8 px. Menu buttons: `rounded-sm`. Selection: `bg-primary/10` + `text-primary` + `font-semibold`. `lg`-size buttons get `group-data-[collapsible=icon]:p-0! group-data-[collapsible=icon]:justify-center` so a 32-px brand block fills the collapsed rail and a 16-px lucide icon still centers in the same row. |
|
|
600
|
-
| Breadcrumb | Active page: `text-primary font-medium`. Links: `text-on-subtle` |
|
|
601
|
-
| Tabs | **Variants:** `default` (pill, `bg-tabs`) and `line` (underline, transparent bg). **Sizes:** `sm` (h-8, text-xs), `md` (h-10, text-sm, default), `lg` (h-12, text-base). **Icon position:** `inline` (default) or `top` (stacks icon above label). **Orientation:** `horizontal` (default) or `vertical` (line variant renders left-edge indicator). Hover: `bg-secondary-hover` (default) / `text-primary` (line). Selected: `bg-tabs-active` + `text-primary font-semibold`. Line variant underline: `bg-primary`. |
|
|
602
|
-
| Select | **Sizes:** `SelectTrigger` accepts `size` prop: `"sm"` (h-8, text-xs) / `"md"` (h-10, text-sm, **default**) / `"lg"` (h-12, text-base) — matches `Input` and `InputGroup` height scale. Item hover: `bg-primary/[0.08]`. Selected: `text-primary font-medium` + checkmark. `SelectTrigger` also accepts `readOnly` prop: blocks interaction, retains full default appearance, chevron renders at `opacity-30`. |
|
|
603
|
-
| Progress | Track: `bg-primary/20`. Indicator: `bg-primary`. Radius: `rounded-2xs` |
|
|
604
|
-
| Spinner | Inherits parent text color. **Always pass `text-primary` for standalone use** |
|
|
605
|
-
| Stepper | Numeric input flanked by `−` / `+` `secondary` `icon-xs` buttons. Composes `InputGroup` internally. Props: `value`, `defaultValue`, `onValueChange`, `min`, `max`, `step` (default 1), `size` (`"sm" \| "md" \| "lg"`, default `"md"`), `disabled`, `placeholder`. **Sizes:** `sm` — h-8 (32px), `icon-xs` buttons, `size-3` icons; `md` — h-10 (40px), `icon-xs` buttons, `size-3.5` icons; `lg` — h-12 (48px), `icon-sm` buttons, `size-4` icons. Matches `Input` and `InputGroup` height scale exactly. Supports controlled & uncontrolled modes, keyboard Arrow Up/Down, and floating-point steps. Default width: `w-32`. An `InputGroupText` unit label (e.g. `USDT`) can be placed in the `inline-end` addon alongside the `+` button — use `font-normal text-on-subtle` for regular weight and subtle colour. Exports `StepperSize` type. |
|
|
606
|
-
| Switch | Pill track (`rounded-full`) with a circle knob (`rounded-full`). Checked track: `bg-primary`. Unchecked track: `bg-input`. Thumb is always `bg-prominent` (white) in both states. Sizes: `default` (h-6 w-11, 18 px knob) / `sm` (h-5 w-9, 14 px knob). |
|
|
607
|
-
| Slider | Thumb: square `rounded-[4px]`, `bg-primary`. Track range: `bg-slider-range` |
|
|
608
|
-
| Dialog/Sheet | Footer buttons should use `size="md"`. Overlay: `bg-overlay` |
|
|
609
|
-
| Menubar | Hover: `bg-primary/[0.08]`. Open state: `bg-primary/10` |
|
|
610
|
-
| Alert | Dismissible **status** notification. Flat-prop API — pass `title` / `description` / `icon` / `action` / `actions` / `onDismiss` directly; no sub-components. (Promotional / marketing surfaces belong on `Banner`.) **Variants:** `info` (`bg-semantic-info/10`), `warning` (`bg-semantic-warning/10`), `danger` (`bg-semantic-error/10`), `success` (`bg-semantic-win/10`). **Layouts:** `inline` (single row: icon · body · optional action · close X) and `card` (icon · body · close X top-right; up to 2 buttons at bottom-left). **Buttons:** `action` (inline, max 1) and `actions` (card, max 2). Strings get wrapped as `Button variant="secondary" size="sm"`; React elements pass through. **Title colour:** `text-on-prominent` across all variants. **Icon colour:** the variant accent (`text-semantic-info` etc.) carries the severity signal; pass `icon={null}` to omit, or any `ReactNode` to override the per-variant default (`Info`, `AlertTriangle`, `XCircle`, `CheckCircle2`). **Single-line height:** `min-h-12` (48px floor) when only `title` or only `description` is provided in inline layout; grows when content wraps on narrow viewports. **Dismiss:** controlled — `onDismiss` callback; parent owns visibility. **A11y:** `role="alert"` + `aria-live="assertive"` for `danger`/`warning`; `role="status"` + `aria-live="polite"` for `info`/`success`. |
|
|
611
|
-
| Banner | Dismissible **promotional / marketing** surface — feature launches, offers, onboarding nudges, cross-promo. Single visual treatment (no severity variants); for status messages use `Alert`. Flat-prop API: `layout`, `title`, `description`, `icon`/`glyph`, `action`, `actions`, `onDismiss`, `dismissLabel`, `onClick`. **Surface:** tinted primary surface (`bg-primary/[0.08]`) with `border-primary/[0.16]` edge, `rounded-sm` (6 px — matches Card / Alert), `px-4 py-3.5`. **Layouts:** `inline` (icon · body · optional action · close X, single row) and `card` (body row + actions row beneath, bottom-left, max 2 buttons). When the body is multi-line (description set, or `layout="card"`), the grid switches to `items-start` so the leading icon top-aligns with the title; single-line banners stay `items-center`. Multi-line banners also pin the close X to `absolute top-3 right-3` and apply `pr-12` to the surface so the body never wraps under the corner. **Buttons:** strings get wrapped in `Button variant="secondary" size="sm"` across every slot (inline `action` and card `actions`). React elements pass through unchanged. **Title:** `text-sm font-bold text-on-prominent`; wrap emphasis in `<b>` for an in-line brand-blue accent (`[&>b]:text-primary`). **Description:** `text-xs font-medium text-on-subtle`, `mt-0.5` from title. **Default icon:** built-in 40 px brand-blue **square** (`rounded-xs bg-primary`, 4 px corners) with a white `Gift` glyph inside. Two ways to customise: `glyph` swaps just the inner icon while keeping the brand-badge shell intact (use this for "different symbol, same brand badge"); `icon` replaces the entire wrapper (use for fully custom artwork). `icon={null}` omits the column. `icon` wins if both are set — a dev warning fires. **`onClick`:** when set, the whole surface becomes the CTA (cursor-pointer, hover/focus states, keyboard activation). Mutually exclusive with `action`/`actions` — buttons are silently dropped and a dev warning fires. Close X stops propagation so dismissing never triggers the surface click. **A11y:** no `role`/`aria-live` (Banner is not a status surface). |
|
|
612
|
-
| Badge | Variants: `default` (solid blue), `default-success`, `default-fail`, `default-warning` (all use `bg-semantic-*` + matching `text-on-semantic-*` foreground); `fill` (blue tint), `fill-success`, `fill-fail`, `fill-warning`; `fill-credit` (**frosted-glass chip** — `bg-semantic-boost-surface` = `oklch(1 0 0 / 0.22)` translucent white + `backdrop-blur-md` + `text-on-primary` white text; readable only on coloured surfaces — designed to overlay a brand-blue hero card / wallet card, matching the wallet mock's `.c-hero-wc`); `fill-demo` (red-orange tint — `bg-semantic-demo/10` + `text-semantic-demo` — dedicated to "demo account" / "test mode" flags, **not** a severity signal); `outline`; `ghost`, `ghost-success`, `ghost-fail`. Base class no longer applies `tracking-wide` — letter spacing is default. |
|
|
613
|
-
| TicketCard | **Icon:** pass any `ReactNode` via `icon`. Icon container: `size-10` rounded-full, `border-2 border-primary`, `text-primary`. **Labels:** `label` (above value) and `stubLabel` (stub button) render in sentence case — do NOT apply `uppercase` or `tracking-widest`. Stub: `w-[100px]` `bg-primary` button, `text-on-primary`, shimmer sweep animation. Disabled stub: `opacity-50`, `cursor-not-allowed`. Perforation notches sit outside the card box — do NOT put `overflow-hidden` on the card wrapper. **`compact`** (default `false`): `true` = mobile layout — reduces left-content horizontal padding from `px-4 gap-4` to `px-2 gap-2`. **For Welcome credit / bonus use cases:** use `CreditTicketCard` instead — it renders a `<Badge variant="fill-credit">` next to (or below, on narrow compact widths) the value. |
|
|
614
|
-
| CreditTicketCard | Same visual shell as `TicketCard` (perforation notches, tear-line, shimmer stub). The card height is **variable** (grows with content via `py-4`) rather than fixed at `h-20`. The credit is displayed as an inline `<Badge variant="fill-credit" size="sm">` formatted as *"{badgeValue} {badgeCurrency}"* (e.g. `10.00 USDT`). The badge composes optional `badgeIcon` (e.g. `<Gift />`) on the left and an info trigger on the right that opens `badgeInfo` (desktop: `Tooltip variant="inverse"`; mobile: `Drawer`). Tokens used: `bg-subtle`, `bg-primary`, `bg-primary-hover`, `text-on-primary`, `bg-semantic-boost-surface` (`#FDCA8A`), `text-on-semantic-boost` (`#521900`, bold). `compact` shrinks padding and lets the badge wrap to a second line under the value only when balance + badge would otherwise overflow into the deposit stub (responsive `flex-wrap`). |
|
|
615
|
-
| Toggle | Pressed: `bg-primary/10` + `border-primary` + `text-primary` |
|
|
616
|
-
| Calendar | Selected: `bg-secondary-hover` + `text-primary font-bold`. Today: primary dot below date |
|
|
617
|
-
|
|
618
|
-
---
|
|
619
|
-
|
|
620
|
-
## 8.5 — Blocks Catalogue
|
|
621
|
-
|
|
622
|
-
> Blocks are fully composed UI sections built from design system primitives. They are **exported from the package** the same as primitives — import them by name and pass data via props.
|
|
623
|
-
> - **Variants** (`layout` / `mode` / `status`) live on a single block, not separate components.
|
|
624
|
-
> - Each block ships with internal state where appropriate (e.g. `NavBarBlock` manages its own mobile-menu drawer).
|
|
625
|
-
> - Blocks appear in the **Blocks** tab of the playground for visual reference, with the demo importing the same exports a consumer would.
|
|
626
|
-
|
|
627
|
-
### `HeroBlock`
|
|
628
|
-
|
|
629
|
-
Marketing hero section with two layouts.
|
|
630
|
-
|
|
631
|
-
```tsx
|
|
632
|
-
import { HeroBlock } from "@trading-game/design-intelligence-layer"
|
|
633
|
-
|
|
634
|
-
<HeroBlock
|
|
635
|
-
layout="centered" // "centered" | "split"
|
|
636
|
-
tagline={{ label: "What's new", suffix: "v2.0" }}
|
|
637
|
-
heading="Solve your customer's main problem"
|
|
638
|
-
body="One or two sentences expanding on the value prop."
|
|
639
|
-
primaryCta={{ label: "Get started" }}
|
|
640
|
-
secondaryCta={{ label: "Learn more" }} // split layout only
|
|
641
|
-
/>
|
|
642
|
-
```
|
|
643
|
-
|
|
644
|
-
| Variant | Description |
|
|
645
|
-
|---------|-------------|
|
|
646
|
-
| `centered` (Desktop) | Centred single-column: tagline pill + heading + body + single primary CTA with `ArrowRight` icon; no image |
|
|
647
|
-
| `split` (Desktop) | Two columns: tagline pill + heading + body + Get started / Learn more CTAs left; square image panel right |
|
|
648
|
-
| `split` (Mobile) | Single column stacked: text content centred above, image panel full-width below |
|
|
649
|
-
|
|
650
|
-
**Components used:** `Button` (default `sm`, `secondary sm`); `ArrowUpRight`, `ArrowRight` icons (lucide)
|
|
651
|
-
|
|
652
|
-
**Tokens used:** `bg-prominent`, `bg-subtle`, `border-border-subtle`, `text-on-prominent`, `text-on-subtle`, `bg-semantic-win`, `rounded-xl`, `rounded-full`, `px-layout-margin-inline`, `gap-layout-gutter`, `py-24`, `text-5xl`, `font-semibold`, `font-display`, `tracking-tight`, `text-lg`, `font-body`, `text-sm`, `shadow-sm`, `max-w-2xl`
|
|
653
|
-
|
|
654
|
-
---
|
|
655
|
-
|
|
656
|
-
### `AuthBlock`
|
|
657
|
-
|
|
658
|
-
Sign-in / sign-up form. Form fields are identical between modes; `mode` drives heading, terms copy, CTA label, and the footer cross-link.
|
|
659
|
-
|
|
660
|
-
```tsx
|
|
661
|
-
import { AuthBlock } from "@trading-game/design-intelligence-layer"
|
|
662
|
-
|
|
663
|
-
<AuthBlock
|
|
664
|
-
mode="sign-in" // "sign-in" | "sign-up"
|
|
665
|
-
logoSrc="/path/to/brand-icon.svg" // consumer-provided
|
|
666
|
-
providers={["google", "telegram", "x"]} // default: all three
|
|
667
|
-
onSubmit={({ email }) => { ... }}
|
|
668
|
-
crossLinkHref="/auth/signup"
|
|
669
|
-
/>
|
|
670
|
-
```
|
|
671
|
-
|
|
672
|
-
| Region | Content |
|
|
673
|
-
|--------|---------|
|
|
674
|
-
| Top | Brand logo + wordmark lockup |
|
|
675
|
-
| Heading | "Sign in" / "Sign up" (mode-driven) |
|
|
676
|
-
| Providers | Configurable OAuth buttons (Google, Telegram, X) |
|
|
677
|
-
| Body | "or" divider + email input + terms paragraph |
|
|
678
|
-
| Footer | Primary CTA + footer cross-link to the opposite mode |
|
|
679
|
-
|
|
680
|
-
**Components used:** `Button`, `Input`, `Link`
|
|
681
|
-
|
|
682
|
-
**Tokens used:** `text-on-prominent`, `text-on-subtle`, `bg-border-subtle`, `font-display`, `font-body`
|
|
683
|
-
|
|
684
|
-
---
|
|
685
|
-
|
|
686
|
-
### `FAQBlock`
|
|
687
|
-
|
|
688
|
-
Frequently-asked-questions section with optional help card.
|
|
689
|
-
|
|
690
|
-
```tsx
|
|
691
|
-
import { FAQBlock } from "@trading-game/design-intelligence-layer"
|
|
692
|
-
|
|
693
|
-
<FAQBlock
|
|
694
|
-
layout="desktop" // "desktop" | "mobile"
|
|
695
|
-
items={[{ value: "q1", question: "...", answer: "..." }, ...]}
|
|
696
|
-
intro={<>Optional intro paragraph with a <Link>link</Link>.</>}
|
|
697
|
-
helpCard={{ title: "Need more help?", body: "...", ctaLabel: "Contact us" }}
|
|
698
|
-
/>
|
|
699
|
-
```
|
|
700
|
-
|
|
701
|
-
| Variant | Description |
|
|
702
|
-
|---------|-------------|
|
|
703
|
-
| `desktop` | `text-5xl` heading, `gap-12`, help card padding `p-8` |
|
|
704
|
-
| `mobile` | `text-4xl` heading, `gap-10`, help card padding `p-6` |
|
|
705
|
-
|
|
706
|
-
**Components used:** `Accordion`, `AccordionItem`, `AccordionTrigger`, `AccordionContent`, `Button`
|
|
707
|
-
|
|
708
|
-
**Tokens used:** `text-on-prominent`, `text-on-subtle`, `bg-subtle`, `font-display`, `font-body`, `rounded-xl`
|
|
709
|
-
|
|
710
|
-
---
|
|
711
|
-
|
|
712
|
-
### `NavBarBlock`
|
|
713
|
-
|
|
714
|
-
A landing page top navigation bar with internal mobile-menu state. Single component handles both desktop bar and mobile drawer.
|
|
715
|
-
|
|
716
|
-
```tsx
|
|
717
|
-
import { NavBarBlock } from "@trading-game/design-intelligence-layer"
|
|
718
|
-
|
|
719
|
-
<NavBarBlock
|
|
720
|
-
brand={{ fullLogoSrc: "...", iconLogoSrc: "...", alt: "Brand" }}
|
|
721
|
-
links={[{ label: "Products" }, { label: "Docs" }, ...]}
|
|
722
|
-
signIn={{ onClick: ... }}
|
|
723
|
-
signUp={{ onClick: ... }}
|
|
724
|
-
/>
|
|
725
|
-
```
|
|
726
|
-
|
|
727
|
-
| Breakpoint | Description |
|
|
728
|
-
|------------|-------------|
|
|
729
|
-
| Desktop (≥600 px) | Full-width bar: full logo + tertiary nav links left; Sign in (tertiary) + Sign up (primary) right |
|
|
730
|
-
| Mobile — closed | Icon logo left, hamburger icon-button right |
|
|
731
|
-
| Mobile — open | Stacked tertiary nav links + full-width Sign in (secondary) / Sign up (primary) below a divider |
|
|
732
|
-
|
|
733
|
-
**Components used:** `Button` (variants: `tertiary`, `secondary`, default; sizes: `sm`, `icon-sm`); `Menu`, `X` icons (lucide)
|
|
734
|
-
|
|
735
|
-
**Tokens used:** `bg-prominent`, `border-border-subtle`, `rounded-md`, `px-layout-margin-inline`
|
|
736
|
-
|
|
737
|
-
---
|
|
738
|
-
|
|
739
|
-
### `HeaderNavigationBlock`
|
|
740
|
-
|
|
741
|
-
A product app top header bar. Includes optional history button with overlaid numeric count badge.
|
|
742
|
-
|
|
743
|
-
```tsx
|
|
744
|
-
import { HeaderNavigationBlock } from "@trading-game/design-intelligence-layer"
|
|
745
|
-
|
|
746
|
-
<HeaderNavigationBlock
|
|
747
|
-
onBack={() => router.back()}
|
|
748
|
-
badge={{ label: "Demo", variant: "fill-demo" }}
|
|
749
|
-
balance={{ amount: "1000.00", currency: "USDT" }}
|
|
750
|
-
history={{ count: 5, onClick: openHistorySheet }} // count 0 hides badge; >99 shows "99+"
|
|
751
|
-
actions={<SoundToggleButton />}
|
|
752
|
-
/>
|
|
753
|
-
```
|
|
754
|
-
|
|
755
|
-
| Region | Content |
|
|
756
|
-
|--------|---------|
|
|
757
|
-
| Left | `NavigationButton` (back arrow, rendered only if `onBack` provided) |
|
|
758
|
-
| Centre | `Badge` (fill-warning "Demo" label) + balance amount + currency |
|
|
759
|
-
| Right | History `NavigationButton` with optional numeric badge (`bg-primary`, `ring-2 ring-prominent`) + `actions` slot for additional icon buttons |
|
|
760
|
-
|
|
761
|
-
**Components used:** `NavigationButton`, `Badge`; `ArrowLeft`, `History` icons (lucide)
|
|
762
|
-
|
|
763
|
-
**Tokens used:** `bg-prominent`, `border-border-subtle`, `text-on-prominent`, `text-on-subtle`, `bg-primary`, `text-on-primary`, `max-w-layout-diagram-small`, `px-layout-margin-inline`
|
|
764
|
-
|
|
765
|
-
---
|
|
766
|
-
|
|
767
|
-
### `OpenPositionsBlock`
|
|
768
|
-
|
|
769
|
-
A slide-in panel listing open trading positions. Responsive — `Sheet` on desktop, `Drawer` on mobile (via `useIsMobile()`).
|
|
770
|
-
|
|
771
|
-
```tsx
|
|
772
|
-
import { OpenPositionsBlock, type Position } from "@trading-game/design-intelligence-layer"
|
|
773
|
-
|
|
774
|
-
const positions: Position[] = [
|
|
775
|
-
{ kind: "rise-fall", direction: "Rise", market: "Vol 100", duration: "30 minutes",
|
|
776
|
-
stake: "1.00 USDT", pnl: "+0.96 USDT", win: true },
|
|
777
|
-
...
|
|
778
|
-
]
|
|
779
|
-
|
|
780
|
-
<OpenPositionsBlock
|
|
781
|
-
trigger={<Button variant="secondary">Active trades</Button>}
|
|
782
|
-
positions={positions}
|
|
783
|
-
sheetTitle="Positions"
|
|
784
|
-
onViewHistory={openHistoryPage}
|
|
785
|
-
/>
|
|
786
|
-
```
|
|
787
|
-
|
|
788
|
-
Positions are a discriminated union by `kind`:
|
|
789
|
-
|
|
790
|
-
| `kind` | Title rendered as | Extra fields |
|
|
791
|
-
|--------|--------------------|--------------|
|
|
792
|
-
| `"rise-fall"` | `direction` (e.g. "Rise" / "Fall") | — |
|
|
793
|
-
| `"swipe"` | `Swipe-<direction>` (e.g. "Swipe-up") | — |
|
|
794
|
-
| `"box-o"` | `"Box-O"` | `multiplier` |
|
|
795
|
-
| `"digits"` | Type label (e.g. "Matches", "Under") | `type`, `digit?` |
|
|
796
|
-
|
|
797
|
-
**Components used:** `Sheet`, `Drawer`, `Item`, `ItemGroup`, `ItemContent`, `ItemTitle`, `ItemActions`, `Empty`, `EmptyHeader`, `EmptyMedia`, `EmptyTitle`, `Button`, `NavigationButton`, `Separator`
|
|
798
|
-
|
|
799
|
-
**Tokens used:** `bg-prominent`, `border-border-subtle`, `text-semantic-win`, `text-semantic-loss`, `text-on-prominent`, `text-on-subtle`
|
|
800
|
-
|
|
801
|
-
---
|
|
802
|
-
|
|
803
|
-
### `ResultBlock`
|
|
804
|
-
|
|
805
|
-
Universal end-of-round result card. Fixed-width (320 px) with animated halo + thumb illustration (bundled inline as base64) + contract/duration badges + CTA.
|
|
806
|
-
|
|
807
|
-
```tsx
|
|
808
|
-
import { ResultBlock } from "@trading-game/design-intelligence-layer"
|
|
809
|
-
|
|
810
|
-
<ResultBlock
|
|
811
|
-
status="win" // "win" | "loss"
|
|
812
|
-
amount="10,000.00"
|
|
813
|
-
currency="USDT"
|
|
814
|
-
contractLabel="Rise"
|
|
815
|
-
duration="2 hours"
|
|
816
|
-
pickedDigit={7} // optional, for Digits contracts
|
|
817
|
-
ctaMode="next-round" // "next-round" | "go-again" | "conversion"
|
|
818
|
-
/>
|
|
819
|
-
```
|
|
820
|
-
|
|
821
|
-
| `ctaMode` | Renders |
|
|
822
|
-
|-----------|---------|
|
|
823
|
-
| `"next-round"` | Single "Next round" button |
|
|
824
|
-
| `"go-again"` | Single "Go again" button |
|
|
825
|
-
| `"conversion"` | "Ready to play for real?" heading + "Deposit now" + "Stay in demo" |
|
|
826
|
-
|
|
827
|
-
The float / shake / halo animations are defined in `src/styles.css` and ship with the package — consumers who `@import "@trading-game/design-intelligence-layer/styles"` get them automatically.
|
|
828
|
-
|
|
829
|
-
**Components used:** `Card`, `Badge` (variant `standard`), `Button`
|
|
830
|
-
|
|
831
|
-
**Tokens used:** `bg-semantic-win`, `bg-semantic-loss`, `text-semantic-win`, `text-semantic-loss`, `text-on-prominent`, `bg-border-prominent/40`, `font-display`, `font-semibold`, `tabular-nums`, `tracking-tight`, `rounded-md`, `shadow-sm`
|
|
832
|
-
|
|
833
|
-
---
|
|
834
|
-
|
|
835
|
-
### `ResultDialog`
|
|
836
|
-
|
|
837
|
-
Fixed-width system dialog (title + body + two CTAs). Used for messages adjacent to `ResultBlock` like "out of balance" or "on a roll" — same width and styling, no thumb or amount.
|
|
838
|
-
|
|
839
|
-
```tsx
|
|
840
|
-
import { ResultDialog } from "@trading-game/design-intelligence-layer"
|
|
841
|
-
|
|
842
|
-
<ResultDialog
|
|
843
|
-
title="You're out of balance."
|
|
844
|
-
body="Deposit to keep playing or stay in demo mode."
|
|
845
|
-
primaryLabel="Deposit now"
|
|
846
|
-
secondaryLabel="Stay in demo"
|
|
847
|
-
/>
|
|
848
|
-
```
|
|
849
|
-
|
|
850
|
-
**Components used:** `Card`, `Button`
|
|
851
|
-
|
|
852
|
-
**Tokens used:** `text-on-prominent`, `text-on-subtle`, `rounded-md`, `shadow-sm`
|
|
853
|
-
|
|
854
|
-
---
|
|
855
|
-
|
|
856
|
-
## 9 — Common Mistakes
|
|
857
|
-
|
|
858
|
-
| Mistake | Correct Approach |
|
|
859
|
-
| ------- | ---------------- |
|
|
860
|
-
| Using hardcoded hex (`#2323FF`) for primary | Use `bg-primary` or `text-primary` |
|
|
861
|
-
| Using `bg-white` or `bg-black` | Use `bg-prominent` or `bg-overlay` |
|
|
862
|
-
| Using `border-border` | Use `border-border-subtle` or `border-border-prominent` |
|
|
863
|
-
| Using `bg-hover` | Use `bg-primary/[0.08]` or `bg-secondary-hover` |
|
|
864
|
-
| Using `text-primary-foreground` | Use `text-on-primary` (the paired foreground for `bg-primary`) |
|
|
865
|
-
| Using `text-on-prominent-static-inverse` for new code | Pick the paired `text-on-<surface>` for whatever surface sits behind: `text-on-primary` for `bg-primary`, `text-on-prominent-inverse` for dark inverse surfaces, `text-on-semantic-win` / `-loss` / `-warning` / `-boost` for semantic colored surfaces. The static-inverse token is kept as a deprecated alias only. |
|
|
866
|
-
| Using `text-on-decorative` | Use `text-on-subtle` |
|
|
867
|
-
| Using `font-mono` expecting Plus Jakarta Sans | Use `font-display` or `font-body` |
|
|
868
|
-
| Using `font-bold` for headings | Use `font-semibold` (600) for headings |
|
|
869
|
-
| Using `uppercase` on buttons | Buttons use sentence case (no `uppercase`) |
|
|
870
|
-
| Using standard TW sizes for headings (e.g. `text-6xl` = 60px) | Use design system values (`text-6xl` = 64px in this system) |
|
|
871
|
-
| Forgetting responsive heading sizes | Headings scale down on mobile (see Section 4.2) |
|
|
872
|
-
| Using `rounded-[4px]` or `rounded-[2px]` | Use `rounded-xs` (4px) or `rounded-2xs` (2px) |
|
|
873
|
-
| Installing `lucide-react` separately | Already bundled — import icons directly |
|
|
874
|
-
| Adding `tailwind.config.js` | Tailwind v4 uses CSS config via the package |
|
|
875
|
-
| Using `bg-gray-*`, `text-zinc-*`, etc. | Use semantic tokens only |
|
|
876
|
-
| Using `text-gray-400` for disabled text | Use `text-on-disabled` |
|
|
877
|
-
|
|
878
|
-
---
|
|
879
|
-
|
|
880
|
-
## 10 — Accessibility Notes
|
|
881
|
-
|
|
882
|
-
1. **Primary blue text on white** (~3.0:1) — reserve for large/bold UI labels only.
|
|
883
|
-
2. **Secondary text `text-on-subtle` on white** (~4.5:1) — meets WCAG AA for normal text.
|
|
884
|
-
3. **Secondary text `text-on-subtle` on white** (~4.5:1) — meets WCAG AA for normal text.
|
|
885
|
-
4. **Win green on white** (~5.0:1) — safe for normal text at AA.
|
|
886
|
-
5. **Loss red on white** (~3.9:1) — use at 18px+ bold or pair with icons.
|
|
887
|
-
6. Always pair semantic colors with **icons or labels** — never communicate meaning through color alone.
|
|
888
|
-
|
|
889
|
-
---
|
|
890
|
-
|
|
891
|
-
## Quick Reference — Code Snippets
|
|
892
|
-
|
|
893
|
-
**Primary CTA:**
|
|
894
|
-
```tsx
|
|
895
|
-
<Button variant="primary" size="lg">Trade Now</Button>
|
|
896
|
-
```
|
|
897
|
-
|
|
898
|
-
**Profit/Loss display:**
|
|
899
|
-
```tsx
|
|
900
|
-
<span className="text-semantic-win font-body font-semibold">+$84.00</span>
|
|
901
|
-
<span className="text-semantic-loss font-body font-semibold">-$120.00</span>
|
|
902
|
-
```
|
|
903
|
-
|
|
904
|
-
**Heading:**
|
|
905
|
-
```tsx
|
|
906
|
-
<h1 className="heading-h1">Trading Game</h1>
|
|
907
|
-
```
|
|
908
|
-
|
|
909
|
-
**Body text:**
|
|
910
|
-
```tsx
|
|
911
|
-
<p className="body-md">Your portfolio summary for today.</p>
|
|
912
|
-
```
|
|
913
|
-
|
|
914
|
-
**Input with focus styling:**
|
|
915
|
-
```tsx
|
|
916
|
-
<Input type="email" placeholder="Enter your email" />
|
|
917
|
-
```
|
|
918
|
-
|
|
919
|
-
**Read-only input:**
|
|
920
|
-
```tsx
|
|
921
|
-
<Input value="Read-only value" readOnly />
|
|
922
|
-
```
|
|
923
|
-
|
|
924
|
-
---
|
|
925
|
-
|
|
926
|
-
## 11 — Release Notes
|
|
927
|
-
|
|
928
|
-
### v0.17.4
|
|
929
|
-
|
|
930
|
-
- **Button `tertiary` variant** — text color changed from `text-primary` (blue) to `text-on-prominent` (black). Hover changed from `bg-primary/[0.08]` to `bg-secondary-hover`. Use `tertiary-inverse` for white text on dark/coloured surfaces (unchanged).
|
|
931
|
-
- **Input `readOnly` state** — native `readOnly` prop now has a distinct visual treatment: `border-transparent`, `bg-subtle/60`, `pointer-events-none`. Renders as a non-interactive display field. Clearly distinguishable from both the default (bordered) and `disabled` (faded/greyed) states.
|
|
932
|
-
- **Demo page sidebar** — replaced custom `<aside>` + plain buttons with the design system `Sidebar` component (`SidebarProvider`, `SidebarMenu`, `SidebarMenuButton` with `isActive`).
|
|
933
|
-
- **Demo page layout** — removed `max-w-5xl` content cap; content now uses the full available width.
|