Appearance and Localization

Whitelisted styling tokens, brand fonts, the card-brand badge and translated labels for the card frames.

Before You Start

Read the following guides before proceeding:

GuideWhy
PCI Compliant SDKIsolation model and package map
SDK SetupRegistering a font CDN origin

Overview

The frames accept whitelisted, typed appearance tokens. They do not accept CSS. Arbitrary CSS inside a card
frame is a data-exfiltration channel — an attribute-selector rule with a url() value leaks a PAN one
character at a time — so every value is re-validated inside the frame against a strict grammar and applied
through CSSOM custom properties, never through generated <style> text.

An invalid value is dropped, the frame logs a console warning, and the default renders. A bad theme
degrades the look and never the isolation.

const appearance = {
  theme: 'dark',
  variables: { colorText: '#FFFFFF', borderRadius: '12px' },
  brandBadge: { style: 'logo', tone: 'color' },
};

createCardTopUpFields(sdk, { auth, appearance });

theme accepts light and dark; any other value renders the light scheme.

Appearance is read when an element mounts. Changing the object afterwards has no effect. To re-theme,
destroy the element and create a new one.


Variables

TokenTypeWhat it styles
colorTextcolorInput and value text
colorLabelcolorField labels
colorPlaceholdercolorPlaceholder text
colorErrorcolorValidation messages and the invalid-field border
colorFocuscolorFocused-field border and accent
colorBackgroundcolorField background
colorBordercolorField border
surfaceColorcolorThe frame document's own background. Defaults to transparent, so your panel shows through
fontFamilyfont stackComma-separated family names
fontUrlfont file URLOne brand font file — see Brand Fonts
fontFacesarrayMulti-weight brand font: [{ url, weight?, style? }]. Takes precedence over fontUrl
fontSizeBaselengthValue font size
fontSizeLabellengthLabel font size
lineHeightBaselengthValue line height
lineHeightLabellengthLabel line height
fontWeightBaseweightValue font weight
fontWeightLabelweightLabel font weight
borderRadiuslengthField corner radius
borderWidthlengthField border width
spacingUnitlengthVertical gap between rows
controlMinHeightlengthMinimum field height

Reveal frames accept four more tokens:

TokenTypeWhat it stylesDefault
copyIconSizelengthSquare size of the copy-button glyph20px
colorCopyIconcolorCopy-button glyphcolorLabel
colorCopyIconHovercolorCopy-button glyph on hovercolorText
colorCopyIconCopiedcolorThe transient "copied" checkmarkcolorFocus

Unknown tokens are dropped without a warning to your page.


Value Grammars

Each type is validated against the pattern below. var(), url(), calc(), quotes, semicolons and braces
fail every one of them by construction.

TypeValidation (regex)Max lengthAccepted forms
color^(#[0-9a-fA-F]{3,8}|rgb\(…\)|rgba\(…\)|hsl\(…\)|hsla\(…\)|[a-zA-Z]{3,20})$40 chars#1A1A1A, rgb(26, 26, 26), rgba(26, 26, 26, 0.5), hsl(0, 0%, 10%), hsla(0, 0%, 10%, 0.5), CSS named colors
length^\d+(\.\d+)?(px|rem|em)$12 chars12px, 1.5rem, 0.75em. Unitless and percentage values are rejected
weight^(normal|bold|[1-9]00)$100900, normal, bold
font stackEach comma-separated name matches ^\s*(?:'[A-Za-z0-9 _-]+'|"[A-Za-z0-9 _-]+"|[A-Za-z0-9 _-]+)\s*$300 charsYourBrand, Inter, sans-serif
font file URL^https:\/\/[^\s"'()\;{}]+\.(woff2|woff|otf|ttf)(\?[^\s"'()\;{}]*)?$500 charshttps://cdn.example.com/fonts/brand-400.woff2

Brand Fonts

A brand font loads from a font file URL. A stylesheet URL is rejected — host-supplied CSS is the channel
the token model exists to close.

variables: {
  fontFamily: 'YourBrand, Inter, sans-serif',
  fontFaces: [
    { url: 'https://cdn.example.com/fonts/brand-400.woff2', weight: '400' },
    { url: 'https://cdn.example.com/fonts/brand-600.woff2', weight: '600' },
  ],
}
FieldTypeRequiredDescription
urlstringYeshttps:// URL of a .woff2, .woff, .otf or .ttf file
weightstringNo100900, normal or bold. Default 400
stylestringNonormal or italic. Default normal

The frame builds the @font-face rules itself and names every face after the first family in fontFamily.
A custom font therefore requires a valid fontFamily; without one, fontUrl and fontFaces are dropped
with a console warning.

Two host-side requirements:

  • The CDN origin must be registered against your client id. It enters the frames' font-src policy.
    Include it in onboarding or request it later.
  • The font host must allow cross-origin loading. Browsers fetch fonts in CORS mode, so the file must
    respond with an Access-Control-Allow-Origin header covering the frame origin. * is acceptable for
    public font files.

Without the CORS header the browser blocks the font and reports net::ERR_FAILED on a 200 response.
The frame falls back to the next family in fontFamily and renders normally, so the failure is visible
only in the console.


Brand Badge

The card-number field shows the detected card brand. The artwork is bundled inside the frame; you select
among fixed presentations and cannot inject markup.

OptionValuesDefaultMeaning
showbooleantrueRender the indicator
stylelogo, textlogoBrand mark or plain brand name
tonecolor, monocolorOriginal brand colors, or a single-color mark drawn in colorLabel. Applies to logo only
backgroundcolortransparentPlate behind the mark
borderRadiuslength or %50%Plate corners — 50% is a circle, 4px a rounded square
sizelength or %24pxPlate size, width equal to height
offsetXsigned length0pxHorizontal nudge; positive moves right
offsetYsigned length0pxVertical nudge; positive moves down

The default position is vertically centered, 16 pixels from the field's right edge. borderRadius and
size accept % in addition to the length units; offsetX and offsetY accept a leading - and no %.

appearance: {
  brandBadge: {
    style: 'logo',
    tone: 'color',
    background: '#FFFFFF',
    borderRadius: '50%',
    size: '24px',
  },
}

Localized Labels

Field labels and validation messages come from your application, already translated. The frames ship
English defaults and render whatever you pass.

createCardTopUpFields(sdk, {
  auth,
  strings: {
    cardNumberLabel: 'Numéro de carte',
    expiryLabel: 'MM/AA',
    cvvLabel: 'CVV',
    nameLabel: 'Titulaire',
    errCardLuhn: 'Numéro de carte invalide',
  },
});

Keys are per element type:

ElementKey table
Top-up collectStrings Keys
Payout collectStrings Keys
RevealStrings Keys

An omitted key renders its English default. Unknown keys are ignored.


Did this page help you?