# Theming **Category**: native **URL**: https://www.heroui.com/docs/native/getting-started/theming **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/getting-started/(handbook)/theming.mdx > Customize HeroUI Native's design system with CSS variables and global styles *** HeroUI Native uses CSS variables for theming. Customize everything from colors to component styles using standard CSS. ## How It Works HeroUI Native's theming system is built on top of [Tailwind CSS v4](https://tailwindcss.com/docs/theme)'s theme via [Uniwind](https://uniwind.dev/). When you import `heroui-native/styles`, it uses Tailwind's built-in color palettes, maps them to semantic variables, automatically switches between light and dark themes, and uses CSS layers and the `@theme` directive for organization. **Naming pattern:** - Colors without a suffix are backgrounds (e.g., `--accent`) - Colors with `-foreground` are for text on that background (e.g., `--accent-foreground`) ## Quick Start **Apply colors in your components:** ```tsx import { View, Text } from 'react-native'; Your app content ; ``` **Switch themes:** HeroUI Native automatically supports dark mode through [Uniwind](https://docs.uniwind.dev/theming/basics). The theme switches between light and dark variants based on system preferences or manual selection: ```tsx import { Uniwind, useUniwind } from 'uniwind'; import { Button } from 'heroui-native'; function ThemeToggle() { const { theme } = useUniwind(); return ( ); } ``` **Override colors:** ```css /* global.css */ @layer theme { @variant light { /* Override any color variable */ --accent: oklch(0.65 0.25 270); /* Custom indigo accent */ --success: oklch(0.65 0.15 155); } @variant dark { --accent: oklch(0.65 0.25 270); --success: oklch(0.75 0.12 155); } } ``` > **Note**: See [Colors](/docs/native/getting-started/colors) for the complete color palette and visual reference. **Create your own theme:** Create multiple themes using Uniwind's variant system. For complete custom theme documentation, see the [Uniwind Custom Themes Guide](https://docs.uniwind.dev/theming/custom-themes). **Important:** All themes must define the same variables. See the [Default Theme](/docs/native/getting-started/colors#default-theme) section for a complete list of all required variables. ```css /* global.css */ @layer theme { :root { @variant ocean-light { /* Base Colors */ --background: oklch(0.95 0.02 230); --foreground: oklch(0.25 0.04 230); /* Surface: Used for non-overlay components (cards, accordions, disclosure groups) */ --surface: oklch(0.98 0.01 230); --surface-foreground: oklch(0.3 0.045 230); --surface-secondary: oklch(0.96 0.012 230); --surface-secondary-foreground: oklch(0.3 0.045 230); --surface-tertiary: oklch(0.94 0.015 230); --surface-tertiary-foreground: oklch(0.3 0.045 230); /* Overlay: Used for floating/overlay components (dialogs, popovers, modals, menus) */ --overlay: oklch(0.998 0.003 230); --overlay-foreground: oklch(0.3 0.045 230); --backdrop: oklch(0% 0 0 / 20%); --muted: oklch(0.55 0.035 230); --default: oklch(0.94 0.018 230); --default-foreground: oklch(0.4 0.05 230); /* Accent */ --accent: oklch(0.6 0.2 230); --accent-foreground: oklch(0.98 0.005 230); /* Form Field Defaults - Colors */ --field-background: oklch(0.98 0.01 230); --field-foreground: oklch(0.25 0.04 230); --field-placeholder: var(--muted); --field-border: transparent; /* Status Colors */ --success: oklch(0.72 0.14 165); --success-foreground: oklch(0.25 0.08 165); --warning: oklch(0.78 0.12 85); --warning-foreground: oklch(0.3 0.08 85); --danger: oklch(0.68 0.18 15); --danger-foreground: oklch(0.98 0.005 15); /* Component Colors */ --segment: oklch(0.98 0.01 230); --segment-foreground: oklch(0.25 0.04 230); /* Misc Colors */ --border: oklch(0 0 0 / 0%); --separator: oklch(0.91 0.015 230); --focus: var(--accent); --link: oklch(0.62 0.17 230); /* Shadows */ --surface-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.04), 0 1px 2px 0 rgba(0, 0, 0, 0.06), 0 0 1px 0 rgba(0, 0, 0, 0.06); --overlay-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.02), 0 -6px 12px 0 rgba(0, 0, 0, 0.01), 0 14px 28px 0 rgba(0, 0, 0, 0.03); --field-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.04), 0 1px 2px 0 rgba(0, 0, 0, 0.06), 0 0 1px 0 rgba(0, 0, 0, 0.06); } @variant ocean-dark { /* Base Colors */ --background: oklch(0.15 0.04 230); --foreground: oklch(0.94 0.01 230); /* Surface: Used for non-overlay components (cards, accordions, disclosure groups) */ --surface: oklch(0.2 0.048 230); --surface-foreground: oklch(0.9 0.015 230); --surface-secondary: oklch(0.24 0.046 230); --surface-secondary-foreground: oklch(0.9 0.015 230); --surface-tertiary: oklch(0.27 0.044 230); --surface-tertiary-foreground: oklch(0.9 0.015 230); /* Overlay: Used for floating/overlay components (dialogs, popovers, modals, menus) */ --overlay: oklch(0.23 0.045 230); --overlay-foreground: oklch(0.9 0.015 230); --backdrop: oklch(0% 0 0 / 20%); --muted: oklch(0.5 0.04 230); --default: oklch(0.25 0.05 230); --default-foreground: oklch(0.88 0.018 230); /* Accent */ --accent: oklch(0.72 0.21 230); --accent-foreground: oklch(0.15 0.04 230); /* Form Field Defaults - Colors */ --field-background: var(--default); --field-foreground: var(--foreground); --field-placeholder: var(--muted); --field-border: transparent; /* Status Colors */ --success: oklch(0.68 0.16 165); --success-foreground: oklch(0.95 0.008 165); --warning: oklch(0.75 0.14 90); --warning-foreground: oklch(0.2 0.04 90); --danger: oklch(0.65 0.2 20); --danger-foreground: oklch(0.95 0.008 20); /* Component Colors */ --segment: oklch(0.22 0.046 230); --segment-foreground: oklch(0.9 0.015 230); /* Misc Colors */ --border: oklch(0 0 0 / 0%); --separator: oklch(0.28 0.045 230); --focus: var(--accent); --link: oklch(0.75 0.18 230); /* Shadows */ --surface-shadow: 0 0 0 0 transparent inset; /* No shadow on dark mode */ --overlay-shadow: 0 0 1px 0 rgba(255, 255, 255, 0.3) inset; --field-shadow: 0 0 0 0 transparent inset; /* Transparent shadow to allow ring utilities to work */ } } } ``` **Important:** When adding custom themes, you must register them in your Metro config: ```js // metro.config.js const { withUniwindConfig } = require('uniwind/metro'); const { wrapWithReanimatedMetroConfig, } = require('react-native-reanimated/metro-config'); const config = { // ... your existing config }; module.exports = withUniwindConfig(wrapWithReanimatedMetroConfig(config), { cssEntryFile: './global.css', dtsFile: './src/uniwind.d.ts', extraThemes: ['ocean-light', 'ocean-dark'], }); ``` Apply themes in your app: ```tsx import { Uniwind } from 'uniwind'; import { Button } from 'heroui-native'; function App() { return ( ); } ``` ## Adding Custom Colors Add your own semantic colors to the theme: ```css @layer theme { @variant light { --info: oklch(0.6 0.15 210); --info-foreground: oklch(0.98 0 0); } @variant dark { --info: oklch(0.7 0.12 210); --info-foreground: oklch(0.15 0 0); } } /* Make the color available to Tailwind */ @theme inline { --color-info: var(--info); --color-info-foreground: var(--info-foreground); } ``` Now use it in your components: ```tsx import { View, Text } from 'react-native'; Info message ; ``` ## Custom Fonts To use a custom font family in your app, you need to load the fonts and then override the font CSS variables. ### 1. Load Fonts in Your App First, load your custom fonts (using Expo's `useFonts` hook for example): ```tsx import { useFonts } from 'expo-font'; import { HeroUINativeProvider } from 'heroui-native'; import { YourFont_400Regular, YourFont_500Medium, YourFont_600SemiBold, } from '@expo-google-fonts/your-font'; export default function App() { const [fontsLoaded] = useFonts({ YourFont_400Regular, YourFont_500Medium, YourFont_600SemiBold, }); if (!fontsLoaded) { return null; // Or return a loading screen } return {/* Your app content */}; } ``` ### 2. Configure Font CSS Variables After loading the fonts, override the font CSS variables in your `global.css` file: ```css @theme { --font-normal: 'YourFont-400Regular'; --font-medium: 'YourFont-500Medium'; --font-semibold: 'YourFont-600SemiBold'; } ``` **Note:** The font names in CSS variables should match the PostScript names of your loaded fonts. Check your font package documentation or use the font names exactly as they appear in your `useFonts` hook. All HeroUI Native components automatically use these font variables, ensuring consistent typography throughout your app. ## Variables Reference HeroUI defines three types of variables: 1. **Base Variables** — Non-changing values like `--white`, `--black` 2. **Theme Variables** — Colors that change between light/dark themes 3. **Calculated Variables** — Automatically generated hover (pressed) states and size variants For a complete reference, see: [Colors Documentation](/docs/native/getting-started/colors), [Default Theme Variables](https://github.com/heroui-inc/heroui-native/blob/main/src/styles/variables.css), [Shared Theme Utilities](https://github.com/heroui-inc/heroui-native/blob/main/src/styles/theme.css) **Calculated variables (Tailwind):** We use Tailwind's `@theme` directive to automatically create calculated variables for hover (pressed) states and radius variants. These are defined in [theme.css](https://github.com/heroui-inc/heroui-native/blob/main/src/styles/theme.css): ```css @theme inline static { --color-background: var(--background); --color-foreground: var(--foreground); --color-surface: var(--surface); --color-surface-foreground: var(--surface-foreground); --color-surface-hover: color-mix(in oklab, var(--surface) 92%, var(--surface-foreground) 8%); --color-surface-secondary: var(--surface-secondary); --color-surface-secondary-foreground: var(--surface-secondary-foreground); --color-surface-tertiary: var(--surface-tertiary); --color-surface-tertiary-foreground: var(--surface-tertiary-foreground); --color-overlay: var(--overlay); --color-overlay-foreground: var(--overlay-foreground); --color-backdrop: var(--backdrop); --color-muted: var(--muted); --color-accent: var(--accent); --color-accent-foreground: var(--accent-foreground); --color-segment: var(--segment); --color-segment-foreground: var(--segment-foreground); --color-border: var(--border); --color-separator: var(--separator); --color-focus: var(--focus); --color-link: var(--link); --color-default: var(--default); --color-default-foreground: var(--default-foreground); --color-success: var(--success); --color-success-foreground: var(--success-foreground); --color-warning: var(--warning); --color-warning-foreground: var(--warning-foreground); --color-danger: var(--danger); --color-danger-foreground: var(--danger-foreground); /* Form Field Tokens */ --color-field: var(--field-background, var(--default)); --color-field-foreground: var(--field-foreground, var(--foreground)); --color-field-placeholder: var(--field-placeholder, var(--muted)); --color-field-border: var(--field-border, var(--border)); --radius-field: var(--field-radius, var(--radius-xl)); --border-width-field: var(--field-border-width, var(--border-width)); --shadow-surface: var(--surface-shadow); --shadow-overlay: var(--overlay-shadow); --shadow-field: var(--field-shadow); /* Calculated Variables */ /* Colors */ /* --- background shades --- */ --color-background-secondary: color-mix(in oklab, var(--background) 96%, var(--foreground) 4%); --color-background-tertiary: color-mix(in oklab, var(--background) 92%, var(--foreground) 8%); --color-background-inverse: var(--foreground); /* ------------------------- */ --color-default-hover: color-mix(in oklab, var(--default) 96%, var(--default-foreground) 4%); --color-accent-hover: color-mix(in oklab, var(--accent) 90%, var(--accent-foreground) 10%); --color-success-hover: color-mix(in oklab, var(--success) 90%, var(--success-foreground) 10%); --color-warning-hover: color-mix(in oklab, var(--warning) 90%, var(--warning-foreground) 10%); --color-danger-hover: color-mix(in oklab, var(--danger) 90%, var(--danger-foreground) 10%); /* Form Field Colors */ --color-field-hover: color-mix(in oklab, var(--field-background, var(--default)) 90%, var(--field-foreground, var(--foreground)) 2%); --color-field-focus: var(--field-background, var(--default)); --color-field-border-hover: color-mix(in oklab, var(--field-border, var(--border)) 88%, var(--field-foreground, var(--foreground)) 10%); --color-field-border-focus: color-mix(in oklab, var(--field-border, var(--border)) 74%, var(--field-foreground, var(--foreground)) 22%); /* Soft Colors */ --color-accent-soft: color-mix(in oklab, var(--accent) 15%, transparent); --color-accent-soft-foreground: var(--accent); --color-accent-soft-hover: color-mix(in oklab, var(--accent) 20%, transparent); --color-danger-soft: color-mix(in oklab, var(--danger) 15%, transparent); --color-danger-soft-foreground: var(--danger); --color-danger-soft-hover: color-mix(in oklab, var(--danger) 20%, transparent); --color-warning-soft: color-mix(in oklab, var(--warning) 15%, transparent); --color-warning-soft-foreground: var(--warning); --color-warning-soft-hover: color-mix(in oklab, var(--warning) 20%, transparent); --color-success-soft: color-mix(in oklab, var(--success) 15%, transparent); --color-success-soft-foreground: var(--success); --color-success-soft-hover: color-mix(in oklab, var(--success) 20%, transparent); /* Separator Colors - Levels */ --color-separator-secondary: color-mix(in oklab, var(--surface) 85%, var(--surface-foreground) 15%); --color-separator-tertiary: color-mix(in oklab, var(--surface) 81%, var(--surface-foreground) 19%); /* Border Colors - Levels (progressive contrast: default → secondary → tertiary) */ /* Light mode: lighter → darker | Dark mode: darker → lighter */ --color-border-secondary: color-mix(in oklab, var(--surface) 78%, var(--surface-foreground) 22%); --color-border-tertiary: color-mix(in oklab, var(--surface) 66%, var(--surface-foreground) 34%); /* Radius and default sizes - defaults can change by just changing the --radius */ --radius-xs: calc(var(--radius) * 0.25); /* 0.125rem (2px) */ --radius-sm: calc(var(--radius) * 0.5); /* 0.25rem (4px) */ --radius-md: calc(var(--radius) * 0.75); /* 0.375rem (6px) */ --radius-lg: calc(var(--radius) * 1); /* 0.5rem (8px) */ --radius-xl: calc(var(--radius) * 1.5); /* 0.75rem (12px) */ --radius-2xl: calc(var(--radius) * 2); /* 1rem (16px) */ --radius-3xl: calc(var(--radius) * 3); /* 1.5rem (24px) */ --radius-4xl: calc(var(--radius) * 4); /* 2rem (32px) */ } ``` Form controls now rely on the `--field-*` variables and their calculated hover/focus variants. Update them in your theme to restyle inputs, checkboxes, radios, and OTP slots without impacting surfaces like buttons or cards. ## Resources - [Colors Documentation](/docs/native/getting-started/colors) - [Styling Guide](/docs/native/getting-started/styling) - [Tailwind CSS v4 Theming](https://tailwindcss.com/docs/theme) - [OKLCH Color Tool](https://oklch.com)