# Integrate chatcn as @xtablo/chat-ui Package

## Overview

Replace the chatscope chat UI library in xtablo-source with chatcn, integrated as a new shared workspace package `@xtablo/chat-ui`. This replaces the rendering layer only — the chat data layer (`useChat` hook, WebSocket, REST) is unchanged.

## Context

- **chatcn** is a React 19 / Tailwind CSS 4 chat component library with messages, composer, reactions, threads, typing indicators, 5 layouts, security utilities, and custom hooks.
- **xtablo-source** is a Turborepo monorepo with pnpm workspaces. Chat UI currently uses `@chatscope/chat-ui-kit-react` in a single component (`apps/main/src/components/ChatMessages.tsx`, 184 lines).
- The chat data layer (`useChat` hook with WebSocket + REST to the chat-worker service) is cleanly separated from the UI and stays unchanged.

## Approach

Copy-and-adapt: copy chatcn's chat component source files into a new `packages/chat-ui/` workspace package, adapting imports and theming to match xtablo's existing patterns.

## Package Structure

```
packages/chat-ui/
├── package.json              # @xtablo/chat-ui
├── tsconfig.json
└── src/
    ├── index.ts              # Barrel export
    ├── components/
    │   ├── chat.tsx          # Core: ChatProvider, ChatMessage, ChatMessages, ChatComposer, etc.
    │   ├── features.tsx      # ChatForwardDialog, ChatEditComposer, ChatSearch, etc.
    │   └── layouts.tsx       # FullMessenger, ChatWidget, InlineChat, ChatBoard, LiveChat, etc.
    ├── hooks.ts              # groupMessages, useAutoScroll, useAutoResize, useTypingIndicator, etc.
    ├── security.ts           # sanitizeUrl, validateFile, sanitizeFileName, etc.
    └── types.ts              # ChatUser, ChatMessageData, ChatConfig, MessageGroup, etc.
```

Source-only package (no build step), same pattern as `@xtablo/shared` and `@xtablo/ui`.

### package.json exports

```json
{
  "name": "@xtablo/chat-ui",
  "version": "0.0.1",
  "private": true,
  "exports": {
    ".": "./src/index.ts",
    "./components/*": "./src/components/*.tsx",
    "./hooks": "./src/hooks.ts",
    "./security": "./src/security.ts",
    "./types": "./src/types.ts"
  },
  "dependencies": {
    "@xtablo/shared": "workspace:*",
    "@xtablo/ui": "workspace:*"
  },
  "peerDependencies": {
    "react": "^19.0.0",
    "react-dom": "^19.0.0",
    "lucide-react": "*",
    "date-fns": "*"
  }
}
```

### tsconfig.json

Mirrors `packages/ui/tsconfig.json`: target ES2022, module ESNext, jsx react-jsx, strict true, moduleResolution bundler, declaration true.

## Dependencies

All dependencies are already present in the monorepo — no new packages to install:

| Dependency | Source |
|---|---|
| `@xtablo/shared` | Workspace (for `cn()` utility) |
| `@xtablo/ui` | Workspace (for Button, Dialog, Avatar primitives) |
| `lucide-react` | Already in monorepo |
| `date-fns` | Already in monorepo |
| `clsx` | Via `@xtablo/shared` |
| `tailwind-merge` | Via `@xtablo/shared` |

**Dropped:** `@base-ui/react` (only used in chatcn's scaffolding `button.tsx`, not in any chat component).

## Import Remapping

When copying chatcn source files into the package, apply these systematic import changes:

| chatcn import | @xtablo/chat-ui import |
|---|---|
| `import { cn } from "@/lib/utils"` | `import { cn } from "@xtablo/shared/lib/cn"` |
| `import { Button } from "@/components/ui/button"` | `import { Button } from "@xtablo/ui/components/button"` |
| Other `@/components/ui/*` imports (Dialog, Avatar, etc.) | Corresponding `@xtablo/ui/components/*` import |

## Theming

Strip chatcn's custom theming system entirely and remap to xtablo's existing Tailwind design tokens.

### What gets removed

- `ChatTheme` type (`"lunar" | "aurora" | "ember" | "midnight"`)
- `data-chat-theme` attribute on components
- `ChatProvider`'s theme prop
- All `var(--chat-*)` CSS custom property references
- chatcn's globals.css theme definitions (not copied)

### Token mapping

All `var(--chat-*)` references in component files are replaced with Tailwind utility classes:

| chatcn token | Tailwind class |
|---|---|
| `--chat-bg-app`, `--chat-bg-main` | `bg-background` |
| `--chat-bg-sidebar` | `bg-sidebar` |
| `--chat-bubble-outgoing` | `bg-primary` |
| `--chat-bubble-incoming` | `bg-muted` |
| `--chat-text-outgoing` | `text-primary-foreground` |
| `--chat-text-incoming` | `text-foreground` |
| `--chat-accent` | `bg-accent` / `text-accent-foreground` |
| `--chat-border` | `border-border` |
| `--chat-text-primary` | `text-foreground` |
| `--chat-text-secondary` | `text-muted-foreground` |

This ensures automatic light/dark mode support via xtablo's existing `.dark` class.

## Component Adaptation

### What stays unchanged

- All chatcn types (`ChatUser`, `ChatMessageData`, `ChatConfig`, `MessageGroup`, `MessageListItem`, `TypingUser`)
- All hooks (`groupMessages`, `useAutoScroll`, `useAutoResize`, `useTypingIndicator`, `formatTimestamp`, `formatDateLabel`)
- All security utilities (`sanitizeUrl`, `validateFile`, `sanitizeFileName`, etc.)
- All component props and APIs

### What changes

- Imports remapped (see above)
- Theme references replaced with Tailwind classes (see above)
- `ChatTheme` type removed from `types.ts`
- Theme prop removed from `ChatProvider`

## Replacing ChatMessages.tsx

The current `apps/main/src/components/ChatMessages.tsx` is rewritten to use `@xtablo/chat-ui`.

### Data transformation

The app-level component transforms xtablo's data model to chatcn's types:

| Current (xtablo) | chatcn equivalent |
|---|---|
| `ChatMessage.userId` + `Member.name` | `ChatMessageData.senderId` + `senderName` |
| `ChatMessage.text` | `ChatMessageData.text` |
| `ChatMessage.createdAt` (ISO string) | `ChatMessageData.timestamp` (Date) |
| `ChatMessage.optimistic` | `ChatMessageData.status: "sending"` |
| `Member.avatar_url` | `ChatUser.avatar` / `ChatMessageData.senderAvatar` |
| `typingUsers: string[]` | `TypingUser[]` (with id + name resolved from members) |

### New component structure

```tsx
<ChatProvider config={{ currentUser, ... }}>
  <ChatMessages items={messageListItems} onLoadMore={onLoadMore} />
  <ChatComposer onSend={onSend} onChange={onTyping} placeholder={t("chat.placeholder")} />
</ChatProvider>
```

### Localization

The package stays i18n-agnostic. French strings currently hardcoded in `ChatMessages.tsx` ("Aujourd'hui", "Hier", "écrit...") are handled at the app level:
- Date labels: override chatcn's `formatDateLabel` with a custom function using i18next
- Typing indicator text: pass translated string as a prop
- Placeholder text: pass via `ChatComposer` placeholder prop

## Cleanup

After the integration:
- Remove `@chatscope/chat-ui-kit-react` from `apps/main/package.json`
- Remove `@chatscope/chat-ui-kit-styles` from `apps/main/package.json`
- Remove the chatscope CSS import from `ChatMessages.tsx`
- Add `@xtablo/chat-ui` to `apps/main/package.json` as a workspace dependency

## Out of Scope

- **Mobile app:** `xtablo-expo` uses `stream-chat-expo` — unchanged
- **Chat data layer:** `useChat` hook, WebSocket connections, chat-worker service — unchanged
- **ChatChannelPreview and ChatHeader:** Already pure Tailwind, no chatscope — unchanged
- **TabloDiscussionSection:** Consumes `ChatMessages` with the same props interface — unchanged
- **New feature adoption:** Reactions, threads, search, pinned messages, etc. are available in the package but not wired up. Future work.
- **Stream Chat CSS:** `.str-chat` overrides in `main.css` — unrelated, unchanged
