# anti-patterns — real bugs, do NOT do these (React v7)

1. **No `init()` during render** — async + side effects → infinite re-render. Use `useEffect` or pre-`createRoot`.
2. **Import the UI Kit CSS once** — duplicate imports = specificity conflicts + doubled variables.
3. **No render before init completes** — components assume the SDK is initialized ("CometChat is not initialized"). Gate with the provider/ready-state.
4. **Never hardcode `AUTH_KEY`** — env var in dev; auth token in prod.
5. **Guard concurrent `login()`** — safe sequentially only; overlap throws "Please wait until the previous login request ends." Cache a module-level in-flight promise (`ensureLoggedIn`, see `lifecycle.md`).
6. **No server-side render** of components — `"use client"` (Next), `client:only="react"` (Astro). See `ssr.md`.
7. **Don't target internal CSS classes** — use `--cometchat-*` variables.
8. **Container needs a content-INDEPENDENT height** — components fill 100% of the container, so a content-driven box both collapses to ~0px (static collapse) AND grows-into-place as content loads (load-transition reflow). Pin it (`100dvh` / a fixed height / a sized grid-flex cell — never `min-height`/`auto`) with a prepared ancestor chain, and size the columns `min-height:0`. The ONE sizing standard: `layout.md`.
9. **Don't re-init on route change** — init once at app level; re-init flickers + drops WebSockets.
10. **Don't invent component names** — check `cometchat-react-v7-components` (and `web-v7.json`). A wrong name (e.g. `<CometChatMessenger>`) is a build error.
11. **No `transform` on a container wrapping chat** — a non-`none` `transform` creates a containing block for `position: fixed` descendants; the UI Kit renders overlays (options menu, emoji picker, file preview, reactions, thread panel) as `position: fixed` and expects them anchored to the viewport. **This includes Tailwind `translate-x-*`/`-translate-y-*`/`scale-*`/`rotate-*`/`transition-transform`** — all compile to `transform` and clip/offset the overlays. Also `filter`, `perspective`, `backdrop-filter`, `will-change: transform`. **Fix:** animate `right`/`left` offset (or `margin-right`) instead of transform — in Tailwind toggle `right-0` ↔ `right-[-420px]` with `transition-[right]`. See `cometchat-react-v7-placement` drawer/widget patterns.
12. **Don't let host global CSS leak into the `.cometchat` subtree.** The kit's layout is self-contained and correct by default (verified vs 7.1.0): `.cometchat-conversations__header` is `flex-shrink:0` / `min-height:64px` (fixed — **NOT `flex:1`**), `.cometchat-conversations__list` is `flex:1`, and list-item titles are **left-aligned**. So if the **conversations header expands to fill height**, or **list-item names render centered**, the cause is a global style bleeding onto kit elements — a `text-align:center` / `align-items:center` / `flex:1` / CSS reset / Tailwind base on an ancestor — or an override of an internal class, NOT the kit. **Fix:** scope global CSS away from the `.cometchat` subtree (no `text-align`/flex-centering/`flex` on the kit's ancestors), never override the internal BEM classes (`.cometchat-*__header`/`__item-*`/`__list` — customize via `--cometchat-*` vars + view slots, #7), and give the mount container an explicit height so `.cometchat-conversations__root { height:100% }` resolves (#8).
13. **Never render a raw localization key as a label** — the kit localizes via `CometChatProvider`; a snake_case token in the UI (`group_info`, `add_members`) is a missing/wrong key or a literal-key render. Use the kit component or `useLocale().getLocalizedString(key)`. See `i18n-rtl-a11y.md`.
14. **Don't `import { CometChat }` just for types** — the SDK namespace is an **ambient global**, so `CometChat.User`/`CometChat.Group`/`CometChat.BaseMessage` resolve as types with NO import. A value import used only in type positions fails the Vite React-TS template's strict config (`noUnusedLocals` + `verbatimModuleSyntax`) with `TS6133: 'CometChat' is declared but its value is never read` — and `import type { CometChat }` does **not** fix it (the type comes from the global, not the import). **Rule:** import `CometChat` **only** when you use it as a value (`msg instanceof CometChat.User`, `CometChat.CometChatHelper.getConversationFromMessage(...)`, `new CometChat.GroupMembersRequestBuilder(...)`); for type-only usage, drop the import and use the ambient global. (AUDIT-007.)
15. **Full-page chat: clear the scaffold boilerplate CSS (the #2 "UI looks broken" defect).** A fresh Vite/CRA/Next app ships template CSS that **centers, width-caps, and pads the root** — Vite's `#root { max-width:1280px; margin:0 auto; padding:2rem; text-align:center }` + `body { display:flex; place-items:center }` (CRA `App.css`, Next `globals.css` have analogues). Drop a `100dvh` chat surface into that and it renders as a **centered ~1280px padded box with big side gutters, message bubbles/overlays clipping off the edge** ("exceeding the viewport / broken"). **Fix:** before the chat CSS, reset it — `html, body, #root { height:100%; margin:0; padding:0 }` + `#root { max-width:none; text-align:left; display:block }` + remove `body{place-items:center}`; give `.cc-app` `overflow:hidden` and the message column `min-width:0; min-height:0; overflow:hidden`. (Verified reproduction: a capped/centered `#root` shoves chat into a ~729px gutter-boxed island; the reset makes it full-bleed. AUDIT-019.) This is invariant (a) of the reflow-free-surface standard — full rule + the load-transition-reflow mode: `layout.md`.
16. **Don't expect an OPAQUE kit sub-surface to inherit a wrapper's background — override the sub-surface's OWN CSS variable.** `.cometchat-message-list` paints an opaque `background: var(--cometchat-message-list-bg)` (default `--cometchat-background-color-03`), so a background set on a wrapping `div` is COVERED by the list and never shows — the list stays the same shade regardless of the wrapper. Canonical case: the **thread panel** — its header/composer paint their own opaque `--cometchat-background-color-01`, so the thread message list looks like the MAIN list (both `-03`) and different from its own header/composer, even after you give the thread wrapper a background. **Fix:** scope the surface's OWN token on the wrapper — `.cc-thread-panel { --cometchat-message-list-bg: var(--cometchat-background-color-01); }` (cascades into the list; matches the thread header/composer, differs from the main list's `-03`; verified vs 7.1.0). Generalizes to any opaque sub-surface: differentiate it by overriding ITS background variable, not the wrapper's, and never the internal `.cometchat-*` class (#7/#12). (AUDIT-020/024; depth: `cometchat-react-v7-customization`.)
17. **Don't write a per-theme override as `[data-theme="dark"] .cometchat { … }` — it matches nothing.** `CometChatProvider` renders ONE wrapper — `<div data-theme="light|dark" class="cometchat">` (verified vs 7.1.0: compiled bundle `jsx("div",{ "data-theme": internalTheme, className: "cometchat" })`) — and the kit defines its tokens on `:root, [data-theme=light]` / `[data-theme=dark]`. So `data-theme` and `.cometchat` are the SAME element; the descendant selector `[data-theme="dark"] .cometchat` looks for a `.cometchat` NESTED inside a `[data-theme]` ancestor, which doesn't exist → the rule silently no-ops (a correct-looking override that does nothing). **Fix:** for a per-theme BRAND token use the same-element selector `.cometchat[data-theme="dark"] { --cometchat-primary-color: … }` (or bare `[data-theme="dark"]`); to retint a kit INTERNAL per theme use `[data-theme="dark"] .cometchat-<bem> { … }` — the wrapper as ancestor, a BEM class as the descendant, which is exactly how the kit writes its own dark rules (e.g. `[data-theme=dark] .cometchat-tooltip`). Never target internal BEM for tokens (#7). (AUDIT-025; depth: `cometchat-react-v7-customization`.)
