mcpField
C
create-theme

create-theme

github.com/open-slide设计与 UI9.4k145 次安装今天更新
代码仓库

关于 create-theme

create-theme 是面向幻灯片作者的技能,用于生成可复用的视觉主题。它会配套创建编写指南和实时预览模块,同时避免改动正式幻灯片及项目配置。

主要功能

  1. 01创建主题文档与预览文件
  2. 02从图片、文字或现有幻灯片提取主题
  3. 03定义配色、字体、布局、组件和动效
  4. 04以 2–3 页示例预览主题
  5. 05仅修改 themes/ 下的文件

适用场景

  1. 01将品牌素材整理为可复用的幻灯片主题
  2. 02从现有幻灯片提取视觉风格
  3. 03在用于创建幻灯片前预览主题

安装

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

$npx skills add https://github.com/open-slide/open-slide --skill create-theme

安装后在 Claude Code 中输入/create-theme确认已加载。

详细介绍

创建幻灯片主题

此技能会在 themes/ 下生成一个主题包:两个配套文件,共同描述可重复使用的视觉标识。

  1. themes/<id>.md — 面向 Agent 的文档:调色板、字体排印、布局、固定的 Title/Footer/Eyebrow 组件、动效。作者选择主题时,create-slide 会读取此文件。
  2. themes/<id>.demo.tsx — 可运行的迷你幻灯片(普通幻灯片模块:export default Page[]),通过 2–3 页展示主题。开发 UI 的 Themes 面板会加载此文件,并将其渲染为主题的实时预览。

两个文件使用相同的主文件名,以便运行时自动配对。

主题不同于幻灯片的 design 常量。主题 Markdown 描述的是创作时的美学方向(create-slide 会将其复制到实际幻灯片的源文件中)。演示 .tsx 是独立的预览,不是真正的幻灯片,不会显示在幻灯片列表中。每张幻灯片中的 const design: DesignSystem = { … }(在 slides/<id>/index.tsx 顶部声明)是运行时令牌对象,用户可以通过 Design 面板对其进行调整。Markdown 确定方向;每张幻灯片的 design 常量让幻灯片可调整;演示 .tsx 让主题可预览。

只在 themes/<id>.md 和 themes/<id>.demo.tsx 下写入文件。切勿修改实际幻灯片或其他配置。主题可覆盖的画布和字号比例默认值位于 slide-authoring 技能中——编写主题前请先阅读该技能,以便明确说明覆盖项。

第 1 步 — 确定输入来源

主题可从以下三种输入形式中的任意组合衍生:

  • 图像参考 — 幻灯片截图、情绪板图片、品牌素材的路径或 URL。
  • 自由文本描述 — 描述所需调色板、字体和风格的文字。
  • 现有幻灯片 — slides/<id>/index.tsx,其视觉标识应提取出来,作为可重复使用的主题。

如果用户的原始消息已明确指定输入,则跳过提问并继续。否则,调用 AskUserQuestion(多选),让用户选择一个或多个来源,并仅在需要时追问(路径、幻灯片 id、描述)。

第 2 步 — 收集原始输入

  • 图像:使用 Read 工具读取每个路径(该工具支持读取图像)。记录主色的十六进制值、字重/字形、布局节奏、装饰图案,以及重复出现的界面元素(标题栏、页脚线、页码)。
  • 文本:提取明确的令牌(十六进制代码、字体名称、动效动词)和隐含的风格词语(“编辑风”“俏皮”“粗野主义”)。将含糊的描述转化为具体决定后再行编写。
  • 现有幻灯片:读取 slides/<id>/index.tsx 并提取:
    • design.palette 对象(或文件顶部的旧式 palette 常量)→ 调色板部分。
    • design.fonts / 字体常量以及任何 font-size 模式 → 字体排印部分。
    • 内边距/对齐模式 → 布局部分。
    • 重复出现的组件(TrafficLights、Eyebrow、Footer 样式辅助函数、WindowShell,……)→ 固定组件部分。
    • @keyframes 块和共享的 styles 字符串 → 动效部分。
    • 设计所体现的美学风格 → 美学段落。

如果输入彼此冲突(例如,图像使用蓝色,但描述要求绿色),请询问用户应以哪一方为准。

第 3 步 — 选择主题 id

使用简短且能描述主题的 kebab-case。示例:editorial-noir、brutalist-mono、pastel-soft、dev-terminal。检查 themes/,避免名称冲突。

第 4 步 — 编写 themes/<id>.md

按以下确切顺序生成文件中的各个章节。章节正文可根据主题调整;所有主题的标题必须保持一致。

---
name: <Human title, e.g. "Editorial Noir">
description: <one-line elevator pitch>
mode: <dark | light — whichever matches the palette's bg>
---

# <Theme name>

## Palette

| Role   | Value     | Notes                          |
| ------ | --------- | ------------------------------ |
| bg     | `#0f172a` | page background                |
| text   | `#f8fafc` | primary copy                   |
| accent | `#fbbf24` | callouts, eyebrow, key numbers |
| muted  | `#94a3b8` | secondary copy, dividers       |
| ...    | ...       | extend as the theme requires   |

## Typography

- Display font: `<stack>` — weight 800–900 for headlines.
- Body font: `<stack>` — weight 400–500.
- Webfont import (omit for system stacks): `<stylesheet URL>` — see `references/webfonts.md` in `slide-authoring` for loading rules.
- Type-scale overrides (only list what differs from `slide-authoring` defaults):
  - Hero title: 180 px (default 140–200 ✓)
  - Body text: 36 px

## Layout

- Content padding: 120 px from canvas edges (1920 × 1080).
- Alignment: left-aligned, single column.
- Grid notes: optional 12-column overlay at 80 px gutter for content pages.

## Fixed components

These are paste-ready. Copy them verbatim into a slide that uses this theme.

### Title

```tsx
const Title = ({ children }: { children: React.ReactNode }) => (
  <h1
    style={{
      fontSize: 140,
      fontWeight: 900,
      lineHeight: 1.05,
      letterSpacing: '-0.02em',
      margin: 0,
      color: '#f8fafc',
    }}
  >
    {children}
  </h1>
);
```

### Footer

Pull the page number from `useSlidePageNumber()` — never hardcode `pageNum` / `total` props.

```tsx
import { useSlidePageNumber } from '@open-slide/core';

const Footer = () => {
  const { current, total } = useSlidePageNumber();
  return (
    <div
      style={{
        position: 'absolute',
        left: 120,
        right: 120,
        bottom: 60,
        display: 'flex',
        justifyContent: 'space-between',
        fontSize: 24,
        color: '#94a3b8',
      }}
    >
      <span>EDITORIAL NOIR · 2026</span>
      <span>{current} / {total}</span>
    </div>
  );
};
```

### Eyebrow / accents (optional)

```tsx
const Eyebrow = ({ children }: { children: React.ReactNode }) => (
  <div style={{ fontSize: 26, letterSpacing: '0.2em', color: '#fbbf24' }}>
    {children}
  </div>
);
```

## Motion

- Philosophy: static / subtle / rich — pick one and explain in one sentence.
- Reusable keyframes (paste-ready, only if the philosophy is subtle or rich):

```css
@keyframes fadeUp {
  from { opacity: 0; transform: translateY(24px); }
  to   { opacity: 1; transform: translateY(0); }
}
```

## Aesthetic

One paragraph. What it feels like, the references it draws on, what to avoid (e.g. "no rounded corners; no gradients; no decorative emoji"). Commit to a single direction — minimal, maximalist, editorial, retro, brutalist, soft/pastel, neon, paper/print.

## Example usage

```tsx
const Cover: Page = () => (
  <div style={{ width: '100%', height: '100%', background: '#0f172a', color: '#f8fafc', padding: 120, display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
    <Eyebrow>CHAPTER 01</Eyebrow>
    <Title>The Big Idea</Title>
    <p style={{ fontSize: 36, color: '#94a3b8', maxWidth: 1200, marginTop: 32 }}>
      A short subtitle that explains what this slide is about.
    </p>
    <Footer />
  </div>
);
```

第 4b 步 — 编写 themes/<id>.demo.tsx

演示文件是一个普通的幻灯片模块——结构与 slides/<id>/index.tsx 相同,只是放在 themes/ 下,让运行时知道它仅用于预览。开发 UI 的 Themes 面板会导入它,并在 SlideCanvas(1920×1080)中渲染。

约定:

  • import { type Page, useSlidePageNumber } from '@open-slide/core';
  • 内联主题 Markdown 中定义的同一组 Title、Footer、Eyebrow 组件——逐字照搬,不做抽象,也不从其他地方导入。演示文件必须与 Markdown 保持同步,这样用户在面板中看到的内容才会与 create-slide 粘贴到实际幻灯片中的内容一致。
  • 导出 2–3 个 Page 组件和一个默认数组。建议包含:一个封面(Eyebrow + Title + 副标题)、一个展示正文排版和强调色的内容页,以及一个结束页或“End”卡片。Markdown 底部的“Example usage”代码块是不错的起点——在此基础上扩展。
  • 如果主题包含值得在后续 Design 面板中展示的运行时可调整令牌,还需export const design: DesignSystem = {...}(在基础导入旁添加 import type { DesignSystem } from '@open-slide/core';)。
  • 不导入资源文件,不从 @/ 导入,不使用仅供幻灯片使用的辅助组件(例如真实幻灯片中的 WindowShell)。在内联 <style> 中使用 Web 字体样式表 @imports 没问题——这是对 webfonts.md 加载规则的有意例外,因为演示文件只会在 Themes 面板中挂载。演示文件必须自包含。

骨架:

import { type Page, useSlidePageNumber } from '@open-slide/core';

const Title = ({ children }: { children: React.ReactNode }) => (
  // …same JSX as in themes/<id>.md
);
const Footer = () => {
  const { current, total } = useSlidePageNumber();
  // …
};
const Eyebrow = ({ children }: { children: React.ReactNode }) => (
  // …
);

const Cover: Page = () => (
  // …
);
const Content: Page = () => (
  // …
);
const Closer: Page = () => (
  // …
);

export default [Cover, Content, Closer];

第 5 步 — 自我审查

完成前运行以下检查清单:

  • 配色至少包含 bg / text / accent / muted,且全部使用十六进制值。
  • Frontmatter 包含 mode,并与配色中的背景相匹配。
  • 字体比例指定 hero、heading、body、caption 的字号(或明确沿用 slide-authoring 默认值)。
  • 至少定义了 Title 和 Footer,使用可直接粘贴的 React 代码和具体的内联样式。
  • 动效部分明确选择 static / subtle / rich 之一。
  • 美学描述明确指出一个统一的风格方向。
  • 两个文件都已写入:themes/<id>.md 和 themes/<id>.demo.tsx。不修改幻灯片,不修改配置。
  • 演示 .tsx 导出 2–3 个页面,并内联与 Markdown 中定义的相同 Title/Footer/Eyebrow 组件。
  • 演示 .tsx 可以在 Themes 面板中正常加载:阅读文件并根据第 4b 步的约定进行核对——不要启动服务器。

第 6 步 — 交接

告知用户:

  • 主题 ID 和两个文件路径(themes/<id>.md + themes/<id>.demo.tsx)。
  • 演示会以实时卡片和详情视图的形式出现在开发 UI 的 Themes 面板中(HMR——无需重启)。
  • /create-slide 下次运行时会将该主题列为可选项。
  • 用一句话概述外观(配色 + 美学风格)。

不要运行开发服务器。不要修改真实幻灯片——即使是为了展示主题也不行;.tsx 演示文件就是展示用的。

反模式

  • ❌ 在带标签的组件代码片段之外,于 themes/<id>.md 中编写可执行代码——Markdown 是文档。
  • ❌ 只生成 Markdown 而没有演示文件,或只生成演示文件而没有 Markdown。主题是一个组合包——每次都必须包含两个文件。
  • ❌ 将 themes/<id>.demo.tsx 当作真实幻灯片。它仅用于预览,位于幻灯片列表之外;绝不要将其放在 slides/ 下。
  • ❌ 在演示文件中从 @/ 或任何幻灯片专用辅助模块导入。演示文件必须自包含。
  • ❌ 用户提供了图片或现有幻灯片时,不要凭空编造配色或字体。应提取,而不是虚构。
  • ❌ 不要编辑 slides/、packages/、package.json 或 open-slide.config.ts。
  • ❌ 不要跳过 Fixed components 部分。Title 和 Footer 最常见的复用目标必须是可直接粘贴的。

评论

支持 Markdown