Titandocs

Components

The primitives, their variants, and the class patterns each one is built from.

Every primitive follows the tokens. Component visuals live in CSS (@layer components); React components are thin wrappers that apply the class and forward props.

Button

src/components/ui/button.tsx, CVA-based.

Base: inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent text-sm font-medium transition-all outline-none focus-visible:ring-3 focus-visible:ring-ring/50 active:translate-y-px disabled:opacity-50

VariantStyle
defaultbg-primary text-primary-foreground hover:bg-primary/80
outlineborder-border bg-background hover:bg-muted
secondarybg-secondary + color-mix hover
ghosttransparent fill, hover:bg-muted
destructivebg-destructive/10 text-destructive hover:bg-destructive/20
linktext-primary underline-offset-4 hover:underline

Sizes: xs (h-6) · sm (h-7) · default (h-8) · lg (h-9) · icon (square size-6→9).

Two live outside CVA: .btn-chrome (the animated shimmer connect button) and .titan-cta (the primary trading CTA — fill #1a1a1f, uppercase, tracking-[0.05em], bold).

Card / Panel

The most repeated pattern in the app:

<div className="rounded-[18px] border border-border bg-[var(--surface)] p-4">
  • Radius 18px, 22px for large.
  • Border border-border, fill --surface.
  • No shadow in-page.
  • Optional .card-lift on hover.
  • Card header often on --surface-2 with a border-b.
Open interest
4.21M
BTC-USDCX
24h volume
18.7M
all markets
Funding
+0.0104%
next in 03:12
Utilisation
82.4%
filling up

Popover

absolute right-0 top-[calc(100%+6px)] z-50
rounded-[var(--r-lg)] border-[.5px]
bg-[rgba(20,20,22,.92)]  →  rgba(255,255,255,.92) in light
backdrop-blur(28px) saturate(1.6)
shadow-[var(--shadow-lg)]
animation: wp-in .2s cubic-bezier(.2,.7,.3,1)

Plus an invisible fixed inset-0 z-40 overlay — click anywhere to dismiss.

overlay : fixed inset-0 z-[96+], bg rgba(0,0,0,.18–.28), backdrop-blur(8px)
panel   : centered, rounded-[18–22px], translucent surface, deep shadow
enter   : scaleIn / kbd-modal-in (.26–.28s, spring)
dismiss : overlay click + Escape

Escape must work. One SDK-provided dialog in the wallet flow opens via the open attribute rather than showModal(), which makes Escape inert — installEscapeHatch() exists purely to fix that. Any modal you write should not need such a patch.

Segmented control / Tabs

The "pill track + thumb" pattern:

track  : flex gap-0.5 p-[3px] rounded-full bg-[var(--surface-3)]
item   : px-2.5 py-[5px] rounded-full text-[11.5px] font-semibold text-[var(--t2)]
active : bg-[var(--surface)] text-[var(--t1)] shadow-[0_1px_2px_rgba(0,0,0,.08)]

Variants: an animated ::before thumb sliding via translateX (deposit tabs), or an animated underline for page tabs (h-0.5 bg-[var(--t1)]). The main nav uses the same logic with aria-current="page" on the active item.

Pill / Badge

inline-flex items-center px-2.5 py-[5px] rounded-full
text-[12px] font-semibold
+ semantic: bg-[var(--green-soft)] text-[var(--green)]
LONGSHORT+14.62%−3.08%Near capacity40×

Table / List

<table className="w-full border-collapse">
  <thead>
    <tr className="text-[9.5–11.5px] uppercase tracking-[0.06–0.1em] text-[var(--t3)]">
      <th className="text-left py-2 px-2.5 border-b border-border">Symbol</th>
      <th className="text-right …">Amount</th>
    </tr>
  </thead>
  <tbody>
    <tr className="hover:bg-[var(--surface-2)] transition-colors">
      <td className="py-2 px-… tabular-nums">…</td>
    </tr>
  </tbody>
</table>

Rules: headers uppercase with wide tracking in --t3; numeric columns right-aligned and tabular; row hover --surface-2; separators border-b border-border with last:border-0; sticky header via sticky top-0 z-[1] bg-[var(--surface)].

MarketSizeEntryMarkLiq.PnL
BTC-USDCXLONG 10×0.4200061,880.0064,212.2556,410.00+979.55
ETH-USDCXSHORT 5×3.24003,410.203,466.803,980.10−183.38
SOL-USDCXLONG 20×112.00186.40191.02178.55+517.44

Order book

grid grid-cols-3, rows py-[3px] (very compact). Depth bars via color-mix. Asks red on top, spread in the centre on --surface-3, bids green below.

PriceSizeTotal
64,215.00.8421054074
64,214.51.2040077312
64,214.00.3188020471
64,213.52.04110131065
64,213.00.102506582
64,212.25spread 1.50
64,211.50.5560035702
64,211.01.88240120875
64,210.50.4209027027
64,210.03.11750200184
64,209.50.9633061856

Charts

ChartLibraryNotes
PriceTradingView Charting LibraryVendored; themed by public/tradingview-theme.css
Equity area@visx/shapestroke/fill var(--green), fillOpacity .16
Ring donutcustom SVGsize=172 strokeWidth=18 ringGap=5, segments via greenRamp(mix)
Sparklineinline SVG72×22, stroke = up ? green : red
Impact ringSVGTriple concentric: margin --warn, health --green, leverage #0A84FF

On this page