关于 stitch-react-components
这项技能可将 Stitch 设计、本地 HTML 或网址转换为适用于 Vite 和普通 React 项目的模块化组件,并指导设计令牌提取、主题处理和组件组织;不适用于 Next.js。
主要功能
- 01将 HTML 设计转换为 React 组件
- 02支持 Stitch、本地文件和网址来源
- 03提取设计令牌并支持深色模式
- 04组织组件、数据和共享类型
- 05提供 HTML 下载脚本
适用场景
- 01在 Vite React 应用中重建 Stitch 屏幕
- 02将本地 HTML 设计转换为 React 组件
- 03将网页设计移植到普通 React 项目
MCP 相关
输入来自 Stitch 屏幕时,技能会通过 Stitch MCP 查找相关工具并获取屏幕元数据;其他 HTML 来源无需 Stitch MCP。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ gabelul/ stitch-kit --skill stitch-react-components安装后在 Claude Code 中输入/stitch-react-components确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/tailwind-to-react.mdresources/architecture-checklist.mdcomponent-template.tsxscripts/fetch-stitch.sh详细介绍
Stitch → Vite / React 组件
限制: 仅当用户明确提到“Stitch”和 React(Vite、CRA,或未提及 Next.js 的“React app”)时,才使用此技能。
你是一名前端工程师,负责将 Stitch 移动端/桌面端设计转换为简洁、模块化的 React 组件,使用 Vite + TypeScript。此技能适用于纯 React 应用,不适用于 Next.js App Router。对于 Next.js,请改用 stitch-nextjs-components。
何时使用此技能,何时使用 Next.js
| 场景 | 使用 |
|---|---|
| 用户说“React app”、“Vite”、“CRA” | stitch-react-components |
| 用户说“Next.js”、“App Router”、“SSR” | stitch-nextjs-components |
| 用户希望之后添加 shadcn/ui 组件 | stitch-react-components → 然后使用 stitch-shadcn-ui |
| 用户需要服务端渲染或基于文件的路由 | stitch-nextjs-components |
前提条件
HTML 源文件。以下任意一种都可以:
- 一个 Stitch 屏幕 — 需要访问 Stitch MCP 并生成屏幕
- 一个 本地 HTML 文件 — 无需 Stitch 账号
- 一个 URL — 无需 Stitch 账号
另外还需要:
- Node.js + npm/pnpm
- 已初始化的 Vite + React 项目:
npm create vite@latest my-app -- --template react-ts
步骤 1:解析来源
后续所有步骤都读取同一个文件:temp/source.html。根据用户提供的来源,选择对应方式获取 HTML 并保存到该文件,然后继续步骤 2——无论标记来自哪里,此技能的其余部分都相同。
来自 Stitch 屏幕:
- 发现命名空间 — 使用
list_tools查找 Stitch MCP 前缀 - 获取元数据 — 使用
[prefix]:get_screen,并提供数字格式的projectId和screenId - 下载 HTML — GCS URL 需要使用可靠的下载器:
bash scripts/fetch-stitch.sh "[htmlCode.downloadUrl]" "temp/source.html" - 视觉检查 — 改写前检查
screenshot.downloadUrl。在该 URL 后附加=s0可获取完整分辨率;无论 API 报告的width/height是多少,原始 URL 都只提供 512px 缩略图。
来自本地 HTML 文件:
mkdir -p temp && cp "path/to/design.html" temp/source.html
来自 URL:
bash scripts/fetch-stitch.sh "https://example.com/page" "temp/source.html"
尽管名称如此,该脚本是通用的加固型下载器:它会跟随重定向、重试暂时性故障、处理 gzip,并在结果为空时明确报错。它不关心 URL 是否指向 Stitch。
**来自屏幕截图:**没有上传途径——Stitch MCP API 没有图像上传工具。可以通过 stitch-mcp-generate-screen-from-text 根据文本提示词重建设计,也可以手动编写 HTML,然后使用上面的本地文件方式。
只有 Stitch 方式需要 API 密钥。转换本地文件或 URL 完全不需要 Google 账号。
步骤 2:项目结构
src/
├── components/ ← One file per component
│ └── [Name].tsx
├── data/
│ └── mockData.ts ← Static content (never in components)
├── theme/
│ ├── tokens.ts ← Design token constants
│ └── useTheme.ts ← Dark mode hook
├── types/
│ └── index.ts ← Shared TypeScript types
├── App.tsx ← Root component
└── main.tsx ← Entry point
步骤 3:提取设计令牌
按以下顺序,从 HTML 实际提供的内容中解析令牌:
<head>中的内联tailwind.config(Stitch 输出的内容)——如果存在,直接使用。- CSS 自定义属性(
:root { --color-primary: ... })——手写和模板化 HTML 中很常见。 - 外链或内联样式表——解析声明的颜色、字体系列、圆角和间距。
- 最后手段——根据标记中出现频率最高的计算值推导令牌(主导背景色、文字颜色、强调色、标题/正文使用的字体、边框圆角),并告知用户你的推断,以便他们纠正。
URL 方式只会下载单个 HTML 响应——外链样式表可能不会一并获取。如果上述方式都无法解析某个令牌,请如实说明,不要凭空编造配色方案。
// src/theme/tokens.ts
export const lightTokens = {
background: '#FFFFFF',
surface: '#F4F4F5',
primary: '#6366F1',
primaryFg: '#FFFFFF',
text: '#09090B',
textMuted: '#71717A',
border: '#E4E4E7',
} as const
export const darkTokens = {
background: '#09090B',
surface: '#18181B',
primary: '#818CF8',
primaryFg: '#09090B',
text: '#FAFAFA',
textMuted: '#A1A1AA',
border: '#27272A',
} as const
export type ThemeTokens = typeof lightTokens
// src/theme/useTheme.ts
import { useEffect, useState } from 'react'
import { lightTokens, darkTokens, type ThemeTokens } from './tokens'
/**
* Returns current theme tokens based on system color scheme.
* Listens for system-level dark/light mode changes.
*/
export function useTheme(): ThemeTokens {
const [isDark, setIsDark] = useState(
() => window.matchMedia('(prefers-color-scheme: dark)').matches
)
useEffect(() => {
const mq = window.matchMedia('(prefers-color-scheme: dark)')
const handler = (e: MediaQueryListEvent) => setIsDark(e.matches)
mq.addEventListener('change', handler)
return () => mq.removeEventListener('change', handler)
}, [])
return isDark ? darkTokens : lightTokens
}
步骤 4:组件转换规则
布局映射
| HTML/CSS | → React / Tailwind |
|---|---|
display:flex; flex-direction:column | <div className="flex flex-col gap-4"> |
display:flex; flex-direction:row | <div className="flex items-center gap-2"> |
justify-content:space-between | <div className="flex justify-between"> |
display:grid; grid-template-columns:1fr 1fr | <div className="grid grid-cols-2 gap-4"> |
overflow-y:scroll | <div className="overflow-y-auto"> |
| 长列表 | items.map(item => <Card key={item.id} {...item} />) |
<img> | <img src="..." alt="..." className="object-cover"> |
Tailwind 类映射
如果源 HTML 中的 Tailwind 类未引用自定义 token,请直接在 JSX 中使用。将自定义 token 映射为 CSS 变量:
// Source HTML: bg-primary → CSS variable → Tailwind arbitrary value
// OR: use inline style with token value
// Option A — Tailwind arbitrary value (if custom tokens in tailwind.config)
<div className="bg-[--color-primary] text-[--color-primaryFg]">
// Option B — inline style with useTheme()
const theme = useTheme()
<div style={{ backgroundColor: theme.primary, color: theme.primaryFg }}>
组件模板
// src/components/StitchComponent.tsx
/**
* Props for StitchComponent — all data via props, never fetched inside.
*/
interface StitchComponentProps {
/** Primary heading text */
title: string
/** Supporting description — optional */
description?: string
/** Primary action callback */
onAction?: () => void
}
/**
* StitchComponent — [describe purpose in one sentence]
*/
export function StitchComponent({
title,
description,
onAction,
}: Readonly<StitchComponentProps>) {
const theme = useTheme()
return (
<div
className="rounded-xl border p-4 gap-2 flex flex-col"
style={{
backgroundColor: theme.surface,
borderColor: theme.border,
}}
>
<h3 className="text-base font-semibold" style={{ color: theme.text }}>
{title}
</h3>
{description ? (
<p className="text-sm" style={{ color: theme.textMuted }}>
{description}
</p>
) : null}
{onAction ? (
<button
onClick={onAction}
className="rounded-lg px-4 py-2 text-sm font-medium transition-opacity hover:opacity-90"
style={{ backgroundColor: theme.primary, color: theme.primaryFg }}
type="button"
>
Action
</button>
) : null}
</div>
)
}
步骤 5:架构规则
- 每个文件仅放置一个组件 — 避免单文件混乱
- 静态数据放在
src/data/mockData.ts中 — 不要在 JSX 中硬编码 - 共享类型放在
src/types/index.ts中 - 每个组件都要有
Readonly<ComponentNameProps>接口 - 不要硬编码十六进制颜色 — 使用
useTheme()或 CSS 变量 - 不要使用
any类型
步骤 6:与 shadcn/ui 集成
将设计转换为基础 React 组件后,可以进一步集成 shadcn/ui:
npx shadcn@latest init # Set up shadcn in your Vite project
npx shadcn@latest add button card input dialog
然后使用 stitch-shadcn-ui 技能,用 shadcn 组件替换原始 HTML 元素,同时保留设计 token。
故障排除
| 问题 | 解决方法 |
|---|---|
| Tailwind 类未生效 | 检查 tailwind.config.js 的 content 是否包含 ./src/**/*.{ts,tsx} |
| 暗色模式无法切换 | 确认在组件层级调用了 useTheme(),而不是将其提升到更高层级 |
| 图片未显示 | 添加明确的 width 和 height,或使用 className="w-full h-auto" |
| props 类型错误 | 确保使用 Readonly<> 包装,并提供所有必需的 props |
参考资料
resources/component-template.tsx— 组件样板resources/architecture-checklist.md— 发布前检查清单references/tailwind-to-react.md— token + 类映射指南(源 HTML → React/Tailwind)scripts/fetch-stitch.sh— 可靠的 GCS HTML 下载器stitch-shadcn-ui— 基础转换后添加 shadcn/ui 组件docs/tailwind-reference.md— Tailwind 实用类查询