FloPayFloPay
Examples

Custom Theme

Style FloPay payment elements with a single `theme` prop or fine-tune with `appearance` and `buttonsStyles` overrides.

FloPay ships six first-class theme bundles plus a 'classic' no-op marker. Pass a single theme value to FloPayCheckout, FloPayAutomaticPaymentButton, or SplitCardForm and the SDK styles both the Stripe-rendered fields and the React-rendered wrapper, submit button, and inputs from the same source.

Design your theme visually in the Theme Playground. Pick a bundle, tweak overrides, and copy the props straight into your code.

Bundled Themes

theme valueAesthetic
'modern-light' / 'modern-dark'Clean & airy — Inter, soft shadows, generous spacing, FloPay-blue accents
'bold-light' / 'bold-dark'Saturated FloPay blue with a gradient pill submit and heavy borders
'glass-light' / 'glass-dark'Translucent surfaces with backdrop blur over a blue gradient
'classic'No-op marker that preserves the historic FloPay look (#EDEDFF wrapper, #4A49FF indigo submit)

All bundles are built around FloPay blue (#1785E0 on light bundles, #60A5FA on dark bundles).

One Prop, Consistent Look

app/checkout/page.tsx
'use client';

import { FloPayCheckout } from '@flopay/react';

export default function ThemedCheckoutPage() {
  return (
    <FloPayCheckout
      sessionId="your-session-uuid"
      theme="bold-dark"
      onComplete={(result) => console.log('Paid!', result)}
    />
  );
}

The same theme value styles the Stripe Elements inside the iframe and the React-rendered wrapper, title, submit button, and name input. No second prop to keep in sync.

Switching Bundles Side-By-Side

app/checkout/ThemeGallery.tsx
'use client';

import { FloPayCheckout } from '@flopay/react';

export function ThemeGallery({ sessionId }: { sessionId: string }) {
  return (
    <div
      style={{
        display: 'grid',
        gap: '1.5rem',
        gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))',
      }}
    >
      <section>
        <h3>Modern Light</h3>
        <FloPayCheckout sessionId={sessionId} theme="modern-light" />
      </section>
      <section>
        <h3>Bold Dark</h3>
        <FloPayCheckout sessionId={sessionId} theme="bold-dark" />
      </section>
      <section>
        <h3>Glass Dark</h3>
        <FloPayCheckout sessionId={sessionId} theme="glass-dark" />
      </section>
    </div>
  );
}

Resolution Precedence

When multiple styling props are present, the SDK resolves them from highest priority to lowest:

  1. Explicit appearance — overrides the theme's appearance (palette + Stripe rules).
  2. Explicit buttonsStyles — merges per-field on top of the theme's button layout.
  3. theme bundle.
  4. Legacy buttonsTheme preset (back-compat for older integrations).
  5. Hardcoded defaults.

This means you can drop a theme onto the component and then surgically override just the fields you need:

Override the submit colour on top of a theme
<FloPayCheckout
  sessionId={sessionId}
  theme="modern-light"
  buttonsStyles={{
    submitButton: { backgroundColor: '#0F172A' },
  }}
/>
Override Stripe Element rules on top of a theme
<FloPayCheckout
  sessionId={sessionId}
  theme="glass-dark"
  appearance={{
    rules: {
      '.Input': { border: '1px solid rgba(255,255,255,0.3)' },
    },
  }}
/>

Picking A Bundle Programmatically

Import the bundle map from @flopay/shared if you need to reference the appearance or button-layout directly (for example, to render a preview swatch outside the SDK):

Reading a theme bundle
import { THEMES, resolveTheme } from '@flopay/shared';

const glassDark = THEMES['glass-dark'];
// { appearance: FloPayAppearance, buttonsLayout: ButtonsLayoutStyles }

const bundle = resolveTheme('bold-light');
if (bundle) {
  console.log(bundle.appearance.variables?.colorPrimary);
}

resolveTheme('classic') returns undefined'classic' is a marker, not a bundle, so the SDK falls through to its hardcoded defaults.

Migrating From buttonsTheme

Legacy values still resolve via the back-compat shim, but new code should use theme:

OldNew
buttonsTheme="default"theme="classic"
buttonsTheme="minimal"theme="modern-light"
buttonsTheme="rounded"theme="modern-light" (rounded corners) or theme="bold-light"
buttonsTheme="dark"theme="bold-dark"

buttonsTheme is silently ignored when theme is supplied alongside it, so a single-line swap is safe.

See Also

On this page