cometchat-react-native-customization
SkillCommunicationTheme, restyle and extend the CometChat React Native UI Kit v5, theme modes and color tokens, per-component style objects, view slots, and the DataSource decorator chain for custom message types. Triggers: change CometChat colors React Native, dark mode RN chat, custom message bubble RN, brand the RN chat UI, custom message type React Native, restyle the message bubble, change the chat font, add a custom bubble RN.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the cometchat-react-native-customization skill
What this skill tells your AI
The instructions your AI receives, as published by cometchat/cometchat-skills in skills/cometchat-react-native-customization/SKILL.md and read by ahel’s review.
Ground truth:
@cometchat/chat-uikit-react-native@5+ catalogrn-v5.json. Docs:/ui-kit/react-native/theme·colors·component-styling·message-bubble-styling. Fetch token names and style keys from docs — never invent them.
Companion skills (read first)
cometchat-react-native-core— install, provider chain, init→login→render. Assumed, not repeated here.
Use this skill when
- "change the chat colors" · "brand the chat UI" · "dark mode" · "restyle the bubbles"
- "custom message type" · "render my own bubble" · "add an option to the message menu"
Prerequisites & install
None beyond core. Theming needs CometChatThemeProvider already in the chain (see core).
Customization mechanism — three layers, cheapest first
There is no CSS. No stylesheets, no className, no --cometchat-* variables. If you are
holding a React snippet with CSS custom properties, it does not apply here.
Layer 1 — theme mode + color tokens (whole app)
The provider takes a theme prop shaped { mode, light, dark }. mode is "light" · "dark" ·
"auto" — "auto" is what makes the kit follow the device (OS) light/dark setting (it reads
useColorScheme()); the provider default is already "auto".
// Fixed dark for the whole app.
<CometChatThemeProvider theme={{ mode: "dark" }}>{/* … */}</CometChatThemeProvider>
// Follow the OS, branded in BOTH schemes. mode:"auto" is the switch;
// set BOTH light and dark or dark falls back to defaults.
<CometChatThemeProvider
theme={{
mode: "auto",
light: { color: { primary: "#F76808" } },
dark: { color: { primary: "#F8935B" } },
}}
>
{/* … */}
</CometChatThemeProvider>
primary drives buttons, outgoing bubbles and active states — it is usually the only token a brand
change needs. Other common tokens: textPrimary, background1, neutral50, extendedPrimary500.
Fetch the full list from /ui-kit/react-native/colors.md rather than guessing a token name.
To follow the OS, use mode: "auto" and set both light and dark. Without the provider,
system theme changes are not reflected at all.
Layer 2 — per-component style objects
Every component takes a style prop holding named sub-style objects — plain RN style objects,
not CSS:
<CometChatConversations style={{ containerStyle: { backgroundColor: "#F7F7F7" } }} />
The same style keys can be set globally through the theme instead, which is preferable when the change should apply everywhere:
<CometChatThemeProvider theme={{ light: { conversationStyles: { /* … */ } } }}>
Style-key names differ per component. Fetch them from that component's page
(/ui-kit/react-native/component-styling.md and the component's own page) — do not pattern-match
from another component.
Layer 3 — read the active theme in your own views
useTheme() returns the resolved theme (already light-or-dark per mode), so custom views match
the kit without re-deriving the palette:
import { useTheme } from "@cometchat/chat-uikit-react-native";
import { Text } from "react-native";
const Label = () => {
const theme = useTheme();
return <Text style={{ color: theme.color.textPrimary }}>Chats</Text>;
};
Custom message types — the DataSource decorator chain
⚠️ RN does NOT have the React plugin API. CometChatMessagePlugin and CometChatPluginRegistry
do not exist in this kit; emitting them will not compile. RN uses a decorator chain.
Extend DataSourceDecorator, override what you need, and register it with ChatConfigurator.enable:
import {
ChatConfigurator, DataSourceDecorator, CometChatMessageTemplate,
} from "@cometchat/chat-uikit-react-native";
const ORDER_TYPE = "order";
class OrderDataSource extends DataSourceDecorator {
// 0. IDENTITY — REQUIRED. The base DataSourceDecorator.getId() THROWS
// ("Method not implemented.") and ChatConfigurator.enable() calls getId() to
// dedupe the registry — so a subclass without this override crashes at
// ChatConfigurator.enable(...), NOT at render. Return a stable, unique id.
getId(): string {
return "order_message_datasource";
}
// 1. RENDER — how the bubble draws.
getAllMessageTemplates(theme?: any, params?: any): CometChatMessageTemplate[] {
const templates = super.getAllMessageTemplates(theme, params);
// append or replace a template here
return templates;
}
// 2. FETCH — WITHOUT THESE TWO THE MESSAGE IS NEVER RETRIEVED.
// CometChatMessageList builds its request from them:
// requestBuilder.setTypes(ChatConfigurator.dataSource.getAllMessageTypes())
// requestBuilder.setCategories(ChatConfigurator.dataSource.getAllMessageCategories())
// A type absent from those filters is excluded server-side. The bubble appears
// optimistically when sent, then vanishes on reload — with no error anywhere.
getAllMessageTypes(): string[] {
return [...super.getAllMessageTypes(), ORDER_TYPE];
}
getAllMessageCategories(): string[] {
const categories = super.getAllMessageCategories();
return categories.includes(CometChat.CATEGORY_CUSTOM)
? categories
: [...categories, CometChat.CATEGORY_CUSTOM];
}
}
// AFTER login(), not merely after init(). CometChatUIKit.login() calls enableExtensions(),
// whose first statement is ChatConfigurator.init() — "re-initialize data source". Anything
// registered earlier is DISCARDED, so a decorator wired at module scope, or straight after
// init(), silently disappears.
await CometChatUIKit.login({ uid: UID });
ChatConfigurator.enable((source) => new OrderDataSource(source));
getId() is REQUIRED on every DataSourceDecorator subclass. It is the ONE base method that
does not delegate to the wrapped source — the base throws Error("Method not implemented."), and
ChatConfigurator.enable() calls getId() to dedupe the registry. Omit it and registration crashes
at ChatConfigurator.enable(...) with Method not implemented. — NOT at render, so it reads as
unrelated. Every built-in decorator (Polls, Stickers, Translation, LinkPreview, Collaborative*)
overrides it; yours must too, returning a stable unique string.
A custom message type is two halves, and only one of them is obvious. Render is
getAllMessageTemplates / getMessageTemplate. Fetch is getAllMessageTypes /
getAllMessageCategories. Ship the render half alone and everything looks right until the first
reload, when every message of your type is gone — no error, no warning.
DataSourceDecorator exposes ~50 overridable methods; the ones you usually want are getId
(mandatory — see above), getAllMessageTemplates, getMessageTemplate, getAllMessageTypes,
getAllMessageCategories, getMessageOptions (the long-press menu) and
getAuxiliaryOptions (composer actions). Always call super.<method>(...) and modify the result —
replacing it wholesale drops every built-in message type.
DOCS GAP (RN-G10):
DataSourceDecorator/MessageDataSource/ExtensionsDataSourceandChatConfigurator.enableare not documented on any RN page — the docs show only mutating existing templates viagetAllMessageTemplates(). Built from the kit source; flag this to the developer rather than presenting it as documented.Partially closed (2026-08-20).
ui-kit/react-native/message-listnow documents the half that actually breaks builds: a custom type must be registered for fetch (getAllMessageTypes/getAllMessageCategories), not only for render, and the decorator must be registered afterlogin()becauseenableExtensions()re-runsChatConfigurator.init(). Still missing: a dedicated RN custom-message-types page coveringDataSourceDecorator/MessageDataSource/ExtensionsDataSourceend to end. Owner: docs.
Customizing an existing bubble without a decorator
To restyle rather than replace, prefer the theme's bubble style keys —
textBubbleStyles, imageBubbleStyles, fileBubbleStyles, pollBubbleStyles and siblings.
Fetch exact keys from /ui-kit/react-native/message-bubble-styling.md.
Common pitfalls
- Reaching for CSS — no stylesheets, no
className, no--cometchat-*. Theme object + RN styles. - Emitting the React plugin API — does not exist; use
ChatConfigurator+DataSourceDecorator. - Omitting
getId()on a decorator — the base throws;ChatConfigurator.enable()calls it → crash at registration withMethod not implemented. - Not calling
superin a decorator override — silently drops all built-in templates. - Setting only
lightwhen the app follows the OS — dark mode then falls back to defaults. - Guessing token or style-key names — fetch them; a wrong key fails silently rather than erroring.
Verify it works
- Every symbol appears in
catalogs/rn-v5.json. npm run verify:fences:rn-v5compiles the examples against the pinned kit.- On device: toggle OS dark mode and confirm the surface follows; confirm a custom template renders and built-in types still render alongside it.
Signals
- GitHub stars
- 109
- Forks
- 2
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
cometchat-react-native-customization- Source
- github.com/cometchat/cometchat-skills