Icon Forge
繪製看起來像來自同一專業圖示集的自訂圖示,並以無執行時期依賴的方式交付。當每個圖示都通過 lint、你已查看 16/20/24px 的預覽圖且其在淺色和深色背景上都清晰可辨且一致,並且生成的元件已以無障礙的方式整合使用時,才算完成。
<skill> 代表包含此檔案的資料夾(例如 .claude/skills/icon-forge, .cursor/skills/icon-forge, .agents/skills/icon-forge)。腳本需要 Node ≥18 且無專案依賴。
使用時機 / 不使用時機
- 使用: 側邊欄、導覽列、儀表板、設定頁面、空白狀態或工具列需要圖示;使用者要求自訂或缺少的圖示;使用者想要用自己的一套小型圖示取代 emoji/佔位符圖示或一個龐大的圖示套件。
- 不使用: Logo 和品牌標誌(商標問題;需要設計師)、favicon/應用程式圖示、插圖或點綴圖、照片/點陣圖、動畫 Lottie。如果使用者明確要求安裝一個圖示庫(例如「就用 Lucide」),請照做;此技能是為自訂路徑設計的。
硬性規則(及其原因)
- 自己繪製每個圖示;不要新增任何圖示庫依賴。 使用者選擇自訂圖示是為了減少打包體積和獲得獨特外觀。不要貼上來自 Lucide、Heroicons、Material 等圖示庫的路徑資料(有授權與原創性問題)。使用
references/glyph-cookbook.md(原創繪圖)作為起始幾何形狀。 - 如果專案已使用某個圖示庫,請比對其格線、筆畫、端點和半徑(請見
scripts/detect.mjs和設計規則 §10)。新圖示必須與現有圖示並列,看起來不突兀。 - 一個圖示集,一個風格。 所有圖示使用相同的格線、筆畫寬度、端點/接合樣式、半徑比例、內邊距和細節程度。一致性比任何單一巧妙的圖示更重要。
- 呈現屬性僅存在於根
<svg>元素上,顏色使用currentColor,且來源不應包含 id、樣式、類別、transform 或<g>。 否則主題切換、深色模式、strokeWidthprop 和內聯顯示將會出錯。 - 在沒有渲染並檢視 PNG 的情況下,絕不能聲稱一個圖示是好的。 在程式碼中看似正確的幾何形狀,在 16px 時經常會失效:出現模糊、閉合間隙、形狀偏移、權重不匹配。
- 執行腳本;不要重新實作它們。 Lint、最佳化、預覽和程式碼生成是確定性的。絕不要手動編輯生成的檔案;請修改
icons/src/並重新建置。 - 不要修改使用者的依賴項。 預覽工具會安裝到
~/.cache/icon-forge(使用--install);SVGO 在找不到時會透過npx執行。在將任何套件加入專案之前,請先詢問。 - 預設為無障礙。 圖示預設為
aria-hidden,除非有標籤;純圖示控制項需加上aria-label;可互動目標尺寸 ≥44px;有意義的圖示需有 ≥3:1 的對比度。
工作流程
1. 檢測技術棧與現有風格
node <skill>/scripts/detect.mjs .
記下框架、TypeScript、Tailwind、任何圖示庫(及其風格預設)、本地 SVG 圖示,以及建議的輸出目錄。如果存在現有圖示集,打開 2-3 個其 SVG 檔案並複製其根元素上的數值。否則使用預設值:24 格線、筆畫 2、圓形端點/接合。
2. 規劃列表:意義 → 隱喻 → 檔名
在繪製前先建立一個簡短表格:標籤 | 隱喻(繪製什麼) | 檔名 | 食譜起點。例如:Projects | kanban board | kanban.svg | kanban。選擇主流隱喻(設計規則 §7),每個意義對應一個隱喻。以 kebab-case 命名檔案。僅在標籤含義不明確且選擇會改變 UI 意義時才詢問使用者;否則自行決定並說明選擇。
3. 在 24 格線上繪製
建立 icons/src/<name>.svg,包含標準的根元素(svg-code-rules.md)。對於每個圖示:
- 從匹配的關鍵線開始:圓形 r10、方形 18(x/y 3)、豎長方形 16×20、橫長方形 20×16。關鍵線是筆畫的中心線。
- 保持筆畫的外緣距離畫布邊緣 ≥1 單位。在大轉角處使用半徑 2,在小轉角處使用 1-1.5;保持間隙 ≥2 單位的空白空間。
- 讓零件要麼完全連接,要麼保持清晰的間隙。對於 2px 筆畫使用整數座標。盡量使用最少的元素(通常 ≤6 個)。
- 從最接近的
references/glyph-cookbook.md條目開始,然後進行調整。當一個字形可以直接使用時,從<skill>/assets/cookbook/<name>.svg複製其幾何形狀。 - 使用幾行 JS 計算重複的幾何形狀(齒、射線、星形頂點),而不是猜測。 先繪製整個圖示集,然後再精煉。一致性是透過並排比較來判斷的。
4. Lint
node <skill>/scripts/lint.mjs icons/src
修正每一個 ✖ 錯誤。將 ⚠ gap、density、scale 和 bounds 視為需要修復的設計問題,而非雜訊。注意每個 ℹ gap 並在步驟 6 中檢查;緊密的平行筆畫(條、線)在 16px 時會模糊,除非它們之間至少有 4 個單位的距離。重新執行,直到顯示 PASS 且沒有你無法證明的警告。可用參數:--grid、--padding、--mode fill、--strict、--json。
5. 最佳化
node <skill>/scripts/optimize.mjs icons/src icons/svg
此步驟會對數字進行四捨五入、執行 SVGO(本地安裝或 npx svgo@4;離線時會回退到內建的 canonicalizer)、重新排序根屬性、並列印每個圖示的位元組數以及總 gzip 大小。也要對輸出進行 lint:node <skill>/scripts/lint.mjs icons/svg。
6. 預覽並查看,然後迭代
node <skill>/scripts/preview.mjs icons/svg --out icons/preview.png \
--sidebar "dashboard:Dashboard,kanban:Projects" --active dashboard # 如果沒有 PNG 引擎,第一次時加上 --install
使用你的圖片檢視工具按以下順序檢視 PNG 圖片:
icons/[email protected]:圖示集條和側邊欄模擬。它足夠小,可以看到所有細節。icons/[email protected]:每個圖示的每個尺寸,以及檢查視圖。它很高,如果你的檢視工具縮小顯示,請裁切它。icons/preview.png:真實的 1× 像素。
它們一起顯示:
- 一個 24/16px 的條,在淺色和深色背景上;
- 一個側邊欄模擬,包含一個活動項目和一個摺疊的快捷欄;
- 每個圖示各自一列,顯示 16/20/24/48 四種尺寸;
- 一個 4 倍檢查視圖,帶有網格、藍色關鍵線和紅色 1px 內邊距限制。
回答 design-rules §12 中的自我審查問題。典型的修正:
| 你看到的問題 | 修正方法 |
|---|---|
| 某個圖示在條中看起來較輕/較小 | 放大到其關鍵線,或加入一個框架/軸(開放的圖形看起來較輕) |
| 某個看起來較重/較複雜 | 移除細節;≤3 條線、≤6 個齒、≤2 行文字 |
| 在 16px 下,零件相接處出現模糊 | 完全連接或將間隙打開至 ≥2 單位 |
| 在檢查視圖中形狀偏向一側 | 重新置中,或為光學平衡微調 0.5-1 單位 |
| 摺疊快捷欄中的隱喻不明確 | 選擇更直接的隱喻(步驟 2) |
重複步驟 3-6,直到再次檢查時找不到任何需要修復的問題。通常需要 1-3 輪。
7. 生成框架輸出
node <skill>/scripts/build.mjs icons/svg --out src/components/icons --framework react --lang ts \
--labels "kanban:Projects,dashboard:Dashboard"
--framework react|vue|svelte|html|all;--lang ts|js;--package @app/icons 會寫入一個 sideEffects:false 的 package.json。輸出是每個圖示一個可 tree-shake 的模組、一個共享的基礎元件(包含 size、color、strokeWidth、absoluteStrokeWidth、title、className)、index 命名匯出,以及 icons.json。HTML 框架會提供 sprite.svg + usage.html。詳細資訊:references/output-formats.md。
然後,如果專案有對應的腳本(npx tsc --noEmit、npm run build),執行類型檢查或建置,並修正任何錯誤。
8. 以無障礙方式整合使用
使用 references/accessibility-and-usage.md 中的模式:
<nav aria-label>;為活動項目設定aria-current="page"以及顏色和背景色;- 圖示設定為
size-5 shrink-0並且是裝飾性的; - 純圖示按鈕需有
aria-label;登出按鈕應使用<button>; - 行高 ≥44px;使用柔和但仍能達到 3:1 對比度的顏色。
輸出格式
最後向使用者提供一份簡短報告:
- 圖示: 一個
標籤 → 元件 → 隱喻的表格,以及資料夾路徑(icons/src、icons/svg、生成的目錄)。 - 檢查結果: lint 結果(錯誤/警告)、最佳化總計(
平均 B/圖示、gzip 總計),以及你檢查過的預覽路徑,並說明你查看後做了哪些修改。 - 使用範例(根據他們的框架),包含無障礙屬性。
- 備註: 風格決策(匹配的格線/筆畫/預設)、需要鏡像處理的 RTL 圖示,以及任何你無法驗證的事項。
範例
使用者:「為我的 Next.js + Tailwind 應用程式的側邊欄製作 Dashboard、Projects、Team、Settings 的圖示。」
→ detect:React (Next) + TS + Tailwind,無圖示庫 → 規劃:dashboard/tiles, kanban, users, settings/gear → 從食譜繪製並調整 → lint PASS → 最佳化:4 個圖示,平均 ~340 B,~0.4 KB gzip → 預覽:Projects 看起來太輕,因此加入橫條;重新檢查 → 使用 --framework react 建置到 src/components/icons → 在導覽元件中使用 <DashboardIcon className="size-5 shrink-0" /> 並設定 aria-current。
參考資料
| 當你需要…時|請閱讀 |
|---|---|
| 選擇尺寸、關鍵線、半徑、間隙、隱喻,或修復預覽問題 | references/design-rules.md |
| 編寫或除錯 SVG 標記,或理解 lint 錯誤 | references/svg-code-rules.md |
| 從常見 UI 圖示的經證明幾何形狀開始(56 個已繪製字形) | references/glyph-cookbook.md + assets/cookbook/*.svg |
| 生成或手動調整 React/Vue/Svelte/Angular/HTML 輸出,或減少打包體積 | references/output-formats.md |
| 編寫使用範例:導覽/側邊欄模式、活動狀態、標籤、對比度、RTL | references/accessibility-and-usage.md |
| 更改生成元件的形狀(props、類別名稱、無障礙預設值) | templates/<framework>/,這些由 build.mjs 讀取;請在那裡編輯,永遠不要在輸出中修改 |
| 測試對此技能的修改 | evals/evals.json |
驗證清單(在報告完成前所有項目都必須為真)
- 未新增任何圖示庫;每個圖示都是為此任務繪製或從食譜調整而來。
- 整個圖示集的風格與專案現有圖示(或預設值)相匹配。
-
lint.mjs在icons/src和icons/svg上顯示 PASS;剩餘的警告已在報告中說明原因。 - 你已在最後一次修改後檢視了預覽 PNG;16px 淺色/深色行是清晰的;沒有圖示比其同類更重、更輕或更大。
- 元件由
build.mjs生成;專案的類型檢查/建置通過(若可用)。 - 使用情況:裝飾性圖示已隱藏、純圖示控制項已標籤、活動狀態不僅靠顏色區分、目標尺寸 ≥44px、對比度 ≥3:1。
- 報告包含尺寸(平均位元組/圖示、gzip 總計)和預覽路徑。