mcpField
S
stitch-svelte-components

stitch-svelte-components

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

关于 stitch-svelte-components

该技能将 Stitch 屏幕、HTML 文件或 URL 转换为采用 Svelte 5 runes API 的组件,面向 SvelteKit 和独立 Svelte 5 项目。流程还涵盖样式、动效、无障碍检查与开发验证。

主要功能

  1. 01转换 HTML 为 Svelte 组件
  2. 02采用 Svelte 5 runes API
  3. 03映射 SvelteKit 文件路由
  4. 04使用作用域 CSS 与设计令牌
  5. 05添加转场并考虑减少动效
  6. 06检查无障碍并验证开发环境

适用场景

  1. 01将 Stitch 屏幕实现为 Svelte 页面
  2. 02把本地 HTML 转为可复用组件
  3. 03将网页 URL 转为 Svelte 界面

MCP 相关

仅从 Stitch 屏幕获取设计数据和 HTML 时需要 Stitch MCP;本地文件和 URL 输入不需要 MCP。

安装

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

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

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

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

resources/
architecture-checklist.md
component-template.svelte
scripts/
fetch-stitch.sh

详细介绍

Stitch → Svelte 5 / SvelteKit 组件

你是一名 Svelte 5 工程师。你将 HTML 源文件——Stitch 屏幕、本地文件或 URL——转换为符合 Svelte 惯例的组件,并使用 runes API($state、$props、$derived、$effect),而不是旧版 Options API。组件使用带自定义属性的作用域 CSS 进行主题设置,使用 Svelte 内置过渡效果实现动画,并默认采用无障碍标记。

注意: 这是唯一面向 Svelte 的 Stitch 技能。官方 react-components 技能面向 Vite/React。项目使用 SvelteKit 时,请使用此技能。

何时使用此技能

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

  • 目标项目使用 SvelteKit 或独立的 Svelte 5
  • 你看到 .svelte 文件、svelte.config.js 或 +page.svelte 约定
  • 用户提到 svelte、sveltekit、$state、$props 或 runes

前提条件

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

  • Stitch 屏幕——需要 Stitch MCP 访问权限和已生成的屏幕
  • 本地 HTML 文件——无需 Stitch 账号
  • URL——无需 Stitch 账号

此外:

  • 目标项目使用 Svelte 5(已启用 runes)——检查 package.json 中是否有 "svelte": "^5"

第 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 步:SvelteKit 文件约定

SvelteKit 使用基于文件的路由。将 Stitch 屏幕映射到以下结构:

src/
├── routes/
│   ├── +layout.svelte        ← Persistent shell (nav, footer)
│   ├── +layout.ts            ← Layout load function (optional)
│   ├── +page.svelte          ← Route page component
│   ├── [route]/
│   │   ├── +page.svelte      ← Sub-route page
│   │   └── +page.ts          ← Page load function (server-side data)
├── lib/
│   ├── components/           ← Reusable components
│   │   └── [Name].svelte
│   ├── data/
│   │   └── mockData.ts       ← Decoupled static content
│   └── types/
│       └── index.ts          ← Shared types
static/                       ← Static assets

关键规则:

  • 页面以 +page.svelte 的形式放在 src/routes/ 中
  • 可复用组件放在 src/lib/components/ 中
  • $lib/ 是 src/lib/ 的别名——务必使用它

第 3 步:Svelte 5 runes API

只使用 runes。 绝不使用旧式 export let、let x = 0 响应式语法或 $: 标签。

属性
<script lang="ts">
  interface Props {
    title: string
    description?: string
    onAction?: () => void
  }

  // $props() replaces export let
  const { title, description = 'Default text', onAction }: Props = $props()
</script>
响应式状态
<script lang="ts">
  // $state() replaces let count = 0
  let count = $state(0)
  let isOpen = $state(false)

  // $derived() replaces $: doubled = count * 2
  const doubled = $derived(count * 2)

  // $effect() replaces onMount / afterUpdate for side effects
  $effect(() => {
    console.log('count changed:', count)
  })
</script>
事件处理

<button onclick={() => count++}>Increment</button>
<button onclick={onAction}>Custom action</button>

步骤 4:使用设计令牌的作用域 CSS

Svelte 默认会将 CSS 限定在组件作用域内——请充分利用这一特性。按以下顺序从源文件中解析颜色,然后将其映射到 :root 中的自定义属性(通过 +layout.svelte 或 app.css),并在各组件中引用:

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

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

在 src/app.css 中(全局):

:root {
  --color-background: #ffffff;
  --color-surface: #f4f4f5;
  --color-primary: /* dominant color from the source */;
  --color-primary-foreground: #ffffff;
  --color-text: #09090b;
  --color-text-muted: #71717a;
  --color-border: #e4e4e7;
}

[data-theme='dark'] {
  --color-background: #09090b;
  --color-surface: #18181b;
  --color-primary: /* same hue, adjusted for dark bg */;
  --color-primary-foreground: #09090b;
  --color-text: #fafafa;
  --color-text-muted: #a1a1aa;
  --color-border: #27272a;
}

在各组件中(作用域内):

<style>
  .card {
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    color: var(--color-text);
    border-radius: 0.5rem;
    padding: 1.5rem;
  }

  .card:hover {
    /* Scoped — won't leak to parent or children */
    border-color: var(--color-primary);
  }
</style>

深色模式切换——在 +layout.svelte 中添加一个 $state:

<script lang="ts">
  let theme = $state<'light' | 'dark'>('light')

  function toggleTheme() {
    theme = theme === 'light' ? 'dark' : 'light'
    document.documentElement.setAttribute('data-theme', theme)
  }
</script>

<svelte:element this="div" data-theme={theme}>
  {@render children()}
</svelte:element>

步骤 5:内置过渡和动画

Svelte 原生支持过渡效果。根据源设计中的动效意图应用以下效果:

<script lang="ts">
  import { fade, fly, slide, scale } from 'svelte/transition'
  import { cubicOut } from 'svelte/easing'

  let show = $state(false)
</script>


<div transition:fade={{ duration: 200 }}>
  Content that fades in
</div>


{#if isOpen}
  <aside transition:fly={{ x: -300, duration: 300, easing: cubicOut }}>
    Sidebar content
  </aside>
{/if}


{#if expanded}
  <div transition:slide={{ duration: 200 }}>
    Expandable content
  </div>
{/if}

始终遵循减少动态效果的设置:

<script lang="ts">
  // Check user preference once
  const prefersReducedMotion = $state(
    typeof window !== 'undefined'
      ? window.matchMedia('(prefers-reduced-motion: reduce)').matches
      : false
  )

  // Conditionally disable transitions
  const transitionOptions = $derived(
    prefersReducedMotion ? {} : { duration: 200 }
  )
</script>

<div transition:fade={transitionOptions}>...</div>

步骤 6:Svelte 中的无障碍访问

Svelte 编译器会针对缺少无障碍属性发出警告——请将所有编译器警告视为错误。

  • role 和 ARIA:使用非语义元素时添加 role。始终同时添加 aria-label 或 aria-labelledby。
  • bind:this:用于程序化焦点管理(例如模态框中的焦点陷阱)。
  • 键盘处理器:非交互元素上的任何 onclick 处理器都需要同时添加 onkeydown/onkeyup,或者改用 <button>。
  • 屏幕阅读器文本:使用 class="sr-only"(在 app.css 中定义)设置视觉隐藏的标签。

<button
  onclick={closeModal}
  aria-label="Close dialog"
  class="icon-btn"
>
  <CloseIcon />
</button>


<dialog
  bind:this={dialogEl}
  aria-labelledby="dialog-title"
  aria-modal="true"
>
  <h2 id="dialog-title">{title}</h2>
</dialog>

步骤 7:执行步骤

  1. 环境检查——如果缺少 node_modules,运行 npm install。
  2. 数据层——根据设计内容创建 src/lib/data/mockData.ts。
  3. 组件起草——以 resources/component-template.svelte 为基础。将所有 StitchComponent 替换为实际的组件名称。
  4. CSS 令牌——将颜色令牌添加到 src/app.css。如果使用 stitch-design-system,则改为导入其生成的 design-tokens.css。
  5. 接线——更新 src/routes/+page.svelte,导入并使用新组件。从 $lib/components/ 导入。
  6. 质量检查——按照 resources/architecture-checklist.md 逐项检查。
  7. 开发验证——运行 npm run dev。切换深色模式。测试键盘导航。

故障排除

问题修复方法
Runes 语法错误确认 package.json 中有 svelte: ^5。旧语法在 Svelte 5 中无效。
$props() 类型错误在 <script> 标签中添加 lang="ts"
CSS 未限定作用域确保样式位于 <style> 块内,而不是通过 .css 导入
过渡效果未播放检查 prefers-reduced-motion 是否导致配置为空
$lib 无法解析确认 tsconfig.json 中有 "paths": {"$lib/*": ["src/lib/*"]}
加载时深色模式闪烁在同步的 <svelte:head> 脚本中从 localStorage 读取主题

与其他技能集成

  • stitch-design-system——先运行,以生成用于 CSS 变量基础的 design-tokens.css。
  • stitch-animate——之后运行,以获取超出上述基础内容的 Svelte 专用过渡模式。
  • stitch-a11y——之后运行;当设计中包含复杂 UI 模式时,用于进行完整的无障碍审计。

参考资料

  • resources/component-template.svelte——可用于生产环境的 Svelte 5 组件样板
  • resources/architecture-checklist.md——发布前质量检查清单
  • scripts/fetch-stitch.sh——可靠的 GCS HTML 下载器

评论

支持 Markdown