Skip to main content
FieldValue
GoalCustomize UI Kit appearance (colors, fonts, dark mode) via theme provider
ProviderCometChatThemeProvider — wrap your app to enable theming
Importimport { CometChatThemeProvider } from "@cometchat/chat-uikit-react-native";
Set mode<CometChatThemeProvider theme={{ mode: "light" }}> or "dark"
Override colorstheme={{ light: { color: { primary: "#F76808" } } }}
Component stylestheme={{ light: { conversationStyles: { ... } } }}
Key tokensprimary, textPrimary, background1, neutral50, extendedPrimary500
ConstraintsColors must be hex values, theme merges with defaults (deep merge)
Full token listColors | GitHub source
Theming controls the look and feel of the chat UI — colors, fonts, and component styles — through the CometChatThemeProvider.
Prerequisites:
  1. Wrap your app with CometChatThemeProvider to enable theming
  2. Wrap with SafeAreaProvider and GestureHandlerRootView for proper layout
  3. Colors must be supplied as hex values (e.g., #F76808)
  4. Theme values are deeply merged with defaults — only override what you need

Theming Contract

Inputs
  • CometChatThemeProvider wrapper with optional theme prop
  • Theme mode: { mode: "light" } or { mode: "dark" }
  • Color overrides: { light: { color: { primary: "#F76808" } } }
  • Component-specific styles: { light: { conversationStyles: { ... } } }
Precedence
  1. Style prop on component (highest priority)
  2. Custom theme via CometChatThemeProvider
  3. Default theme (lowest priority)
Outputs
  • Primary color changes buttons, outgoing bubbles, and active states
  • Background tokens change panels and surfaces
  • Typography tokens change fonts across the UI
  • Component styles override specific component appearances

Top Tokens (Quick Mapping)

For the complete list, see Colors.
TokenCommon Usage
primaryPrimary accent color (buttons, outgoing bubbles, active states)
extendedPrimary500Mid primary shade (secondary accents/hover)
extendedPrimary900Darker primary shade (outgoing bubble shade)
neutral50White/dark surface (light: #FFFFFF, dark: #141414)
neutral300Neutral surface (incoming bubbles/panels)
background1Main app background
background2Secondary/panel background
textPrimaryPrimary text color
textSecondarySecondary/caption text
info, warning, success, errorSemantic state colors

Using Theming in Your Project

By default, the theme is automatically selected based on the system settings, ensuring that your app aligns with the user’s preferred light or dark mode unless you choose to override it with a custom theme. The CometChatThemeProvider is used to apply a custom theme to your components. By setting the theme prop with a specific mode, such as { mode: 'dark' }, you can override the default system theme and ensure that the UI is displayed in the desired light or dark mode. This allows you to provide a consistent visual experience based on the selected theme mode.
To ensure the app dynamically adapts to the device’s OS-level light or dark theme, it must be wrapped in the CometChatThemeProvider. Without this wrapper, system theme changes will not be reflected in the app’s UI.
Here’s an example of how to explicitly set the theme mode to light:
import { SafeAreaView } from "react-native-safe-area-context";
import { CometChatThemeProvider } from "@cometchat/chat-uikit-react-native";

return (
  <SafeAreaView style={{ flex: 1 }}>
    <CometChatThemeProvider theme={{ mode: "light" }}>
      {/* Component */}
    </CometChatThemeProvider>
  </SafeAreaView>
);

Customization

To customize the primary color in your app, you can override the primary color attribute in the theme. Here’s how to override the primary color for the light theme:
import { SafeAreaView } from "react-native-safe-area-context";
import { CometChatThemeProvider } from "@cometchat/chat-uikit-react-native";

return (
  <SafeAreaView style={{ flex: 1 }}>
    <CometChatThemeProvider
      theme={{
        light: {
          color: {
            primary: "#F76808",
          },
        },
      }}
    >
      {/* Component */}
    </CometChatThemeProvider>
  </SafeAreaView>
);
All default icons are implemented as SVGs.For these icons, only the following imageStyle properties are supported:
  • tintColor
  • height
  • width
Any extra properties provided in imageStyle will be ignored for default icons.For custom icons, you can provide either JSX components or an ImageSourcePropType. JSX Components: These are rendered as-is, and no additional styles are applied.ImageSourcePropType (e.g., PNG, JPEG): The entire imageStyle passed will be applied to the image as expected.

Overriding the Theme for Specific Components by Customizing Style Properties

The following example shows how the light theme for the CometChatConversations component is overridden directly by setting custom theme properties within the CometChatThemeProvider. This ensures that CometChatConversations uses a specific light theme, independent of the global theme applied to the rest of the app. The light theme is customized further by defining specific styles, such as the background color for the conversation container. This approach allows you to customize the theme for specific components while keeping the global theme intact.
import {
  CometChatConversations,
  CometChatUIKit,
  CometChatUiKitConstants,
  UIKitSettings,
  useTheme,
} from "@cometchat/chat-uikit-react-native";
import { CometChatThemeProvider } from "@cometchat/chat-uikit-react-native/src/theme/provider";
import { SafeAreaView } from "react-native-safe-area-context";
import Messages from "./src/Messages";

//other code

const theme = useTheme();

return (
  <SafeAreaView style={{ flex: 1 }}>
    <CometChatThemeProvider
      theme={{
        light: {
          conversationStyles: {
            containerStyle: {
              backgroundColor: theme.color.extendedPrimary500,
            },
          },
        },
      }}
    >
      {loggedIn && (
        <>
          <CometChatConversations
            style={{
              containerStyle: {
                display: messageUser || messageGroup ? "none" : "flex",
              },
            }}
            onItemPress={(item: CometChat.Conversation) => {
              if (
                item.getConversationType() ==
                CometChatUiKitConstants.ConversationTypeConstants.user
              ) {
                setMessageUser(item.getConversationWith() as CometChat.User);
                return;
              }
              setMessageGroup(item.getConversationWith() as CometChat.Group);
            }}
          ></CometChatConversations>
          {(messageUser || messageGroup) && (
            <Messages
              user={messageUser}
              group={messageGroup}
              onBack={() => {
                setMessageUser(undefined);
                setMessageGroup(undefined);
              }}
            />
          )}
        </>
      )}
    </CometChatThemeProvider>
  </SafeAreaView>
);

Supplying Custom Theme to Specific Components by wrapping them in a separate CometChatThemeProvider

The following example shows how the theme for the CometChatConversations component is specifically overridden by wrapping it in a separate CometChatThemeProvider. This allows CometChatConversations to use a dark mode theme, independent of the global theme applied to the rest of the app. Additionally, the dark theme is further customized for the component by defining specific styles, such as the background color for the conversation container. This approach enables you to tailor the theme for specific components while maintaining the overall consistency of the global theme.
import {
  CometChatConversations,
  CometChatUIKit,
  CometChatUiKitConstants,
  UIKitSettings,
  useTheme,
  CometChatThemeProvider,
} from "@cometchat/chat-uikit-react-native";
import { SafeAreaView } from "react-native-safe-area-context";
import Messages from "./src/Messages";

//other code

const theme = useTheme();

return (
  <SafeAreaView style={{ flex: 1 }}>
    <CometChatThemeProvider>
      {loggedIn && (
        <>
          <CometChatThemeProvider
            theme={{
              mode: "dark",
              dark: {
                conversationStyles: {
                  containerStyle: {
                    backgroundColor: theme.color.extendedPrimary600,
                  },
                },
              },
            }}
          >
            <CometChatConversations
              style={{
                containerStyle: {
                  display: messageUser || messageGroup ? "none" : "flex",
                },
              }}
              onItemPress={(item: CometChat.Conversation) => {
                if (
                  item.getConversationType() ==
                  CometChatUiKitConstants.ConversationTypeConstants.user
                ) {
                  setMessageUser(item.getConversationWith() as CometChat.User);
                  return;
                }
                setMessageGroup(item.getConversationWith() as CometChat.Group);
              }}
            ></CometChatConversations>
          </CometChatThemeProvider>
          {(messageUser || messageGroup) && (
            <Messages
              user={messageUser}
              group={messageGroup}
              onBack={() => {
                setMessageUser(undefined);
                setMessageGroup(undefined);
              }}
            />
          )}
        </>
      )}
    </CometChatThemeProvider>
  </SafeAreaView>
);
When customizing theme properties, whether by overriding specific properties or supplying a completely custom theme, the provided values will be deeply merged with the default theme. This means that only the specified properties will be overridden, while all other properties will retain their default values. Additionally, if a style is passed through props, it will take priority over the style provided via the theme. The deep merge occurs in the following order of priority:
  1. The style prop (highest priority)
  2. The custom theme
  3. The default theme (lowest priority)
This ensures that customizations are prioritized and applied while preserving the integrity of the default theme.
// The custom theme is merged with the default theme (handled internally)
const mergedTheme = internalDeepMergeImplementation(defaultTheme, customTheme);

// The style prop is applied with higher priority, merging it with the previous result (handled internally)
const finalConversationsStyle = internalDeepMergeImplementation(
  mergedTheme,
  conversationStyleProp
);

Next Steps