Ai-design-components building-ai-chat
Builds AI chat interfaces and conversational UI with streaming responses, context management, and multi-modal support. Use when creating ChatGPT-style interfaces, AI assistants, code copilots, or conversational agents. Handles streaming text, token limits, regeneration, feedback loops, tool usage visualization, and AI-specific error patterns. Provides battle-tested components from leading AI products with accessibility and performance built in.
git clone https://github.com/ancoleman/ai-design-components
T=$(mktemp -d) && git clone --depth=1 https://github.com/ancoleman/ai-design-components "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/building-ai-chat" ~/.claude/skills/ancoleman-ai-design-components-building-ai-chat && rm -rf "$T"
skills/building-ai-chat/SKILL.mdAI Chat Interface Components
Purpose
Define the emerging standards for AI/human conversational interfaces in the 2024-2025 AI integration boom. This skill leverages meta-knowledge from building WITH Claude to establish definitive patterns for streaming UX, context management, and multi-modal interactions. As the industry lacks established patterns, this provides the reference implementation others will follow.
When to Use
Activate this skill when:
- Building ChatGPT-style conversational interfaces
- Creating AI assistants, copilots, or chatbots
- Implementing streaming text responses with markdown
- Managing conversation context and token limits
- Handling multi-modal inputs (text, images, files, voice)
- Dealing with AI-specific errors (hallucinations, refusals, limits)
- Adding feedback mechanisms (thumbs, regeneration, editing)
- Implementing conversation branching or threading
- Visualizing tool/function calling
Quick Start
Minimal AI chat interface in under 50 lines:
import { useChat } from 'ai/react'; export function MinimalAIChat() { const { messages, input, handleInputChange, handleSubmit, isLoading, stop } = useChat(); return ( <div className="chat-container"> <div className="messages"> {messages.map(m => ( <div key={m.id} className={`message ${m.role}`}> <div className="content">{m.content}</div> </div> ))} {isLoading && <div className="thinking">AI is thinking...</div>} </div> <form onSubmit={handleSubmit} className="input-form"> <input value={input} onChange={handleInputChange} placeholder="Ask anything..." disabled={isLoading} /> {isLoading ? ( <button type="button" onClick={stop}>Stop</button> ) : ( <button type="submit">Send</button> )} </form> </div> ); }
For complete implementation with streaming markdown, see
examples/basic-chat.tsx.
Core Components
Message Display
Build user, AI, and system message bubbles with streaming support:
// User message <div className="message user"> <div className="content">{message.content}</div> <time className="timestamp">{formatTime(message.timestamp)}</time> </div> // AI message with streaming <div className="message ai"> <Streamdown className="content">{message.content}</Streamdown> {message.isStreaming && <span className="cursor">▊</span>} </div> // System message <div className="message system"> <Icon type="info" /> <span>{message.content}</span> </div>
For markdown rendering, code blocks, and formatting details, see
references/message-components.md.
Input Components
Create rich input experiences with attachments and voice:
<div className="input-container"> <button onClick={attachFile} aria-label="Attach file"> <PaperclipIcon /> </button> <textarea value={input} onChange={handleChange} onKeyDown={handleKeyDown} placeholder="Type a message..." rows={1} style={{ height: textareaHeight }} /> <button onClick={toggleVoice} aria-label="Voice input"> <MicIcon /> </button> <button type="submit" disabled={!input.trim() || isLoading}> <SendIcon /> </button> </div>
Response Controls
Essential controls for AI responses:
<div className="response-controls"> {isStreaming && ( <button onClick={stop} className="stop-btn"> Stop generating </button> )} {!isStreaming && ( <> <button onClick={regenerate} aria-label="Regenerate response"> <RefreshIcon /> Regenerate </button> <button onClick={continueGeneration} aria-label="Continue"> Continue </button> <button onClick={editMessage} aria-label="Edit message"> <EditIcon /> Edit </button> </> )} </div>
Feedback Mechanisms
Collect user feedback to improve AI responses:
<div className="feedback-controls"> <button onClick={() => sendFeedback('positive')} aria-label="Good response" className={feedback === 'positive' ? 'selected' : ''} > <ThumbsUpIcon /> </button> <button onClick={() => sendFeedback('negative')} aria-label="Bad response" className={feedback === 'negative' ? 'selected' : ''} > <ThumbsDownIcon /> </button> <button onClick={copyToClipboard} aria-label="Copy"> <CopyIcon /> </button> <button onClick={share} aria-label="Share"> <ShareIcon /> </button> </div>
Streaming & Real-Time UX
Progressive rendering of AI responses requires special handling:
// Use Streamdown for AI streaming (handles incomplete markdown) import { Streamdown } from '@vercel/streamdown'; // Auto-scroll management useEffect(() => { if (shouldAutoScroll()) { messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); } }, [messages]); // Smart auto-scroll heuristic function shouldAutoScroll() { const threshold = 100; // px from bottom const isNearBottom = container.scrollHeight - container.scrollTop - container.clientHeight < threshold; const userNotReading = !hasUserScrolledUp && !isTextSelected; return isNearBottom && userNotReading; }
For complete streaming patterns, auto-scroll behavior, and stop generation, see
references/streaming-ux.md.
Context Management
Communicate token limits clearly to users:
// User-friendly token display function TokenIndicator({ used, total }) { const percentage = (used / total) * 100; const remaining = total - used; return ( <div className="token-indicator"> <div className="progress-bar"> <div className="progress-fill" style={{ width: `${percentage}%` }} /> </div> <span className="token-text"> {percentage > 80 ? `⚠️ About ${Math.floor(remaining / 250)} messages left` : `${Math.floor(remaining / 250)} pages of conversation remaining`} </span> </div> ); }
For summarization strategies, conversation branching, and organization, see
references/context-management.md.
Multi-Modal Support
Handle images, files, and voice inputs:
// Image upload with preview function ImageUpload({ onUpload }) { return ( <div className="upload-zone" onDrop={handleDrop} onDragOver={preventDefault} > <input type="file" accept="image/*" onChange={handleFileSelect} multiple hidden ref={fileInputRef} /> {previews.map(preview => ( <img key={preview.id} src={preview.url} alt="Upload preview" /> ))} </div> ); }
For complete multi-modal patterns including voice and screen sharing, see
references/multi-modal.md.
Error Handling
Handle AI-specific errors gracefully:
// Refusal handling if (response.type === 'refusal') { return ( <div className="error refusal"> <Icon type="info" /> <p>I cannot help with that request.</p> <details> <summary>Why?</summary> <p>{response.reason}</p> </details> <p>Try asking: {response.suggestion}</p> </div> ); } // Rate limit communication if (error.code === 'RATE_LIMIT') { return ( <div className="error rate-limit"> <p>Please wait {error.retryAfter} seconds</p> <CountdownTimer seconds={error.retryAfter} onComplete={retry} /> </div> ); }
For comprehensive error patterns, see
references/error-handling.md.
Tool Usage Visualization
Show when AI is using tools or functions:
function ToolUsage({ tool }) { return ( <div className="tool-usage"> <div className="tool-header"> <Icon type={tool.type} /> <span>{tool.name}</span> {tool.status === 'running' && <Spinner />} </div> {tool.status === 'complete' && ( <details> <summary>View details</summary> <pre>{JSON.stringify(tool.result, null, 2)}</pre> </details> )} </div> ); }
For function calling, code execution, and web search patterns, see
references/tool-usage.md.
Implementation Guide
Recommended Stack
Primary libraries (validated November 2025):
# Core AI chat functionality npm install ai @ai-sdk/react @ai-sdk/openai # Streaming markdown rendering npm install @vercel/streamdown # Syntax highlighting npm install react-syntax-highlighter # Security for LLM outputs npm install dompurify
Performance Optimization
Critical for smooth streaming:
// Memoize message rendering const MemoizedMessage = memo(Message, (prev, next) => prev.content === next.content && prev.isStreaming === next.isStreaming ); // Debounce streaming updates const debouncedUpdate = useMemo( () => debounce(updateMessage, 50), [] ); // Virtual scrolling for long conversations import { VariableSizeList } from 'react-window';
For detailed performance patterns, see
references/streaming-ux.md.
Security Considerations
Always sanitize AI outputs:
import DOMPurify from 'dompurify'; function SafeAIContent({ content }) { const sanitized = DOMPurify.sanitize(content, { ALLOWED_TAGS: ['p', 'br', 'strong', 'em', 'code', 'pre', 'blockquote', 'ul', 'ol', 'li'], ALLOWED_ATTR: ['class'] }); return <Streamdown>{sanitized}</Streamdown>; }
Accessibility
Ensure AI chat is usable by everyone:
// ARIA live regions for screen readers <div role="log" aria-live="polite" aria-relevant="additions"> {messages.map(msg => ( <article key={msg.id} role="article" aria-label={`${msg.role} message`}> {msg.content} </article> ))} </div> // Loading announcements <div role="status" aria-live="polite" className="sr-only"> {isLoading ? 'AI is responding' : ''} </div>
For complete accessibility patterns, see
references/accessibility.md.
Bundled Resources
Scripts (Token-Free Execution)
- Run
to parse incomplete markdown during streamingscripts/parse_stream.js - Run
to estimate token usage and context limitsscripts/calculate_tokens.py - Run
to format message history for exportscripts/format_messages.js
References (Progressive Disclosure)
- Complete streaming UX patternsreferences/streaming-patterns.md
- Token limits and conversation strategiesreferences/context-management.md
- Image, file, and voice handlingreferences/multimodal-input.md
- User feedback and RLHF patternsreferences/feedback-loops.md
- AI-specific error scenariosreferences/error-handling.md
- Visualizing function calls and tool usereferences/tool-usage.md
- Screen reader and keyboard supportreferences/accessibility-chat.md
- Detailed library documentationreferences/library-guide.md
- Streaming performance patternsreferences/performance-optimization.md
Examples
- Minimal ChatGPT-style interfaceexamples/basic-chat.tsx
- Advanced streaming with memoizationexamples/streaming-chat.tsx
- Images and file uploadsexamples/multimodal-chat.tsx
- IDE-style code copilotexamples/code-assistant.tsx
- Function calling visualizationexamples/tool-calling-chat.tsx
Assets
- Curated prompts for different use casesassets/system-prompts.json
- Pre-built message componentsassets/message-templates.json
- User-friendly error messagesassets/error-messages.json
- Light, dark, and high-contrast themesassets/themes.json
Design Token Integration
All visual styling uses the design-tokens system:
/* Message bubbles use design tokens */ .message.user { background: var(--message-user-bg, var(--color-primary)); color: var(--message-user-text, var(--color-white)); padding: var(--message-padding, var(--spacing-md)); border-radius: var(--message-border-radius, var(--radius-lg)); } .message.ai { background: var(--message-ai-bg, var(--color-gray-100)); color: var(--message-ai-text, var(--color-text-primary)); }
See
skills/design-tokens/ for complete theming system.
Key Innovations
This skill provides industry-first solutions for:
- Memoized streaming rendering - 10-50x performance improvement
- Intelligent auto-scroll - User activity-aware scrolling
- Token metaphors - User-friendly context communication
- Incomplete markdown handling - Graceful partial rendering
- RLHF patterns - Effective feedback collection
- Conversation branching - Non-linear conversation trees
- Multi-modal integration - Seamless file/image/voice handling
- Accessibility-first - Built-in screen reader support
Strategic Importance
This is THE most critical skill because:
- Perfect timing - Every app adding AI (2024-2025 boom)
- No standards exist - Opportunity to define patterns
- Meta-advantage - Building WITH Claude = intimate UX knowledge
- Unique challenges - Streaming, context, hallucinations all new
- Reference implementation - Can become the standard others follow
Master this skill to lead the AI interface revolution.