# Customization

The `appearance` option restyles the Footprint flow to match your product's design. Every SDK accepts it: JavaScript, Expo, React Native, Flutter, Swift, and Kotlin. A complete example lives in [onefootprint/examples](https://github.com/onefootprint/examples/tree/master/idv/frontend-vite-vanilla).

## Variables

Variables are the first place to theme the flow. Each one maps to a CSS variable, so you can inspect the result with your browser's DOM explorer. Set a value in any unit you prefer: pixels, rem, hex, rgb, and so on. The tables below list every variable.

This call squares the corners and recolors the primary button:

```typescript
import "@onefootprint/footprint-js/dist/footprint-js.css";
import { onboarding } from "@onefootprint/footprint-js";

onboarding.initialize({
  onboardingSessionToken: "obtok_UxM6Vbvk2Rcy1gzcSuXgk3sj3L9I0pAnNH",
  onComplete: (validationToken) => {
    console.log(validationToken);
  },
  appearance: {
    variables: {
      borderRadius: "0px",
      buttonPrimaryBg: "#315E4C",
      buttonPrimaryHoverBg: "#46866c",
      buttonPrimaryColor: "#FFF",
    },
  },
});
```

### Status colours

| Variable       | Description                 |
| -------------- | --------------------------- |
| `colorError`   | Sets the error text color   |
| `colorSuccess` | Sets the success text color |
| `colorWarning` | Sets the warning text color |

## Global variables

A higher-level token sets the default for a group of lower-level tokens. The table lists each higher-level token and the tokens it sets by default.

| Higher-level token | Lower-level tokens influenced                                                                                                                                                                             |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `borderRadius`     | `buttonBorderRadius`, `containerBorderRadius`, `inputBorderRadius`, `dropdownBorderRadius`, `radioSelectBorderRadius`, `checkboxBorderRadius`                                                             |
| `colorError`       | `borderColorError`, `hintErrorColor`, `linkButtonDestructiveColor`                                                                                                                                        |
| `colorAccent`      | `linkColor`, `linkButtonColor`, `linkButtonHoverColor`, `linkButtonActiveColor`, `radioSelectSelectedColor`, `radioSelectSelectedBorderColor`, `radioSelectComponentsIconSelectedBg`, `checkboxCheckedBg` |
| `borderColorError` | `inputErrorBorderColor`                                                                                                                                                                                   |

Set a higher-level token to propagate one choice across its group. Set a lower-level token individually to override that default for a single component.

### Container

Wraps the entire Footprint component.

| Variable                | Description                              |
| ----------------------- | ---------------------------------------- |
| `containerBg`           | Sets the container body background color |
| `containerElevation`    | Determines the container's shadow        |
| `containerBorder`       | Defines the container's border           |
| `containerBorderRadius` | Defines the container's border radius    |
| `containerMaxWidth`     | Defines the container's max width        |

For inline integrations, `containerMaxWidth` (for example `containerMaxWidth: '480px'`) constrains and centers the content while the outer container fills the available space. The modal variant has a predetermined width.

### Link

Links behave like standard anchor tags; the `Terms of Service` link is a common example. To style more properties or states, use [rules](#rules).

Links take their color from `colorAccent`, which also drives link buttons and radio selection.

| Variable      | Description                             |
| ------------- | --------------------------------------- |
| `colorAccent` | Defines the link color and link buttons |

### Label

The label is the native HTML element paired with an input field.

| Variable     | Description               |
| ------------ | ------------------------- |
| `labelColor` | Sets the label color      |
| `labelFont`  | Determines the label font |

### Input

Input covers every input field in the flow, including the PIN, phone, and address inputs.

| Variable                     | Description                                                                |
| ---------------------------- | -------------------------------------------------------------------------- |
| `inputBorderRadius`          | Determines the input border radius                                         |
| `inputBorderWidth`           | Sets the input border width                                                |
| `inputFont`                  | Sets the input font                                                        |
| `inputHeight`                | Sets the input height                                                      |
| `inputPlaceholderColor`      | Defines the input placeholder color                                        |
| `inputColor`                 | Sets the input color                                                       |
| `inputBg`                    | Defines the input background color                                         |
| `inputBorderColor`           | Sets the input border color                                                |
| `inputHoverBg`               | Determines the input background color when hovered                         |
| `inputHoverBorderColor`      | Sets the input border color when hovered                                   |
| `inputFocusBg`               | Determines the input background color when focused                         |
| `inputFocusBorderColor`      | Sets the input border color when focused                                   |
| `inputFocusElevation`        | Sets the input box shadow when focused                                     |
| `inputErrorBg`               | Determines the input background color when an error is present             |
| `inputErrorBorderColor`      | Sets the input border color when an error is present                       |
| `inputErrorHoverBg`          | Determines the input background color when an error is present and hovered |
| `inputErrorHoverBorderColor` | Sets the input border color when an error is present and hovered           |
| `inputErrorFocusBg`          | Determines the input background color when an error is present and focused |
| `inputErrorFocusBorderColor` | Sets the input border color when an error is present and focused           |
| `inputErrorFocusElevation`   | Sets the input box shadow when an error is present and focused             |
| `inputElevation`             | Determines the input box shadow                                            |
| `inputHoverElevation`        | Sets the input box shadow when hovered                                     |
| `inputErrorElevation`        | Sets the input box shadow when an error is present                         |
| `inputErrorHoverElevation`   | Sets the input box shadow when an error is present and hovered             |

### Hint

Hints are the text below an input field. They show an error or extra information.

| Variable         | Description                                                      |
| ---------------- | ---------------------------------------------------------------- |
| `hintColor`      | Sets the hint color                                              |
| `hintErrorColor` | Determines the hint color when the input field is in error state |
| `hintFont`       | Defines the hint font                                            |

### LinkButton

A link button is the standard button without a background.

| Variable                           | Description                                                                    |
| ---------------------------------- | ------------------------------------------------------------------------------ |
| `linkButtonColor`                  | Sets the button color                                                          |
| `linkButtonHoverColor`             | Defines the button color when hovered                                          |
| `linkButtonActiveColor`            | Sets the button color when pressed                                             |
| `linkButtonDestructiveColor`       | Determines the button color when it signifies a destructive action             |
| `linkButtonDestructiveHoverColor`  | Sets the button color when it signifies a destructive action and is hovered    |
| `linkButtonDestructiveActiveColor` | Determines the button color when it signifies a destructive action and pressed |

### Button

Variables for the primary and secondary buttons.

| Variable                             | Description                                                   |
| ------------------------------------ | ------------------------------------------------------------- |
| `buttonBorderRadius`                 | Defines the button border radius                              |
| `buttonBorderWidth`                  | Sets the button border width                                  |
| `buttonPrimaryBg`                    | Sets the primary button's background color                    |
| `buttonPrimaryColor`                 | Defines the primary button's color                            |
| `buttonPrimaryBorderColor`           | Determines the primary button's border color                  |
| `buttonPrimaryHoverBg`               | Sets the primary button's background color when hovered       |
| `buttonPrimaryHoverColor`            | Defines the primary button's color when hovered               |
| `buttonPrimaryHoverBorderColor`      | Determines the primary button's border color when hovered     |
| `buttonPrimaryActiveBg`              | Sets the primary button's background color when activated     |
| `buttonPrimaryActiveColor`           | Defines the primary button's color when activated             |
| `buttonPrimaryActiveBorderColor`     | Determines the primary button's border color when activated   |
| `buttonPrimaryDisabledBg`            | Sets the primary button's background color when disabled      |
| `buttonPrimaryDisabledColor`         | Defines the primary button's color when disabled              |
| `buttonPrimaryDisabledBorderColor`   | Determines the primary button's border color when disabled    |
| `buttonPrimaryLoadingBg`             | Sets the primary button's background color when loading       |
| `buttonPrimaryLoadingColor`          | Defines the primary button's color when loading               |
| `buttonsPrimaryLoadingBorderColor`   | Sets the primary button's border color when loading           |
| `buttonSecondaryBg`                  | Sets the secondary button's background color                  |
| `buttonSecondaryColor`               | Defines the secondary button's color                          |
| `buttonSecondaryBorderColor`         | Determines the secondary button's border color                |
| `buttonSecondaryHoverBg`             | Sets the secondary button's background color when hovered     |
| `buttonSecondaryHoverColor`          | Defines the secondary button's color when hovered             |
| `buttonSecondaryHoverBorderColor`    | Determines the secondary button's border color when hovered   |
| `buttonSecondaryActiveBg`            | Sets the secondary button's background color when activated   |
| `buttonSecondaryActiveColor`         | Defines the secondary button's color when activated           |
| `buttonSecondaryActiveBorderColor`   | Determines the secondary button's border color when activated |
| `buttonSecondaryDisabledBg`          | Sets the secondary button's background color when disabled    |
| `buttonSecondaryDisabledColor`       | Defines the secondary button's color when disabled            |
| `buttonSecondaryDisabledBorderColor` | Determines the secondary button's border color when disabled  |
| `buttonSecondaryLoadingBg`           | Sets the secondary button's background color when loading     |
| `buttonSecondaryLoadingColor`        | Defines the secondary button's color when loading             |

### Dropdown

Dropdowns pair with input fields: the phone input uses one for the list of countries, and the address input uses one for the list of results.

| Variable                 | Description                                |
| ------------------------ | ------------------------------------------ |
| `dropdownBg`             | The dropdown background color              |
| `dropdownHoverBg`        | The dropdown background color when hovered |
| `dropdownBorderColor`    | The dropdown border color when activated   |
| `dropdownBorderWidth`    | The dropdown border width                  |
| `dropdownBorderRadius`   | The dropdown border radius                 |
| `dropdownElevation`      | The dropdown box shadow                    |
| `dropdownColorPrimary`   | The dropdown primary color                 |
| `dropdownColorSecondary` | The dropdown secondary color               |
| `dropdownFooterBg`       | The dropdown footer background             |

### Radio select

Radio select appears in two places. When an onboarding starts with a sandbox key, it selects the outcome; that choice is only visible in sandbox and hidden from users. During identity document verification, it lets the user pick which type of identity document to verify with.

| Variable                                      | Description                                            |
| --------------------------------------------- | ------------------------------------------------------ |
| `radioSelectBg`                               | The background of the radio select component           |
| `radioSelectColor`                            | The text color when not selected                       |
| `radioSelectHoverColor`                       | The hover text color when not selected                 |
| `radioSelectSelectedColor`                    | The text color when selected                           |
| `radioSelectSelectedHoverColor`               | The hover text color when selected                     |
| `radioSelectBorderRadius`                     | The border radius of the radio select component        |
| `radioSelectBorderWidth`                      | The border width of the radio select component         |
| `radioSelectBorderColor`                      | The border color of the radio select component         |
| `radioSelectHoverBg`                          | The hover background of the radio select component     |
| `radioSelectHoverBorderColor`                 | The hover border color of the radio select component   |
| `radioSelectSelectedBg`                       | The background of the selected radio item              |
| `radioSelectSelectedBorderColor`              | The border color of the selected radio item            |
| `radioSelectComponentsIconBg`                 | The background of the icon in the radio item           |
| `radioSelectComponentsIconHoverBg`            | The hover background of the icon in the radio item     |
| `radioSelectComponentsIconSelectedBg`         | The background of the selected icon in the radio item  |
| `radioSelectComponentsIconColor`              | The color of the icon in the radio item                |
| `radioSelectComponentsIconHoverColor`         | The hover color of the icon in the radio item          |
| `radioSelectComponentsIconSelectedColor`      | The color of the selected icon in the radio item       |
| `radioSelectComponentsIconSelectedHoverColor` | The hover color of the selected icon in the radio item |

### Checkbox

Checkboxes appear wherever the flow asks for consent or a multi-choice selection.

| Variable                        | Description                                             |
| ------------------------------- | ------------------------------------------------------- |
| `checkboxBg`                    | Defines the checkbox background color                   |
| `checkboxBorderColor`           | Sets the checkbox border color                          |
| `checkboxBorderRadius`          | Determines the checkbox border radius                   |
| `checkboxBorderWidth`           | Sets the checkbox border width                          |
| `checkboxCheckedBg`             | Defines the checkbox background color when checked      |
| `checkboxCheckedBorderColor`    | Sets the checkbox border color when checked             |
| `checkboxCheckedCheckmarkColor` | Sets the checkmark color when checked                   |
| `checkboxHoverBg`               | Defines the checkbox background color when hovered      |
| `checkboxHoverBorderColor`      | Sets the checkbox border color when hovered             |
| `checkboxDisabledBg`            | Defines the checkbox background color when disabled     |
| `checkboxDisabledBorderColor`   | Sets the checkbox border color when disabled            |
| `checkboxErrorBorderColor`      | Sets the checkbox border color when an error is present |

## Custom fonts

Footprint loads custom fonts from [Google Fonts](https://fonts.google.com/). Pass a `fontSrc` URL in the `appearance` option, and the SDK loads the font and applies it across the component.

We strongly recommend also setting `fontFamily` in `variables` so the font applies consistently. The SDK tries to extract the font family from the Google Fonts URL, but setting `fontFamily` yourself gives you control over the value and the fallback chain.

This call loads Poppins and applies it to the flow:

```typescript
import "@onefootprint/footprint-js/dist/footprint-js.css";
import { onboarding } from "@onefootprint/footprint-js";

onboarding.initialize({
  onboardingSessionToken: "obtok_...",
  onComplete: (validationToken) => {
    console.log(validationToken);
  },
  appearance: {
    fontSrc:
      "https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap",
    variables: {
      fontFamily: "'Poppins', sans-serif",
    },
  },
});
```

We recommend a Google Fonts URL for `fontSrc`. Other font sources may produce unexpected results.

| Property     | Location                          | Description                                          |
| ------------ | --------------------------------- | ---------------------------------------------------- |
| `fontSrc`    | `appearance.fontSrc`              | A Google Fonts URL that loads the font stylesheet    |
| `fontFamily` | `appearance.variables.fontFamily` | The CSS `font-family` value applied to the component |

## Rules

Use `rules` for styles the variables do not cover. A rule applies arbitrary CSS to one of the elements listed below.

This call animates buttons on hover, adds a focus ring to inputs, and underlines hovered links:

```typescript
import '@onefootprint/footprint-js/dist/footprint-js.css';
import { onboarding } from '@onefootprint/footprint-js';

onboarding.initialize({
  onboardingSessionToken: 'obtok_UxM6Vbvk2Rcy1gzcSuXgk3sj3L9I0pAnNH',
  onComplete: (validationToken) => {
    console.log(validationToken);
  },
  appearance: {
    rules: {
      button: {
        transition: 'all .2s linear',
      },
      'button:hover': {
        transform: 'translateY(-1px)',
      },
      'input:focus': {
        boxShadow: '0 0 0 4px rgba(74, 36, 219, 0.12)',
      },
      'link:hover': {
        textDecoration: 'underline',
      },
    }
  },
});
```

### Available rules

| Selector             | Description              |
| -------------------- | ------------------------ |
| `button`             | The button               |
| `button:hover`       | The button, hovered      |
| `button:focus`       | The button, focused      |
| `button:active`      | The button, active       |
| `input`              | The input                |
| `input:hover`        | The input, hovered       |
| `input:focus`        | The input, focused       |
| `input:active`       | The input, active        |
| `pinInput`           | The OTP pin input        |
| `pinInput:hover`     | The pin input, hovered   |
| `pinInput:focus`     | The pin input, focused   |
| `pinInput:active`    | The pin input, active    |
| `checkbox`           | The checkbox             |
| `checkbox:hover`     | The checkbox, hovered    |
| `checkbox:checked`   | The checkbox, checked    |
| `checkbox:disabled`  | The checkbox, disabled   |
| `label`              | The input label          |
| `hint`               | The hint below an input  |
| `link`               | The link                 |
| `link:hover`         | The link, hovered        |
| `link:focus`         | The link, focused        |
| `linkButton`         | The link button          |
| `linkButton:hover`   | The link button, hovered |
| `linkButton:focus`   | The link button, focused |
| `linkButton:active`  | The link button, active  |
| `pageHeader`         | The page header          |
| `pageHeaderTitle`    | The page header title    |
| `pageHeaderSubtitle` | The page header subtitle |

## Localization configuration

### Setting the language and locale

The `l10n` (localization) option sets the language and locale of the flow.

For Spanish-speaking users, set `language` to `"es"` and the flow renders in Spanish:

```typescript
import "@onefootprint/footprint-js/dist/footprint-js.css";
import { onboarding } from "@onefootprint/footprint-js";

const l10n = {
  language: "es",
};

onboarding.initialize({
  onboardingSessionToken: "obtok_UxM6Vbvk2Rcy1gzcSuXgk3sj3L9I0pAnNH",
  onComplete: (validationToken) => {
    console.log(validationToken);
  },
  l10n,
});
```

For users in Mexico, also set `locale` to `"es-MX"` (Spanish, Mexico). The locale drives how Footprint formats dates and numbers and which cultural conventions it follows:

```typescript
import "@onefootprint/footprint-js/dist/footprint-js.css";
import { onboarding } from "@onefootprint/footprint-js";

const l10n = {
  language: "es",
  locale: "es-MX",
};

onboarding.initialize({
  onboardingSessionToken: "obtok_UxM6Vbvk2Rcy1gzcSuXgk3sj3L9I0pAnNH",
  onComplete: (validationToken) => {
    console.log(validationToken);
  },
  l10n,
});
```

### Available l10n properties

| Property   | Type             | Description                                 |
| ---------- | ---------------- | ------------------------------------------- |
| `locale`   | `en-US`, `es-MX` | Optional. Locale for date/number formatting |
| `language` | `en`, `es`       | Language code for UI text localization      |