For the complete documentation index, see llms.txt. This page is also available as Markdown.

Theming

Twenty-three tokens, twenty-two CSS variables, and the isolation rule that makes them the only way in.

Pass a partial theme to any widget, or once to StableGenieProvider:

import { StableGenieExchange } from "@glacislabs/stablegenie-zerodelta";

<StableGenieExchange
  theme={{ mode: "dark", accent: "#8c9bff", accentText: "#0b0d12", radius: "16px" }}
/>

resolveTheme() picks darkTheme when mode === "dark" and lightTheme otherwise, then spreads your overrides on top. You only name what you want to change.

The theme prop is the only way in. Tokens are emitted as CSS custom properties written inline on the widget's own root element, never on :root. Page CSS cannot leak into the widget and the widget cannot leak out. A host stylesheet targeting the widget's internal class names is unsupported and will break without warning.

Tokens

StableGenieTheme is flat — 23 fields, all optional when you pass a partial.

Colour

Field
CSS variable
Light
Dark

accent

--sg-accent

#4358e1

#4358e1

accentText

--sg-accent-text

#ffffff

#ffffff

bg

--sg-bg

#ffffff

#0e1115

surface

--sg-surface

#f7f8fe

#1b1d22

border

--sg-border

#e8ebfb

#343541

text

--sg-text

#2c2d34

#ffffff

textMuted

--sg-text-muted

#959699

#87888a

info

--sg-info

same as accent

#8c9bff

danger

--sg-danger

#df1b41

#ff5470

success

--sg-success

#2abd7d

#2abd7d

What each colour paints:

  • bg — the card, and the controls that sit on a tinted pane (the token button, the percent chips, the swap button). In dark mode those controls are surface lifted 8 % toward info, so they still read as raised.

  • surface — the tinted You pay / You receive panes and the From / To tiles.

  • border — the ring around the detail rows (Compliance, Quote, the rate box) and the wallet chip.

  • text — every heading and value. Labels and the greyed decimals of an amount are tone steps of this one colour (90, 80, 60 and 35 %), so a host names it once.

  • textMuted — secondary lines: the chain under a ticker, the dollar line, the balance label.

  • info — the Quote row's icon and its Best return pill. Omitted, it follows accent. The dark palette's default is a lighter lavender that reads on the dark card; a dark theme that brings its own accent and no info gets its accent. Set a neutral here when your accent could be read as a verdict — the Emerald and Sand presets use #292a30.

  • success — the compliance shield and its Passed pill, and the connected-wallet dot.

Shape and type

Field
CSS variable
Default
Applies to

radius

--sg-radius

24px

the outer card, the pill's dialog

radiusControl

--sg-radius-control

24px

panes, tiles, the detail rows, token button

radiusCta

--sg-radius-cta

24px

the primary button and the pill face

font

--sg-font

'Helvetica Neue', Helvetica, Arial, system-ui, sans-serif

everything except the amounts

fontDisplay

--sg-font-display

Benzin, followed by font

the amounts

The small pieces follow the control radius: the percent chips at half of it, the wallet chip and the verdict pills at two thirds.

fontDisplay names Benzin, but the widget never loads it. Benzin is the ZeroDelta display face; the widget ships no font file and makes no font request. On a page that already loads Benzin the amounts use it, and everywhere else they fall back to font. If you set font and leave fontDisplay unset, the amounts follow your font — a re-branded card is never left with one foreign face.

Motion

Identical in light and dark — motion does not theme. Every rule that uses these is prefers-reduced-motion guarded, so a user who asks for less motion gets it regardless of what you set.

Field
CSS variable
Default
Used for

motionFast

--sg-motion-fast

160ms

small state flips

motionBase

--sg-motion-base

220ms

expand / collapse, the modal

motionSlow

--sg-motion-slow

320ms

the drawer, the receipt

motionDeliberate

--sg-motion-deliberate

480ms

the success sweep

easeOutSoft

--sg-ease-out-soft

cubic-bezier(0.22,0.61,0.36,1)

entrances

easeInOut

--sg-ease-in-out

cubic-bezier(0.4,0,0.2,1)

reversible morphs

easeSpring

--sg-ease-spring

cubic-bezier(0.34,1.56,0.64,1)

the ZeroDelta Link pop

mode

mode is the only field with no CSS variable. It selects which base palette the other twenty-two are spread over.

Dark mode is yours to decide

The widget does not read prefers-color-scheme itself — it renders the mode you give it, so it always matches your page rather than fighting it. Follow the OS setting like this:

Presets

The five palettes the widget playground offers. Copy the object you want.

Measured contrast of the CTA label on its accent: light and dark 5.6:1, Black/White 14.3:1, Sand 8.5:1 — all WCAG AA. Emerald measures 3.9:1, which meets AA for large text only; darken the accent if your CTA copy must meet AA at 14 px.

Corners

The three radii move together. The playground drives all three from one slider:

0 gives a square card; 24 is the default.

Picking accentText for a brand colour

If you set accent to your own brand colour, set accentText to whichever of black or white is legible on it. This is the helper the playground uses:

Sizing

The compact card is 380 px wide at most and centres in its container. The wide layout is a 360 px card beside a 280 px You receive card, and folds to one column when its container is narrower than 660 px. Set heightPx to fix the height and scroll the content inside — useful in a fixed checkout panel. Omit it for fit-content.

What you cannot theme

Layout, copy, the ZeroDelta brand mark, the ordering of funding routes, and the success visual — which is accent-tinted by design and never a loud green surface. These are fixed so that a payment surface looks and behaves the same wherever it is embedded.

See every token live, with a copyable snippet, in the widget playground.