Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

theme

Customize the appearance of SDK UI dialogs (onboarding, signing, transactions, permissions).

Type: JawTheme Required: No Default: { mode: 'auto', borderRadius: 'md', fontStack: 'system' }

Quick Start

import { JAW, Mode } from '@jaw.id/core';
import { ReactUIHandler } from '@jaw.id/ui';
 
const jaw = JAW.create({
  apiKey: 'your-api-key',
  theme: {
    mode: 'dark',
    accentColor: '#6366f1',
    borderRadius: 'lg',
  },
  preference: {
    mode: Mode.AppSpecific,
    uiHandler: new ReactUIHandler(),
  },
});

Theme Properties

PropertyTypeDefaultDescription
mode'light' | 'dark' | 'auto''auto'Color scheme. 'auto' follows the user's system preference.
accentColorstringPrimary color as hex (e.g. '#6366f1'). Applied to buttons, focus rings, links.
accentColorForegroundstringauto-detectedText color on accent backgrounds. Auto-detected from luminance if omitted.
borderRadius'sm' | 'md' | 'lg''md'Corner rounding for cards, buttons, and inputs.
fontStack'system' | 'rounded' | 'mono''system'Font family preset.
cssVariablesRecord<string, string>Granular CSS variable overrides (see below).

Three Layers of Customization

Layer 1: Simple Props (recommended)

Covers 90% of use cases. Pass mode, accentColor, and borderRadius.

const jaw = JAW.create({
  apiKey: 'your-api-key',
  theme: {
    mode: 'dark',
    accentColor: '#e11d48', // Rose
    borderRadius: 'lg',
  },
  preference: {
    mode: Mode.AppSpecific,
    uiHandler: new ReactUIHandler(),
  },
});

Layer 2: CSS Variable Overrides

For precise control, override individual CSS variables. These take highest priority.

const jaw = JAW.create({
  apiKey: 'your-api-key',
  theme: {
    mode: 'dark',
    accentColor: '#7b3fe4',
    cssVariables: {
      '--jaw-color-background': 'oklch(0.15 0.02 280)',
      '--jaw-color-card': 'oklch(0.20 0.02 280)',
      '--jaw-font-family': '"Berkeley Mono", monospace',
    },
  },
  preference: {
    mode: Mode.AppSpecific,
    uiHandler: new ReactUIHandler(),
  },
});

Layer 3: Raw CSS (escape hatch)

Target [data-jaw-modal-container] in your own CSS. No SDK changes needed.

[data-jaw-modal-container] {
  --jaw-color-primary: oklch(0.65 0.25 270);
  --jaw-color-background: oklch(0.12 0.01 260);
  font-family: 'Inter', sans-serif;
}

Passing Theme to ReactUIHandler

You can pass the theme in two places. Both work, and the constructor theme takes precedence:

Via JAW.create()
// Theme flows through SDK -> UIHandler.init()
const jaw = JAW.create({
  apiKey: 'your-api-key',
  theme: { mode: 'dark', accentColor: '#6366f1' },
  preference: {
    mode: Mode.AppSpecific,
    uiHandler: new ReactUIHandler(),
  },
});

Auto Mode (System Preference)

When mode is 'auto' (the default), the SDK detects the user's system color scheme and switches dynamically. If the user changes their OS dark/light preference while a dialog is open, it updates live.

theme: {
  mode: 'auto';
} // follows system preference

Available CSS Variables

Use these with cssVariables for granular overrides. All values use the OKLCH color space.

Colors

VariableDescription
--jaw-color-backgroundDialog backdrop
--jaw-color-foregroundPrimary text
--jaw-color-cardCard/section backgrounds
--jaw-color-card-foregroundCard text
--jaw-color-primaryButtons, links, focus rings
--jaw-color-primary-foregroundText on primary backgrounds
--jaw-color-secondarySecondary backgrounds
--jaw-color-secondary-foregroundSecondary text
--jaw-color-mutedMuted/disabled backgrounds
--jaw-color-muted-foregroundMuted text
--jaw-color-accentHover/active state backgrounds
--jaw-color-accent-foregroundAccent text
--jaw-color-borderBorders and dividers
--jaw-color-inputInput field borders
--jaw-color-ringFocus ring color
--jaw-color-destructiveError/danger backgrounds
--jaw-color-destructive-foregroundError/danger text
--jaw-color-successSuccess state
--jaw-color-success-foregroundSuccess text
--jaw-color-warningWarning state
--jaw-color-warning-foregroundWarning text
--jaw-color-infoInfo state
--jaw-color-info-foregroundInfo text

Layout

VariableDescription
--jaw-radiusBase border radius (e.g. 0.625rem)
--jaw-font-familyFont family string

How Accent Color Works

When you set accentColor, the SDK:

  1. Converts your hex color to OKLCH color space
  2. Sets it as --jaw-color-primary (buttons, links)
  3. Auto-detects a contrasting foreground color (light text for dark accents, dark text for light accents)
  4. Derives a subtle tint for hover states (--jaw-color-accent)
  5. Creates a desaturated variant for focus rings (--jaw-color-ring)

In dark mode, dark accent colors are automatically lightened for better visibility.

To override the auto-detected foreground, pass accentColorForeground:

theme: {
  accentColor: '#1e1e2e',
  accentColorForeground: '#ffffff',  // force white text
}

Related Configuration

  • mode - Authentication mode (AppSpecific required for theming)
  • AppSpecific - AppSpecific mode setup
  • appName - App name shown in dialogs
  • appLogoUrl - App logo shown in dialogs