> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ravn.exchange/llms.txt
> Use this file to discover all available pages before exploring further.

# Theming the widget

> Match the embedded widget's colors, corner radius, and font to your product, no CSS, previewed live in the Playground.

Theming is sent as part of the same `config` object [`createRavnWidgetBridge`](/sdks/widget#createravnwidgetbridge-options) already sends at handshake: there's no separate API, no CSS to override, and no rebuild of the widget. Set the fields you want, leave the rest out, and those defaults stay untouched.

```ts theme={null}
import { createRavnWidgetBridge } from "@ravnexchange/widget-connector";

const bridge = createRavnWidgetBridge({
  iframe: iframeRef.current,
  widgetOrigin: "https://app.ravn.exchange",
  getWallet: () => (isEvmConnected ? evmWallet : null),
  getSolanaWallet: () => (isSolanaConnected ? solanaWallet : null),
  config: {
    primaryColor: "#7C3AED",
    secondaryColor: "#A78BFA",
    borderRadius: 16,
    fontFamily: "Georgia, serif",
  },
});
```

<Card title="Try it live in the Playground" icon="palette" href="https://app.ravn.exchange/widget/playground">
  Every field below, previewed in the real widget. Pick a preset or tune your own palette, then copy the resulting `config` straight into your integration.
</Card>

## Colors

<ParamField body="primaryColor" type="string">The CTA/highlight color: swap button, active states. Also picks a readable label color for CTA buttons automatically (near-black or near-cream, whichever contrasts better), so a dark `primaryColor` never produces unreadable dark-on-dark button text.</ParamField>
<ParamField body="secondaryColor" type="string">The secondary accent: tab underline and some glow effects.</ParamField>
<ParamField body="background" type="string">The widget's own backdrop, behind the card.</ParamField>
<ParamField body="cardBackground" type="string">The card shell. Every recessed surface inside it (input fields, the token chip, dropdown rows) gets a shade darker automatically, so they stay visibly recessed instead of collapsing into the same flat surface as the card around them.</ParamField>
<ParamField body="textPrimary" type="string">Primary text color.</ParamField>
<ParamField body="textSecondary" type="string">Secondary/muted text color.</ParamField>
<ParamField body="success" type="string">Confirmation states: completed swaps, positive deltas.</ParamField>
<ParamField body="error" type="string">Error and alert states.</ParamField>

All eight accept any valid CSS color (`#rrggbb`, `rgb()`, a named color). A value the widget can't parse as a color is dropped, not passed through broken.

## Shape and typography

<ParamField body="borderRadius" type="number">Corner radius in px, applied to every control and to the card shell together, so the two never drift out of sync into two different rounding scales side by side. `0` is a real value (sharp corners), not "unset".</ParamField>
<ParamField body="fontFamily" type="string">Any valid CSS `font-family` value, e.g. `"Inter, sans-serif"`. The widget only sets the property (same as most embeddable widgets); it doesn't fetch the font for you. If you're picking a Google Font, load it on your own page (or the page embedding the widget) the normal way, e.g. a `<link>` to `fonts.googleapis.com` or `@import` in your CSS, before it'll actually render.</ParamField>

## What's not themeable

A few things LI.FI's widget exposes don't have an equivalent here, on purpose rather than by omission:

* **No `appearance` (light/dark) toggle.** The widget's whole visual language (translucent hairlines, glow and text-shadow accents) is tuned for a dark canvas. A real light mode needs its own design pass, not a background-color swap, so it isn't offered as a config flag yet.
* **No `warning` color.** RAVN's UI doesn't have a distinct warning tier; the one place that might use it reuses the `error` color instead. Adding a `warning` field would theme a color with nothing in the product it maps to.
* **No per-surface shadow/border toggles.** The card carries a fixed, sensible elevation by default; there's no on/off knob for it yet.

## Presets

The Playground ships four starting points: Default, Violet, Watermelon, and Mono, each just a plain `config` object like the one above. Watermelon, for example:

```ts theme={null}
config: {
  primaryColor: "#E11D48",
  secondaryColor: "#FB7185",
  background: "#FFF1F2",
  cardBackground: "#FFFFFF",
  textPrimary: "#1F2937",
  textSecondary: "#6B7280",
  borderRadius: 20,
}
```

Open a preset in the Playground and use the **Copy** button under "Your config" to grab its exact object, then tweak from there.

## Playground

<Card title="Widget Playground" icon="palette" href="https://app.ravn.exchange/widget/playground">
  `app.ravn.exchange/widget/playground`
</Card>

The Playground is the real `/widget/v1` widget in an iframe, driven by the real `@ravnexchange/widget-connector` bridge, not a static mockup. Every change to a color, the radius slider, or the font dropdown re-runs the actual `bridge:init` handshake with your new config, so what you see is exactly what an integration gets.

* **Presets** apply a full config in one click: a fast way to see the range before tuning your own.
* **Color palette** gives a text field (accepts any CSS color) and a native color picker for each of the eight color fields, side by side.
* **Shape & type** covers `borderRadius` (slider + number field) and `fontFamily` (a dropdown of curated options; the widget only sets `font-family`, so the Playground loads each Google Font itself just for the preview).
* **Your config** shows the live `config` object and a ready-to-paste `createRavnWidgetBridge({...})` snippet, with a one-click Copy button.

No wallet connection is required to use it: the preview renders with `getWallet`/`getSolanaWallet` both returning `null`, so it shows the widget's pre-connect state.
