Introduction
Components
- Accordion
- Action Sheet
- Alert
- Audio Player
- Audio Recorder
- Audio Waveform
- Avatar
- Badge
- BottomSheet
- Button
- Camera
- Camera Preview
- Card
- Carousel
- Checkbox
- Collapsible
- Color Picker
- Combobox
- Date Picker
- File Picker
- Gallery
- Hello Wave
- Icon
- Image
- Input
- Input OTP
- Link
- MediaPicker
- Mode Toggle
- Onboarding
- ParallaxScrollView
- Picker
- Popover
- Progress
- Radio
- ScrollView
- SearchBar
- Separator
- Share
- Sheet
- Skeleton
- Spinner
- Switch
- Table
- Tabs
- Text
- Toast
- Toggle
- Video
- View
Charts
Installation
pnpm dlx bna-ui add useColorScheme
Usage
import { useColorScheme } from '@/hooks/useColorScheme';
export function ThemedComponent() {
const colorScheme = useColorScheme();
return (
<View
style={{
backgroundColor: colorScheme === 'dark' ? '#000' : '#fff',
}}
>
{/* Your themed content */}
</View>
);
}
API Reference
useColorScheme
Returns the user's preferred color scheme with platform-specific optimizations.
Returns
Type | Description |
---|---|
'light' | 'dark' | null | The current color scheme. Returns null if the color scheme cannot be determined initially. |
Platform Behavior
Native (iOS/Android)
- Uses React Native's built-in
useColorScheme
hook - Automatically updates when the system color scheme changes
- Returns the actual system preference immediately
- Listens for system-level theme changes
Web
- Implements hydration-safe color scheme detection
- Returns
'light'
during server-side rendering to prevent hydration mismatches - Updates to the actual system preference after client-side hydration
- Listens for system color scheme changes via media queries
Implementation Details
The hook uses platform-specific files to handle different environments:
useColorScheme.ts
- Default implementation for React NativeuseColorScheme.web.ts
- Web-specific implementation with hydration safety
Web Hydration Safety
The web implementation includes a hydration check to prevent mismatches between server and client rendering:
const [hasHydrated, setHasHydrated] = useState(false);
useEffect(() => {
setHasHydrated(true);
}, []);
if (hasHydrated) {
return colorScheme;
}
return 'light'; // Safe default during SSR
Use Cases
This hook is essential for:
- Implementing dark mode support in your applications
- Creating theme-aware components
- Adapting UI colors based on system preferences
- Ensuring consistent theming across platforms
- Building accessible applications with proper contrast ratios
Best Practices
Handling Null Values
Always handle the null
case, especially during initial renders:
const colorScheme = useColorScheme();
const isDark = colorScheme === 'dark';
const backgroundColor = isDark ? '#000' : '#fff';
Theme Provider Pattern
Create a centralized theme provider for consistent theming:
import { useColorScheme } from '@/hooks/useColorScheme';
import { createContext, useContext } from 'react';
const ThemeContext = createContext<'light' | 'dark'>('light');
export function ThemeProvider({ children }: { children: React.ReactNode }) {
const colorScheme = useColorScheme();
return (
<ThemeContext.Provider value={colorScheme ?? 'light'}>
{children}
</ThemeContext.Provider>
);
}
export function useTheme() {
return useContext(ThemeContext);
}
Color Palette Management
Define comprehensive color palettes for each theme:
const colors = {
light: {
background: '#ffffff',
text: '#000000',
primary: '#007AFF',
secondary: '#8E8E93',
border: '#E5E5E7',
},
dark: {
background: '#000000',
text: '#ffffff',
primary: '#0A84FF',
secondary: '#636366',
border: '#38383A',
},
};
export function useThemeColors() {
const colorScheme = useColorScheme();
return colors[colorScheme ?? 'light'];
}
Performance Optimization
Memoize theme-dependent calculations to avoid unnecessary re-renders:
import { useMemo } from 'react';
export function useThemedStyles() {
const colorScheme = useColorScheme();
return useMemo(
() => ({
container: {
backgroundColor: colorScheme === 'dark' ? '#000' : '#fff',
flex: 1,
},
text: {
color: colorScheme === 'dark' ? '#fff' : '#000',
},
}),
[colorScheme]
);
}
Testing Both Modes
Always test your application in both light and dark modes:
// Test component
export function ThemeTestComponent() {
const colorScheme = useColorScheme();
return (
<View style={{ padding: 20 }}>
<Text>Current theme: {colorScheme}</Text>
<Text>Test your components in both modes!</Text>
</View>
);
}
Advanced Usage
Custom Theme Hook
Create a more sophisticated theme hook with additional features:
import { useColorScheme } from '@/hooks/useColorScheme';
import { useMemo } from 'react';
interface Theme {
colors: {
primary: string;
secondary: string;
background: string;
text: string;
border: string;
};
spacing: {
xs: number;
sm: number;
md: number;
lg: number;
xl: number;
};
borderRadius: {
sm: number;
md: number;
lg: number;
};
}
export function useTheme(): Theme {
const colorScheme = useColorScheme();
return useMemo(() => {
const isDark = colorScheme === 'dark';
return {
colors: {
primary: isDark ? '#0A84FF' : '#007AFF',
secondary: isDark ? '#636366' : '#8E8E93',
background: isDark ? '#000000' : '#FFFFFF',
text: isDark ? '#FFFFFF' : '#000000',
border: isDark ? '#38383A' : '#E5E5E7',
},
spacing: {
xs: 4,
sm: 8,
md: 16,
lg: 24,
xl: 32,
},
borderRadius: {
sm: 4,
md: 8,
lg: 12,
},
};
}, [colorScheme]);
}
Dependencies
react-native
- Required for the baseuseColorScheme
hookreact
- Required for the web implementation hooks (useState, useEffect)
Accessibility
The hook helps maintain proper accessibility by:
- Respecting user's system-level accessibility preferences
- Supporting high contrast modes automatically
- Enabling proper color contrast ratios for different themes
- Ensuring consistent theming across the application
On This Page
InstallationUsageAPI ReferenceuseColorSchemeReturnsPlatform BehaviorNative (iOS/Android)WebImplementation DetailsWeb Hydration SafetyUse CasesBest PracticesHandling Null ValuesTheme Provider PatternColor Palette ManagementPerformance OptimizationTesting Both ModesAdvanced UsageCustom Theme HookDependenciesAccessibility