Iconsaz:自定义图标包
构建一套全新的原创图标包,使其看起来像属于用户的品牌:与字体的笔触感觉一致,与 UI 的圆角语言相同,与营销材料的氛围相匹配。质量标准参照最好的公共图标包(Lucide、Phosphor、Tabler、Heroicons、Material Symbols、Untitled UI):统一网格、统一描边规则、统一光学尺寸、可预测的命名。输出是用户自己的图标包,不是其中任何一个的副本。
本技能中包含的文件
| 文件 | 何时读取 |
|---|---|
references/question-flow.md | 第 1 步:14 个问题的准确措辞、选项、默认值和批量处理 |
references/style-rules.md | 第 2-7 步:基准规则、品牌到风格的映射、构建规则、起始目录、隐喻库 |
references/rtl-and-culture.md | 第 8 步,以及当产品是 RTL 或涉及多个地区时 |
templates/style-brief.md | 第 3 步:复制并填写;同时也是用户需要保留的文件 |
scripts/validate_icons.py | 第 6、7、9 步:检查网格、内边距、描边、viewBox、currentColor、隐藏图层、命名、完整性、RTL 配对 |
scripts/preview_sheet.py | 第 6 步和第 9 步:生成 preview.html(尺寸、网格缩放、亮/暗色、颜色、RTL 切换) |
scripts/package_pack.py | 第 10 步:验证,然后将 SVG + 扁平化的 Figma 就绪副本 + 预览 + 简报 + 导入指南打包成 zip |
这些脚本是纯 Python 3.8+,无依赖。使用 python scripts/<name>.py --help 运行。
两种模式
- 新包: 执行下面的完整工作流程。
- 扩充包: 用户提供先前由本技能生成的风格简报(包含
icon-specJSON 块)。跳过访谈和品牌扫描。读取简报,仅询问要添加哪些图标(并为抽象概念提供隐喻),按照简报的精确数字绘制,针对它进行验证,将新图标添加到图标列表中,增加次版本号并添加更新日志条目。在此模式下,绝不更改网格、描边、内边距或圆角半径:与旧图标精确匹配是关键。如果用户想要更改风格,那将是一个新的主版本,并且必须重新绘制每个图标。
工作流程
在三个关键节点让用户参与进来:品牌扫描(第 2 步)、简报(第 3 步)和测试图标(第 6 步)。基于错误的假设绘制 60 个图标比进行一次额外的确认浪费用户更多时间。
1. 访谈
按照 references/question-flow.md 中的顺序,每次提出三到四个问题。在可能的情况下,使用结构化问题工具(例如 AskUserQuestion)进行多项选择问题,对于上传和文本答案使用普通聊天。
- 如果用户跳过某个问题,从参考中选择默认值,在一行内说明你选择了什么以及原因,然后继续。不要再次询问。
- 不要向用户索要他们现有的图标,如果他们提供了,感谢他们并将其放在一边。这是一套新的图标;旧图标会将风格拉回团队试图摆脱的方向。他们的设计系统规则(网格、描边、圆角半径)是受欢迎的,这正是问题 9 所问的。
- 上传的截图可能包含当前图标。仅使用它们来了解哪里需要图标(第 4 步),而绝不了解它们应该如何呈现。
2. 品牌 DNA 扫描
研究所有上传的内容:Logo、品牌指南、颜色、字体、情绪板、营销材料和截图。使用 references/style-rules.md(“从品牌到图标风格”)中的映射表,根据证据推导出风格。查看:
- 字体: UI 尺寸下的笔画粗细、端点(圆形、扁平、斜角)、字碗的圆度、x-height、几何 vs 人文。这决定了描边重量和端点/连接样式。
- Logo: 相对于其尺寸的线条权重、角落形状、角度(45° vs 自由)、任何标志性特征(缺口、卷曲、切角),这些可能成为微妙的包级特征。
- UI 截图: 组件圆角半径、边框宽度、密度、间距。这决定了图标圆角半径和尺寸集。
- 颜色和图像: 这些仅用于确定氛围。图标以
currentColor形式提供。
将发现以表格形式呈现,并请用户确认或更正:
| 信号 | 证据 | 决定 | 置信度 |
|---|---|---|---|
| 描边 | 正文字体是 Nunito Regular,16 像素文本下笔画≈ 1.6 像素 | 24 像素下为 2 像素,20 像素下为 1.75 像素 | 高 |
当证据不足时,要明确说明(“未提供字体,因此仅从 Logo 推断描边,置信度中等”)。
3. 风格简报
复制 templates/style-brief.md,填写每个部分并展示给用户。它涵盖网格和内边距、各尺寸的描边、端点样式和连接样式、圆角半径、样式和状态、尺寸、氛围、命名、RTL 决策以及按类别分组的完整图标列表。底部的 icon-spec JSON 块是脚本读取的内容,因此请确保其与正文保持同步。在绘制任何内容之前需获得明确批准。
4. 缺失图标查找器
逐个区域浏览每个截图(导航、标题、工具栏、按钮、列表行、表单字段、空状态、通知和状态、设置行、卡片),并列出每个需要图标的位置。提供一个表格——屏幕、位置、所需图标、是否已在列表中?——并在用户同意后将缺失的图标添加到简报的图标列表中。如果没有截图,请使用 references/style-rules.md 中的起始目录以及产品上下文。
5. 隐喻选项
对于每个抽象概念(退款、咨询、同步、入职、订阅、忠诚度、合规性等),提供两到三个视觉想法,每个都附上一行理由,并使用 references/rtl-and-culture.md 标记任何文化风险。references/style-rules.md 中的“隐喻库”提供了起点。让用户选择,然后将选择记录在简报中,因为下一位设计师需要知道为什么 refund 是一个带有返回箭头的硬币。
6. 测试图标
先绘制三到四个样本:home、search、settings 以及最具特色的产品特定图标。以每种批准的样式、每种尺寸绘制每一个。然后运行
python scripts/validate_icons.py icons/ --brief style-brief.md --samples
python scripts/preview_sheet.py icons/ --brief style-brief.md -o preview.html
修复所有错误,亲自查看预览(如果有浏览器,请打开它并检查 1× 尺寸,而不仅仅是缩放),然后展示给用户。询问哪些感觉不对。此阶段的典型调整:描边稍粗或稍细、角落更柔和、更多或更少的细节。如有任何更改,请更新简报。在用户批准样本之前,不要开始绘制全套图标。
7. 全套绘制
按照下面的“如何绘制”绘制简报中的每个图标。按类别工作,并在每个类别之后运行验证器,这样就不会在 80 个图标之后才发现系统性的错误。
8. RTL 和文化
如果文本方向是 RTL 或两者兼有,则为每个方向性图标(箭头、返回和前进、发送、回复、撤销和重做、退出、列表缩进等)创建一个镜像的 -rtl 版本。保持非方向性图标不变;镜像时钟或播放按钮是一个错误。对照文化风险列表检查每个图标。两个列表都在 references/rtl-and-culture.md 中。在规范的 directional 列表中标记方向性图标,以便验证器检查配对。
9. 最终检查
在未使用 --samples 的情况下运行验证器。必须报告零错误。然后通过目视检查,因为脚本无法判断可识别性:
- 简报中的每个图标都以每种样式和尺寸存在(验证器:完整性)。
- 每个图标都遵循简报:网格、内边距、描边、端点、连接、圆角半径(验证器)。
- 整个图标集的光学尺寸均匀;在预览网格中,没有图标看起来比其相邻图标更大或更小(验证器:对异常值发出警告)。
- 每个图标在最小尺寸下仍然清晰:查看预览的 1× 行。如果两个细节合并,请在该尺寸中移除一个细节,而不是加粗描边。
- 名称遵循
category/name/variant/size、小写的 kebab-case,并且在任何地方含义相同(验证器:命名)。 - RTL 配对存在并且真正相互镜像(验证器:RTL)。
- 没有文化敏感符号混入。
在交付之前修复所有失败项并重新运行检查。
10. 交付
Figma Professional(或更高版本): 使用 Figma MCP 构建库。如果其工具缺失或未认证,请告知用户需要连接,并提供 zip 包作为替代。如果可用 figma-use 等 Figma 技能,请在第一次写入调用之前加载它。
- 创建一个包含三个页面的新文件:封面、图标 和 用法。
- 在 图标 页面上,为每个类别创建一个区域。对于每个图标,将每个 SVG 转换为节点(
figma.createNodeFromSvg),将每个节点转换为组件,使用变体属性(style=outline, state=default, size=24)命名组件,并使用figma.combineAsVariants将它们组合成一个命名为category/name的组件集。保持描边为描边;不要将其轮廓化。 - 每次写入调用构建一个类别。大批量会超时,失败只会影响一个类别,而不是整个包。在每个类别之后截取屏幕截图,并与预览进行比较。
- 封面: 包名、版本、氛围词汇和一组英雄图标网格。用法: 尺寸以及何时使用每个尺寸、文本旁边的间距、活动/非活动规则、RTL 规则、命名、做/不做的示例,以及“要添加图标,请与技能共享风格简报”。
- 同时交出来自下一步的 zip 包,因为开发人员无论如何都需要 SVG。
Figma Free(或没有 Figma): Figma MCP 无法在免费计划上写入库文件,因此请交付文件:
python scripts/package_pack.py icons/ --brief style-brief.md --out dist/
在有错误时会拒绝打包,在有警告但未审查时也会拒绝;仅在每个剩余警告是预期的情况下才添加 --allow-warnings。然后它会写入 dist/<pack>-v<version>.zip,其中包含 svg/(category/name/variant/size.svg 树)、figma/(扁平的 category__name__variant__size.svg 副本,在 Figma 中一次批量重命名后将成为斜杠名称)、preview.html、manifest.json、风格简报和 IMPORT-TO-FIGMA.md(包含将图标导入 Figma 并转换为具有变体的组件的逐步说明)。在聊天中也总结这些步骤。
11. 保存简报
将最终的风格简报保存在交付物旁边(命名为 <pack>-style-brief.md),并告诉用户,使用这些或近似的话:“请保留此文件。下次你需要图标时,首先与我分享它,新图标将与这个包完全匹配。”
如何绘制
在商定的网格上手动编写 SVG,就像在设计工具中构建矢量一样。每个尺寸在其自己的原生画布上绘制(20 像素对应 viewBox="0 0 20 20" 等),因此小尺寸可以获得自己的描边和简化的细节,就像 Material 的光学尺寸和 Heroicons 的 20 和 16 像素集的做法一样。
- 根元素:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">。在根元素上设置绘制属性,让形状继承,这能使每个图标保持一致。 - 在网格上使用基元(
circle、带rx的rect、line、带弧线的path)。将坐标保持为整数或半整数单位(最多四分之一单位)。离网格的点在 1× 下会显示模糊。 - 颜色仅为
currentColor。填充形状使用fill="currentColor"。双色调的第二种色调是简报透明度下的currentColor,绝不用第二种颜色。 - 没有变换、隐藏元素、
<text>、嵌入图像、<style>、ID 或编辑器元数据。将所有内容展平为简单的几何体。 - 使形状适应其关键线(圆形、正方形、竖向或横向矩形;请参阅 style-rules),这样圆形图标和方形图标看起来大小相同。
- 内部间隙至少为一个笔画宽度宽,在 16 像素时更宽。
- 填充变体遵循与轮廓相同的轮廓,细节作为间隙被挖空。它们应该读作相同的图标,即“已打开”状态。
- 要制作更小的尺寸,从缩放至新画布的 24 像素几何体开始,将点对齐到网格,从简报中设置该尺寸的描边,然后移除不再适合的细节。切勿仅缩放文件。
- 匹配品牌字体:端点样式和连接样式镜像其终端,曲线镜像其字碗,如果简报要求,包级特征(一个缺口,一个切角)可以呼应 Logo。
一个最小的轮廓图标示例:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="10.5" cy="10.5" r="7"/>
<path d="M15.5 15.5 21 21"/>
</svg>
工作目录结构
icons/<category>/<name>/<variant>/<size>.svg e.g. icons/nav/home/outline/24.svg
icons/nav/arrow-back-rtl/outline/24.svg 镜像的 RTL 孪生
style-brief.md 已填写的模板,包含 icon-spec 块
preview.html 生成的
dist/<pack>-v<version>.zip 生成的
规范的图标名称是不含 .svg 的路径,因此 nav/home/outline/24。这也是 Figma 组件名称,使代码、设计和文件保持一致。
与用户沟通
许多使用此工具的是设计师,而不是开发人员。在提到“描边”时也说“线条粗细”,在提到“圆角半径”时也说“角落圆度”,并解释任何脚本输出的含义,而不是直接粘贴原始输出。保持每次交互简短:几个问题、一个决定或一个需要审查的事项。