@deriv-ds/design-intelligence-layer 0.6.1 → 0.6.2
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/.claude/skills/build/SKILL.md +74 -14
- package/.claude/skills/build/references/components-and-tokens.md +49 -22
- package/AGENTS.md +3 -3
- package/CHANGELOG.md +7 -0
- package/README.md +21 -15
- package/dist/index.cjs +1473 -1181
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +42 -6
- package/dist/index.d.ts +42 -6
- package/dist/index.js +1491 -1209
- package/dist/index.js.map +1 -1
- package/guides/design-system-guide/deriv-design-intelligence-guide.md +214 -176
- package/guides/design-system-guide/icon-reference.md +1 -1
- package/guides/design-system-guide/quill-ds-guide.md +31 -30
- package/guides/rules/design-system-consuming-project.mdc +42 -30
- package/package.json +1 -1
- package/src/styles.css +73 -3
|
@@ -123,6 +123,8 @@ Rule: don't add `flex-1` to the body unless `get_design_context` confirms the fo
|
|
|
123
123
|
|
|
124
124
|
The package ships whole page sections as blocks. **Before you build any region from primitives, match it against the block catalog.** A region that corresponds to a shipped block must be *imported*, not mocked up — re-implementing a navbar, hero, or card the package already exports is a defect, even if your version "looks right".
|
|
125
125
|
|
|
126
|
+
**Step 0 — classify the page type FIRST, then apply the App Shell defaults.** Before matching individual regions, decide what kind of page this is (home/dashboard, trading, form/settings, marketing/landing, auth, standalone). Home/dashboard pages have a **mandatory default app shell** — a header block + `Navbar` — that must be included *even when the prompt or frame never mentions them* (see [App Shell defaults](#app-shell-defaults--homedashboard-pages) below). This is the fix for the most common defect: a home page rendered with no top header and no bottom nav. Match on **intent and implication, not just explicit mentions** — a "home page" implies the shell whether or not the word "navbar" appears.
|
|
127
|
+
|
|
126
128
|
**Procedure — for every distinct region of the page (header strip, nav, hero/balance area, banner, highlight cards, trading cards, action buttons, empty state, referral panel, footer/section wrapper):**
|
|
127
129
|
|
|
128
130
|
1. **Identify the region's intent** — not its pixels. "Top nav with menu items", "balance/total-assets header", "promo banner card", "row of highlight cards", "account card with balance + actions", "empty trading list", "referral invite panel". The intent is what you match on.
|
|
@@ -142,6 +144,48 @@ Record every region's outcome (`block: <Name>` or `composed`) — this feeds the
|
|
|
142
144
|
|
|
143
145
|
---
|
|
144
146
|
|
|
147
|
+
## App Shell defaults — home/dashboard pages
|
|
148
|
+
|
|
149
|
+
**Home and dashboard pages ship with an app shell by default — a header block on top and a `Navbar`.** These regions are *implied* by the page type, so the Block Matching gate must inject them even when the user's prompt or the Figma frame never names them. A home page rendered as a bare content column with no top header and no bottom nav is a defect — this section exists to kill it.
|
|
150
|
+
|
|
151
|
+
**When it applies:** the page is classified (gate Step 0) as **home** or **dashboard** — prompts like "home page", "dashboard", "wallet home", "main app screen", or a Figma frame that is clearly the app home/landing-after-login. It does NOT auto-apply to marketing/landing pages, auth screens, or explicitly standalone screens (a single card, a success screen, one onboarding step).
|
|
152
|
+
|
|
153
|
+
**What the shell is:**
|
|
154
|
+
|
|
155
|
+
| Shell region | Block | Notes |
|
|
156
|
+
|---|---|---|
|
|
157
|
+
| Top header | `HeaderAppHome` (home) or `HeaderApp` (in-app sub-page) | Match to the frame's header if one is shown; **inject `HeaderAppHome` if the design omits it** on a home/dashboard page. |
|
|
158
|
+
| Navigation | `Navbar` (responsive) | Renders `NavDesktopSidebar` ≥768px and `NavMobileBottomBar` <768px automatically. Wire `activeId` to the current page. |
|
|
159
|
+
|
|
160
|
+
**Rules:**
|
|
161
|
+
- Include the shell by default on home/dashboard builds. **Skip it only** when the user explicitly says "no nav / no header / just the content", or the page is clearly not a home/dashboard.
|
|
162
|
+
- The shell counts as matched blocks — read their real props (`HeaderAppHomeProps`, `Navbar`'s `activeId`/`badges`/`onNavChange`) from `dist/index.d.ts` before wiring, per gate step 4.
|
|
163
|
+
- Record the shell decision in the Build Report's block audit — either `block: HeaderAppHome` + `block: Navbar`, or `omitted (reason)`.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Responsive coverage — every build ships mobile AND desktop
|
|
168
|
+
|
|
169
|
+
**Every page build must render correctly at BOTH a mobile viewport (~375px) and a desktop viewport (~1440px).** A mobile-only render (the second common defect) is not "done". Blocks are designed for this: `Navbar` is responsive internally, and heroes/trading blocks ship as mobile/desktop pairs.
|
|
170
|
+
|
|
171
|
+
**How to cover both viewports:**
|
|
172
|
+
- **Responsive blocks** (`Navbar`, `Section`, and any block taking a `layout` prop) work at both widths out of the box — use them directly.
|
|
173
|
+
- **Paired blocks** (mobile/desktop hero + trading variants) have no single responsive export — render BOTH and switch on the package's **768px breakpoint** using visibility utilities, mirroring how `Navbar` picks its variant:
|
|
174
|
+
|
|
175
|
+
```tsx
|
|
176
|
+
{/* mobile hero <768px */}
|
|
177
|
+
<div className="md:hidden"><HeroMobileHomeTotalAssets /></div>
|
|
178
|
+
{/* desktop hero ≥768px */}
|
|
179
|
+
<div className="hidden md:block"><HeroDesktopHomeWithBalance /></div>
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
- The mobile/desktop pairing table lives in [references/components-and-tokens.md](references/components-and-tokens.md) (Blocks section) — resolve BOTH variants of every paired region before writing JSX.
|
|
183
|
+
- **Only render a single viewport** when the user explicitly restricts scope ("mobile only", "just the desktop view").
|
|
184
|
+
|
|
185
|
+
**Mode 4 (Figma) responsive rule:** the provided frame is the 1:1 ground truth **at its own viewport**. The *other* viewport is generated by default from the corresponding desktop/mobile block variants and brand-consistent layout — flagged in the Build Report as "generated, no frame provided". If the user supplies frames for both viewports, each is its own 1:1 replica. The visual-diff loop (4.4) runs against the frame's viewport; the generated viewport gets the runtime responsive checks (Final Checklist), not a pixel diff.
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
145
189
|
## Mode 1 — Router
|
|
146
190
|
|
|
147
191
|
When invoked, classify the user's message:
|
|
@@ -220,11 +264,13 @@ If the user immediately follows with a build request, chain into the matching mo
|
|
|
220
264
|
2. Read `node_modules/@deriv-ds/design-intelligence-layer/guides/rules/design-system-consuming-project.mdc`.
|
|
221
265
|
3. Read [references/components-and-tokens.md](references/components-and-tokens.md) for the canonical component list and token cheatsheet.
|
|
222
266
|
4. **Run Preflight** (above) to clean any leftover Geist/font/`:root` scaffold defects.
|
|
223
|
-
5. **
|
|
224
|
-
6.
|
|
225
|
-
7.
|
|
226
|
-
8.
|
|
227
|
-
9.
|
|
267
|
+
5. **Classify the page type** (gate Step 0) — home/dashboard, trading, form/settings, marketing, auth, standalone. If home/dashboard, the **App Shell defaults** apply: include `HeaderAppHome` (or `HeaderApp`) + `Navbar` by default, even though the prompt didn't name them.
|
|
268
|
+
6. **Run the Block Matching gate** (above) over the page's regions — any region the prompt names OR implies that maps to a block (app shell header + nav, hero/balance header, banner, highlights, explore, trading cards, action buttons, empty state, referral) is imported as that block, not mocked up. Only the regions with no block match proceed to primitive composition.
|
|
269
|
+
7. Map the remaining (non-block) regions to components. For each required UI element, confirm it's on the list (HARD RULE 1). Anything missing → compose from package components + tokens, flag in the Build Report.
|
|
270
|
+
8. Sketch the layout structurally (flex/grid utilities are fine); if the page has a bottom action bar, use the **Page layout scaffold** above. Then drop in matched blocks and package components. Every colour/radius/font value goes through the **Token Resolution Loop**. Page background → `bg-card`, primary text → `text-prominent` (never `bg-prominent` as a surface). Typography → `heading-*`/`body-*` classes (NOT `text-heading-*`).
|
|
271
|
+
9. **Cover both viewports** (see [Responsive coverage](#responsive-coverage--every-build-ships-mobile-and-desktop)) — use responsive blocks directly and render both variants of any paired block behind `md:hidden` / `hidden md:block`, unless the user restricted scope to one viewport.
|
|
272
|
+
10. Write copy in a voice aligned with `deriv-brand-voice.md`.
|
|
273
|
+
11. Run the Final Checklist below.
|
|
228
274
|
|
|
229
275
|
---
|
|
230
276
|
|
|
@@ -272,6 +318,8 @@ Build a table with one row per **visible node** from `get_metadata` (not just "k
|
|
|
272
318
|
|
|
273
319
|
Generate the page from the contract — the contract is the spec, the screenshot is the ground truth. Register all created tokens in `globals.css` first, then write JSX using only generated classes and package components.
|
|
274
320
|
|
|
321
|
+
**App shell + responsive expansion:** if the frame is a home/dashboard page, apply the **App Shell defaults** (inject `HeaderAppHome`/`HeaderApp` + `Navbar` even if the frame omits them). Then expand to the viewport the frame does NOT cover per the **Mode 4 responsive rule** — swap paired blocks to their opposite variant (`HeroMobile*` ⇄ `HeroDesktop*`) behind `md:hidden` / `hidden md:block`, and let responsive blocks (`Navbar`, `Section`) handle themselves. The generated viewport is brand-consistent layout, not a pixel replica — flag it in the Build Report.
|
|
322
|
+
|
|
275
323
|
### 4.4 Visual-diff loop — iterate until it matches
|
|
276
324
|
|
|
277
325
|
"Renders without errors" proves nothing about parity. With the dev server running:
|
|
@@ -337,6 +385,15 @@ The runtime check below is the backstop: a token-intended element whose computed
|
|
|
337
385
|
|
|
338
386
|
**Blocks matched, not mocked** — every page region went through the Block Matching gate. No region hand-rolls a navbar, hero, card, banner, action-button cluster, empty state, or referral panel that the package already ships as a block. A region built from primitives must have NO matching block in the catalog — confirm before declaring done; this is recorded in the Build Report's block audit.
|
|
339
387
|
|
|
388
|
+
**App shell present (home/dashboard)** — if the page is a home/dashboard build, confirm the default shell is there: a header block (`HeaderAppHome`/`HeaderApp`) at the top AND `Navbar`. A home page with no header or no nav is a defect unless the user explicitly opted out (record the opt-out in the block audit).
|
|
389
|
+
|
|
390
|
+
**Responsive verification** — the build must work at BOTH viewports, not just mobile. With the preview running, `preview_resize` to **375px** and to **1440px** and confirm at each:
|
|
391
|
+
- At **1440px**: `Navbar` renders the **desktop sidebar** (not the mobile bottom bar); no mobile-only block is stretched full-width; paired blocks show their desktop variant.
|
|
392
|
+
- At **375px**: `Navbar` renders the **bottom bar**; paired blocks show their mobile variant; no horizontal overflow.
|
|
393
|
+
- The header block (on home/dashboard) is present at both widths.
|
|
394
|
+
- (Mode 4) the frame's own viewport still matches the visual-diff loop result; the generated viewport is laid out cleanly.
|
|
395
|
+
A single-viewport render is a defect unless the user restricted scope.
|
|
396
|
+
|
|
340
397
|
**Import audit** — every import in the diff comes from `@deriv-ds/design-intelligence-layer`, including icons via `<Icon />`. No `lucide-react` or other icon lib. No `@/components/ui/*`. No `@deriv-com/quill-ui*`. Every imported name exists in `dist/index.d.ts` (beware `Tabs`/`Notification`/`Chart`/`Resizable`/`Direction` — see the hallucinated-imports table).
|
|
341
398
|
|
|
342
399
|
**Created tokens registered** — every class generated by the Token Resolution Loop has its `@theme inline` registration in `globals.css`, named by intent, listed for the Build Report.
|
|
@@ -412,25 +469,28 @@ The build is not "done" until the runtime checks pass **and** you present this r
|
|
|
412
469
|
|
|
413
470
|
**Hallucinated classes must be fixed before this report is shown** — the table is proof they were caught and corrected, not a to-do list.
|
|
414
471
|
|
|
415
|
-
3. **Block audit (Block Matching gate)** — one row per page region, proving each was matched against the block catalog and either imported as a block or consciously composed. A region that *should* have used a block but was hand-rolled is a defect — fix before showing this report.
|
|
472
|
+
3. **Block audit (Block Matching gate)** — one row per page region, proving each was matched against the block catalog and either imported as a block or consciously composed. A region that *should* have used a block but was hand-rolled is a defect — fix before showing this report. For home/dashboard pages, the **app shell rows (header + nav) are mandatory** — show them as imported blocks or as an explicit user opt-out.
|
|
416
473
|
|
|
417
474
|
| Region | Outcome | Evidence / reason |
|
|
418
475
|
|---|---|---|
|
|
419
|
-
|
|
|
420
|
-
|
|
|
476
|
+
| App header | `block: HeaderAppHome` | app shell default (home page); export in dist/index.d.ts |
|
|
477
|
+
| Navigation | `block: Navbar` | app shell default; responsive sidebar/bottom-bar; export in dist/index.d.ts |
|
|
478
|
+
| Balance header | `block: HeroMobileHomeTotalAssets` + `HeroDesktopHomeWithBalance` | paired mobile/desktop, `md:hidden` switch |
|
|
421
479
|
| Promo strip | `composed` | no block matches a 2-up promo grid — flagged |
|
|
422
480
|
|
|
423
|
-
4. **
|
|
481
|
+
4. **Responsive coverage** — state which viewports were built and verified (mobile ~375px, desktop ~1440px), which regions used responsive blocks vs paired mobile/desktop variants, and — in Mode 4 — which viewport was a 1:1 frame replica vs generated from the opposite block variant. A build verified at only one viewport must say so and why (explicit user scope).
|
|
482
|
+
|
|
483
|
+
5. **Created tokens** — every `@theme inline` registration added to `globals.css`, with which loop step produced it (semantic var / primitive / exact value) and whether it's dark-mode-aware.
|
|
424
484
|
|
|
425
|
-
|
|
485
|
+
6. **Fidelity results (Mode 4)** — visual-diff loop: how many iterations, what was fixed each pass. Then the contract: every row ✅ matched or listed as a deviation with the reason. State explicitly: zero invented elements, zero omitted elements, copy verbatim.
|
|
426
486
|
|
|
427
|
-
|
|
487
|
+
7. **⚠ Flagged** — composed (non-package) elements, token substitutions, assumptions made. If nothing was flagged, say so explicitly.
|
|
428
488
|
|
|
429
|
-
|
|
489
|
+
8. **Intentional DS behaviours** — surface things that look like bugs but aren't (e.g. the coral focus ring on inputs), so the user doesn't try to "fix" them.
|
|
430
490
|
|
|
431
|
-
|
|
491
|
+
9. **Needs your review** — anything uncertain or that you couldn't verify (e.g. preview tools unavailable), plus any critic violations still unresolved after 3 rounds.
|
|
432
492
|
|
|
433
|
-
|
|
493
|
+
10. **Independent audit** — the critic verdict: how many rounds ran, and what it caught and you fixed (hallucinated imports, unregistered tokens, out-of-scope edits). If the critic could not run (no subagent + you did the fresh pass yourself), say so.
|
|
434
494
|
|
|
435
495
|
---
|
|
436
496
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Components & tokens — `@deriv-ds/design-intelligence-layer`
|
|
2
2
|
|
|
3
|
-
This is the **authoritative cheatsheet** for building in a consuming project, verified against the published package (v0.6.
|
|
3
|
+
This is the **authoritative cheatsheet** for building in a consuming project, verified against the published package (v0.6.2). If something isn't here and isn't in the package's `dist/index.d.ts`, it doesn't exist — resolve it with the Token Resolution Loop (for styles) or compose it from real components (for UI). Never invent an import or a class. (The `npm run check:skill-catalog` script in the source repo guards this list against the package's real exports.)
|
|
4
4
|
|
|
5
5
|
> **Verification targets** (the package ships compiled — there is NO `src/index.ts`):
|
|
6
6
|
> - Components → `node_modules/@deriv-ds/design-intelligence-layer/dist/index.d.ts`
|
|
@@ -125,9 +125,10 @@ grep -w "<ComponentName>" node_modules/@deriv-ds/design-intelligence-layer/dist/
|
|
|
125
125
|
|
|
126
126
|
These files exist under `components/ui/` in the source repo but are **not** re-exported from the package, so they are not importable by consumers. Treat them as nonexistent and compose the equivalent from real exports:
|
|
127
127
|
|
|
128
|
-
- `navigation-menu` (`NavigationMenu*`) — use `Navbar` / the nav blocks, or compose with `DropdownMenu` / `Sidebar`.
|
|
129
128
|
- `theme-toggle` (`ThemeToggle`) — compose from `Button` + `Switch` + `<Icon />`.
|
|
130
129
|
|
|
130
|
+
> `NavigationMenu*` (`NavigationMenu`, `NavigationMenuList`, `NavigationMenuItem`, `NavigationMenuTrigger`, `NavigationMenuContent`, `NavigationMenuLink`, `NavigationMenuIndicator`, `NavigationMenuViewport`) **is now a real export** — prefer the `Navbar` / nav blocks for app navigation, but the primitive is available when you need a custom menu. Verify with `grep -w NavigationMenu node_modules/@deriv-ds/design-intelligence-layer/dist/index.d.ts` against the installed version.
|
|
131
|
+
|
|
131
132
|
### Secondary exports (real, but rarely imported directly)
|
|
132
133
|
|
|
133
134
|
Exported and valid, but niche — only reach for them when you specifically need them: `ChartStyle` (internal to the Chart family), `IconSizeContext` (advanced `<Icon />` sizing). Most builds never touch these.
|
|
@@ -200,25 +201,26 @@ variable `component/app/background/normal` (`#ffffff`) → **`bg-card`**.
|
|
|
200
201
|
| `text-primary` | brand text — coral | #FF444F |
|
|
201
202
|
| `text-warning` | warning text | #C47D00 |
|
|
202
203
|
| `text-info` | informational text | #0777C4 |
|
|
204
|
+
| `text-success` | success text — green | #007A22 light / #4DBC6B dark |
|
|
205
|
+
| `text-error` | error / danger text — red | #C40000 light / #FF4D4D dark |
|
|
206
|
+
| `text-on-primary` / `text-on-success` / `text-on-error` / `text-on-warning` / `text-on-info` | foreground for text/icons **on a solid coloured surface** (`bg-primary`, `bg-success`, …) — always-legible static-inverse | #FFFFFF |
|
|
203
207
|
|
|
204
|
-
###
|
|
208
|
+
### Status colours — now built in
|
|
205
209
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
+
`text-success`, `text-error`, `text-warning`, `text-info` are **shipped utilities** (theme-aware —
|
|
211
|
+
they flip automatically in dark mode). Their solid `bg-*` / `border-*` / `ring-*` counterparts also
|
|
212
|
+
generate (`bg-success`, `bg-error`, `border-success`, …) and pair with the `text-on-*` foregrounds
|
|
213
|
+
above. For a **subtle opaque status tint** that reads identically on any background (cards, chips,
|
|
214
|
+
banners) use the surface utilities:
|
|
210
215
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
--color-error: var(--text-error-default); /* #C40000 light / #FF4D4D dark → text-error */
|
|
216
|
-
--color-success-fill: var(--background-success-default); /* green tint → bg-success-fill */
|
|
217
|
-
--color-error-fill: var(--background-error-default); /* red tint → bg-error-fill */
|
|
218
|
-
}
|
|
219
|
-
```
|
|
216
|
+
| Class | Use |
|
|
217
|
+
|---|---|
|
|
218
|
+
| `bg-success-surface` / `bg-error-surface` / `bg-warning-surface` / `bg-info-surface` | opaque status tint background (color-mix — no bleed-through on coloured surfaces) |
|
|
219
|
+
| `bg-success/10`, `bg-error/16`, … | alpha status tint (fine on the page canvas; can bleed on coloured surfaces) |
|
|
220
220
|
|
|
221
|
-
|
|
221
|
+
Only **game-specific profit/loss** utilities (`text-win`, `text-loss`, `bg-win`, `bg-loss`) are NOT
|
|
222
|
+
shipped — register those with the Token Creation pattern below (map to `--text-success-default` /
|
|
223
|
+
`--text-error-default`). Never use a raw green/red hex or `text-green-600`.
|
|
222
224
|
|
|
223
225
|
### Borders & ring
|
|
224
226
|
|
|
@@ -232,7 +234,7 @@ This is the canonical Token Creation pattern (below) — never use a raw green/r
|
|
|
232
234
|
| `ring-ring` | focus ring — **coral** | #FF444F |
|
|
233
235
|
|
|
234
236
|
> `border-border` is deprecated — use `border-border-subtle` or `border-border-prominent`.
|
|
235
|
-
> `border-success` / `border-error`
|
|
237
|
+
> `border-success` / `border-error` now generate (solid status colour) alongside `bg-success` / `bg-error`.
|
|
236
238
|
|
|
237
239
|
### Radius
|
|
238
240
|
|
|
@@ -247,10 +249,9 @@ definition, so they produce **no CSS** — the element silently inherits a wrong
|
|
|
247
249
|
|
|
248
250
|
| ❌ Doesn't exist | ✅ Real fix |
|
|
249
251
|
|---|---|
|
|
250
|
-
| `text-on-prominent` | `text-prominent` |
|
|
252
|
+
| `text-on-prominent` | `text-prominent` (`text-on-prominent` is always-white — for dark/coloured surfaces only) |
|
|
251
253
|
| `text-on-subtle` | `text-subtle` |
|
|
252
|
-
| `
|
|
253
|
-
| `bg-loss` / `text-loss` / `bg-win` / `text-win` | registered `text-error` / `text-success` |
|
|
254
|
+
| `bg-loss` / `text-loss` / `bg-win` / `text-win` | register first (game profit/loss — see Status colours above), then use |
|
|
254
255
|
| `bg-prominent` (as page bg) | `bg-card` |
|
|
255
256
|
| `bg-subtle` (as page bg) | `bg-card` / `bg-primary-canvas` |
|
|
256
257
|
| `text-heading-h1`, `text-body-md`, `text-heading-mega` | `heading-h1`, `body-md`, `heading-hero` (see Typography) |
|
|
@@ -396,7 +397,33 @@ The **"matches when"** column is what the Block Matching gate matches on — int
|
|
|
396
397
|
| **Referral** | `Referral` | refer-a-friend / invite panel |
|
|
397
398
|
| **Section** | `Section` | eyebrow tag + title + control cluster + segmented control wrapping a content slot (children) |
|
|
398
399
|
|
|
399
|
-
Most heroes/trading blocks also export a `*Skeleton` variant for loading states.
|
|
400
|
+
Most heroes/trading blocks also export a `*Skeleton` variant for loading states.
|
|
401
|
+
|
|
402
|
+
### Default app shell — home/dashboard pages
|
|
403
|
+
|
|
404
|
+
**Home and dashboard pages ship a default app shell even when the prompt/frame never mentions it:** a header block on top + `Navbar`. The build skill's Block Matching gate injects these automatically (see SKILL.md → *App Shell defaults*). Skip only on explicit user opt-out, or for marketing/auth/standalone screens.
|
|
405
|
+
|
|
406
|
+
| Shell region | Block | Wire |
|
|
407
|
+
|---|---|---|
|
|
408
|
+
| Top header | `HeaderAppHome` (home) / `HeaderApp` (in-app sub-page) | avatar, notification badge, actions |
|
|
409
|
+
| Navigation | `Navbar` (responsive) | `activeId`, `badges`, `onNavChange` |
|
|
410
|
+
|
|
411
|
+
### Mobile / desktop variant pairing — render BOTH viewports
|
|
412
|
+
|
|
413
|
+
Blocks target **both** a mobile (~375px) and desktop (~1440px) viewport. Some blocks are responsive on their own; others ship as an explicit mobile/desktop pair with **no** single responsive export — render BOTH and switch on the **768px** breakpoint with `md:hidden` (mobile) / `hidden md:block` (desktop), mirroring how `Navbar` picks its variant internally. Resolve BOTH variants of every paired region before writing JSX. Render a single viewport only when the user restricts scope.
|
|
414
|
+
|
|
415
|
+
| Region | Mobile | Desktop | Responsive? |
|
|
416
|
+
|---|---|---|---|
|
|
417
|
+
| Navigation | `NavMobileBottomBar` | `NavDesktopSidebar` | **Yes — use `Navbar`** (auto-switches) |
|
|
418
|
+
| Hero — home (title) | `HeroMobileHomeTitle` | `HeroDesktopHomeOnboarding` | No — pair + `md:` switch |
|
|
419
|
+
| Hero — home (balance) | `HeroMobileHomeTotalAssets` | `HeroDesktopHomeWithBalance` | No — pair + `md:` switch |
|
|
420
|
+
| Hero — main | `HeroMobileMain` | `HeroDesktopMain` | No — pair + `md:` switch |
|
|
421
|
+
| Hero — secondary | `HeroMobileSecondary` | `HeroDesktopSecondary` | No — pair + `md:` switch |
|
|
422
|
+
| Hero — transaction | `HeroMobileTransaction` | *(reuse mobile / compose)* | No |
|
|
423
|
+
| Section | `Section` | `Section` | Yes — same export |
|
|
424
|
+
| Trading / home cards | responsive via `layout` prop where present | — | Prefer `layout` prop |
|
|
425
|
+
|
|
426
|
+
New blocks favour a single `layout="mobile" \| "desktop"` prop over separate exports — check the block's props in `dist/index.d.ts` before assuming a pair.
|
|
400
427
|
|
|
401
428
|
---
|
|
402
429
|
|
package/AGENTS.md
CHANGED
|
@@ -10,7 +10,7 @@ Before building any landing page, product screen, game view, or feature UI, you
|
|
|
10
10
|
|
|
11
11
|
**Design principles** — the decision framework for every layout, hierarchy, motion, copy, and component choice:
|
|
12
12
|
```
|
|
13
|
-
node_modules/@deriv-ds/design-intelligence-layer/guides/design-principles/
|
|
13
|
+
node_modules/@deriv-ds/design-intelligence-layer/guides/design-principles/quill-design-principles.md
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
**Accessibility standards** — the inclusion standard every screen must meet (WCAG 2.1 AA):
|
|
@@ -75,7 +75,7 @@ Re-copy both after every version bump so the shims match the installed release.
|
|
|
75
75
|
## Step 3 — Core rules summary
|
|
76
76
|
|
|
77
77
|
1. **Check before building** — if a component exists in `@deriv-ds/design-intelligence-layer`, import it. Never re-implement it.
|
|
78
|
-
2. **Tokens only** — use semantic token classes (`bg-
|
|
78
|
+
2. **Tokens only** — use semantic token classes (`bg-primary-canvas`, `text-prominent`, `border-default`, etc.). Never hardcode hex values, raw Tailwind palette colors, or CSS variables.
|
|
79
79
|
3. **Design principles and accessibility first** — every screen must reflect the 8 design principles and meet the accessibility standards (WCAG 2.1 AA). Run both checklists before shipping.
|
|
80
80
|
4. **No separate installs** — do not install `tailwindcss` or other bundled dependencies separately. Never install or import `lucide-react` or any other icon library.
|
|
81
81
|
5. **Icons** — use the exported `<Icon />` component (`@deriv/quill-icons`): `<Icon name="bell" weight="bold" />`. Three weights: `regular` (unselected nav, subtle), `bold` (default), `fill` (selected nav, strong actions). Full catalog of names, weights, and intent → icon mappings: `guides/design-system-guide/icon-reference.md`. At runtime, `ICON_NAMES` and `iconAvailableWeights(name)` are exported from the package.
|
|
@@ -102,7 +102,7 @@ Re-copy both after every version bump so the shims match the installed release.
|
|
|
102
102
|
## Reference
|
|
103
103
|
|
|
104
104
|
- Full token + component reference: `node_modules/@deriv-ds/design-intelligence-layer/README.md`
|
|
105
|
-
- Design principles: `node_modules/@deriv-ds/design-intelligence-layer/guides/design-principles/
|
|
105
|
+
- Design principles: `node_modules/@deriv-ds/design-intelligence-layer/guides/design-principles/quill-design-principles.md`
|
|
106
106
|
- Accessibility standards: `node_modules/@deriv-ds/design-intelligence-layer/guides/accessibility-standards/trading-game-accessibility-standards.md`
|
|
107
107
|
- Personas: `node_modules/@deriv-ds/design-intelligence-layer/guides/personas/trading-game-player-field-guide.md`
|
|
108
108
|
- Brand voice: `node_modules/@deriv-ds/design-intelligence-layer/guides/brand-voice/deriv-brand-voice.md`
|
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.6.2]
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- **Focus ring contrast (WCAG 1.4.11 / 2.4.7)** — the base focus outline was rendered at 50% alpha and the `--ring` token (coral-700) fell well under the 3:1 minimum once composited. `--ring` is now blue-800 (`#1789e1`), rendered at full opacity, and every component's `focus-visible` ring is standardized to `ring-2 ring-ring ring-offset-2 ring-offset-primary-surface` — verified at ≥3:1 against both light and dark surfaces, and against coral primary buttons via the offset gap. (#38)
|
|
14
|
+
- **`prefers-reduced-motion` support** — added a global `@media (prefers-reduced-motion: reduce)` rule that collapses animation/transition durations and disables smooth scrolling package-wide. (#38)
|
|
15
|
+
- **Stale agent-facing docs** — corrected `AGENTS.md`'s design-principles path (was pointing at a non-existent file) and refreshed ring-color references in the consuming-project rules and design-system guides to match the shipped coral/blue theme. (#38)
|
|
16
|
+
|
|
10
17
|
## [0.6.1]
|
|
11
18
|
|
|
12
19
|
### Note
|
package/README.md
CHANGED
|
@@ -87,7 +87,7 @@ Icons are provided by **`@deriv/quill-icons`** via the bundled `Icon` component
|
|
|
87
87
|
import { Icon } from "@deriv-ds/design-intelligence-layer"
|
|
88
88
|
|
|
89
89
|
<Icon name="bell" />
|
|
90
|
-
<Icon name="circle-check" weight="fill" className="text-success" />
|
|
90
|
+
<Icon name="circle-check" weight="fill" className="text-[var(--text-success-default)]" />
|
|
91
91
|
```
|
|
92
92
|
|
|
93
93
|
The full icon catalog is at `node_modules/@deriv-ds/design-intelligence-layer/guides/design-system-guide/icon-reference.md`.
|
|
@@ -146,6 +146,7 @@ The full icon catalog is at `node_modules/@deriv-ds/design-intelligence-layer/gu
|
|
|
146
146
|
| Link | `Link` |
|
|
147
147
|
| Loading Spinner | `LoadingSpinner` |
|
|
148
148
|
| Native Select | `NativeSelect, NativeSelectOptGroup, NativeSelectOption` |
|
|
149
|
+
| Navigation Menu | `NavigationMenu, NavigationMenuList, NavigationMenuItem, NavigationMenuTrigger, NavigationMenuContent, NavigationMenuLink, ...` |
|
|
149
150
|
| Notification | `NotificationBanner, NotificationItem, NotificationDivider` |
|
|
150
151
|
| OTP Field | `CodeInput, CodeInputGroup, CodeInputSlot, CodeInputSeparator` |
|
|
151
152
|
| Pagination | `Pagination, PaginationContent, PaginationLink, ...` |
|
|
@@ -164,7 +165,7 @@ The full icon catalog is at `node_modules/@deriv-ds/design-intelligence-layer/gu
|
|
|
164
165
|
| Sidebar | `Sidebar, SidebarProvider, SidebarMenu, SidebarMenuItem, ...` |
|
|
165
166
|
| Skeleton | `Skeleton` |
|
|
166
167
|
| Slider | `Slider` |
|
|
167
|
-
| Snackbar | `Snackbar` |
|
|
168
|
+
| Snackbar | `Snackbar` (+ imperative `toast` — re-exported from sonner) |
|
|
168
169
|
| Spinner | `Spinner` |
|
|
169
170
|
| Stepper | `Stepper` |
|
|
170
171
|
| Switch | `Switch` |
|
|
@@ -190,18 +191,23 @@ Wire each block's props/children to your real content — don't re-implement the
|
|
|
190
191
|
|
|
191
192
|
### Available blocks
|
|
192
193
|
|
|
193
|
-
| Block |
|
|
194
|
-
|
|
195
|
-
| NavBar | `Navbar` (responsive) · `NavMobileBottomBar` · `NavDesktopSidebar` |
|
|
196
|
-
| Header | `HeaderApp` · `HeaderAppHome` · `HeaderBranding` |
|
|
197
|
-
| Hero — home | `HeroMobileHomeTitle` · `HeroMobileHomeTotalAssets` · `HeroDesktopHomeOnboarding` · `HeroDesktopHomeWithBalance` |
|
|
198
|
-
| Hero — main / secondary / transaction | `HeroMobileMain` · `HeroDesktopMain` · `HeroMobileSecondary` · `HeroDesktopSecondary` · `HeroMobileTransaction` |
|
|
199
|
-
| Hero action button | `HeroActionButton` |
|
|
200
|
-
| Home — banner
|
|
201
|
-
|
|
|
202
|
-
|
|
|
203
|
-
|
|
|
204
|
-
|
|
|
194
|
+
| Block | Variants / exports | Description |
|
|
195
|
+
|---|---|---|
|
|
196
|
+
| NavBar | `Navbar` (responsive) · `NavMobileBottomBar` · `NavDesktopSidebar` — props `activeId`, `badges`, `onNavChange` | App navigation. `Navbar` auto-switches: sidebar ≥768px, bottom tab bar <768px. |
|
|
197
|
+
| Header | `HeaderApp` · `HeaderAppHome` · `HeaderBranding` | App top header. Home (avatar + notifications + Ask Amy), in-app sub-page (back, tabs, actions), or branding bar (language + actions). |
|
|
198
|
+
| Hero — home | `HeroMobileHomeTitle` · `HeroMobileHomeTotalAssets` · `HeroDesktopHomeOnboarding` · `HeroDesktopHomeWithBalance` (+ `*Skeleton`) | Home top area: greeting/title, total-assets balance, or onboarding hero. Mobile/desktop pair. |
|
|
199
|
+
| Hero — main / secondary / transaction | `HeroMobileMain` · `HeroDesktopMain` · `HeroMobileSecondary` · `HeroDesktopSecondary` · `HeroMobileTransaction` (+ `*Skeleton`) | Primary/secondary page hero with account tabs + action buttons; transaction details card. |
|
|
200
|
+
| Hero action button | `HeroActionButton` | The prominent circular action button used inside heroes. |
|
|
201
|
+
| Home — banner | `HomeBanner` · `BannerCard` — props `banner`, `layout`, `onClose` | Promo / announcement banner (carousel of cards, or a single dismissible card). |
|
|
202
|
+
| Home — highlights | `HomeHighlights` · `HomeHighlightCard` — prop `cards` | Row/grid of highlight cards. |
|
|
203
|
+
| Home — explore | `HomeExploreDeriv` | "Explore Deriv" discovery section. |
|
|
204
|
+
| Trading — account card | `TradingAccountCard` — prop `layout` | Account card with balance + actions. |
|
|
205
|
+
| Trading — action buttons | `TradingActionButtonsPrimary` · `TradingActionButtonsSecondary` (+ `*Skeleton`) | Deposit / withdraw / transfer action button cluster. |
|
|
206
|
+
| Trading — empty | `TradingEmpty` (+ `TradingEmptySkeleton`) | Empty trading list / no-accounts state. |
|
|
207
|
+
| Account activated | `AccountActivatedCard` | "Account activated" confirmation card. |
|
|
208
|
+
| Feedback / success | `FeedbackSuccessScreen` · `FeedbackTradeWithAccounts` · `FeedbackTransferSuggestion` | Post-action success / confirmation screens. |
|
|
209
|
+
| Referral | `Referral` — props `metrics`, … | Refer-a-friend / invite panel with metrics. |
|
|
210
|
+
| Section | `Section` | Section header pattern: eyebrow tag, title (+ chevron), control cluster, segmented control, content slot (`children`). |
|
|
205
211
|
|
|
206
212
|
Block source files live in `components/blocks/`. Most heroes and trading blocks also export a `*Skeleton` loading variant. See `.claude/skills/build/references/components-and-tokens.md` for the full catalog with "matches when" hints.
|
|
207
213
|
|
|
@@ -715,7 +721,7 @@ This project uses @deriv-ds/design-intelligence-layer (Quill Design System). Bef
|
|
|
715
721
|
3. Read node_modules/@deriv-ds/design-intelligence-layer/guides/personas/trading-game-player-field-guide.md — understand the player personas that shape all copy and UX
|
|
716
722
|
4. Read node_modules/@deriv-ds/design-intelligence-layer/guides/brand-voice/deriv-brand-voice.md — apply the brand voice: channel-specific voice, banned phrases, vocabulary, and formatting rules for all player-facing copy
|
|
717
723
|
5. Check if the component exists in the package — import it, don't re-implement
|
|
718
|
-
6. Use only design token classes (bg-
|
|
724
|
+
6. Use only design token classes (bg-primary-canvas, text-prominent, border-default, etc.) — no hardcoded hex or raw Tailwind palette colors
|
|
719
725
|
7. Do not install lucide-react — icons come from @deriv/quill-icons via the bundled Icon component; do not install tailwindcss or other bundled dependencies separately
|
|
720
726
|
8. If no token exists for a value, ask before using a hardcoded value
|
|
721
727
|
9. After upgrading the package: prefer package imports over local copies of components; if replacing local UI code with the package version, tell the user what was overwritten; re-copy guides/rules/design-system-consuming-project.mdc into .cursor/rules if using Cursor
|