gluestack-ui logo
Get Updates
Prompt to React Native UI
Home
Components
Hooks
Apps
MCP Server
Guides
Home
Overview
IntroductionQuick Start
Getting Started
InstallationTooling SetupVS Code ExtensionsFigma UI KitCLIgluestack-ui-nativewind-utils
Core Concepts
AccessibilityUniversal
Performance
Benchmarks
Theme Configuration
Default TokensCustomizing ThemeDark Mode
Components
All Components
Typography
HeadingrscTextrsc
Layout
BoxrscCenterrscDividerHStackrscVStackrscGridalpha, rsc
Feedback
AlertProgressSpinnerToast
Data Display
BadgeCardrscTablealpha
Forms
ButtonCheckboxFormControlInputLinkPressableRadioSelectSliderSwitchTextarea
Overlay
AlertDialogDrawerMenuModalPopoverPortalTooltip
Disclosure
ActionsheetAccordionBottomSheetalpha
Media And Icons
AvatarImageIconrsc
Others
FabSkeletonalpha, rsc
Hooks
useBreakPointValue
useMediaQuery
Apps
Dashboard App
Kitchensink App
Todo App
Starter Kit
MCP Server
MCP Server
Guides
Recipes
LinearGradient
Tutorials
Building Ecommerce App
More
Upgrade to v2Upgrade to v3FAQsReleasesRoadmapTroubleshootingDiscord FAQs

Dark Mode

Customize the theme in gluestack-ui v3 with Tailwind dark mode, UI theme dark mode colors, and React Native light & dark mode for different color schemes and color mode support.

Color Scheme

gluestack-ui provides two ways of switching the color scheme or color mode: using CSS variables and using the
dark:
className support with
nativewind
.

Using CSS Variables

With CSS variables, you can configure multiple color schemes in the
config.ts
file. This file contains two predefined color schemes:
light
and
dark
. It utilizes the vars functionality from nativewind to switch token values when the color mode is changed. This approach results in less code and makes configuring tokens for different color schemes easier.

Usage

Let's look at an example where we define the
primary
token and switch it.
  1. Step 1:First, define the color token in your
    tailwind.config.js
    file and assign a variable value as shown below, following Tailwind's recommendation for using CSS variables in Tailwind.
// tailwind.config.js

module.exports = {
  theme: {
    extend: {
      colors: {
        primary: 'rgb(var(--color-primary)/<alpha-value>)',
      },
    },
  },
};
  1. Step 2:Now, define the values of that CSS variable for the
    light
    and
    dark
    color schemes in the
    config.ts
    file as shown below. Reference.
// config.ts

export const config = {
  light: vars({
    '--color-primary': '51 51 51',
  }),
  dark: vars({
    '--color-primary': '240 240 240',
  }),
};
  1. Step 3:Pass the color mode to the
    GluestackUIProvider
    using the
    mode
    prop and use the tokens inside your code.
    mode
    prop accepts three values:
    system
    ,
    light
    and
    dark
    .
  • system
    : It uses the system color mode.
  • light
    : It uses the light color mode.
  • dark
    : It uses the dark color mode.
// App.tsx

import { GluestackUIProvider } from '@/components/ui/gluestack-ui-provider';
import { Box } from '@/components/ui/box';
import { Button, ButtonText } from '@/components/ui/Button';
import { useState } from 'react';

export default function App() {
  const [colorMode, setColorMode] = (useState < 'light') | ('dark' > 'light');

  return (
    <GluestackUIProvider mode={colorMode}>
      <Box className="bg-primary flex-1">
        <Button
          onPress={() => {
            setColorMode(colorMode === 'light' ? 'dark' : 'light');
          }}
        >
          <ButtonText>Toggle color mode</ButtonText>
        </Button>
      </Box>
    </GluestackUIProvider>
  );
}

Using Tailwind Dark Mode

gluestack-ui also supports Tailwind's default
dark:
concept. Let's see how to use it with an example.
// App.tsx

import { GluestackUIProvider } from '@/components/ui/gluestack-ui-provider';
import { Box } from '@/components/ui/box';
import { Button, ButtonText } from '@/components/ui/Button';
import { useState } from 'react';

export default function App() {
  const [colorMode, setColorMode] = (useState < 'light') | ('dark' > 'light');

  return (
    <GluestackUIProvider mode={colorMode}>
      <Box className="bg-white dark:bg-black flex-1">
        <Button
          onPress={() => {
            setColorMode(colorMode === 'light' ? 'dark' : 'light');
          }}
        >
          <ButtonText>Toggle color mode</ButtonText>
        </Button>
      </Box>
    </GluestackUIProvider>
  );
}
In the above example, we switch the background color of our Box component in dark mode using the
dark:
syntax. To use dark mode, we need to change the
darkMode
strategy to
"class"
for the web and
"media"
for native devices in the
tailwind.config.js
file. You can achieve this by setting the
DARK_MODE
environment variable as shown below.
// tailwind.config.js

module.exports = {
  darkMode: process.env.DARK_MODE ? process.env.DARK_MODE : 'media',
  // rest of the config
};
After this, we need to update our scripts in the
package.json
file as shown below:
{
  "scripts": {
    "android": "DARK_MODE=media expo start --android",
    "ios": "DARK_MODE=media expo start --ios",
    "web": "DARK_MODE=class expo start --web"
  }
}
For Next.js projects, you can directly set the
darkMode
strategy to
"class"
without needing to change the scripts.
Important Note
Note: This is a temporary solution until we fix the issue with nativewind for the
darkMode:"class"
strategy.

Persist Color Mode

Step 1: Install the following dependencies:
npm i @react-native-async-storage/async-storage
We will use the
@react-native-async-storage/async-storage
package to store the color mode in the device's local storage. You can also use other storage solutions.
Step 2: Create a new file
ThemeProvider.tsx
at
components/ui/ThemeProvider
.
// components/ui/ThemeProvider/ThemeProvider.tsx
"use client";

import React, { createContext, useState, useEffect, useContext } from "react";
import AsyncStorage from "@react-native-async-storage/async-storage";

type Theme = "light" | "dark";

interface ThemeContextType {
  theme: Theme;
  toggleTheme: () => void;
}

export const ThemeContext = createContext<ThemeContextType | undefined>(
  undefined
);

export const ThemeProvider = ({ children }: { children: React.ReactNode }) => {
  const [theme, setTheme] = useState<Theme>("light");

  useEffect(() => {
    (async () => {
      const savedTheme = (await AsyncStorage.getItem("theme")) as
        | Theme
        | "light";
      if (savedTheme) {
        setTheme(savedTheme);
        AsyncStorage.setItem("theme", savedTheme);
      }
    })();
  }, []);

  const toggleTheme = () => {
    const newTheme = theme === "light" ? "dark" : "light";
    setTheme(newTheme);
    AsyncStorage.setItem("theme", newTheme);
  };

  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
};

export const useTheme = () => {
  const context = useContext(ThemeContext);
  if (context === undefined) {
    throw new Error("useTheme must be used within a ThemeProvider");
  }
  return context;
};
Step 3: Update your app's root to utilize the
ThemeProvider
component.
Please refer to the Tailwind CSS dark mode documentation for more information and core concepts of dark mode.
Edit this page on GitHub
Go backCustomizing Theme
Up nextAll Components
Go backCustomizing Theme
Up nextAll Components