Skip to main content

Documentation Index

Fetch the complete documentation index at: https://copylabs.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

Dark Mode

Radix Themes Native provides built-in support for dark mode with automatic color scheme detection and manual control.

Automatic Dark Mode

By default, the theme follows the device’s color scheme:
import { ThemeProvider } from 'radix-native-ui';

export default function App() {
  return (
    <ThemeProvider>
      {/* Theme will automatically match device settings */}
      <AppContent />
    </ThemeProvider>
  );
}

Manual Dark Mode

Fixed Mode

Set a fixed mode that doesn’t respond to device settings:
// Always light mode
<ThemeProvider appearance="light">
  <AppContent />
</ThemeProvider>

// Always dark mode
<ThemeProvider appearance="dark">
  <AppContent />
</ThemeProvider>
The appearance prop is the preferred way to set the color scheme. It accepts 'light', 'dark', or 'inherit'. The legacy mode prop is still supported for backward compatibility.

Forced Mode

Use forcedMode to override device settings completely:
<ThemeProvider forcedMode="dark">
  {/* Always dark, even if device is in light mode */}
  <AppContent />
</ThemeProvider>

Toggle Dark Mode

Implement a theme toggle using the useThemeActions hook:
import {
  ThemeProvider,
  useThemeActions,
  useThemeMode,
  Button
} from 'radix-native-ui';

function ThemeToggle() {
  const mode = useThemeMode();
  const { toggleMode } = useThemeActions();

  return (
    <Button onPress={toggleMode}>
      Switch to {mode === 'light' ? 'dark' : 'light'} mode
    </Button>
  );
}

function App() {
  return (
    <ThemeProvider>
      <ThemeToggle />
    </ThemeProvider>
  );
}

Controlled Dark Mode

Manage theme mode with state:
import { useState } from 'react';
import { ThemeProvider, useThemeMode, Button } from 'radix-native-ui';

function App() {
  const [appearance, setAppearance] = useState<'light' | 'dark'>('light');

  return (
    <ThemeProvider
      appearance={appearance}
      onModeChange={setAppearance}
    >
      <Button onPress={() => setAppearance(a => a === 'light' ? 'dark' : 'light')}>
        Toggle Theme
      </Button>
    </ThemeProvider>
  );
}

Persist Theme Preference

Store user preference with AsyncStorage:
import { useState, useEffect } from 'react';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { ThemeProvider } from 'radix-native-ui';

const THEME_KEY = '@theme_mode';

function App() {
  const [mode, setMode] = useState<'light' | 'dark' | undefined>(undefined);
  const [isLoaded, setIsLoaded] = useState(false);

  // Load saved theme on mount
  useEffect(() => {
    AsyncStorage.getItem(THEME_KEY).then((savedMode) => {
      if (savedMode) {
        setMode(savedMode as 'light' | 'dark');
      }
      setIsLoaded(true);
    });
  }, []);

  // Save theme when it changes
  const handleModeChange = async (newMode: 'light' | 'dark') => {
    setMode(newMode);
    await AsyncStorage.setItem(THEME_KEY, newMode);
  };

  if (!isLoaded) {
    return null; // Or a loading screen
  }

  return (
    <ThemeProvider
      appearance={mode}
      onModeChange={handleModeChange}
    >
      <AppContent />
    </ThemeProvider>
  );
}

Dark Mode Colors

Colors automatically adapt to the current mode:
import { useTheme, useThemeMode } from 'radix-native-ui';

function ThemedComponent() {
  const theme = useTheme();
  const mode = useThemeMode();

  // Access mode-specific colors
  const backgroundColor = mode === 'dark'
    ? theme.colors.gray.dark[2]
    : theme.colors.gray[2];

  const textColor = mode === 'dark'
    ? theme.colors.gray.dark[12]
    : theme.colors.gray[12];

  return (
    <View style={{ backgroundColor, padding: 16 }}>
      <Text style={{ color: textColor }}>
        Themed content
      </Text>
    </View>
  );
}

System Theme Detection

The theme automatically detects system preference changes:
import { ThemeProvider, useThemeMode } from 'radix-native-ui';

function SystemThemeIndicator() {
  const mode = useThemeMode();

  return (
    <Text>
      Current theme: {mode} (following system)
    </Text>
  );
}

// When mode prop is undefined, it follows the system
<ThemeProvider>
  <SystemThemeIndicator />
</ThemeProvider>

Best Practices

  1. Test both modes - Always test your UI in both light and dark modes
  2. Use theme colors - Don’t hardcode colors; use theme values for automatic adaptation
  3. Check contrast - Ensure text is readable in both modes
  4. Consider images - Some images may need different versions for each mode
  5. Persist preference - Save user’s theme preference for a better experience