--- phase: 21-chat-foundation plan: 02 type: execute wave: 1 depends_on: [] files_modified: - ui/src/components/ChatMarkdownMessage.tsx - ui/src/components/ChatMarkdownMessage.test.tsx - ui/src/components/ChatInput.tsx - ui/src/components/ChatInput.test.tsx - ui/src/index.css autonomous: true requirements: - CHAT-02 - CHAT-03 - INPUT-01 - INPUT-07 - THEME-01 - THEME-02 must_haves: truths: - "Agent messages render with full markdown: code blocks with syntax highlighting, tables, lists, headings, links, inline images" - "Code blocks have a one-click copy button and a language label" - "Code block syntax highlighting colors match the active theme (Catppuccin Mocha, Tokyo Night, Catppuccin Latte)" - "Chat input auto-resizes from 1 line up to 6 lines then scrolls internally" - "Enter sends, Shift+Enter inserts newline, Escape clears input or closes panel" - "Chat interface respects the Nexus theme system via CSS variables" artifacts: - path: "ui/src/components/ChatMarkdownMessage.tsx" provides: "Markdown message renderer with syntax highlighting and copy button" contains: "rehypeHighlight" - path: "ui/src/components/ChatInput.tsx" provides: "Auto-resize textarea with keyboard shortcuts" contains: "onKeyDown" - path: "ui/src/components/ChatMarkdownMessage.test.tsx" provides: "Tests for markdown rendering, code block copy button" min_lines: 30 - path: "ui/src/components/ChatInput.test.tsx" provides: "Tests for keyboard shortcuts" min_lines: 30 key_links: - from: "ui/src/components/ChatMarkdownMessage.tsx" to: "ui/src/components/MarkdownBody.tsx" via: "extends MarkdownBody pattern with rehypeHighlight" pattern: "rehypeHighlight" - from: "ui/src/index.css" to: "highlight.js themes" via: "CSS overrides for .hljs per theme class" pattern: "\\.hljs" --- Build the two core presentational components for chat: the markdown message renderer (with syntax highlighting and copy button) and the auto-resize text input (with keyboard shortcuts). Also install rehype-highlight and add theme-aware highlight.js CSS. Purpose: These components are self-contained and have no dependency on the backend API. Building them in Wave 1 alongside Plan 01 maximizes parallelism. Output: Two tested React components ready to be composed into the ChatPanel in Plan 03. @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/phases/21-chat-foundation/21-RESEARCH.md @.planning/phases/21-chat-foundation/21-UI-SPEC.md From ui/src/components/MarkdownBody.tsx: ```typescript import Markdown, { type Components } from "react-markdown"; import remarkGfm from "remark-gfm"; import { useTheme, THEME_META } from "../context/ThemeContext"; interface MarkdownBodyProps { children: string; className?: string; resolveImageSrc?: (src: string) => string | null; } // Uses: {content} ``` From ui/src/context/ThemeContext.tsx: ```typescript export type Theme = "catppuccin-mocha" | "tokyo-night" | "catppuccin-latte"; export const THEME_META: Record; // Theme classes on : .dark (both dark themes), .theme-tokyo-night (tokyo-night only) // No class for catppuccin-mocha (it's the default dark), no class for catppuccin-latte (it's light) ``` From ui/src/components/ui/textarea.tsx (shadcn Textarea): ```typescript // Standard shadcn Textarea component, wraps