@deriv-ds/design-intelligence-layer 0.6.0 → 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.
@@ -0,0 +1,490 @@
1
+ # Components & tokens — `@deriv-ds/design-intelligence-layer`
2
+
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
+
5
+ > **Verification targets** (the package ships compiled — there is NO `src/index.ts`):
6
+ > - Components → `node_modules/@deriv-ds/design-intelligence-layer/dist/index.d.ts`
7
+ > - Tokens / variables / primitives → `node_modules/@deriv-ds/design-intelligence-layer/src/styles.css`
8
+
9
+ ---
10
+
11
+ ## Canonical component list (importable from the package)
12
+
13
+ ```tsx
14
+ import {
15
+ // Layout & structure
16
+ Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter, CardAction,
17
+ AspectRatio,
18
+ ScrollArea, ScrollBar,
19
+ ResizablePanelGroup, ResizablePanel, ResizableHandle, // NOTE: no bare `Resizable`
20
+ Separator,
21
+ Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarGroup, SidebarGroupLabel,
22
+ SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarMenuSub, SidebarProvider,
23
+ SidebarTrigger, SidebarInset, SidebarRail, SidebarSeparator,
24
+
25
+ // Forms & input
26
+ Input,
27
+ PhoneInput,
28
+ EmailOrPhoneInput,
29
+ InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea,
30
+ SearchField,
31
+ InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator,
32
+ CodeInput, CodeInputGroup, CodeInputSlot, CodeInputSeparator,
33
+ Textarea,
34
+ Select, SelectTrigger, SelectValue, SelectContent, SelectItem, SelectGroup, SelectLabel, SelectSeparator,
35
+ NativeSelect, NativeSelectOption, NativeSelectOptGroup,
36
+ Combobox, ComboboxInput, ComboboxTrigger, ComboboxContent, ComboboxItem, ComboboxList,
37
+ ComboboxValue, ComboboxEmpty, ComboboxGroup, ComboboxLabel, ComboboxChip, ComboboxChips,
38
+ Checkbox, CheckboxField,
39
+ RadioGroup, RadioGroupItem, RadioGroupField,
40
+ Switch,
41
+ Toggle,
42
+ ToggleGroup, ToggleGroupItem,
43
+ SegmentedControl, SegmentedControlList, SegmentedControlTrigger, SegmentedControlContent,
44
+ Slider,
45
+ Label,
46
+ Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend,
47
+ FieldSeparator, FieldSet, FieldTitle,
48
+ Form, FormField, FormItem, FormLabel, FormControl, FormDescription, FormMessage,
49
+
50
+ // Navigation
51
+ Button,
52
+ SocialButton, // social-login button (provider variants), from button.tsx
53
+ Link,
54
+ Tab, TabList, TabTrigger, TabContent, // NOTE: singular — Tabs/TabsList/TabsTrigger/TabsContent do NOT exist
55
+ Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, BreadcrumbEllipsis,
56
+ Pagination, PaginationContent, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious,
57
+ PaginationEllipsis, PaginationBullets,
58
+ DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, DropdownMenuLabel,
59
+ DropdownMenuSeparator, DropdownMenuGroup, DropdownMenuCheckboxItem, DropdownMenuRadioGroup,
60
+ DropdownMenuRadioItem, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger,
61
+ ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuTrigger, ContextMenuSeparator,
62
+ Command, CommandDialog, CommandInput, CommandList, CommandItem, CommandGroup, CommandEmpty,
63
+ CommandSeparator, CommandShortcut,
64
+ Stepper,
65
+
66
+ // Overlays & surfaces
67
+ Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, DialogClose,
68
+ Drawer, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerTitle, DrawerTrigger, DrawerClose,
69
+ Sheet, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, SheetClose,
70
+ Popover, PopoverContent, PopoverTrigger, PopoverAnchor, PopoverHeader, PopoverTitle, PopoverDescription,
71
+ HoverCard, HoverCardContent, HoverCardTrigger,
72
+ Tooltip, TooltipContent, TooltipProvider, TooltipTrigger,
73
+
74
+ // Feedback & status
75
+ Badge, BadgeDot,
76
+ Chip,
77
+ Tag,
78
+ NotificationBanner, NotificationItem, NotificationDivider, // NOTE: no bare `Notification`
79
+ SectionMessage, SectionMessageTitle, SectionMessageDescription,
80
+ Snackbar,
81
+ Spinner,
82
+ LoadingSpinner,
83
+ Skeleton,
84
+ Progress,
85
+ Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle,
86
+
87
+ // Data display
88
+ Table, TableBody, TableCaption, TableCell, TableHead, TableHeader, TableRow, TableFooter,
89
+ Calendar, CalendarDayButton,
90
+ Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious,
91
+ ChartContainer, ChartTooltip, ChartTooltipContent, ChartLegend, ChartLegendContent, // NOTE: no bare `Chart`
92
+ ListItem, ListItemTitle, ListItemDescription, ListItemContent, ListItemIcon, ListItemMedia,
93
+ ListItemActions, ListItemFlag, ListItemFooter, ListItemGroup, ListItemHeader, ListItemSeparator,
94
+ Accordion, AccordionContent, AccordionItem, AccordionTrigger,
95
+ Collapsible, CollapsibleContent, CollapsibleItem, CollapsibleTrigger,
96
+
97
+ // Utility
98
+ Avatar, AvatarFallback, AvatarImage, AvatarBadge, AvatarGroup, AvatarGroupCount,
99
+ Kbd, KbdGroup,
100
+ DirectionProvider, // NOTE: no bare `Direction`; hook is `useDirection`
101
+ } from "@deriv-ds/design-intelligence-layer"
102
+
103
+ // Helpers & hooks
104
+ import { cn, useIsMobile, useDirection, useSidebar, useFormField } from "@deriv-ds/design-intelligence-layer"
105
+ ```
106
+
107
+ **Anything NOT exported from `dist/index.d.ts` does not exist in the package.** To prove an export exists:
108
+
109
+ ```bash
110
+ grep -w "<ComponentName>" node_modules/@deriv-ds/design-intelligence-layer/dist/index.d.ts
111
+ # zero hits = doesn't exist → use the closest real component or compose one
112
+ ```
113
+
114
+ ### ⚠ Commonly hallucinated imports — look valid, don't exist
115
+
116
+ | ❌ Doesn't exist | ✅ Real export |
117
+ |---|---|
118
+ | `Tabs`, `TabsList`, `TabsTrigger`, `TabsContent` | `Tab`, `TabList`, `TabTrigger`, `TabContent` |
119
+ | `Resizable` | `ResizablePanelGroup` + `ResizablePanel` + `ResizableHandle` |
120
+ | `Notification` | `NotificationBanner` / `NotificationItem` |
121
+ | `Chart` | `ChartContainer` (+ `ChartTooltip`, `ChartLegend`) |
122
+ | `Direction` | `DirectionProvider` / `useDirection` |
123
+
124
+ ### ⚠ In the source tree but NOT exported — do not import
125
+
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
+
128
+ - `theme-toggle` (`ThemeToggle`) — compose from `Button` + `Switch` + `<Icon />`.
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
+
132
+ ### Secondary exports (real, but rarely imported directly)
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.
135
+
136
+ ---
137
+
138
+ ## Icons
139
+
140
+ Icons come from the package's `<Icon />` component (a wrapper over `@deriv/quill-icons`). **Never install or import `lucide-react` or any other icon library.** Import `Icon` from the package and pass a `name` (plus optional `weight`):
141
+
142
+ ```tsx
143
+ import { Icon } from "@deriv-ds/design-intelligence-layer"
144
+
145
+ <Icon name="arrow-right" /> // default weight: bold
146
+ <Icon name="chevron-down" weight="regular" className="size-4 text-subtle" />
147
+ <Icon name="circle-check" weight="fill" className="size-4 text-success" />
148
+ ```
149
+
150
+ Three weights: `regular` (thin — subtle/unselected), `bold` (medium outline — the default, most UI), `fill` (solid — selected/strong actions). The full name catalog lives at `node_modules/@deriv-ds/design-intelligence-layer/guides/design-system-guide/icon-reference.md`; `ICON_NAMES` and `iconAvailableWeights(name)` are exported from the package at runtime.
151
+
152
+ Use an icon ONLY when the Figma frame / design actually shows that glyph — match it to the closest catalog `name`, and never substitute a "close enough" icon for an exported Figma asset.
153
+
154
+ ---
155
+
156
+ ## Token cheatsheet — use these classes ONLY
157
+
158
+ > Every class below maps to a `--color-*` entry in the package's `src/styles.css` `@theme inline`
159
+ > block — that is the ONLY thing that makes a utility class real in Tailwind v4. A class with no
160
+ > `--color-*` definition produces **no CSS** and silently inherits the wrong colour.
161
+ >
162
+ > **Existence proof for any colour class** (`bg-X` / `text-X` / `border-X` / `ring-X` → token name `X`):
163
+ > ```bash
164
+ > grep -- "--color-X:" node_modules/@deriv-ds/design-intelligence-layer/src/styles.css
165
+ > # zero hits = the class does NOT exist → use a real token or register one (see Token Creation)
166
+ > ```
167
+
168
+ ### ⚠ Background vs text tokens — the #1 trap
169
+
170
+ `prominent` and `subtle` are **text / foreground** colours, not surfaces:
171
+
172
+ - `--color-prominent → var(--text-prominent-default)` = #181C25 (near-black). So **`bg-prominent` paints near-black** — it's an *inverse* surface for dark elements, NOT a white page background.
173
+ - **Page / surface backgrounds are a separate family:** `bg-card`, `bg-primary-canvas`, etc.
174
+
175
+ **Never use `bg-prominent` / `bg-subtle` as a page or header background.** Map the Figma
176
+ variable `component/app/background/normal` (`#ffffff`) → **`bg-card`**.
177
+
178
+ ### Backgrounds (surfaces)
179
+
180
+ | Class | Use | Value (light) |
181
+ |---|---|---|
182
+ | `bg-card` | page / card / panel surface — **the default white background** | #FFFFFF |
183
+ | `bg-primary-surface` | white surface (alias of `bg-card`) | #FFFFFF |
184
+ | `bg-primary-canvas` | neutral page canvas (app shell behind cards) | #F6F7F8 |
185
+ | `bg-secondary-surface` | subtle muted surface | #F6F7F8 |
186
+ | `bg-secondary-canvas` | alternate canvas | #FFFFFF |
187
+ | `bg-popover` | popover / dropdown surface | #FFFFFF |
188
+ | `bg-prominent` | **inverse (near-black) surface only** — tooltips, inverted chips. NOT a page bg | #181C25 |
189
+ | `bg-overlay` | modal backdrop only | black 50% |
190
+ | `bg-primary` | brand primary (CTAs) — **coral** | #FF444F |
191
+ | `bg-primary-hover` | primary hover | coral-800 |
192
+ | `bg-secondary-hover` | outline / secondary hover | #F6F7F8 |
193
+
194
+ ### Text
195
+
196
+ | Class | Use | Value (light) |
197
+ |---|---|---|
198
+ | `text-prominent` | primary text — **near-black** (NOT `text-on-prominent`, which doesn't exist) | #181C25 |
199
+ | `text-subtle` | secondary / description text | #181C25 @ 48% |
200
+ | `text-on-prominent-static-inverse` | always white — text on coral / dark / inverse surfaces | #FFFFFF |
201
+ | `text-primary` | brand text — coral | #FF444F |
202
+ | `text-warning` | warning text | #C47D00 |
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 |
207
+
208
+ ### Status colours — now built in
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:
215
+
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
+
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`.
224
+
225
+ ### Borders & ring
226
+
227
+ | Class | Use | Value (light) |
228
+ |---|---|---|
229
+ | `border-border-subtle` | default UI borders, dividers, cards | #181C25 @ 8% |
230
+ | `border-border-prominent` | outline-variant components, heavier dividers | #181C25 @ 16% |
231
+ | `border-default` | global default border | #181C25 @ 16% |
232
+ | `border-input` | input field borders | #181C25 @ 8% |
233
+ | `border-selected` | selected-state border (solid dark) | #181C25 |
234
+ | `ring-ring` | focus ring — **coral** | #FF444F |
235
+
236
+ > `border-border` is deprecated — use `border-border-subtle` or `border-border-prominent`.
237
+ > `border-success` / `border-error` now generate (solid status colour) alongside `bg-success` / `bg-error`.
238
+
239
+ ### Radius
240
+
241
+ `--radius-xs`, `--radius-sm`, `--radius-md`, `--radius-lg`, `--radius-xl` are defined → use
242
+ `rounded-xs` … `rounded-xl`. Never `rounded-[Npx]` — if a Figma radius matches no step, register a
243
+ radius token (Token Creation pattern) instead.
244
+
245
+ ### ⚠ Commonly hallucinated classes — look valid, don't exist, render the WRONG colour
246
+
247
+ These pass the forbidden-pattern grep (they look like semantic tokens) but have no `--color-*`
248
+ definition, so they produce **no CSS** — the element silently inherits a wrong colour:
249
+
250
+ | ❌ Doesn't exist | ✅ Real fix |
251
+ |---|---|
252
+ | `text-on-prominent` | `text-prominent` (`text-on-prominent` is always-white — for dark/coloured surfaces only) |
253
+ | `text-on-subtle` | `text-subtle` |
254
+ | `bg-loss` / `text-loss` / `bg-win` / `text-win` | register first (game profit/loss — see Status colours above), then use |
255
+ | `bg-prominent` (as page bg) | `bg-card` |
256
+ | `bg-subtle` (as page bg) | `bg-card` / `bg-primary-canvas` |
257
+ | `text-heading-h1`, `text-body-md`, `text-heading-mega` | `heading-h1`, `body-md`, `heading-hero` (see Typography) |
258
+
259
+ **Runtime tell:** a token-intended element whose computed `background-color` is `rgba(0,0,0,0)` or
260
+ whose text colour inherited instead of applying = hallucinated class.
261
+
262
+ ---
263
+
264
+ ## Token Creation — registering tokens the package doesn't ship
265
+
266
+ When a design value has no existing utility class, NEVER inline it and NEVER stop the build.
267
+ Register a token in the consuming project's `globals.css` (after the DS imports) and use the
268
+ generated class. Resolution order — first match wins:
269
+
270
+ 1. **Existing semantic token** from the tables above → use it directly.
271
+ 2. **Package semantic variable** (theme-aware — flips in dark mode automatically). Find it in
272
+ `src/styles.css` (`--text-*-default`, `--background-*-default`, etc.):
273
+ ```css
274
+ @theme inline { --color-success: var(--text-success-default); }
275
+ ```
276
+ 3. **Package primitive** (1294 of them: `--primitive-coral-700`, `--primitive-slate-1200`,
277
+ `--primitive-blue-500`, …). Grep the resolved hex to find it:
278
+ ```bash
279
+ grep -i "#1A2233" node_modules/@deriv-ds/design-intelligence-layer/src/styles.css
280
+ ```
281
+ ```css
282
+ @theme inline { --color-brand-coral: var(--primitive-coral-700); } /* → bg-brand-coral */
283
+ ```
284
+ ⚠ Primitives are static — they do NOT flip in dark mode. Prefer step 2 when a semantic var exists.
285
+ 4. **Exact hex, centralized** — only when no package variable resolves to the design's value.
286
+ The hex lives in ONE place (the theme), never in JSX:
287
+ ```css
288
+ @theme inline { --color-figma-hero-overlay: #1A2233; } /* → bg-figma-hero-overlay */
289
+ ```
290
+
291
+ Naming: follow the package's convention — `--color-<intent>` (e.g. `--color-success`,
292
+ `--color-brand-coral`), not `--color-green` or `--color-1A2233`. Same pattern applies to radius
293
+ (`--radius-<name>`) and font sizes. **Every registered token must be listed in the Build Report.**
294
+
295
+ Referencing a primitive or raw var **inline** is still forbidden — `bg-[var(--primitive-coral-700)]` never; register, then use the class.
296
+
297
+ ---
298
+
299
+ ## Forbidden patterns — never write these
300
+
301
+ ```
302
+ ❌ #FF444F, #000000, rgba(0,0,0,0.5) — hex / rgba in JSX or class names (even brand coral — use bg-primary)
303
+ ❌ bg-gray-100, text-zinc-500, bg-red-500,
304
+ text-blue-600, bg-amber-100, bg-black — ANY raw Tailwind palette, every hue
305
+ ❌ bg-[#EEEEEE], text-[rgba(...)] — arbitrary colour values
306
+ ❌ bg-[var(--border-subtle)] — raw CSS var inline (register a token instead)
307
+ ❌ hsl(var(--primary)) — Tailwind v3 syntax
308
+ ❌ rounded-[12px] — arbitrary radius (use rounded-xs…xl or register)
309
+ ❌ font-[...] / style={{fontFamily}} — font-family overrides (use font-display / font-body)
310
+ ❌ bg-prominent as a page/header background — near-black inverse surface (see trap above)
311
+ ❌ bg-black/50 — raw opacity on non-token (backdrop → bg-overlay)
312
+ ```
313
+
314
+ ### Opacity on a real token is fine
315
+
316
+ ```
317
+ ✅ bg-primary/20, border-border-subtle/50, ring-ring/10
318
+ ```
319
+
320
+ ### Layout utilities — exempt from token rules
321
+
322
+ ```
323
+ ✅ flex, grid, gap-4, p-6, m-2, w-full, h-screen, max-w-lg
324
+ ✅ p-[18px], gap-[12px], w-[327px] — exact px from Figma auto-layout (fidelity!)
325
+ ✅ z-50, overflow-hidden, opacity-50, transition-all
326
+ ✅ col-span-2, items-center, justify-between
327
+ ```
328
+
329
+ Token rules apply **only** to: colour (bg, text, border, ring, shadow colour), border radius, and
330
+ font family. Spacing/sizing should use the **exact values from the design** — arbitrary px values
331
+ are encouraged there when the Figma auto-layout values don't match a Tailwind step.
332
+
333
+ ---
334
+
335
+ ## Button variants
336
+
337
+ ```tsx
338
+ <Button variant="primary" /> // Coral filled — main CTA
339
+ <Button variant="secondary" /> // Black outline, white bg — secondary action
340
+ <Button variant="tertiary" /> // Text only, underline on hover — minimal
341
+ ```
342
+
343
+ Sizes: `lg` (48px), `md` (40px, default), `sm` (32px), plus `icon-lg | icon-md | icon-sm`.
344
+ Tones: `normal`, `inverse`, `static-light`, `static-dark`.
345
+
346
+ ## Badge variants
347
+
348
+ ```tsx
349
+ // Solid
350
+ <Badge variant="default" /> // Coral (brand)
351
+ <Badge variant="default-success" /> // Green
352
+ <Badge variant="default-fail" /> // Red
353
+
354
+ // Tint
355
+ <Badge variant="fill" /> // Coral tint bg
356
+ <Badge variant="fill-success" /> // Green tint bg
357
+ <Badge variant="fill-fail" /> // Red tint bg
358
+
359
+ // Outline (black border, hover grey)
360
+ <Badge variant="outline" />
361
+
362
+ // Ghost (transparent bg)
363
+ <Badge variant="ghost" />
364
+ <Badge variant="ghost-success" />
365
+ <Badge variant="ghost-fail" />
366
+ ```
367
+
368
+ ---
369
+
370
+ ## Blocks — importable from the package
371
+
372
+ Blocks ship as named exports — **import them directly, never re-implement.** Matching a page region to a block is the **Block Matching gate** in the build skill: if a region in a Figma frame or a text prompt corresponds to a block below, import that exact block and tune it to the content — do NOT mock up a look-alike. Only compose from primitives + tokens when **no** block matches, and flag the composition in the Build Report. Never invent a block import name.
373
+
374
+ ```tsx
375
+ import { Navbar, HeroDesktopMain, Section, TradingAccountCard, Referral } from "@deriv-ds/design-intelligence-layer"
376
+ // Navbar is responsive: sidebar on desktop (≥768px), bottom bar on mobile (<768px).
377
+ // For explicit control, NavMobileBottomBar and NavDesktopSidebar are also exported.
378
+ ```
379
+
380
+ The **"matches when"** column is what the Block Matching gate matches on — intent, not pixels.
381
+
382
+ | Region | Import(s) | Matches when (prompt or frame shows…) |
383
+ |---|---|---|
384
+ | **Navbar** | `Navbar` (responsive) · `NavMobileBottomBar` · `NavDesktopSidebar` | top/side nav, nav menu, sidebar nav, bottom tab bar, "navbar" / "nav menu" |
385
+ | **Header** | `HeaderApp` · `HeaderAppHome` · `HeaderBranding` | app top header strip, branded header bar, "header" |
386
+ | **Hero — home** | `HeroMobileHomeTitle` · `HeroMobileHomeTotalAssets` · `HeroDesktopHomeOnboarding` · `HeroDesktopHomeWithBalance` | home top area: greeting/title, total-assets/balance header, onboarding hero |
387
+ | **Hero — main/secondary/transaction** | `HeroMobileMain` · `HeroDesktopMain` · `HeroMobileSecondary` · `HeroDesktopSecondary` · `HeroMobileTransaction` | primary/secondary page hero, transaction hero |
388
+ | **Hero action button** | `HeroActionButton` | the prominent action button(s) sitting inside a hero |
389
+ | **Home — banner** | `HomeBanner` · `BannerCard` | promo / announcement banner card on home |
390
+ | **Home — highlights** | `HomeHighlights` · `HomeHighlightCard` | row/grid of highlight cards, "highlights" |
391
+ | **Home — explore** | `HomeExploreDeriv` | "explore Deriv" discovery section |
392
+ | **Trading — account card** | `TradingAccountCard` | account card with balance + actions |
393
+ | **Trading — action buttons** | `TradingActionButtonsPrimary` · `TradingActionButtonsSecondary` (+ `…Skeleton`) | deposit/withdraw/transfer action button cluster |
394
+ | **Trading — empty** | `TradingEmpty` (+ `TradingEmptySkeleton`) | empty trading list / no-accounts state |
395
+ | **Account activated card** | `AccountActivatedCard` | "account activated" confirmation card |
396
+ | **Feedback / success** | `FeedbackSuccessScreen` · `FeedbackTradeWithAccounts` · `FeedbackTransferSuggestion` | success screen, post-action confirmation/feedback |
397
+ | **Referral** | `Referral` | refer-a-friend / invite panel |
398
+ | **Section** | `Section` | eyebrow tag + title + control cluster + segmented control wrapping a content slot (children) |
399
+
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.
427
+
428
+ ---
429
+
430
+ ## Typography
431
+
432
+ The package defines **bare utility classes** in `styles.css` (no `text-` prefix):
433
+
434
+ - Families: `font-display` / `font-body` (Inter loads automatically with the DS styles import)
435
+ - Headings: `heading-hero`, `heading-h1`, `heading-h2`, `heading-h3`, `heading-h4`, `heading-h5`, `heading-h6`
436
+ - Body: `body-xl`, `body-lg`, `body-md`, `body-sm`, `body-xs`
437
+
438
+ ```tsx
439
+ <h1 className="heading-h1 text-prominent">Title</h1>
440
+ <p className="body-md text-subtle">Description</p>
441
+ ```
442
+
443
+ ⚠ `text-heading-h1`, `text-body-md`, `text-heading-mega` do NOT exist — they render at the browser
444
+ default size. Never override `font-family` manually in CSS. When a Figma text style doesn't match a
445
+ scale step exactly, start from the closest `heading-*`/`body-*` class and override the deltas with
446
+ standard utilities (`font-extrabold`, `text-[18px]`, `leading-[24px]`, `tracking-[-0.2px]`) — size,
447
+ weight, line-height, and letter-spacing are NOT colour tokens, so exact values from Figma are
448
+ allowed and preferred for fidelity. Only `font-family` itself is locked to `font-display`/`font-body`.
449
+
450
+ ---
451
+
452
+ ## Intentional DS behaviours — do NOT "fix" these
453
+
454
+ - The **focus ring** on `Select`, `Input`, `SelectTrigger`, etc. (`ring-ring`, coral, shown on
455
+ `:focus-visible`) is built into the package as WCAG focus indication. It is **expected** — do
456
+ not remove it, override it to `ring-0`, or flag it as a bug.
457
+
458
+ ---
459
+
460
+ ## Quick install reference
461
+
462
+ ```bash
463
+ npm install @deriv-ds/design-intelligence-layer
464
+ ```
465
+
466
+ ```css
467
+ /* The @source path is RELATIVE TO THIS CSS FILE — count the directories up to the project root: */
468
+
469
+ /* app/globals.css (Next.js, no src dir) */
470
+ @import "@deriv-ds/design-intelligence-layer/styles";
471
+ @import "tailwindcss";
472
+ @source "../node_modules/@deriv-ds/design-intelligence-layer/dist";
473
+
474
+ /* src/app/globals.css (Next.js with --src-dir) */
475
+ @import "@deriv-ds/design-intelligence-layer/styles";
476
+ @import "tailwindcss";
477
+ @source "../../node_modules/@deriv-ds/design-intelligence-layer/dist";
478
+
479
+ /* src/index.css (Vite) */
480
+ @import "@deriv-ds/design-intelligence-layer/styles";
481
+ @import "tailwindcss";
482
+ @source "../node_modules/@deriv-ds/design-intelligence-layer/dist";
483
+ ```
484
+
485
+ **Verify the path resolved:** if DS component internals render unstyled (e.g. a Button with no
486
+ fill), the `@source` path is wrong — Tailwind found no classes to generate. Fix the `../` count.
487
+
488
+ Vite-only: add `@tailwindcss/vite` to `vite.config.ts`. Next.js needs no extra config.
489
+
490
+ **Do NOT** install `lucide-react`, `tailwindcss`, or create a `tailwind.config.js` — these are handled by the package.
@@ -0,0 +1,3 @@
1
+ Build UI strictly from the `@deriv-ds/design-intelligence-layer` package — pages, screens, and components.
2
+
3
+ First read and follow **`.claude/skills/build/SKILL.md`** in this repo and every file it links under `.claude/skills/build/references/`. Execute exactly as that skill specifies — package imports only, token-only styling, Figma visual fidelity, and the accessibility checklist.
@@ -0,0 +1,6 @@
1
+ ---
2
+ inclusion: manual
3
+ ---
4
+ Build UI strictly from the `@deriv-ds/design-intelligence-layer` package — pages, screens, and components.
5
+
6
+ First read and follow **`.claude/skills/build/SKILL.md`** in this repo and every file it links under `.claude/skills/build/references/`. Execute exactly as that skill specifies — package imports only, token-only styling, Figma visual fidelity, and the accessibility checklist.
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/trading-game-design-principles.md
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):
@@ -48,12 +48,34 @@ node_modules/@deriv-ds/design-intelligence-layer/guides/rules/design-system-cons
48
48
  cp node_modules/@deriv-ds/design-intelligence-layer/guides/rules/design-system-consuming-project.mdc .cursor/rules/
49
49
  ```
50
50
 
51
+ **Claude Code users:** The package also ships a `build` skill that enforces these rules during every UI build. Copy it into your project (re-copy after each upgrade), then invoke it with `/build`:
52
+
53
+ ```bash
54
+ mkdir -p .claude/skills && cp -R node_modules/@deriv-ds/design-intelligence-layer/.claude/skills/build .claude/skills/
55
+ ```
56
+
57
+ **Cursor users:** Copy the shipped `/build` command shim (points at the `.claude/skills/build/` copy above, so copy that first):
58
+
59
+ ```bash
60
+ mkdir -p .cursor/commands
61
+ cp node_modules/@deriv-ds/design-intelligence-layer/.cursor/commands/build.md .cursor/commands/build.md
62
+ ```
63
+
64
+ **Kiro users:** Copy the shipped `#build` steering doc the same way:
65
+
66
+ ```bash
67
+ mkdir -p .kiro/steering
68
+ cp node_modules/@deriv-ds/design-intelligence-layer/.kiro/steering/build.md .kiro/steering/build.md
69
+ ```
70
+
71
+ Re-copy both after every version bump so the shims match the installed release.
72
+
51
73
  ---
52
74
 
53
75
  ## Step 3 — Core rules summary
54
76
 
55
77
  1. **Check before building** — if a component exists in `@deriv-ds/design-intelligence-layer`, import it. Never re-implement it.
56
- 2. **Tokens only** — use semantic token classes (`bg-prominent`, `text-on-prominent`, `border-border`, etc.). Never hardcode hex values, raw Tailwind palette colors, or CSS variables.
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.
57
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.
58
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.
59
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.
@@ -80,7 +102,7 @@ cp node_modules/@deriv-ds/design-intelligence-layer/guides/rules/design-system-c
80
102
  ## Reference
81
103
 
82
104
  - Full token + component reference: `node_modules/@deriv-ds/design-intelligence-layer/README.md`
83
- - Design principles: `node_modules/@deriv-ds/design-intelligence-layer/guides/design-principles/trading-game-design-principles.md`
105
+ - Design principles: `node_modules/@deriv-ds/design-intelligence-layer/guides/design-principles/quill-design-principles.md`
84
106
  - Accessibility standards: `node_modules/@deriv-ds/design-intelligence-layer/guides/accessibility-standards/trading-game-accessibility-standards.md`
85
107
  - Personas: `node_modules/@deriv-ds/design-intelligence-layer/guides/personas/trading-game-player-field-guide.md`
86
108
  - Brand voice: `node_modules/@deriv-ds/design-intelligence-layer/guides/brand-voice/deriv-brand-voice.md`
package/CHANGELOG.md CHANGED
@@ -7,6 +7,29 @@ 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
+
17
+ ## [0.6.1]
18
+
19
+ ### Note
20
+ - **`0.6.0` was published in error** by a tag pushed against the wrong commit before the skills PR was merged — it contains the old pre-merge codebase mislabeled as `0.6.0` and has been deprecated on npm. `0.6.1` is the real release of everything listed below; no code changes from `0.6.0`'s intended content, only the correct commit and version number.
21
+
22
+ ## [0.6.0]
23
+
24
+ ### Added
25
+ - **Three AI agent skills**, runnable from Claude Code, Cursor, and Kiro:
26
+ - `build` — **npm-published**, for package consumers. Builds pages/screens/components strictly from the published package (text prompt, Figma link, or pasted block), enforcing token-only styling, the Block Matching gate, and an accessibility checklist. Ends with an independent critic pass and an offer to open a PR.
27
+ - `component` — **source-repo only**, for extending the design system. Authors a new UI primitive end-to-end (component file, package export, playground page, nav wiring, and consumer docs), with a dedupe gate against the existing catalog.
28
+ - `block` — **source-repo only**, for extending the design system. Authors a new composite Block end-to-end (block file, package export, playground page, nav wiring, and the `build` skill's block catalog), with the same dedupe gate and critic pass.
29
+ - **Cross-agent shims** — `.cursor/commands/{build,component,block}.md` (Cursor `/build`, `/component`, `/block`) and `.kiro/steering/{build,component,block}.md` (Kiro `#build`, `#component`, `#block`), all pointing at the same canonical `SKILL.md` files so every agent runs identical rules. Only the `build` shims are published to npm — `component`/`block` shims live in this repo only, alongside the skills they invoke.
30
+ - **Skill catalog drift guard** — `npm run check:skill-catalog` (wired into CI) fails the build if a component/block is exported but missing from the `build` skill's catalog, or documented in the catalog but not actually exported — keeping the Block Matching gate from ever hand-rolling a look-alike of a shipped block.
31
+ - **Skills foundation page** in the playground, documenting all three skills, their guardrails (dedupe-first, independent critic audit, bounded loops, idempotent edits, ask-then-PR), and how to invoke them per agent.
32
+
10
33
  ## [0.5.2]
11
34
 
12
35
  ### Added
@@ -57,7 +80,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
57
80
  ### Security
58
81
  - Patched CVE-2026-53550 and CVE-2026-49356 (dependency bumps).
59
82
 
60
- [Unreleased]: https://github.com/deriv-com/design-intelligence-layer/compare/v0.5.1...HEAD
83
+ [Unreleased]: https://github.com/deriv-com/design-intelligence-layer/compare/v0.6.1...HEAD
84
+ [0.6.1]: https://github.com/deriv-com/design-intelligence-layer/compare/v0.5.2...v0.6.1
61
85
  [0.5.1]: https://github.com/deriv-com/design-intelligence-layer/compare/v0.5.0...v0.5.1
62
86
  [0.5.0]: https://github.com/deriv-com/design-intelligence-layer/compare/v0.4.5...v0.5.0
63
87
  [0.4.5]: https://github.com/deriv-com/design-intelligence-layer/releases/tag/v0.4.5