mcpField
S
stitch-html-components

stitch-html-components

github.com/gabelul开发4745 次安装14 周前更新
代码仓库

关于 stitch-html-components

将 Stitch 设计、本地 HTML 或 URL 转换为语义化 HTML5 和 CSS,无需框架或构建步骤。适用于跨平台页面、静态站点和移动 WebView,并采用移动优先样式及精简 JavaScript。

主要功能

  1. 01将 HTML 来源转为语义化 HTML5 和 CSS
  2. 02支持 Stitch、本地文件和 URL
  3. 03生成明暗模式 CSS 变量
  4. 04采用移动优先响应式样式
  5. 05将 JavaScript 限于基础交互

适用场景

  1. 01创建无框架的静态页面
  2. 02为移动 WebView 准备 HTML
  3. 03在选择框架前搭建原型

MCP 相关

处理 Stitch 来源时,技能会使用 Stitch MCP 工具发现工具命名空间并获取屏幕元数据,然后下载 HTML。本地文件和 URL 不需要 Stitch MCP。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/gabelul/stitch-kit --skill stitch-html-components

安装后在 Claude Code 中输入/stitch-html-components确认已加载。

附带文件resources/architecture-checklist.mdscripts/fetch-stitch.sh

详细介绍

Stitch → HTML5 + CSS(平台无关)

你是一名专注于简洁、无依赖 HTML 和 CSS 的前端工程师。你可以将 HTML 源文件——Stitch 屏幕、本地文件或 URL——转换为带有 CSS 自定义属性的语义化 HTML5,无需 React、无需 Svelte,也无需构建步骤。输出可在任何环境中运行:桌面浏览器、移动浏览器、iOS WebView、Android WebView、Capacitor 应用和 Ionic 容器。

何时使用此技能

在以下情况下使用此技能:

  • 用户需要平台无关的输出,例如“只要 HTML”“不要框架”“到处都能运行”
  • 目标是在移动应用中使用 WebView(Capacitor、Ionic、Cordova)
  • 构建静态网站或嵌入 CMS
  • 用户尚未选择框架,想先做一个可运行的原型
  • 在使用 Capacitor 封装为原生移动应用之前,先生成 HTML 基础结构

前提条件

一个 HTML 源文件。以下任意一种都可以:

  • 一个 Stitch 屏幕——需要访问 Stitch MCP,并且已有生成的屏幕
  • 一个 本地 HTML 文件——无需 Stitch 账号
  • 一个 URL——无需 Stitch 账号

步骤 1:确定源文件

后续所有步骤都会读取同一个文件:temp/source.html。根据用户提供的内容,选择相应方式将 HTML 放到该文件中,然后继续执行步骤 2——无论标记来自哪里,本技能的其余部分都相同。

来自 Stitch 屏幕:

  1. 发现命名空间——使用 list_tools 查找 Stitch MCP 前缀
  2. 获取元数据——使用 [prefix]:get_screen 获取设计 JSON
  3. 下载 HTML——GCS URL 需要使用可靠的下载器:
    bash scripts/fetch-stitch.sh "[htmlCode.downloadUrl]" "temp/source.html"
    
  4. 视觉审查——改写前检查 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:文件结构

output/
├── index.html           ← Main page (or rename per screen)
├── css/
│   ├── tokens.css       ← CSS custom properties (light + dark)
│   ├── base.css         ← Reset, body defaults, typography
│   └── components.css   ← Component styles
├── js/
│   └── main.js          ← Minimal JS (theme toggle, mobile menu only)
└── assets/
    └── images/

对于多屏幕项目,每个屏幕都使用单独的 HTML 文件。共享 CSS 放在 tokens.css 和 base.css 中。

步骤 3:CSS 自定义属性

将源文件中的颜色映射为语义化令牌。始终同时生成浅色和深色主题。按以下顺序解析十六进制值:

  1. <head> 中的内联 tailwind.config(Stitch 生成的内容)——如果存在,直接使用。
  2. 源文件中已有的 CSS 自定义属性(:root { --color-primary: ... })——手写和模板化 HTML 中很常见。
  3. 外链或内联样式表——解析声明的颜色、字体系列、圆角和间距。
  4. 最后的办法——根据标记中出现频率最高的计算值推导令牌(主要背景色、文字颜色、强调色、标题/正文字体、圆角),并告知用户你的推断,以便他们进行修正。

URL 方式只会下载单个 HTML 响应——外链样式表可能不会一并下载。如果以上方式都无法确定某个令牌,请如实说明,不要自行编造配色方案。

/* css/tokens.css */

:root {
  --color-background: [hex];
  --color-surface: [hex];
  --color-primary: [hex];
  --color-primary-fg: [hex];
  --color-text: [hex];
  --color-text-muted: [hex];
  --color-border: [hex];

  --font-sans: [font-stack];
  --font-mono: ui-monospace, monospace;

  --radius-sm: [value];
  --radius-md: [value];
  --radius-lg: [value];

  --shadow-sm: 0 1px 3px rgb(0 0 0 / 0.1);
  --shadow-md: 0 4px 12px rgb(0 0 0 / 0.1);

  --transition: 150ms cubic-bezier(0.4, 0, 0.2, 1);
}

/* Dark mode — system preference */
@media (prefers-color-scheme: dark) {
  :root {
    --color-background: [dark-hex];
    --color-surface: [dark-hex];
    --color-primary: [dark-adjusted-hex];
    --color-primary-fg: [dark-hex];
    --color-text: [dark-hex];
    --color-text-muted: [dark-hex];
    --color-border: [dark-hex];
  }
}

/* Dark mode — manual toggle via data-theme="dark" on <html> */
[data-theme="dark"] {
  --color-background: [dark-hex];
  --color-surface: [dark-hex];
  /* ... same values as above */
}

如果项目已有 design-tokens.css(来自 stitch-design-system),请导入它,而不是重新创建令牌。

步骤 4:基础 CSS

/* css/base.css */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html {
  font-size: 16px;
  /* Safe area insets for notched phones */
  padding: env(safe-area-inset-top) env(safe-area-inset-right)
           env(safe-area-inset-bottom) env(safe-area-inset-left);
  -webkit-text-size-adjust: 100%; /* Prevent font scaling on iOS rotation */
}

body {
  font-family: var(--font-sans);
  background-color: var(--color-background);
  color: var(--color-text);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

/* Skip link for accessibility */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0,0,0,0); white-space: nowrap; border-width: 0;
}

.skip-link { /* ... see stitch-a11y skill */ }

/* Focus ring — keyboard only */
*:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

步骤 5:语义化 HTML 结构

将 Stitch 布局转换为语义化 HTML5。只要有合适的语义元素,就绝不使用 <div>:

Stitch 元素→ HTML 元素
页面外壳 / 应用框架<body> → <header> + <main> + <footer>
导航栏<nav aria-label="Main navigation">
主要内容区域<main id="main-content">
文章 / 帖子 / 卡片内容<article>
侧边栏<aside>
页面分区<section aria-labelledby="section-id">
按钮(无 href)<button type="button">
带导航功能的链接<a href="...">
表单容器<form>,并为每个输入项添加 <label>
图片<img alt="描述性文本">

移动端 HTML 模板:

<!DOCTYPE html>
<html lang="en" data-theme="light">
<head>
  <meta charset="UTF-8">
  
  <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
  
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="default">
  
  <meta name="theme-color" content="[--color-background hex]">

  <title>[Screen title]</title>
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="stylesheet" href="css/tokens.css">
  <link rel="stylesheet" href="css/base.css">
  <link rel="stylesheet" href="css/components.css">
</head>
<body>
  
  <a href="#main-content" class="skip-link">Skip to content</a>

  
  <div class="app-shell">
    <header class="app-header" role="banner">
      <nav aria-label="Main navigation">
        
      </nav>
    </header>

    <main id="main-content" class="app-main">
      
    </main>

    
    <nav class="bottom-nav" aria-label="Tab navigation">
      
    </nav>
  </div>

  <script src="js/main.js" type="module"></script>
</body>
</html>

步骤 6:移动端优先的 CSS 规则

每个组件都必须遵循以下移动端约束:

触控目标
/* All interactive elements: minimum 44×44px tap area */
button, a, [role="button"] {
  min-height: 44px;
  min-width: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
滚动
/* Smooth scroll on iOS */
.scrollable {
  overflow-y: scroll;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain; /* Prevent scroll chaining */
}
底部导航栏
.bottom-nav {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  /* Account for iOS home indicator */
  padding-bottom: env(safe-area-inset-bottom);
  background: var(--color-surface);
  border-top: 1px solid var(--color-border);
  display: flex;
  justify-content: space-around;
  z-index: 100;
}

/* Push main content above bottom nav */
.app-main {
  padding-bottom: calc(60px + env(safe-area-inset-bottom));
}
响应式断点
/* Mobile-first: base styles are for mobile */

/* Tablet (768px+) */
@media (min-width: 768px) {
  .container { max-width: 720px; margin: 0 auto; }
}

/* Desktop (1024px+) */
@media (min-width: 1024px) {
  .container { max-width: 1200px; }
  .bottom-nav { display: none; } /* Hide bottom nav, use sidebar */
  .sidebar { display: block; }   /* Show desktop sidebar */
}

步骤 7:精简 JavaScript

将 JS 减至最低限度。只有以下功能需要 JS:

  1. 主题切换(深色 / 浅色)
  2. 移动端菜单打开 / 关闭
  3. 手风琴 / 标签页的交互行为
// js/main.js

// Dark mode toggle
const html = document.documentElement;
const savedTheme = localStorage.getItem('theme') || 'light';
html.setAttribute('data-theme', savedTheme);

document.getElementById('theme-toggle')?.addEventListener('click', () => {
  const next = html.getAttribute('data-theme') === 'dark' ? 'light' : 'dark';
  html.setAttribute('data-theme', next);
  localStorage.setItem('theme', next);
});

// Mobile menu toggle
document.getElementById('menu-toggle')?.addEventListener('click', () => {
  const nav = document.getElementById('mobile-nav');
  const expanded = nav.getAttribute('aria-expanded') === 'true';
  nav.setAttribute('aria-expanded', String(!expanded));
  nav.classList.toggle('is-open');
});

步骤 8:Capacitor / WebView 说明

如果此 HTML 将嵌入 Capacitor 或 Ionic 应用:

  • 所有资源路径都必须是相对路径(不能以 / 开头):./css/tokens.css、./assets/logo.png
  • Capacitor 从 www/ 或 dist/ 目录读取内容——请将输出放在那里
  • Capacitor 的 capacitor.config.json 设置 WebDir:"webDir": "www"
  • 如需调用原生 API(相机、文件系统),请使用 Capacitor 插件 JS API——这超出了本技能的范围

故障排除

问题解决方法
iOS 旋转屏幕后字体看起来放大了在 html 中添加 -webkit-text-size-adjust: 100%
内容被刘海遮挡添加 env(safe-area-inset-*) 内边距
iOS 上滚动感觉卡顿添加 -webkit-overflow-scrolling: touch
底部导航遮挡内容为 <main> 添加 padding-bottom,其值等于导航栏高度加安全区内边距
移动端点击延迟(300ms)为按钮添加 touch-action: manipulation

集成

  • 先运行 stitch-design-system 生成 design-tokens.css——导入该文件,而不是重新创建设计令牌
  • 之后运行 stitch-a11y,进行无障碍检查
  • 运行 stitch-animate 添加纯 CSS 过渡效果(大多数动画无需 JS)

参考资料

  • resources/mobile-template.html — 完整的移动端 HTML 样板
  • resources/architecture-checklist.md — 发布前检查清单
  • scripts/fetch-stitch.sh — 可靠的 GCS HTML 下载器

评论

支持 Markdown