Skip to main content

theme

The theme prop on TaxKitProvider controls how the iframe renders visually. It takes six optional fields:

interface TaxKitTheme {
light?: ThemeContract;
dark?: ThemeContract;
mode?: 'light' | 'dark';
partnerLogo?: string | { light: string; dark: string };
fonts?: PartnerFontDefinition[];
fontStylesheets?: string | string[];
}

The ThemeContract field names (background, foreground, primary, muted / mutedForeground, accent, destructive, border, input, popover / popoverForeground, radius) match the canonical shadcn / Radix token contract. The iframe's UI is built on CoinTracker's @cointracker/base-ui, which is itself a shadcn-patterned library on top of Radix primitives — if you've worked with shadcn before, the semantics are identical. The ct*-prefixed fields are CoinTracker-specific surfaces with no shadcn equivalent; leave them unset for defaults.

Token values are any valid CSS color string (#0052FF, rgb(0, 82, 255), hsl(216 100% 50%), rgba(0, 82, 255, 0.8)). The iframe doesn't validate — an invalid string renders as the browser default.

Fields

theme.lightThemeContract

Color and spacing tokens applied when the iframe renders in light mode. See ThemeContract below for the full token list.

theme.darkThemeContract

Color and spacing tokens applied when the iframe renders in dark mode.

theme.mode'light' | 'dark'

Force light or dark mode. When omitted, the iframe defaults to the user's OS preference (via prefers-color-scheme).

theme.partnerLogostring | { light: string; dark: string }

Partner logo shown in the iframe header. Pass a single URL string to use the same image in both modes, or { light, dark } for mode-specific variants. When unset, the SDK falls back to its built-in logo for known partner slugs (coinbase, kraken). See Partner branding below.

theme.fontsPartnerFontDefinition[]

Self-hosted @font-face definitions injected into the iframe. Each entry maps to one @font-face rule — use this when the partner brand font isn't bundled with the SDK and you control the source URLs. See Partner branding below.

theme.fontStylesheetsstring | string[]

External font stylesheet URL(s) — Google Fonts, Adobe Fonts, Bunny Fonts. Injected as <link rel="stylesheet"> so the provider handles @font-face, unicode-range subsetting, and format negotiation. See Partner branding below.

Example

<TaxKitProvider
fetchAccessToken={fetchAccessToken}
theme={{
mode: 'dark',
light: {
radius: '0.5rem',
spacing: '0.25rem',
fontSans: '"Inter", sans-serif',
background: 'rgb(255, 255, 255)',
foreground: 'rgb(10, 11, 13)',
primary: 'rgb(0, 82, 255)',
// …see ThemeContract for all available tokens
},
dark: {
radius: '0.5rem',
spacing: '0.25rem',
fontSans: '"Inter", sans-serif',
background: 'rgb(10, 11, 13)',
foreground: 'rgb(245, 248, 255)',
primary: 'rgb(55, 115, 245)',
},
}}
>
<YourApp />
</TaxKitProvider>

If your parent re-renders frequently, memoize the theme object (or its light/dark sub-objects) with useMemo — the provider already wraps the contract in useMemo internally, so stable references from your side avoid re-firing the dispatcher's CONFIG effect. The same applies to partnerLogo (when passed as an object), fonts, and fontStylesheets: pass stable references to avoid unnecessary iframe-side <style> / <link> re-injection.

Partner branding

Three optional fields make it possible to brand the iframe with a partner's own logo and fonts — without bundling assets into the SDK.

Replaces the SDK's built-in mark in the iframe header. Accepts either a single URL (used in both modes) or a per-mode object:

// Single URL — same image in light and dark
theme={{
partnerLogo: 'https://cdn.your-partner.com/logo.svg',
}}
// Per-mode variants for inverted logos
theme={{
partnerLogo: {
light: 'https://cdn.your-partner.com/logo-dark-on-light.svg',
dark: 'https://cdn.your-partner.com/logo-light-on-dark.svg',
},
}}
  • Host your own asset. Point at a CORS-accessible URL on your CDN or origin. Prefer SVG; if you ship PNG, keep it small (≤ 128px square).
  • Sizing is locked. The visual size is constrained by the iframe header — oversized images won't break layout — but bandwidth is still on you.
  • Alt text is auto-derived from the partner slug (e.g. "Coinbase logo"). You do not pass it.
  • Fallback: when unset, the SDK uses its built-in logo for known partner slugs (coinbase, kraken). New partners that don't supply partnerLogo get nothing in the header.

Self-hosted fonts: fonts

@font-face definitions for woff2/woff/ttf/otf files you serve from your own CDN. Each entry is injected verbatim, so you control format, weight, style, and font-display.

theme={{
fonts: [
{
family: 'Partner Sans',
src: 'https://cdn.your-partner.com/partner-sans-regular.woff2',
weight: '400',
style: 'normal',
},
{
family: 'Partner Sans',
src: 'https://cdn.your-partner.com/partner-sans-bold.woff2',
weight: '700',
style: 'normal',
},
],
light: { fontSans: '"Partner Sans", sans-serif', /* …other tokens */ },
dark: { fontSans: '"Partner Sans", sans-serif', /* …other tokens */ },
}}

The PartnerFontDefinition shape mirrors the standard CSS @font-face descriptors:

interface PartnerFontDefinition {
family: string;
src: string;
weight?: string;
style?: string;
display?: string;
}

After registering the family, reference it from light.fontSans and dark.fontSans like any other font chain.

External stylesheets: fontStylesheets

For off-the-shelf web fonts (Google Fonts, Adobe Fonts, Bunny Fonts), pass the stylesheet URL(s) directly. The iframe injects each as <link rel="stylesheet">, so the font provider handles @font-face, format negotiation, and unicode-range subsetting:

// Single URL
theme={{
fontStylesheets:
'https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap',
light: { fontSans: '"Inter", sans-serif', /* … */ },
dark: { fontSans: '"Inter", sans-serif', /* … */ },
}}
// Multiple URLs
theme={{
fontStylesheets: [
'https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap',
'https://use.typekit.net/your-kit-id.css',
],
}}

Which font field do I use?

ScenarioUse
You self-host .woff2 files on your CDNfonts
You're loading a Google Font / Adobe Font / Bunny FontfontStylesheets
Mix of bothBoth — they're independent

ThemeContract fields

Every field is optional. Unset tokens fall back to the iframe's defaults.

backgroundstring

Page background color.

foregroundstring

Default text color on background.

primarystring

Brand color used for primary buttons, focus rings, and emphasis.

secondarystring

Secondary surface color (e.g. card backgrounds).

mutedstring

Muted surface color for low-emphasis backgrounds.

mutedForegroundstring

Muted text color for low-emphasis copy.

accentstring

Accent surface color (used for hover/active states on neutral controls).

destructivestring

Color for destructive actions and error states.

warningstring

Color for warning states.

successstring

Color for success states.

borderstring

Default border color.

inputstring

Border color for form inputs.

popoverstring

Popover/modal background. Defaults to background when not provided.

popoverForegroundstring

Popover/modal text color. Defaults to foreground when not provided.

radiusstring

Default border-radius for components.

buttonRadiusstring

Button border-radius. Defaults to the Coinbase pill shape (9999px) when not provided.

cardRadiusstring

Card/container border-radius. Defaults to 1rem (16px) when not provided.

spacingstring

Base spacing unit.

fontSansstring

Sans-serif font stack.

ctCardSurfacestring

CoinTracker-specific surface token used inside the kit.

ctForegroundstring

CoinTracker-specific foreground token.

ctEmphasisstring

CoinTracker-specific emphasis token.

ctSecondarystring

CoinTracker-specific secondary token.