Skip to main content

Theme Configuration

Provide the theme property on the object you pass into checkout.mount('element-id', { ...config }) after creating the instance with new PayNextCheckout(), as shown in Mount the Checkout.
theme
'light' | 'dark' | 'system'
Theme mode for the checkout UI.
  • 'light': Fixed light theme
  • 'dark': Fixed dark theme
  • 'system': Resolves to browser’s prefers-color-scheme at mount time, then fixed
  • undefined: Defaults to 'light' and listens for system theme changes
When theme is undefined, the SDK automatically updates when the user changes their system theme preference. When explicitly set (including 'system'), the theme is fixed and does not listen to system changes.
import { PayNextCheckout, type PayNextConfig } from '@paynext/sdk'

const checkout = new PayNextCheckout()

const config: PayNextConfig = {
  clientToken: 'your-client-token',
  environment: 'sandbox',
  apiVersion: '1.0.0',
  theme: 'dark',
}

await checkout.mount('checkout-container', config)

Payment Button Styling

Payment buttons automatically adapt to the theme:
  • Apple Pay: style: 'black' (light) / 'white' (dark)
  • Google Pay: color: 'black' (light) / 'white' (dark)
  • PayPal: color: 'gold' (light) / 'white' (dark)
Custom button styles in styles.ApplePayButton, styles.GooglePayButton, or styles.PayPalButton override theme defaults.

CSS Variables

Override theme tokens by passing styles.cssVariables (type CSSVariablesConfig) when you mount the SDK, or target .checkout / .checkout.dark classes from your stylesheet. Unset values fall back to the active theme defaults.
Variables marked “inherits” are not redefined in dark mode and use the light theme value. Variables marked “same” are explicitly set to the same value in both themes.

Complete Token Reference

VariableLight defaultDark defaultDescription
--paynext-sdk-bgtransparenttransparentCheckout container background
--paynext-sdk-text#1a1a1a#ffffffPrimary text color
--paynext-sdk-border#e0e0e0#404040Default border color
--paynext-sdk-border-focus#6b7280#9ca3afBorder color on focus
--paynext-sdk-border-radius12pxinheritsGlobal border radius
--paynext-sdk-input-bgtransparenttransparentInput field background
--paynext-sdk-input-texthsla(0, 0%, 10%, 0.9)hsla(0, 0%, 90%, 0.9)Input text color
--paynext-sdk-input-focus-shadow0 0 0 1px rgba(13, 118, 110, 0.7), 0 1px 1px 0 rgba(0, 0, 0, 0.07), 0 0 0 4px rgba(13, 118, 110, 0.3)sameFocus ring/shadow
--paynext-sdk-placeholder#9ca3af#6b7280Placeholder text color
--paynext-sdk-error#ef4444#f87171Error text color
--paynext-sdk-error-border#dc2727#f87171Error border color
--paynext-sdk-disabled-bg#ebedef#374151Disabled input background
--paynext-sdk-disabled-text#9ca3af#6b7280Disabled input text
--paynext-sdk-button-bg#0d766e#0d766eSubmit button background
--paynext-sdk-button-hover-bg#0d766d25inheritsButton hover background
--paynext-sdk-button-text#ffffff#ffffffButton text color
--paynext-sdk-button-hover-opacity0.70.8Button hover opacity
--paynext-sdk-card-bg#252525#ffffffCard icon container
--paynext-sdk-card-icon#565656#d1d5dbCard icon color

Override from Config

Pass cssVariables through the styles option when mounting:
config-override.ts
import { PayNextCheckout, type CSSVariablesConfig, type StylesConfig } from '@paynext/sdk'

const cssVariables: CSSVariablesConfig = {
  '--paynext-sdk-bg': '#0b1220',
  '--paynext-sdk-text': '#e2e8f0',
  '--paynext-sdk-button-bg': 'linear-gradient(135deg, #0ea5e9, #6366f1)',
  '--paynext-sdk-border-radius': '14px',
  '--paynext-sdk-input-focus-shadow': 'none' // Remove default focus ring
}

const styles: StylesConfig = { cssVariables }

const checkout = new PayNextCheckout()
await checkout.mount('checkout-container', {
  clientToken: 'your-token',
  environment: 'sandbox',
  apiVersion: '1.0.0',
  styles
})
Set --paynext-sdk-input-focus-shadow to none to disable the default teal focus ring and apply your own focus styles via component styling or external CSS.

Override from External CSS

Target the .checkout class from your stylesheet:
styles.css
/* Light theme overrides */
.checkout {
  --paynext-sdk-border: #e5e7eb;
  --paynext-sdk-border-focus: #6366f1;
  --paynext-sdk-input-focus-shadow: 0 0 0 3px rgba(99, 102, 241, 0.2);
}

/* Dark theme overrides */
.checkout.dark {
  --paynext-sdk-border: #374151;
  --paynext-sdk-border-focus: #818cf8;
}

Style Presets

Create reusable style presets for different design systems:
minimal-preset.ts
import type { CSSVariablesConfig, StylesConfig } from '@paynext/sdk'

const minimalPreset: StylesConfig = {
  cssVariables: {
    '--paynext-sdk-input-focus-shadow': 'none',
    '--paynext-sdk-border': '#000000',
    '--paynext-sdk-border-focus': '#000000',
    '--paynext-sdk-border-radius': '0px'
  },
  SubmitButton: {
    styles: {
      background: '#000000',
      borderRadius: '0px',
      textTransform: 'uppercase',
      letterSpacing: '1px'
    }
  }
}

TypeScript Reference

The SDK exports full type definitions for theme configuration:
types.ts
import { PayNextCheckout, type PayNextConfig } from '@paynext/sdk'
import type { CSSVariablesConfig, ThemeMode, StylesConfig } from '@paynext/sdk'

// Theme mode type
const theme: ThemeMode = 'system' // 'light' | 'dark' | 'system'

// Typed CSS variables
const cssVariables: CSSVariablesConfig = {
  '--paynext-sdk-bg': '#0b1220',
  '--paynext-sdk-text': '#e2e8f0',
  '--paynext-sdk-border': '#1e293b',
  '--paynext-sdk-border-focus': '#3b82f6',
  '--paynext-sdk-input-bg': '#1e293b',
  '--paynext-sdk-input-text': '#f1f5f9',
  '--paynext-sdk-input-focus-shadow': '0 0 0 2px rgba(59, 130, 246, 0.3)',
  '--paynext-sdk-placeholder': '#64748b',
  '--paynext-sdk-error': '#f87171',
  '--paynext-sdk-error-border': '#f87171',
  '--paynext-sdk-disabled-bg': '#374151',
  '--paynext-sdk-disabled-text': '#6b7280',
  '--paynext-sdk-button-bg': '#3b82f6',
  '--paynext-sdk-button-text': '#ffffff',
  '--paynext-sdk-button-hover-bg': '#2563eb',
  '--paynext-sdk-button-hover-opacity': '0.9',
  '--paynext-sdk-border-radius': '8px',
  '--paynext-sdk-card-bg': '#334155',
  '--paynext-sdk-card-icon': '#94a3b8'
}

// Combined styles config
const styles: StylesConfig = {
  cssVariables,
  // Component-level overrides still work alongside cssVariables
  SubmitButton: {
    styles: { fontWeight: '600' }
  }
}

const config: PayNextConfig = {
  clientToken: 'your-client-token',
  environment: 'sandbox',
  apiVersion: '1.0.0',
  theme,
  styles,
}

const checkout = new PayNextCheckout()
await checkout.mount('checkout-container', config)
All CSSVariablesConfig properties are optional. Only override the tokens you need to change.