Skip to main content

Theme System

Set your brand once on SpiceFlowProvider. Every SDK component inherits it automatically.
<SpiceFlowProvider
  provider="privy"
  network="mainnet"
  nativeChainId={8453}
  theme={{
    primaryColor: "#f97316",
    dark: true,
    appName: "MyApp",
  }}
>
  {children}
</SpiceFlowProvider>

SpiceTheme Options

OptionTypeDefaultDescription
primaryColorstring"#EA4B4B"Accent color — buttons, highlights, active states
darkbooleanfalseDark or light mode
shellstringMode defaultModal outer background
cardstringMode defaultCard and input area background
textstringMode defaultPrimary text color
textMutedstringMode defaultSecondary/label text color
borderstringMode defaultBorder color
borderRadiusstring"8px"Border radius applied across all components
fontFamilystring"Helvetica Neue"Primary font family
appNamestring"Spicenet"App name shown in modal headers
logoReactNodeCustom logo for modal headers
Surface tokens (shell, card, text, textMuted, border) have sensible defaults per mode — only set what you want to override.

Dark Mode

// Dark
<SpiceFlowProvider theme={{ primaryColor: "#f97316", dark: true }}>

// Light
<SpiceFlowProvider theme={{ primaryColor: "#f97316", dark: false }}>

Default Surface Colors

TokenDarkLight
shell#141414#ffffff
card#1e1e1e#f9fafb
text#ffffff#111827
textMuted#888888#6b7280
border{primaryColor}33{primaryColor}22

Custom Surfaces

Override any surface token alongside the mode:
<SpiceFlowProvider
  theme={{
    primaryColor: "#10b981",
    dark: true,
    shell: "#0f1f15",
    card: "#0a1a10",
    border: "#1a3a20",
    borderRadius: "12px",
  }}
>

Per-Component Override

Pass styles to any component to override the provider theme for that instance only:
// Different accent on a single modal
<SpiceDeposit
  isOpen={isOpen}
  onClose={onClose}
  styles={{ primaryColor: "#10b981" }}
/>

// Force dark on one component even if provider is light
<SpiceWithdraw
  isOpen={isOpen}
  onClose={onClose}
  dark={true}
  styles={{ primaryColor: "#3b82f6" }}
/>

// Full button + input customisation
<SpiceDeposit
  isOpen={isOpen}
  onClose={onClose}
  styles={{
    primaryColor: "#10b981",
    button: { backgroundColor: "#10b981", color: "#ffffff", borderRadius: "8px" },
    inputVariant: "dark",
    fontFamily: '"Inter", sans-serif',
  }}
/>

Available styles keys per component

ComponentKeys
SpiceDepositprimaryColor, button.backgroundColor, button.color, button.borderRadius, inputVariant, fontFamily
SpiceWithdrawprimaryColor, button.backgroundColor, button.color, fontFamily
SpiceSupplyprimaryColor, button.backgroundColor, button.color, inputVariant
SpiceLockModalprimaryColor, button.backgroundColor, button.color, fontFamily
LpModalprimaryColor, fontFamily
AccountDisplayprimaryColor, fontFamily
SpiceBalanceprimaryColor, fontFamily
inputVariant accepts "light" or "dark" to override the input field style independently of the global mode.

Fonts

The SDK uses two fonts:
  • Helvetica Neue — all body text, labels, headings, descriptions
  • IBM Plex Mono — amounts, addresses, hashes, button labels
Override the body font via theme.fontFamily. The monospace font is always used for technical displays.

Examples

Orange Dark

<SpiceFlowProvider theme={{ primaryColor: "#f97316", dark: true }}>

Blue Light

<SpiceFlowProvider theme={{ primaryColor: "#3b82f6", dark: false }}>

Green Dark with Custom Surfaces

<SpiceFlowProvider
  theme={{
    primaryColor: "#10b981",
    dark: true,
    shell: "#0f1f15",
    card: "#0a1a10",
    borderRadius: "12px",
  }}
>

Sharp Trading UI

<SpiceFlowProvider
  theme={{
    primaryColor: "#5BFFB0",
    dark: true,
    shell: "#0a0a0a",
    card: "#111111",
    borderRadius: "0px",
  }}
>

Building Custom Components

Use useSpiceBrand to match the SDK theme inside your own components:
import { useSpiceBrand } from "@spicenet-io/spiceflow-ui";

function CustomCard() {
  const { primaryColor, dark, palette } = useSpiceBrand();

  return (
    <div style={{
      backgroundColor: palette.cardBg,
      color: palette.textPrimary,
      border: `1px solid ${palette.cardBorder}`,
      borderRadius: "8px",
      padding: "16px",
    }}>
      <h3 style={{ color: primaryColor }}>Custom card</h3>
      <p style={{ color: palette.textSecondary }}>Matches SDK palette</p>
    </div>
  );
}
palette is the fully-resolved palette for the current mode — dark or light values depending on dark. It exposes: shell, cardBg, inputBg, hoverBg, textPrimary, textSecondary, inputText, inputPlaceholder, cardBorder, inputBorder, buttonBorder, and semantic tokens (successBg, errorBg, warningBg, infoBg, and their border/text variants). dk is the raw dark palette, useful when you need dark-specific values regardless of mode (e.g. for overlay rendering).

Next Steps

Components

See all available components

Configuration

Configure providers and chains

Examples

See styled examples in action

Best Practices

Follow integration best practices