Skip to content

Custom Color Scheme Hook

By default, the plugin uses React Native’s built-in useColorScheme() hook for dark: and light: modifiers. You can configure it to use a custom color scheme hook from theme providers like React Navigation, Expo, or your own implementation.

babel.config.js
module.exports = {
plugins: [
[
"@mgcrea/react-native-tailwind/babel",
{
colorScheme: {
importFrom: "@/hooks/useColorScheme", // Module to import from
importName: "useColorScheme", // Hook name to import
},
},
],
],
};

Override system color scheme with user preferences from a store:

src/hooks/useColorScheme.ts
import { useColorScheme as useSystemColorScheme } from "react-native";
import { profileStore } from "@/stores/profileStore";
import { type ColorSchemeName } from "react-native";
export const useColorScheme = (): ColorSchemeName => {
const systemColorScheme = useSystemColorScheme();
const userTheme = profileStore.theme; // 'dark' | 'light' | 'auto'
// Return user preference, or fall back to system if set to 'auto'
return userTheme === 'auto' ? systemColorScheme : userTheme;
};
babel.config.js
{
colorScheme: {
importFrom: "@/hooks/useColorScheme",
importName: "useColorScheme"
}
}

Integrate with React Navigation’s theme system:

hooks/useColorScheme.ts
import { useTheme as useNavTheme } from "@react-navigation/native";
import { type ColorSchemeName } from "react-native";
export const useColorScheme = (): ColorSchemeName => {
const { dark } = useNavTheme();
return dark ? "dark" : "light";
};
babel.config.js
{
colorScheme: {
importFrom: "@/hooks/useColorScheme",
importName: "useColorScheme"
}
}

Use Expo Router’s theme hook:

babel.config.js
{
colorScheme: {
importFrom: "expo-router",
importName: "useColorScheme"
}
}

Mock color scheme for tests:

test/mocks/useColorScheme.ts
export const useColorScheme = () => "light"; // Or "dark" for dark mode tests
// babel.config.js (test environment)
{
colorScheme: {
importFrom: "@/test/mocks/useColorScheme",
importName: "useColorScheme"
}
}

When you use dark: or light: modifiers:

<View className="bg-white dark:bg-gray-900" />

The plugin will:

  1. Import your custom hook: import { useColorScheme } from "@/hooks/useColorScheme"
  2. Inject it in components: const _twColorScheme = useColorScheme();
  3. Generate conditionals: _twColorScheme === "dark" && styles._dark_bg_gray_900

Without custom configuration, the plugin uses React Native’s built-in hook:

import { useColorScheme } from "react-native"

This works out of the box for basic system color scheme detection.

  • Your custom hook must return ColorSchemeName (type from React Native: "light" | "dark" | null | undefined)
  • The hook must be compatible with React’s rules of hooks (can only be called in function components)
  • Import merging works automatically if you already import from the same source
src/context/ThemeContext.tsx
import { createContext, useContext, useState, ReactNode } from "react";
import { useColorScheme as useSystemColorScheme } from "react-native";
import { type ColorSchemeName } from "react-native";
type ThemeContextType = {
colorScheme: ColorSchemeName;
setColorScheme: (scheme: "light" | "dark" | "auto") => void;
};
const ThemeContext = createContext<ThemeContextType | undefined>(undefined);
export function ThemeProvider({ children }: { children: ReactNode }) {
const systemColorScheme = useSystemColorScheme();
const [userPreference, setUserPreference] = useState<"light" | "dark" | "auto">("auto");
const colorScheme = userPreference === "auto" ? systemColorScheme : userPreference;
return (
<ThemeContext.Provider value={{ colorScheme, setColorScheme: setUserPreference }}>
{children}
</ThemeContext.Provider>
);
}
export function useColorScheme(): ColorSchemeName {
const context = useContext(ThemeContext);
if (!context) throw new Error("useColorScheme must be used within ThemeProvider");
return context.colorScheme;
}
babel.config.js
module.exports = {
plugins: [
[
"@mgcrea/react-native-tailwind/babel",
{
colorScheme: {
importFrom: "@/context/ThemeContext",
importName: "useColorScheme",
},
},
],
],
};

Now your components will use the custom hook:

function MyComponent() {
// Uses your custom useColorScheme from ThemeContext
return (
<View className="bg-white dark:bg-gray-900">
<Text className="text-gray-900 dark:text-white">Theme-aware text</Text>
</View>
);
}