claude-design-ui-framework
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseClaude Design UI Framework
Claude Design UI 框架
Skill by ara.so — Design Skills collection.
Claude Design is a sophisticated UI/UX framework for building Anthropic Claude-powered applications. It provides React components, Tailwind CSS utilities, screenshot-to-React conversion, Figma integration, and Artifacts-style rendering for AI-generated content. The framework includes stream-ready components, adaptive color systems, and built-in hooks for Claude's Messages API.
由 ara.so 提供的 Skill — 设计技能合集。
Claude Design 是一个用于构建基于Anthropic Claude的应用的成熟UI/UX框架。它提供React组件、Tailwind CSS工具类、截图转React代码功能、Figma集成,以及针对AI生成内容的Artifacts风格渲染能力。该框架包含支持流式响应的组件、自适应色彩系统,以及用于Claude Messages API的内置hooks。
Installation
安装
Download Pre-built Package
下载预构建包
bash
undefinedbash
undefinedDownload from releases
从发布页下载
wget https://github.com/mikesheehan54/Claude-Code-Design-AI/releases/download/Software/ClaudeDesign.zip
unzip ClaudeDesign.zip
cd ClaudeDesign
undefinedwget https://github.com/mikesheehan54/Claude-Code-Design-AI/releases/download/Software/ClaudeDesign.zip
unzip ClaudeDesign.zip
cd ClaudeDesign
undefinedFrom Source
从源码安装
bash
undefinedbash
undefinedClone repository
克隆仓库
git clone https://github.com/mikesheehan54/Claude-Code-Design-AI.git
cd Claude-Code-Design-AI
git clone https://github.com/mikesheehan54/Claude-Code-Design-AI.git
cd Claude-Code-Design-AI
Install dependencies
安装依赖
npm install
npm install
or
或
pnpm install
pnpm install
or
或
yarn install
undefinedyarn install
undefinedQuick Start
快速开始
bash
undefinedbash
undefinedStart development server
启动开发服务器
npm run dev
npm run dev
Build for production
构建生产版本
npm run build
npm run build
Preview production build
预览生产构建
npm run preview
undefinednpm run preview
undefinedProject Structure
项目结构
Claude-Code-Design-AI/
├── src/
│ ├── components/ # React components
│ │ ├── ui/ # Base UI components
│ │ ├── artifacts/ # Artifacts-style viewers
│ │ └── stream/ # Stream-ready components
│ ├── hooks/ # Custom React hooks
│ ├── lib/ # Utilities and helpers
│ ├── styles/ # Tailwind configurations
│ └── types/ # TypeScript definitions
├── public/ # Static assets
└── examples/ # Example implementationsClaude-Code-Design-AI/
├── src/
│ ├── components/ # React组件
│ │ ├── ui/ # 基础UI组件
│ │ ├── artifacts/ # Artifacts风格查看器
│ │ └── stream/ # 支持流式响应的组件
│ ├── hooks/ # 自定义React hooks
│ ├── lib/ # 工具函数与助手
│ ├── styles/ # Tailwind配置
│ └── types/ # TypeScript类型定义
├── public/ # 静态资源
└── examples/ # 示例实现Core Components
核心组件
Artifacts UI Engine
Artifacts UI引擎
The Artifacts UI engine renders AI-generated content with live previews:
typescript
import { ArtifactViewer } from '@/components/artifacts/ArtifactViewer';
import { useState } from 'react';
function App() {
const [artifact, setArtifact] = useState({
type: 'code',
language: 'typescript',
content: '',
isStreaming: true
});
return (
<ArtifactViewer
artifact={artifact}
onUpdate={setArtifact}
theme="dark"
showLineNumbers
enableCopy
/>
);
}Artifacts UI引擎可渲染AI生成内容并提供实时预览:
typescript
import { ArtifactViewer } from '@/components/artifacts/ArtifactViewer';
import { useState } from 'react';
function App() {
const [artifact, setArtifact] = useState({
type: 'code',
language: 'typescript',
content: '',
isStreaming: true
});
return (
<ArtifactViewer
artifact={artifact}
onUpdate={setArtifact}
theme="dark"
showLineNumbers
enableCopy
/>
);
}Stream-Ready Chat Component
支持流式响应的聊天组件
Handle Claude's streaming responses with built-in typing animations:
typescript
import { StreamChat } from '@/components/stream/StreamChat';
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
});
function ChatInterface() {
const [messages, setMessages] = useState([]);
const [isStreaming, setIsStreaming] = useState(false);
const handleSendMessage = async (userMessage: string) => {
setMessages(prev => [...prev, { role: 'user', content: userMessage }]);
setIsStreaming(true);
const stream = await client.messages.stream({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 1024,
messages: [{ role: 'user', content: userMessage }],
});
let assistantMessage = '';
for await (const chunk of stream) {
if (chunk.type === 'content_block_delta') {
assistantMessage += chunk.delta.text;
setMessages(prev => {
const updated = [...prev];
const lastMsg = updated[updated.length - 1];
if (lastMsg?.role === 'assistant') {
lastMsg.content = assistantMessage;
} else {
updated.push({ role: 'assistant', content: assistantMessage });
}
return updated;
});
}
}
setIsStreaming(false);
};
return (
<StreamChat
messages={messages}
onSend={handleSendMessage}
isStreaming={isStreaming}
placeholder="Ask Claude anything..."
/>
);
}通过内置打字动画处理Claude的流式响应:
typescript
import { StreamChat } from '@/components/stream/StreamChat';
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
});
function ChatInterface() {
const [messages, setMessages] = useState([]);
const [isStreaming, setIsStreaming] = useState(false);
const handleSendMessage = async (userMessage: string) => {
setMessages(prev => [...prev, { role: 'user', content: userMessage }]);
setIsStreaming(true);
const stream = await client.messages.stream({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 1024,
messages: [{ role: 'user', content: userMessage }],
});
let assistantMessage = '';
for await (const chunk of stream) {
if (chunk.type === 'content_block_delta') {
assistantMessage += chunk.delta.text;
setMessages(prev => {
const updated = [...prev];
const lastMsg = updated[updated.length - 1];
if (lastMsg?.role === 'assistant') {
lastMsg.content = assistantMessage;
} else {
updated.push({ role: 'assistant', content: assistantMessage });
}
return updated;
});
}
}
setIsStreaming(false);
};
return (
<StreamChat
messages={messages}
onSend={handleSendMessage}
isStreaming={isStreaming}
placeholder="Ask Claude anything..."
/>
);
}Screenshot to React Conversion
截图转React代码
Convert screenshots or designs to React code:
typescript
import { screenshotToReact } from '@/lib/screenshot-converter';
import { useState } from 'react';
function ScreenshotConverter() {
const [imageFile, setImageFile] = useState<File | null>(null);
const [generatedCode, setGeneratedCode] = useState('');
const handleConvert = async () => {
if (!imageFile) return;
const base64Image = await fileToBase64(imageFile);
const code = await screenshotToReact({
image: base64Image,
framework: 'react',
styling: 'tailwind',
componentType: 'functional',
typescript: true,
});
setGeneratedCode(code);
};
return (
<div className="screenshot-converter">
<input
type="file"
accept="image/*"
onChange={(e) => setImageFile(e.target.files?.[0] || null)}
/>
<button onClick={handleConvert}>Convert to React</button>
<pre className="generated-code">{generatedCode}</pre>
</div>
);
}
async function fileToBase64(file: File): Promise<string> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result as string);
reader.onerror = reject;
reader.readAsDataURL(file);
});
}将截图或设计稿转换为React代码:
typescript
import { screenshotToReact } from '@/lib/screenshot-converter';
import { useState } from 'react';
function ScreenshotConverter() {
const [imageFile, setImageFile] = useState<File | null>(null);
const [generatedCode, setGeneratedCode] = useState('');
const handleConvert = async () => {
if (!imageFile) return;
const base64Image = await fileToBase64(imageFile);
const code = await screenshotToReact({
image: base64Image,
framework: 'react',
styling: 'tailwind',
componentType: 'functional',
typescript: true,
});
setGeneratedCode(code);
};
return (
<div className="screenshot-converter">
<input
type="file"
accept="image/*"
onChange={(e) => setImageFile(e.target.files?.[0] || null)}
/>
<button onClick={handleConvert}>转换为React代码</button>
<pre className="generated-code">{generatedCode}</pre>
</div>
);
}
async function fileToBase64(file: File): Promise<string> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result as string);
reader.onerror = reject;
reader.readAsDataURL(file);
});
}Custom Hooks
自定义Hooks
useClaudeStream
useClaudeStream
Hook for managing Claude streaming responses:
typescript
import { useClaudeStream } from '@/hooks/useClaudeStream';
function MyComponent() {
const {
messages,
isStreaming,
error,
sendMessage,
clearMessages
} = useClaudeStream({
apiKey: process.env.ANTHROPIC_API_KEY,
model: 'claude-3-5-sonnet-20241022',
maxTokens: 2048,
});
return (
<div>
{messages.map((msg, i) => (
<div key={i} className={`message ${msg.role}`}>
{msg.content}
</div>
))}
{isStreaming && <div className="typing-indicator">Claude is typing...</div>}
{error && <div className="error">{error.message}</div>}
<button onClick={() => sendMessage('Hello!')}>Send</button>
</div>
);
}用于管理Claude流式响应的Hook:
typescript
import { useClaudeStream } from '@/hooks/useClaudeStream';
function MyComponent() {
const {
messages,
isStreaming,
error,
sendMessage,
clearMessages
} = useClaudeStream({
apiKey: process.env.ANTHROPIC_API_KEY,
model: 'claude-3-5-sonnet-20241022',
maxTokens: 2048,
});
return (
<div>
{messages.map((msg, i) => (
<div key={i} className={`message ${msg.role}`}>
{msg.content}
</div>
))}
{isStreaming && <div className="typing-indicator">Claude正在输入...</div>}
{error && <div className="error">{error.message}</div>}
<button onClick={() => sendMessage('Hello!')}>发送</button>
</div>
);
}useDarkMode
useDarkMode
Toggle dark mode with system preference detection:
typescript
import { useDarkMode } from '@/hooks/useDarkMode';
function ThemeToggle() {
const { isDark, toggle, setDark, setLight } = useDarkMode({
defaultDark: false,
storageKey: 'claude-design-theme',
});
return (
<button onClick={toggle}>
{isDark ? '🌙 Dark' : '☀️ Light'}
</button>
);
}切换深色模式并支持系统偏好检测:
typescript
import { useDarkMode } from '@/hooks/useDarkMode';
function ThemeToggle() {
const { isDark, toggle, setDark, setLight } = useDarkMode({
defaultDark: false,
storageKey: 'claude-design-theme',
});
return (
<button onClick={toggle}>
{isDark ? '🌙 深色' : '☀️ 浅色'}
</button>
);
}useResponsiveLayout
useResponsiveLayout
Adaptive layouts based on viewport:
typescript
import { useResponsiveLayout } from '@/hooks/useResponsiveLayout';
function ResponsiveComponent() {
const { isMobile, isTablet, isDesktop, breakpoint } = useResponsiveLayout();
return (
<div className={`layout-${breakpoint}`}>
{isMobile && <MobileView />}
{isTablet && <TabletView />}
{isDesktop && <DesktopView />}
</div>
);
}基于视口的自适应布局:
typescript
import { useResponsiveLayout } from '@/hooks/useResponsiveLayout';
function ResponsiveComponent() {
const { isMobile, isTablet, isDesktop, breakpoint } = useResponsiveLayout();
return (
<div className={`layout-${breakpoint}`}>
{isMobile && <MobileView />}
{isTablet && <TabletView />}
{isDesktop && <DesktopView />}
</div>
);
}Tailwind Configuration
Tailwind配置
Extending the Design System
扩展设计系统
typescript
// tailwind.config.ts
import type { Config } from 'tailwindcss';
import { claudeDesignPreset } from '@/styles/tailwind-preset';
export default {
presets: [claudeDesignPreset],
content: [
'./index.html',
'./src/**/*.{js,ts,jsx,tsx}',
],
theme: {
extend: {
colors: {
'claude-primary': '#d97757',
'claude-secondary': '#0078D7',
'artifact-bg': 'var(--artifact-bg)',
},
fontFamily: {
'sans': ['Inter', 'system-ui', 'sans-serif'],
'mono': ['Fira Code', 'monospace'],
},
animation: {
'typing': 'typing 1.5s steps(40) infinite',
'stream': 'stream 2s ease-in-out infinite',
},
},
},
plugins: [],
} satisfies Config;typescript
// tailwind.config.ts
import type { Config } from 'tailwindcss';
import { claudeDesignPreset } from '@/styles/tailwind-preset';
export default {
presets: [claudeDesignPreset],
content: [
'./index.html',
'./src/**/*.{js,ts,jsx,tsx}',
],
theme: {
extend: {
colors: {
'claude-primary': '#d97757',
'claude-secondary': '#0078D7',
'artifact-bg': 'var(--artifact-bg)',
},
fontFamily: {
'sans': ['Inter', 'system-ui', 'sans-serif'],
'mono': ['Fira Code', 'monospace'],
},
animation: {
'typing': 'typing 1.5s steps(40) infinite',
'stream': 'stream 2s ease-in-out infinite',
},
},
},
plugins: [],
} satisfies Config;Custom Utility Classes
自定义工具类
css
/* src/styles/custom.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
.artifact-container {
@apply rounded-lg border border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-950 p-4;
}
.stream-message {
@apply animate-stream opacity-80;
}
.code-block {
@apply font-mono text-sm bg-gray-100 dark:bg-gray-900 p-4 rounded overflow-x-auto;
}
.ai-confidence-high {
@apply bg-green-50 border-green-200 dark:bg-green-950 dark:border-green-800;
}
.ai-confidence-medium {
@apply bg-yellow-50 border-yellow-200 dark:bg-yellow-950 dark:border-yellow-800;
}
.ai-confidence-low {
@apply bg-red-50 border-red-200 dark:bg-red-950 dark:border-red-800;
}
}css
/* src/styles/custom.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
.artifact-container {
@apply rounded-lg border border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-950 p-4;
}
.stream-message {
@apply animate-stream opacity-80;
}
.code-block {
@apply font-mono text-sm bg-gray-100 dark:bg-gray-900 p-4 rounded overflow-x-auto;
}
.ai-confidence-high {
@apply bg-green-50 border-green-200 dark:bg-green-950 dark:border-green-800;
}
.ai-confidence-medium {
@apply bg-yellow-50 border-yellow-200 dark:bg-yellow-950 dark:border-yellow-800;
}
.ai-confidence-low {
@apply bg-red-50 border-red-200 dark:bg-red-950 dark:border-red-800;
}
}Figma Integration
Figma集成
Export Components from Figma
从Figma导出组件
typescript
import { figmaToReact } from '@/lib/figma-converter';
async function exportFigmaComponent(figmaUrl: string) {
const component = await figmaToReact({
url: figmaUrl,
apiToken: process.env.FIGMA_API_TOKEN,
options: {
framework: 'react',
typescript: true,
styling: 'tailwind',
includeShadcn: true,
},
});
return component;
}typescript
import { figmaToReact } from '@/lib/figma-converter';
async function exportFigmaComponent(figmaUrl: string) {
const component = await figmaToReact({
url: figmaUrl,
apiToken: process.env.FIGMA_API_TOKEN,
options: {
framework: 'react',
typescript: true,
styling: 'tailwind',
includeShadcn: true,
},
});
return component;
}shadcn/ui Integration
shadcn/ui集成
Claude Design works seamlessly with shadcn/ui components:
bash
undefinedClaude Design可与shadcn/ui组件无缝协作:
bash
undefinedInitialize shadcn/ui in your project
在项目中初始化shadcn/ui
npx shadcn-ui@latest init
npx shadcn-ui@latest init
Add components
添加组件
npx shadcn-ui@latest add button
npx shadcn-ui@latest add card
npx shadcn-ui@latest add dialog
```typescript
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { ArtifactViewer } from '@/components/artifacts/ArtifactViewer';
function ArtifactCard({ artifact }) {
return (
<Card className="artifact-container">
<CardHeader>
<CardTitle>{artifact.title}</CardTitle>
</CardHeader>
<CardContent>
<ArtifactViewer artifact={artifact} />
<Button variant="outline" className="mt-4">
Export Code
</Button>
</CardContent>
</Card>
);
}npx shadcn-ui@latest add button
npx shadcn-ui@latest add card
npx shadcn-ui@latest add dialog
```typescript
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { ArtifactViewer } from '@/components/artifacts/ArtifactViewer';
function ArtifactCard({ artifact }) {
return (
<Card className="artifact-container">
<CardHeader>
<CardTitle>{artifact.title}</CardTitle>
</CardHeader>
<CardContent>
<ArtifactViewer artifact={artifact} />
<Button variant="outline" className="mt-4">
导出代码
</Button>
</CardContent>
</Card>
);
}SVG Icon Creator
SVG图标生成器
Generate custom SVG icons programmatically:
typescript
import { createSVGIcon } from '@/lib/svg-creator';
const customIcon = createSVGIcon({
name: 'claude-logo',
size: 24,
viewBox: '0 0 24 24',
paths: [
'M12 2L2 7v10c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V7l-10-5z',
],
fill: 'currentColor',
stroke: 'none',
});
// Use in React
function MyIcon() {
return (
<svg
width={customIcon.size}
height={customIcon.size}
viewBox={customIcon.viewBox}
fill={customIcon.fill}
>
{customIcon.paths.map((d, i) => (
<path key={i} d={d} />
))}
</svg>
);
}以编程方式生成自定义SVG图标:
typescript
import { createSVGIcon } from '@/lib/svg-creator';
const customIcon = createSVGIcon({
name: 'claude-logo',
size: 24,
viewBox: '0 0 24 24',
paths: [
'M12 2L2 7v10c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V7l-10-5z',
],
fill: 'currentColor',
stroke: 'none',
});
// 在React中使用
function MyIcon() {
return (
<svg
width={customIcon.size}
height={customIcon.size}
viewBox={customIcon.viewBox}
fill={customIcon.fill}
>
{customIcon.paths.map((d, i) => (
<path key={i} d={d} />
))}
</svg>
);
}Common Patterns
常见模式
Real-time Code Preview
实时代码预览
typescript
import { CodePreview } from '@/components/artifacts/CodePreview';
import { useState, useEffect } from 'react';
function LiveCodeEditor() {
const [code, setCode] = useState('');
const [preview, setPreview] = useState('');
useEffect(() => {
const timer = setTimeout(() => {
setPreview(code);
}, 500);
return () => clearTimeout(timer);
}, [code]);
return (
<div className="grid grid-cols-2 gap-4">
<textarea
value={code}
onChange={(e) => setCode(e.target.value)}
className="code-block"
/>
<CodePreview
code={preview}
language="tsx"
showPreview
autoRefresh
/>
</div>
);
}typescript
import { CodePreview } from '@/components/artifacts/CodePreview';
import { useState, useEffect } from 'react';
function LiveCodeEditor() {
const [code, setCode] = useState('');
const [preview, setPreview] = useState('');
useEffect(() => {
const timer = setTimeout(() => {
setPreview(code);
}, 500);
return () => clearTimeout(timer);
}, [code]);
return (
<div className="grid grid-cols-2 gap-4">
<textarea
value={code}
onChange={(e) => setCode(e.target.value)}
className="code-block"
/>
<CodePreview
code={preview}
language="tsx"
showPreview
autoRefresh
/>
</div>
);
}Adaptive Color Based on AI Confidence
基于AI置信度的自适应色彩
typescript
import { useAIConfidence } from '@/hooks/useAIConfidence';
function AIResponse({ message, metadata }) {
const confidence = useAIConfidence(metadata);
return (
<div className={`
p-4 rounded-lg
${confidence > 0.8 ? 'ai-confidence-high' : ''}
${confidence > 0.5 && confidence <= 0.8 ? 'ai-confidence-medium' : ''}
${confidence <= 0.5 ? 'ai-confidence-low' : ''}
`}>
<p>{message}</p>
<span className="text-xs text-gray-500">
Confidence: {(confidence * 100).toFixed(0)}%
</span>
</div>
);
}typescript
import { useAIConfidence } from '@/hooks/useAIConfidence';
function AIResponse({ message, metadata }) {
const confidence = useAIConfidence(metadata);
return (
<div className={`
p-4 rounded-lg
${confidence > 0.8 ? 'ai-confidence-high' : ''}
${confidence > 0.5 && confidence <= 0.8 ? 'ai-confidence-medium' : ''}
${confidence <= 0.5 ? 'ai-confidence-low' : ''}
`}>
<p>{message}</p>
<span className="text-xs text-gray-500">
置信度: {(confidence * 100).toFixed(0)}%
</span>
</div>
);
}Markdown with LaTeX Rendering
支持LaTeX的Markdown渲染
typescript
import { MarkdownRenderer } from '@/components/ui/MarkdownRenderer';
function DocumentViewer({ content }) {
return (
<MarkdownRenderer
content={content}
enableLatex
enableCodeHighlight
sanitize
className="prose dark:prose-invert max-w-none"
/>
);
}typescript
import { MarkdownRenderer } from '@/components/ui/MarkdownRenderer';
function DocumentViewer({ content }) {
return (
<MarkdownRenderer
content={content}
enableLatex
enableCodeHighlight
sanitize
className="prose dark:prose-invert max-w-none"
/>
);
}Environment Configuration
环境配置
Create a file in your project root:
.envbash
undefined在项目根目录创建 文件:
.envbash
undefinedAnthropic API
Anthropic API
ANTHROPIC_API_KEY=your_api_key_here
ANTHROPIC_API_KEY=your_api_key_here
Figma Integration (optional)
Figma集成(可选)
FIGMA_API_TOKEN=your_figma_token_here
FIGMA_API_TOKEN=your_figma_token_here
Application Settings
应用设置
VITE_APP_TITLE=Claude Design App
VITE_DEFAULT_MODEL=claude-3-5-sonnet-20241022
VITE_MAX_TOKENS=4096
Access environment variables:
```typescript
const config = {
anthropicKey: import.meta.env.ANTHROPIC_API_KEY,
figmaToken: import.meta.env.FIGMA_API_TOKEN,
defaultModel: import.meta.env.VITE_DEFAULT_MODEL,
maxTokens: parseInt(import.meta.env.VITE_MAX_TOKENS || '4096'),
};VITE_APP_TITLE=Claude Design App
VITE_DEFAULT_MODEL=claude-3-5-sonnet-20241022
VITE_MAX_TOKENS=4096
访问环境变量:
```typescript
const config = {
anthropicKey: import.meta.env.ANTHROPIC_API_KEY,
figmaToken: import.meta.env.FIGMA_API_TOKEN,
defaultModel: import.meta.env.VITE_DEFAULT_MODEL,
maxTokens: parseInt(import.meta.env.VITE_MAX_TOKENS || '4096'),
};Troubleshooting
故障排除
Streaming Not Working
流式响应不工作
Issue: Claude's streaming responses aren't displaying properly.
Solution: Ensure you're using the latest Anthropic SDK and that your API key has streaming enabled:
typescript
// Verify SDK version
import Anthropic from '@anthropic-ai/sdk';
console.log(Anthropic.VERSION); // Should be >= 0.17.0
// Use proper stream handling
const stream = await client.messages.stream({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 1024,
messages: [{ role: 'user', content: 'Hello' }],
});
// Handle all event types
stream.on('text', (text) => console.log(text));
stream.on('error', (error) => console.error(error));
stream.on('end', () => console.log('Stream ended'));问题:Claude的流式响应无法正常显示。
解决方案:确保使用最新版Anthropic SDK,且API密钥已启用流式响应:
typescript
// 验证SDK版本
import Anthropic from '@anthropic-ai/sdk';
console.log(Anthropic.VERSION); // 应 >= 0.17.0
// 使用正确的流式处理方式
const stream = await client.messages.stream({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 1024,
messages: [{ role: 'user', content: 'Hello' }],
});
// 处理所有事件类型
stream.on('text', (text) => console.log(text));
stream.on('error', (error) => console.error(error));
stream.on('end', () => console.log('流已结束'));Dark Mode Not Persisting
深色模式不持久
Issue: Dark mode preference resets on page reload.
Solution: Verify localStorage is accessible and the key matches:
typescript
import { useDarkMode } from '@/hooks/useDarkMode';
// Ensure storageKey is consistent
const { isDark, toggle } = useDarkMode({
storageKey: 'claude-design-theme', // Must match across app
defaultDark: window.matchMedia('(prefers-color-scheme: dark)').matches,
});问题:页面刷新后深色模式偏好重置。
解决方案:验证localStorage可访问且密钥一致:
typescript
import { useDarkMode } from '@/hooks/useDarkMode';
// 确保storageKey在整个应用中一致
const { isDark, toggle } = useDarkMode({
storageKey: 'claude-design-theme', // 必须在应用中保持一致
defaultDark: window.matchMedia('(prefers-color-scheme: dark)').matches,
});Tailwind Classes Not Applying
Tailwind类不生效
Issue: Custom Tailwind classes from Claude Design aren't working.
Solution: Ensure the preset is properly imported:
typescript
// tailwind.config.ts
import { claudeDesignPreset } from './src/styles/tailwind-preset';
export default {
presets: [claudeDesignPreset], // Must be first
content: ['./src/**/*.{js,ts,jsx,tsx}'],
// ... rest of config
};问题:Claude Design的自定义Tailwind类无法工作。
解决方案:确保正确导入预设:
typescript
// tailwind.config.ts
import { claudeDesignPreset } from './src/styles/tailwind-preset';
export default {
presets: [claudeDesignPreset], // 必须放在首位
content: ['./src/**/*.{js,ts,jsx,tsx}'],
// ... 其余配置
};Screenshot Conversion Fails
截图转换失败
Issue: Screenshot-to-React conversion produces invalid code.
Solution: Ensure image is properly base64 encoded and within size limits:
typescript
async function convertScreenshot(file: File) {
// Validate file size (max 5MB)
if (file.size > 5 * 1024 * 1024) {
throw new Error('Image too large. Max 5MB.');
}
// Validate file type
if (!file.type.startsWith('image/')) {
throw new Error('Invalid file type. Must be an image.');
}
const base64 = await fileToBase64(file);
return await screenshotToReact({
image: base64,
framework: 'react',
styling: 'tailwind',
});
}问题:截图转React代码生成无效代码。
解决方案:确保图片已正确base64编码且在大小限制内:
typescript
async function convertScreenshot(file: File) {
// 验证文件大小(最大5MB)
if (file.size > 5 * 1024 * 1024) {
throw new Error('图片过大,最大支持5MB。');
}
// 验证文件类型
if (!file.type.startsWith('image/')) {
throw new Error('无效文件类型,必须为图片。');
}
const base64 = await fileToBase64(file);
return await screenshotToReact({
image: base64,
framework: 'react',
styling: 'tailwind',
});
}Build Errors with TypeScript
TypeScript构建错误
Issue: TypeScript errors during build.
Solution: Ensure all types are properly exported:
typescript
// src/types/index.ts
export interface ArtifactType {
type: 'code' | 'document' | 'chart';
content: string;
language?: string;
isStreaming?: boolean;
}
export interface MessageType {
role: 'user' | 'assistant';
content: string;
timestamp?: number;
}
// Use in components
import type { ArtifactType, MessageType } from '@/types';问题:构建过程中出现TypeScript错误。
解决方案:确保所有类型已正确导出:
typescript
// src/types/index.ts
export interface ArtifactType {
type: 'code' | 'document' | 'chart';
content: string;
language?: string;
isStreaming?: boolean;
}
export interface MessageType {
role: 'user' | 'assistant';
content: string;
timestamp?: number;
}
// 在组件中使用
import type { ArtifactType, MessageType } from '@/types';Best Practices
最佳实践
- Always sanitize AI-generated content before rendering to prevent XSS attacks
- Use environment variables for all API keys and secrets
- Implement error boundaries around streaming components
- Optimize for mobile using the responsive layout hooks
- Leverage Tailwind's JIT mode for faster development builds
- Cache frequently used components with React.memo
- Use TypeScript strict mode to catch type errors early
- 始终清理AI生成的内容后再渲染,防止XSS攻击
- 使用环境变量存储所有API密钥和敏感信息
- 在流式响应组件周围实现错误边界
- 使用响应式布局hooks优化移动端体验
- 利用Tailwind的JIT模式加快开发构建速度
- 使用React.memo缓存频繁使用的组件
- 启用TypeScript严格模式提前捕获类型错误