{"id":"8955f5b9-b4b4-45e4-b2fe-1ab9dbda5595","shortId":"YgNX4g","kind":"skill","title":"cometchat-theming","tagline":"Customize CometChat UI to match the user's app design system. Covers the CSS variable cascade, preset themes, brand color overrides, design system extraction, dark mode, and framework-specific override locations.","description":"> **Companion skills:** `cometchat-core` covers CSS import placement\n> and the one-import rule; `cometchat-customization` covers\n> component-level CSS selectors for deeper overrides;\n> `cometchat-troubleshooting` handles cases where the theme doesn't\n> apply.\n\n## Purpose\n\nTeach Claude how to theme CometChat in a v3 (AI-written) integration.\nThemes are just CSS variable overrides — you write them directly into\nthe project's CSS (or, for Astro, the React island file). **Do not use\nthe `cometchat apply-theme` CLI command — it was a v2 tool that expects\na CLI-generated `.cometchat/state.json` marker that v3 integrations\ndon't create, and it will fail with \"No integration found\".**\n\n---\n\n## 1. How CometChat theming works\n\n### The CSS variable cascade\n\nCometChat's entire visual identity is driven by **200+ CSS custom\nproperties** defined in `@cometchat/chat-uikit-react/css-variables.css`.\nThis file is imported once at the app root (see `cometchat-core`).\nEvery `<CometChat*>` component reads these variables — there is no\ncomponent-level style-props API for colors, fonts, or spacing.\n\nTo override: write CSS rules that set `--cometchat-*` variables on\n`:root` (or a scoped container), **after** the `css-variables.css`\nimport. The cascade does the rest — every component picks up the new\nvalues automatically.\n\n```css\n/* Must appear AFTER the @import of css-variables.css */\n:root {\n  --cometchat-primary-color: #6C63FF;\n  --cometchat-background-color-01: #FFFFFF;\n  --cometchat-text-color-primary: #141414;\n  --cometchat-font-family: \"Inter\", sans-serif;\n  --cometchat-radius-2: 8px;\n}\n```\n\n### Dark mode\n\nTwo broad strategies — pick based on how the project already handles dark mode.\n\n**Strategy A — OS-driven only** (simplest). Overrides live inside a `@media (prefers-color-scheme: dark)` block. The browser swaps themes based on the user's OS preference:\n\n```css\n@media (prefers-color-scheme: dark) {\n  :root {\n    --cometchat-primary-color: #7B73FF;\n    --cometchat-background-color-01: #1A1A2E;\n    --cometchat-text-color-primary: #E0E0E0;\n    /* ... remaining dark overrides ... */\n  }\n}\n```\n\n**Strategy B — App-controlled theme toggle.** If the project already has a theme toggle (next-themes, Tailwind `dark:` prefix, React Context, etc.), wire CometChat's dark mode to the same trigger. The shared trigger is typically a CSS class or `data-theme` attribute on `<html>` or `<body>`. Scope the override to that selector:\n\n```css\n/* next-themes default: applies a `.dark` class to <html> */\n.dark :root {\n  --cometchat-primary-color: #7B73FF;\n  --cometchat-background-color-01: #1A1A2E;\n  --cometchat-text-color-primary: #E0E0E0;\n}\n\n/* OR if the project uses data-theme=\"dark\" on <html> (common with Tailwind CSS v4) */\n[data-theme=\"dark\"] :root {\n  --cometchat-primary-color: #7B73FF;\n  --cometchat-background-color-01: #1A1A2E;\n  --cometchat-text-color-primary: #E0E0E0;\n}\n\n/* OR for Tailwind's `class` strategy with `darkMode: 'class'` in tailwind.config */\nhtml.dark {\n  --cometchat-primary-color: #7B73FF;\n  --cometchat-background-color-01: #1A1A2E;\n  --cometchat-text-color-primary: #E0E0E0;\n}\n```\n\n**How to tell which selector the project uses:**\n\n| Library / setup | Selector to target |\n|---|---|\n| `next-themes` (Next.js default) | `.dark` on `<html>` |\n| Tailwind with `darkMode: 'class'` | `html.dark` (or `.dark` on any ancestor) |\n| Tailwind with `darkMode: 'media'` | Matches `@media (prefers-color-scheme: dark)` — use Strategy A |\n| Tailwind CSS v4 (`@custom-variant dark`) | `[data-theme=\"dark\"]` by default |\n| Radix UI / shadcn defaults | `.dark` class on `<html>` |\n| Custom React Context (`useTheme()` hook) | Check what the context writes to the DOM — usually a class on `<html>` or `<body>` |\n\n**Rule:** whichever selector is toggled by the app's theme system, use that same selector as the CometChat override's parent. The UI Kit components sit inside the app's DOM, so they inherit whatever variable values are active at the nearest matching scope.\n\n**Do not** emit both Strategy A and Strategy B in the same stylesheet unless the user explicitly wants \"follow OS except when app toggle is set.\" That's a legitimate pattern but usually over-engineered for a first integration — ship Strategy B alone if the project has a toggle, Strategy A if it doesn't.\n\n### Why Astro is different\n\nAstro's `client:only=\"react\"` islands run in isolation — global\nstylesheets in `.astro` layouts do not cascade into them. CSS variable\noverrides in a global `.css` file will have no effect on CometChat\ncomponents. The overrides must live **inside the React island `.tsx`\nfile** (typically `src/cometchat/ChatApp.tsx`), as an inline `<style>`\ntag or a CSS import within the component.\n\n---\n\n## 2. Use this skill when\n\nThe user wants to customize the look and feel of an already-integrated\nCometChat UI. Trigger phrases:\n\n- `/cometchat theming`, `/cometchat theme` (or invoke the cometchat-theming skill via your agent's mechanism — keyword \"cometchat theming\" or \"match brand colors\" works in most agents)\n- \"match my brand colors\"\n- \"make cometchat dark mode\"\n- \"change the chat colors\"\n- \"customize the cometchat ui\"\n- \"the chat doesn't match my design system\"\n\n## 3. Preconditions\n\nThe project must already have a CometChat integration. Check by looking\nfor `.cometchat/config.json` and the UI Kit dependency:\n\n```bash\ntest -f .cometchat/config.json && cat package.json | grep \"@cometchat/chat-uikit-react\"\n```\n\nIf neither is present, **stop** and tell the user to run `/cometchat`\nto create an integration first. Theming requires the provider +\n`css-variables.css` import to already be in place.\n\n## 4. When to use which path\n\n| Situation | Path |\n|---|---|\n| Complete, opinionated theme fast | **Path A** — Preset |\n| Brand color hex (and optionally font/radius) | **Path B** — Brand color |\n| Existing Tailwind config or CSS custom properties | **Path C** — Design system extraction |\n\n---\n\n## 5. Preset values\n\nFive built-in presets. All values are in the table below — write them\ndirectly into the override CSS; do **not** try to call a CLI for this.\n\n| Preset | `--cometchat-primary-color` | `--cometchat-text-color-primary` | `--cometchat-background-color-01` | `--cometchat-font-family` | `--cometchat-radius-2` | Dark mode included |\n|---|---|---|---|---|---|---|\n| `slack` | `#611f69` | `#1d1c1d` | `#ffffff` | `Lato, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif` | `8px` | no |\n| `whatsapp` | `#25d366` | `#111b21` | `#f0f2f5` | `'Segoe UI', Helvetica, Arial, sans-serif` | `12px` | no |\n| `imessage` | `#007aff` | `#000000` | `#ffffff` | `-apple-system, BlinkMacSystemFont, 'SF Pro Text', sans-serif` | `18px` | no |\n| `discord` | `#5865f2` | `#dcddde` | `#36393f` | `'gg sans', 'Noto Sans', Helvetica, Arial, sans-serif` | `8px` | **yes** |\n| `notion` | `#2eaadc` | `#37352f` | `#ffffff` | `-apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif` | `6px` | no |\n\n## 6. Where to write the overrides\n\nTarget file is determined by `framework` in `.cometchat/config.json`:\n\n| Framework | Target file |\n|---|---|\n| `reactjs` | `src/index.css` (append `:root { ... }` block after the existing import) |\n| `nextjs` | `src/app/globals.css` (App Router) or `styles/globals.css` (Pages Router) |\n| `react-router` | `app/app.css` (or `src/index.css` if you used a Vite-style structure) |\n| `astro` | Inline `<style>` tag or imported CSS **inside** `src/cometchat/ChatApp.tsx` (see section 1 for why) |\n\nThe override block must be written **after** the existing\n`@cometchat/chat-uikit-react/css-variables.css` import so it takes\nprecedence. If the project imports the CometChat CSS in a TSX file\n(e.g. `src/main.tsx`), the override can still live in the adjacent\n`index.css` because it appears in the DOM after the JS import resolves.\n\n## 7. Steps\n\n### Step 1 — Ask what theme source to use\n\nIf the user already specified a preset name, brand color, or pointed\nto a design system file, skip to Step 2.\n\nOtherwise ask the user (preserve the structured shape — `question`/`header`/`multiSelect`/`options[].label`/`options[].description`):\n- **question:** \"How do you want to theme CometChat?\"\n- **header:** \"Theme\"\n- **multiSelect:** false\n- **options:**\n  1. label: \"Use a preset\", description: \"Pick one of: slack, whatsapp, imessage, discord, notion.\"\n  2. label: \"Match my brand\", description: \"Give me your primary brand color (hex). I'll also ask about font and radius.\"\n  3. label: \"Match my existing design system\", description: \"Point me at your tailwind.config.{js,ts} or your CSS variables file. I'll extract the tokens.\"\n\n### Step 2 — Build the override block\n\n**Path A — Preset:** Look up the preset in section 5's table. Emit a\n`:root { ... }` block with those five variables. If the preset's\n`Dark mode included` column is \"yes\" (currently just `discord`),\nalso emit a `@media (prefers-color-scheme: dark) { :root { ... } }`\nblock with sensible dark variants (invert background to dark, text to\nlight, keep primary).\n\n**Path B — Custom brand color:** The user gave you a hex (e.g.\n`#853953`). Emit at minimum:\n\n```css\n:root {\n  --cometchat-primary-color: #853953;\n}\n```\n\nThen ask if they want:\n- a matching font family (defaults to the project's existing font\n  stack from `body { font-family: ... }` in the project's main CSS)\n- a border radius (defaults to `8px`)\n- dark mode variants\n\n### Step 3 — Read the current CSS file\n\nRead the target file (see section 6) so you can append to it instead\nof overwriting existing rules. Check the file doesn't already have a\n`--cometchat-primary-color` line — if it does, you're updating an\nearlier theming pass; replace that block rather than duplicating.\n\n### Step 4 — Write / update the override block\n\nUse `Edit` to insert or replace the `:root` block. Keep it grouped and\ncommented so the user can see where their theme lives:\n\n```css\n/* CometChat theme override — edit these to change the chat UI */\n:root {\n  --cometchat-primary-color: #853953;\n  --cometchat-font-family: \"Inter\", sans-serif;\n}\n```\n\n**Path C — Design system extraction:** Read\n`tailwind.config.{js,ts}` (look for `theme.colors.primary`,\n`theme.colors.background`, `theme.fontFamily.sans`,\n`theme.borderRadius`) or the project's root CSS file (look for\n`--primary`, `--background`, etc.). Extract the tokens. Then use\nPath B's block shape with the extracted values.\n\n### Step 5 — Save the choice to config\n\n```bash\nnpx @cometchat/skills-cli config set theme \"<preset-or-custom>\"\n```\n\nWhere `<preset-or-custom>` is the preset name (e.g. `slack`) or\n`custom` for Path B / Path C.\n\n### Step 6 — Tell the user to restart the dev server\n\nThe theme is applied. Tell the user:\n1. Restart the dev server (CSS changes need a fresh reload)\n2. Refresh the chat page\n3. Verify the colors match their design\n\nIf the theme doesn't appear to apply:\n- Double-check the override block is **after** the css-variables.css\n  import in the DOM order\n- For Astro: confirm the override is inside the `.tsx` island, not a\n  global `.css` file\n- Route to `cometchat-troubleshooting` for deeper triage.\n\n## 8. Extended variable list (reference)\n\nBeyond the five \"headline\" variables in the preset table, common ones\nworth knowing:\n\n| Variable | What it controls |\n|---|---|\n| `--cometchat-primary-color` | Active message bubble, primary buttons, brand accents |\n| `--cometchat-text-color-primary` | Main body text |\n| `--cometchat-text-color-secondary` | Timestamps, muted labels |\n| `--cometchat-background-color-01` | Main app background |\n| `--cometchat-background-color-02` | Panels (conversation list, details sidebar) |\n| `--cometchat-background-color-03` | Hover / selected states |\n| `--cometchat-border-color-light` | Dividers between rows |\n| `--cometchat-font-family` | All text |\n| `--cometchat-radius-2` | Medium radius (bubbles, buttons) |\n| `--cometchat-radius-3` | Larger radius (panels) |\n\nFor the full 200+ list, query the docs MCP (see below) or read\n`node_modules/@cometchat/chat-uikit-react/dist/styles/css-variables/css-variables.css`.\n\n## 9. Docs MCP contract\n\nThe CometChat docs MCP at `cometchat-docs` is the canonical source for:\n\n- The full CSS variable list (200+ tokens) with descriptions\n- Component-level styling selectors (`.cometchat-message-bubble-outgoing`,\n  `.cometchat-conversations-header`, etc.)\n- Dark mode patterns beyond the simple invert\n- Font / radius / spacing token names\n\n**When to use it:**\n- Component-level overrides beyond the 10 tokens above (e.g., \"make\n  incoming bubbles green\" needs a specific selector) — query the docs\n  MCP. Never invent CSS class names from memory.\n- If the docs MCP is not installed and the user asks for this, tell\n  them: \"I need the CometChat docs MCP for component-level styling.\n  Install it with `claude mcp add --transport http cometchat-docs\n  https://www.cometchat.com/docs/mcp` and re-run.\"\n\n**Canonical reference URL:**\nhttps://www.cometchat.com/docs/ui-kit/react/theme\n\n## Hard rules\n\n- **Do NOT call `cometchat apply-theme`.** It's a v2 CLI command that\n  requires a CLI-generated `.cometchat/state.json` and fails on v3\n  AI-written integrations. Write CSS directly instead.\n- Never apply theming to a project without an existing CometChat\n  integration (no `.cometchat/config.json` = no integration).\n- Always write theme overrides **after** the css-variables.css import.\n- Never invent CSS variable names. Use the preset table (section 5),\n  the common-variables table (section 8), or query the docs MCP.\n- Never edit `node_modules` or vendor files.\n- Astro is special: theme overrides must live inside the `.tsx`\n  React island file, not a global `.css`.\n- Always use `npx @cometchat/skills-cli` for config saves.","tags":["cometchat","theming","skills","agent-skills","ai-agent","chat","claude-code","cursor","messaging","nextjs","react","react-native"],"capabilities":["skill","source-cometchat","skill-cometchat-theming","topic-agent-skills","topic-ai-agent","topic-chat","topic-claude-code","topic-cometchat","topic-cursor","topic-messaging","topic-nextjs","topic-react","topic-react-native","topic-ui-kit"],"categories":["cometchat-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/cometchat/cometchat-skills/cometchat-theming","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add cometchat/cometchat-skills","source_repo":"https://github.com/cometchat/cometchat-skills","install_from":"skills.sh"}},"qualityScore":"0.463","qualityRationale":"deterministic score 0.46 from registry signals: · indexed on github topic:agent-skills · 27 github stars · SKILL.md body (13,676 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T19:04:56.328Z","embedding":null,"createdAt":"2026-05-07T13:05:16.275Z","updatedAt":"2026-05-18T19:04:56.328Z","lastSeenAt":"2026-05-18T19:04:56.328Z","tsv":"'01':255,337,423,460,489 '1':147 '141414':262 '1a1a2e':338,424,461,490 '2':274 '200':164 '6c63ff':250 '7b73ff':332,418,455,484 '8px':275 'activ':617 'ai':85 'ai-written':84 'alon':666 'alreadi':287,358 'ancestor':526 'api':199 'app':12,178,351,586,607,645 'app-control':350 'appear':239 'appli':73,116,407 'apply-them':115 'astro':105,680,683,695 'attribut':393 'automat':236 'b':349,631,665 'background':253,335,421,458,487 'base':282,313 'block':308 'brand':22 'broad':279 'browser':310 'cascad':19,155,225,699 'case':67 'check':566 'class':388,410,472,476,520,559,576 'claud':76 'cli':118,129 'cli-gener':128 'client':685 'color':23,201,249,254,260,305,324,331,336,342,417,422,428,454,459,465,483,488,494,535 'cometchat':2,5,39,52,64,80,114,149,156,182,185,212,247,252,258,264,272,329,334,340,373,415,420,426,452,457,463,481,486,492,596,715 'cometchat-background-color':251,333,419,456,485 'cometchat-cor':38,181 'cometchat-custom':51 'cometchat-font-famili':263 'cometchat-primary-color':246,328,414,451,480 'cometchat-radius':271 'cometchat-text-color-primari':257,339,425,462,491 'cometchat-them':1 'cometchat-troubleshoot':63 'cometchat/chat-uikit-react/css-variables.css':170 'cometchat/state.json':131 'command':119 'common':441 'companion':36 'compon':56,186,194,230,603,716 'component-level':55,193 'contain':219 'context':370,563,569 'control':352 'core':40,183 'cover':15,41,54 'creat':138 'css':17,42,58,91,102,153,165,208,237,320,387,402,444,542,702,708 'css-variables.css':222,244 'custom':4,53,166,545,561 'custom-vari':544 'dark':28,276,289,307,326,346,367,375,409,412,439,449,515,523,537,547,551,558 'darkmod':475,519,529 'data':391,437,447,549 'data-them':390,436,446,548 'deeper':61 'default':406,514,553,557 'defin':168 'design':13,25 'differ':682 'direct':97 'doesn':71,677 'dom':573,609 'driven':162,295 'e0e0e0':344,430,467,496 'effect':713 'emit':625 'engin':658 'entir':158 'etc':371 'everi':184,229 'except':643 'expect':126 'explicit':639 'extract':27 'fail':142 'famili':266 'ffffff':256 'file':109,172,709,726 'first':661 'follow':641 'font':202,265 'found':146 'framework':32 'framework-specif':31 'generat':130 'global':692,707 'handl':66,288 'hook':565 'html.dark':479,521 'ident':160 'import':43,49,174,223,242 'inherit':612 'inlin':731 'insid':300,605,721 'integr':87,135,145,662 'inter':267 'island':108,688,724 'isol':691 'kit':602 'layout':696 'legitim':652 'level':57,195 'librari':505 'live':299,720 'locat':35 'marker':132 'match':8,531,621 'media':302,321,530,532 'mode':29,277,290,376 'must':238,719 'nearest':620 'new':234 'next':364,404,511 'next-them':363,403,510 'next.js':513 'one':48 'one-import':47 'os':294,318,642 'os-driven':293 'over-engin':656 'overrid':24,34,62,93,206,298,347,398,597,704,718 'parent':599 'pattern':653 'pick':231,281 'placement':44 'prefer':304,319,323,534 'prefers-color-schem':303,322,533 'prefix':368 'preset':20 'primari':248,261,330,343,416,429,453,466,482,495 'project':100,286,357,434,503,669 'prop':198 'properti':167 'purpos':74 'radius':273 'radix':554 'react':107,369,562,687,723 'read':187 'remain':345 'rest':228 'root':179,215,245,327,413,450 'rule':50,209,579 'run':689 'san':269 'sans-serif':268 'scheme':306,325,536 'scope':218,396,622 'see':180 'selector':59,401,501,507,581,593 'serif':270 'set':211,648 'setup':506 'shadcn':556 'share':382 'ship':663 'simplest':297 'sit':604 'skill':37 'skill-cometchat-theming' 'source-cometchat' 'space':204 'specif':33 'src/cometchat/chatapp.tsx':728 'strategi':280,291,348,473,539,627,630,664,673 'style':197 'style-prop':196 'stylesheet':635,693 'swap':311 'system':14,26,589 'tailwind':366,443,470,517,527,541 'tailwind.config':478 'target':509 'teach':75 'tell':499 'text':259,341,427,464,493 'theme':3,21,70,79,88,117,150,312,353,361,365,392,405,438,448,512,550,588 'toggl':354,362,583,646,672 'tool':124 'topic-agent-skills' 'topic-ai-agent' 'topic-chat' 'topic-claude-code' 'topic-cometchat' 'topic-cursor' 'topic-messaging' 'topic-nextjs' 'topic-react' 'topic-react-native' 'topic-ui-kit' 'trigger':380,383 'troubleshoot':65 'tsx':725 'two':278 'typic':385,727 'ui':6,555,601 'unless':636 'use':112,435,504,538,590 'user':10,316,638 'usethem':564 'usual':574,655 'v2':123 'v3':83,134 'v4':445,543 'valu':235,615 'variabl':18,92,154,189,213,614,703 'variant':546 'visual':159 'want':640 'whatev':613 'whichev':580 'wire':372 'work':151 'write':95,207,570 'written':86","prices":[{"id":"f1a8e0e2-6019-4543-8960-e0d017b89be4","listingId":"8955f5b9-b4b4-45e4-b2fe-1ab9dbda5595","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"cometchat","category":"cometchat-skills","install_from":"skills.sh"},"createdAt":"2026-05-07T13:05:16.275Z"}],"sources":[{"listingId":"8955f5b9-b4b4-45e4-b2fe-1ab9dbda5595","source":"github","sourceId":"cometchat/cometchat-skills/cometchat-theming","sourceUrl":"https://github.com/cometchat/cometchat-skills/tree/main/skills/cometchat-theming","isPrimary":false,"firstSeenAt":"2026-05-07T13:05:16.275Z","lastSeenAt":"2026-05-18T19:04:56.328Z"}],"details":{"listingId":"8955f5b9-b4b4-45e4-b2fe-1ab9dbda5595","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"cometchat","slug":"cometchat-theming","github":{"repo":"cometchat/cometchat-skills","stars":27,"topics":["agent-skills","ai-agent","chat","claude-code","cometchat","cursor","messaging","nextjs","react","react-native","ui-kit"],"license":null,"html_url":"https://github.com/cometchat/cometchat-skills","pushed_at":"2026-05-18T05:04:24Z","description":"Add CometChat chat to any React, Next.js, React Native, Angular, Android, iOS, or Flutter project through your AI coding agent. Works with Claude Code, Cursor, Codex, VS Code Copilot, Windsurf, Cline, Kiro, and 50+ more agents.","skill_md_sha":"3b105e4cfcb4f898be334970ef3af9aa4b0ca8e7","skill_md_path":"skills/cometchat-theming/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/cometchat/cometchat-skills/tree/main/skills/cometchat-theming"},"layout":"multi","source":"github","category":"cometchat-skills","frontmatter":{"name":"cometchat-theming","license":"MIT","description":"Customize CometChat UI to match the user's app design system. Covers the CSS variable cascade, preset themes, brand color overrides, design system extraction, dark mode, and framework-specific override locations.","compatibility":"Node.js >=18; @cometchat/chat-uikit-react ^6; integration must already be applied"},"skills_sh_url":"https://skills.sh/cometchat/cometchat-skills/cometchat-theming"},"updatedAt":"2026-05-18T19:04:56.328Z"}}