@trading-game/design-intelligence-layer 0.13.3 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -614,71 +614,237 @@ These are styling behaviors you can't discover from TypeScript types alone:
614
614
 
615
615
  ## 8.5 — Blocks Catalogue
616
616
 
617
- > Blocks are fully composed UI sections built from design system primitives. They appear in the **Blocks** tab of the playground.
618
- > - Blocks are **NOT exported** from the npm package they are playground demonstrations only.
619
- > - To build them in a consuming project, import the underlying components (`Button`, etc.) from `@trading-game/design-intelligence-layer` and compose them manually using design tokens only.
620
- > - Do NOT mistake a Block for a component it will not appear in Rule 1's component list.
617
+ > 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.
618
+ > - **Variants** (`layout` / `mode` / `status`) live on a single block, not separate components.
619
+ > - Each block ships with internal state where appropriate (e.g. `NavBarBlock` manages its own mobile-menu drawer).
620
+ > - Blocks appear in the **Blocks** tab of the playground for visual reference, with the demo importing the same exports a consumer would.
621
621
 
622
- ### NavBar
622
+ ### `HeroBlock`
623
623
 
624
- A landing page top navigation bar with Desktop and Mobile breakpoint variants.
624
+ Marketing hero section with two layouts.
625
+
626
+ ```tsx
627
+ import { HeroBlock } from "@trading-game/design-intelligence-layer"
628
+
629
+ <HeroBlock
630
+ layout="centered" // "centered" | "split"
631
+ tagline={{ label: "What's new", suffix: "v2.0" }}
632
+ heading="Solve your customer's main problem"
633
+ body="One or two sentences expanding on the value prop."
634
+ primaryCta={{ label: "Get started" }}
635
+ secondaryCta={{ label: "Learn more" }} // split layout only
636
+ />
637
+ ```
625
638
 
626
639
  | Variant | Description |
627
640
  |---------|-------------|
628
- | Desktop | Full-width bar: logo left, ghost nav links centre-left, Sign in (ghost) + Sign up (primary) right |
629
- | Mobile closed | Logo left, hamburger icon-button right |
630
- | Mobile — open | Logo + close icon top row; stacked ghost nav links + full-width Sign in / Sign up below a divider |
641
+ | `centered` (Desktop) | Centred single-column: tagline pill + heading + body + single primary CTA with `ArrowRight` icon; no image |
642
+ | `split` (Desktop) | Two columns: tagline pill + heading + body + Get started / Learn more CTAs left; square image panel right |
643
+ | `split` (Mobile) | Single column stacked: text content centred above, image panel full-width below |
631
644
 
632
- **Components used:** `Button` (variants: `ghost`, `primary`, `secondary`; sizes: `sm`, `icon-sm`)
645
+ **Components used:** `Button` (default `sm`, `secondary sm`); `ArrowUpRight`, `ArrowRight` icons (lucide)
633
646
 
634
- **Tokens used:** `bg-prominent`, `bg-primary`, `border-border-subtle`, `rounded-xs`, `rounded-md`
647
+ **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`
635
648
 
636
649
  ---
637
650
 
638
- ### Hero
651
+ ### `AuthBlock`
652
+
653
+ Sign-in / sign-up form. Form fields are identical between modes; `mode` drives heading, terms copy, CTA label, and the footer cross-link.
654
+
655
+ ```tsx
656
+ import { AuthBlock } from "@trading-game/design-intelligence-layer"
657
+
658
+ <AuthBlock
659
+ mode="sign-in" // "sign-in" | "sign-up"
660
+ logoSrc="/path/to/brand-icon.svg" // consumer-provided
661
+ providers={["google", "telegram", "x"]} // default: all three
662
+ onSubmit={({ email }) => { ... }}
663
+ crossLinkHref="/auth/signup"
664
+ />
665
+ ```
666
+
667
+ | Region | Content |
668
+ |--------|---------|
669
+ | Top | Brand logo + wordmark lockup |
670
+ | Heading | "Sign in" / "Sign up" (mode-driven) |
671
+ | Providers | Configurable OAuth buttons (Google, Telegram, X) |
672
+ | Body | "or" divider + email input + terms paragraph |
673
+ | Footer | Primary CTA + footer cross-link to the opposite mode |
674
+
675
+ **Components used:** `Button`, `Input`, `Link`
676
+
677
+ **Tokens used:** `text-on-prominent`, `text-on-subtle`, `bg-border-subtle`, `font-display`, `font-body`
678
+
679
+ ---
639
680
 
640
- Landing page hero sections in multiple layout types.
681
+ ### `FAQBlock`
682
+
683
+ Frequently-asked-questions section with optional help card.
684
+
685
+ ```tsx
686
+ import { FAQBlock } from "@trading-game/design-intelligence-layer"
687
+
688
+ <FAQBlock
689
+ layout="desktop" // "desktop" | "mobile"
690
+ items={[{ value: "q1", question: "...", answer: "..." }, ...]}
691
+ intro={<>Optional intro paragraph with a <Link>link</Link>.</>}
692
+ helpCard={{ title: "Need more help?", body: "...", ctaLabel: "Contact us" }}
693
+ />
694
+ ```
641
695
 
642
696
  | Variant | Description |
643
697
  |---------|-------------|
644
- | Type 1 — Desktop | Two columns: tagline pill + heading + body + Get started / Learn more CTAs left; square image panel right |
645
- | Type 1 — Mobile | Single column stacked: text content centred above, image panel full-width below |
646
- | Type 2 — Desktop | Centred single-column: tagline pill + heading + body + single primary CTA with `ArrowRight` icon; no image |
698
+ | `desktop` | `text-5xl` heading, `gap-12`, help card padding `p-8` |
699
+ | `mobile` | `text-4xl` heading, `gap-10`, help card padding `p-6` |
647
700
 
648
- **Components used:** `Button` (default `sm`, `secondary sm`); `ArrowUpRight`, `ArrowRight` icons (lucide)
701
+ **Components used:** `Accordion`, `AccordionItem`, `AccordionTrigger`, `AccordionContent`, `Button`
649
702
 
650
- **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`
703
+ **Tokens used:** `text-on-prominent`, `text-on-subtle`, `bg-subtle`, `font-display`, `font-body`, `rounded-xl`
651
704
 
652
705
  ---
653
706
 
654
- ### Sheet Open Positions
707
+ ### `NavBarBlock`
655
708
 
656
- A slide-in panel listing the user's open trading positions. Responsive renders as a right-side `Sheet` on desktop and a bottom `Drawer` on mobile.
709
+ A landing page top navigation bar with internal mobile-menu state. Single component handles both desktop bar and mobile drawer.
657
710
 
658
- | State | Description |
659
- |-------|-------------|
660
- | Active | Scrollable list of open positions with direction, asset, stake, and P&L per row. Win/loss coloured with semantic tokens. Footer button links to transaction history. |
661
- | Empty | Empty state with icon and "No trades yet." message in place of the list. |
711
+ ```tsx
712
+ import { NavBarBlock } from "@trading-game/design-intelligence-layer"
713
+
714
+ <NavBarBlock
715
+ brand={{ fullLogoSrc: "...", iconLogoSrc: "...", alt: "Brand" }}
716
+ links={[{ label: "Products" }, { label: "Docs" }, ...]}
717
+ signIn={{ onClick: ... }}
718
+ signUp={{ onClick: ... }}
719
+ />
720
+ ```
662
721
 
663
- **Components used:** `Sheet`, `Drawer`, `Item`, `ItemGroup`, `ItemContent`, `ItemTitle`, `ItemDescription`, `ItemActions`, `Empty`, `EmptyHeader`, `EmptyMedia`, `EmptyTitle`, `Button`, `NavigationButton`, `Separator`
722
+ | Breakpoint | Description |
723
+ |------------|-------------|
724
+ | Desktop (≥600 px) | Full-width bar: full logo + tertiary nav links left; Sign in (tertiary) + Sign up (primary) right |
725
+ | Mobile — closed | Icon logo left, hamburger icon-button right |
726
+ | Mobile — open | Stacked tertiary nav links + full-width Sign in (secondary) / Sign up (primary) below a divider |
664
727
 
665
- **Tokens used:** `bg-prominent`, `border-border-subtle`, `text-semantic-win`, `text-semantic-loss`, `text-on-prominent`, `text-on-subtle`
728
+ **Components used:** `Button` (variants: `tertiary`, `secondary`, default; sizes: `sm`, `icon-sm`); `Menu`, `X` icons (lucide)
729
+
730
+ **Tokens used:** `bg-prominent`, `border-border-subtle`, `rounded-md`, `px-layout-margin-inline`
666
731
 
667
732
  ---
668
733
 
669
- ### Header navigation
734
+ ### `HeaderNavigationBlock`
670
735
 
671
- A product app top header bar. Not a landing page component used inside the trading game itself.
736
+ A product app top header bar. Includes optional history button with overlaid numeric count badge.
737
+
738
+ ```tsx
739
+ import { HeaderNavigationBlock } from "@trading-game/design-intelligence-layer"
740
+
741
+ <HeaderNavigationBlock
742
+ onBack={() => router.back()}
743
+ badge={{ label: "Demo", variant: "fill-warning" }}
744
+ balance={{ amount: "1000.00", currency: "USDT" }}
745
+ history={{ count: 5, onClick: openHistorySheet }} // count 0 hides badge; >99 shows "99+"
746
+ actions={<SoundToggleButton />}
747
+ />
748
+ ```
672
749
 
673
750
  | Region | Content |
674
751
  |--------|---------|
675
- | Left | `NavigationButton` (back arrow) |
676
- | Centre | `Badge` (fill-warning "Demo" label) + account balance amount + currency label |
677
- | Right | `NavigationButton` icons for history and sound toggle |
752
+ | Left | `NavigationButton` (back arrow, rendered only if `onBack` provided) |
753
+ | Centre | `Badge` (fill-warning "Demo" label) + balance amount + currency |
754
+ | Right | History `NavigationButton` with optional numeric badge (`bg-primary`, `ring-2 ring-prominent`) + `actions` slot for additional icon buttons |
755
+
756
+ **Components used:** `NavigationButton`, `Badge`; `ArrowLeft`, `History` icons (lucide)
757
+
758
+ **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`
759
+
760
+ ---
761
+
762
+ ### `OpenPositionsBlock`
763
+
764
+ A slide-in panel listing open trading positions. Responsive — `Sheet` on desktop, `Drawer` on mobile (via `useIsMobile()`).
765
+
766
+ ```tsx
767
+ import { OpenPositionsBlock, type Position } from "@trading-game/design-intelligence-layer"
768
+
769
+ const positions: Position[] = [
770
+ { kind: "rise-fall", direction: "Rise", market: "Vol 100", duration: "30 minutes",
771
+ stake: "1.00 USDT", pnl: "+0.96 USDT", win: true },
772
+ ...
773
+ ]
774
+
775
+ <OpenPositionsBlock
776
+ trigger={<Button variant="secondary">Active trades</Button>}
777
+ positions={positions}
778
+ sheetTitle="Positions"
779
+ onViewHistory={openHistoryPage}
780
+ />
781
+ ```
782
+
783
+ Positions are a discriminated union by `kind`:
784
+
785
+ | `kind` | Title rendered as | Extra fields |
786
+ |--------|--------------------|--------------|
787
+ | `"rise-fall"` | `direction` (e.g. "Rise" / "Fall") | — |
788
+ | `"swipe"` | `Swipe-<direction>` (e.g. "Swipe-up") | — |
789
+ | `"box-o"` | `"Box-O"` | `multiplier` |
790
+ | `"digits"` | Type label (e.g. "Matches", "Under") | `type`, `digit?` |
791
+
792
+ **Components used:** `Sheet`, `Drawer`, `Item`, `ItemGroup`, `ItemContent`, `ItemTitle`, `ItemActions`, `Empty`, `EmptyHeader`, `EmptyMedia`, `EmptyTitle`, `Button`, `NavigationButton`, `Separator`
793
+
794
+ **Tokens used:** `bg-prominent`, `border-border-subtle`, `text-semantic-win`, `text-semantic-loss`, `text-on-prominent`, `text-on-subtle`
795
+
796
+ ---
797
+
798
+ ### `ResultBlock`
799
+
800
+ Universal end-of-round result card. Fixed-width (320 px) with animated halo + thumb illustration (bundled inline as base64) + contract/duration badges + CTA.
801
+
802
+ ```tsx
803
+ import { ResultBlock } from "@trading-game/design-intelligence-layer"
804
+
805
+ <ResultBlock
806
+ status="win" // "win" | "loss"
807
+ amount="10,000.00"
808
+ currency="USDT"
809
+ contractLabel="Rise"
810
+ duration="2 hours"
811
+ pickedDigit={7} // optional, for Digits contracts
812
+ ctaMode="next-round" // "next-round" | "go-again" | "conversion"
813
+ />
814
+ ```
815
+
816
+ | `ctaMode` | Renders |
817
+ |-----------|---------|
818
+ | `"next-round"` | Single "Next round" button |
819
+ | `"go-again"` | Single "Go again" button |
820
+ | `"conversion"` | "Ready to play for real?" heading + "Deposit now" + "Stay in demo" |
821
+
822
+ 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.
823
+
824
+ **Components used:** `Card`, `Badge` (variant `standard`), `Button`
825
+
826
+ **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`
827
+
828
+ ---
829
+
830
+ ### `ResultDialog`
831
+
832
+ 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.
833
+
834
+ ```tsx
835
+ import { ResultDialog } from "@trading-game/design-intelligence-layer"
836
+
837
+ <ResultDialog
838
+ title="You're out of balance."
839
+ body="Deposit to keep playing or stay in demo mode."
840
+ primaryLabel="Deposit now"
841
+ secondaryLabel="Stay in demo"
842
+ />
843
+ ```
678
844
 
679
- **Components used:** `NavigationButton`, `Badge`
845
+ **Components used:** `Card`, `Button`
680
846
 
681
- **Tokens used:** `bg-prominent`, `border-border-subtle`, `text-on-prominent`, `text-on-subtle`
847
+ **Tokens used:** `text-on-prominent`, `text-on-subtle`, `rounded-md`, `shadow-sm`
682
848
 
683
849
  ---
684
850
 
@@ -210,22 +210,30 @@ Wait for confirmation before proceeding.
210
210
 
211
211
  ---
212
212
 
213
- ## Rule 8 — Blocks are playground-only (not package exports)
213
+ ## Rule 8 — Blocks are first-class exports (import them by name)
214
214
 
215
- **Blocks** are pre-composed UI sections (e.g. NavBar) demonstrated in the **Blocks** tab of the design system playground. They are **not** exported from `@trading-game/design-intelligence-layer`.
215
+ **Blocks** are opinionated, composed UI sections exported from `@trading-game/design-intelligence-layer` the same as primitives. Import by name and pass data via props. Variants live as a `layout` / `mode` / `status` prop on a single block, not as separate components.
216
216
 
217
217
  ```
218
- Do NOT import blocks from the package — they don't exist there
219
- Do NOT treat block names (e.g. "NavBar") as component names from Rule 1
220
- To build a block pattern in your project: compose it manually using package components + tokens
221
- Reference guides/design-system-guide/trading-game-ds-guide.md Section 8.5 for block structure
218
+ Import blocks directly from the package — same pattern as primitives
219
+ Pass data via props; variants are configured via a single variant prop
220
+ Block names ARE valid component names (treat them like Rule 1 components)
221
+ Do NOT re-implement a block by hand if a block export already covers it
222
+ ❌ Do NOT split variants into separate blocks — use the variant prop
222
223
  ```
223
224
 
224
- | Block | Playground tab | Importable? |
225
- |-------|---------------|-------------|
226
- | NavBar | Blocks NavBar | Nobuild with `Button` + tokens |
227
- | Hero (Type 1) | Blocks Hero | Nobuild with `Button` + tokens; two-column layout with image panel |
228
- | Hero (Type 2) | Blocks Hero | Nobuild with `Button` + `ArrowRight` icon + tokens; centred single-column, no image |
225
+ | Block | Variants | Importable? |
226
+ |-------|----------|-------------|
227
+ | `HeroBlock` | `layout: "centered" \| "split"` | Yes`import { HeroBlock }` |
228
+ | `AuthBlock` | `mode: "sign-in" \| "sign-up"` | Yes — `import { AuthBlock }` |
229
+ | `FAQBlock` | `layout: "desktop" \| "mobile"` | Yes`import { FAQBlock }` |
230
+ | `NavBarBlock` | — (internal mobile-menu state) | Yes — `import { NavBarBlock }` |
231
+ | `HeaderNavigationBlock` | — (optional `history.count` badge) | Yes — `import { HeaderNavigationBlock }` |
232
+ | `OpenPositionsBlock` | `Position` discriminated union | Yes — `import { OpenPositionsBlock, type Position }` |
233
+ | `ResultBlock` | `status` + `ctaMode` | Yes — `import { ResultBlock }` |
234
+ | `ResultDialog` | — | Yes — `import { ResultDialog }` |
235
+
236
+ See `guides/design-system-guide/trading-game-ds-guide.md` § 8.5 for full per-block API, used components, and used tokens.
229
237
 
230
238
  ---
231
239
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trading-game/design-intelligence-layer",
3
- "version": "0.13.3",
3
+ "version": "0.15.0",
4
4
  "description": "Trading Game Design System — shadcn/ui components with Tailwind CSS v4",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
package/src/styles.css CHANGED
@@ -490,4 +490,26 @@
490
490
  font-weight: 600;
491
491
  font-size: 8px;
492
492
  line-height: 12px;
493
+ }
494
+
495
+ /* ── Result block — icon motion ─────────────────────────────── */
496
+ [data-results-motion="halo"] {
497
+ opacity: 0.22;
498
+ }
499
+ [data-results-motion="icon-win"] {
500
+ animation: results-icon-float 2.2s ease-in-out infinite;
501
+ }
502
+ [data-results-motion="icon-loss"] {
503
+ animation: results-icon-shake 2.4s ease-in-out infinite;
504
+ }
505
+ @keyframes results-icon-float {
506
+ 0%, 100% { transform: translateY(0) rotate(0); }
507
+ 50% { transform: translateY(-10px) rotate(-4deg); }
508
+ }
509
+ @keyframes results-icon-shake {
510
+ 0%, 100% { transform: rotate(-8deg); }
511
+ 50% { transform: rotate(8deg); }
512
+ }
513
+ @media (prefers-reduced-motion: reduce) {
514
+ [data-results-motion] { animation: none !important; }
493
515
  }