Skip to main content

Theming Expo native components

Warning

Expo native components are currently in beta. If you run into any issues, please reach out to the support team.

You can customize the appearance of Clerk's Expo native componentsExpo Icon by passing a theme option to the @clerk/expo config plugin. The plugin reads a JSON file at prebuild time and applies it to both iOS and Android.

Configure the plugin

Create a clerk-theme.json file in your project and reference it from the plugin in your app.json:

app.json
{
  "expo": {
    "plugins": [
      [
        "@clerk/expo",
        {
          "theme": "./clerk-theme.json"
        }
      ]
    ]
  }
}

Apply the theme

Run npx expo prebuild --clean (or rerun npx expo run:ios / npx expo run:android) so the plugin picks up the theme. The JSON is validated during prebuild — invalid hex colors or value types will fail the build with a descriptive error.

Theme schema

Every key is optional. Provide only what you want to override; everything else falls back to the default Clerk theme.

clerk-theme.json
{
  "colors": {
    "primary": "#6C47FF",
    "background": "#FFFFFF",
    "input": "#F5F5F5",
    "danger": "#EF4444",
    "success": "#10B981",
    "warning": "#F59E0B",
    "foreground": "#0F172A",
    "mutedForeground": "#64748B",
    "primaryForeground": "#FFFFFF",
    "inputForeground": "#0F172A",
    "neutral": "#94A3B8",
    "border": "#E2E8F0",
    "ring": "#6C47FF",
    "muted": "#F1F5F9",
    "shadow": "#00000020"
  },
  "darkColors": {
    "primary": "#8B6FFF",
    "background": "#0B0B0F",
    "foreground": "#FFFFFF",
    "border": "#1F2937"
  },
  "design": {
    "borderRadius": 12,
    "fontFamily": "Inter"
  }
}

colors

Light mode color tokens. Each value must be a 6- or 8-digit hex string (8-digit includes an alpha channel, e.g. #00000080). Unknown keys are ignored with a warning.

KeyDescription
primaryPrimary action color (buttons, links, focus).
backgroundSurface background.
inputInput field background.
dangerDestructive / error states.
successSuccess states.
warningWarning states.
foregroundPrimary text color on background.
mutedForegroundSecondary / helper text.
primaryForegroundText color used on top of primary (e.g. button labels).
inputForegroundText color inside inputs.
neutralNeutral accent color.
borderBorders and dividers.
ringFocus ring.
mutedMuted surface (badges, subtle backgrounds).
shadowShadow color.

darkColors

Same shape as colors, applied automatically when the device is in dark mode. Any tokens you omit fall back to the default dark theme.

When darkColors is provided, native components automatically use the dark palette when the device is in dark mode. To enable system dark mode in your app, set "userInterfaceStyle": "automatic" in your app.json. If you pin your app to "light" or "dark", the native components will always use the corresponding palette.

design

KeyTypePlatformDescription
borderRadiusnumberiOS + AndroidCorner radius applied across components, in points/dp.
fontFamilystringiOS onlyCustom font family name. The font must be bundled with your iOS app and registered in Info.plist (UIAppFonts).

Note

Custom font families are currently iOS-only. Android uses the system font.

The plugin does not modify your app's userInterfaceStyle setting. To control whether your app follows the system appearance or is pinned to light/dark mode, set "userInterfaceStyle" in your app.json.

Theme changes only affect the native views (<AuthView />, <UserProfileView />, and <UserButton />). They do not affect web components or other React Native UI elements in your app.

Troubleshooting

My theme changes aren't showing up

Run npx expo prebuild --clean to regenerate the native projects. The theme is only read at prebuild time.

Clerk theme: invalid hex color for colors.primary

All color values must be hex strings with a leading # and 6 or 8 hex digits.

Clerk theme file not found

The theme path is resolved relative to your project root. Double-check the path in app.json.

Dark mode isn't switching on iOS

Make sure you're providing darkColors and that "userInterfaceStyle" is set to "automatic" in your app.json.

I removed the theme prop but the old theme is still applied

Run npx expo prebuild --clean after removing the theme option. Incremental prebuilds can keep previously generated native files.

Feedback

What did you think of this content?

Last updated on