Communitygithub.com

MohamedRamadanSalah/figma-lens

從 Figma 設計稿導入 UI,利用 figma-lens 導出的設計資料(design/<frame>/spec.md、tokens.json、截圖、SVG 圖示)實現像素級精準度 — 無需 Figma MCP 或 Dev Mode。每當使用者要求「從 Figma」建立、實作、比對或修復畫面/元件、提及 design/ 資料夾或 figma-lens 匯出、或想要生成符合 Figma 框架的 Flutter 或網頁(HTML/CSS/React/Tailwind)程式碼時使用。

figma-lens 是什麼?

figma-lens 是一款 Figma 外掛程式,搭配本地端橋接器使用,可將 Figma 框架以結構化格式匯出,包含精確的規格說明、標記、資產和圖示。其技能指示(SKILL.md)明確定義了AI代理的完整工作流程:首先閱讀專案根目錄下的 `design/<frame>/spec.md` 以獲取精確的尺寸、佈局樹、變數和樣式;接著分析 `sections/*.png` 獲取細節;並強制使用 `figma-lens.map.json` 中的元件映射,將 Figma 的元件和設計標記對應到專案中已存在的程式碼(Flutter 或 Web),僅在找不到對應項目時才使用原始數值。技能還包含一個關鍵的「比對與修正」循環:AI 代理會使用 `figma-lens check` 命令自動比較實際渲染結果與 Figma 設計稿的差異,產出差異報告和並排截圖,並根據報告中列出的差異(依偏差百分比排序)進行修正,直到差異 ≤ 3%。此技能主要支援 Flutter(並提供完整的 Figma 屬性到 Flutter Widget 的對應表)和 Web(CSS/Tailwind/React,並提供對應的 CSS 屬性對應表),可運行於任何支援命令列工具和 Node.js 的開發環境,例如 Claude Code、Cursor 或 Codex。

相容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/MohamedRamadanSalah/figma-lens/tree/HEAD/skill/figma-lens

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

figma-lens:建立與 Figma 相符的 UI

figma-lens 是一個 Figma 外掛程式加上本地端橋接器。使用者在 Figma 桌面版中選取框架,然後點擊 Export to Claude。橋接器會為每個框架寫入一個資料夾:

design/
  INDEX.md              ← 所有已匯出框架的清單(從這裡開始)
  <frame>/
    spec.md             ← 優先閱讀:精簡的圖層樹,包含精確數值
    spec.json           ← 完整資料(+ Figma 為每個圖層產生的 CSS),當 spec.md 不夠用時使用
    tokens.json         ← 變數(所有模式)、樣式、原始數值的使用次數
    [email protected]       ← 完整渲染(預設 2x)
    sections/NN-name.png ← 頂層區塊的全解析度裁切
    assets/*.svg        ← 圖示/向量圖,可直接使用
    images/*            ← 用作影像填充的原始點陣圖
    compare/            ← 由 `figma-lens check` 寫入(report.md、side-by-side.png、diff.png)
figma-lens.map.json     ← (專案根目錄)Figma 元件/標記 → 此專案中的實際程式碼

figma-lens 指令是來自 figma-lens 儲存庫的命令列工具(在該目錄中執行 npm link 可使其成為全域指令;否則請執行 node <figma-lens>/bin/figma-lens.js …)。執行 figma-lens help 可查看所有指令。

如果尚未匯出

  1. 為使用者的專案啟動橋接器並讓它持續在背景執行: figma-lens bridge --out <project>/design。
  2. 請使用者在 Figma 桌面版中選取框架 → 外掛程式 → 開發 → Figma Lens → Export to Claude。
  3. 讀取 design/INDEX.md 以確認匯出成功。

切勿在可以匯出設計稿時,僅根據描述猜測設計。請要求使用者進行匯出。

工作流程

  1. 完整閱讀 spec.md(檔案很小)。記下框架尺寸、佈局樹、變數和樣式,以及資產。
  2. 查看圖片。 逐一閱讀 sections/*.png 以取得細節。僅使用 [email protected] 來查看整體畫面,因為大型圖片在檢視時會被縮小。所有數值都來自 spec,切勿從像素測量中取得。
  3. 使用元件對應表(請參閱下方「元件對應表」)。spec.md 中每個 ⇒ USE … 都是強制性的:必須使用該 widget/元件及其屬性對應,並使用對應的標記((color/primary ⇒ AppColors.primary))而非原始數值。對於標記為 (not in map) 的項目,請在程式碼中搜尋既有主題和 widget(Flutter 的 ThemeData、AppColors、TextTheme、間距常數、lib/widgets;網頁的 CSS 變數、Tailwind 設定、src/components)。僅在找不到任何標記時使用原始數值,並告知使用者您新增了哪些。
  4. 重複使用元件。 標記為 component Button {Type=Primary} 的圖層應使用專案中已有的 Button widget 或具有相符屬性的元件。僅在找不到現有元件時才建立新的可重複使用元件,並將其新增至對應表。
  5. 從上到下建構,遵循樹狀結構。 自動佈局對應到 Row/Column/flex(對應表如下)。僅 @x,y 圖層(無自動佈局,或標記為 absolute)才需要使用 Stack/Positioned 或絕對定位。
  6. 使用匯出的檔案。 將 assets/*.svg 和 images/* 放入專案的資產資料夾中並加以引用。切勿重新繪製圖示,也切勿替換成不同的圖示集。
  7. 完全複製文字,包含 spec.md 中 "…" 內的大小寫、標點符號和阿拉伯文/由右至左字串。具有多個 run 行的文字需要 rich text(TextSpan / 巢狀 spans)。
  8. 使用比對與修正循環進行驗證(如下)。不要只憑閱讀程式碼就宣告畫面完成;必須透過截圖差異來證明。

比對與修正循環

建立畫面後,比對實際結果與 Figma 設計稿,並修正差異:

  1. 執行建置以顯示該畫面:
    • 網頁:啟動開發伺服器並開啟該路由。
    • Flutter web:flutter run -d web-server --web-port 8080,然後使用該 URL。
    • Flutter Android:在模擬器/裝置上執行應用程式,並導航到該畫面。
  2. 進行檢查:
    • 網頁 / Flutter web:figma-lens check --design design/<frame> --url http://localhost:<port>/<route> (檢視區會自動設定為框架的尺寸和縮放比例)。
    • Android:figma-lens check --design design/<frame> --adb --crop-top <狀態列像素高度> [--crop-bottom <導覽列像素高度>] (狀態列約 24–48 dp × 裝置密度;將其裁切掉,僅比對應用程式內容)。
  3. 閱讀 design/<frame>/compare/report.md(不符百分比、差異最大的區域以及每個區域中的 Figma 圖層 ID)並查看 compare/side-by-side.png(Figma | 建置結果 | 差異,紅色 = 不同)。
  4. 從上到下修正:先修正高度或間距差異(它們會影響下方所有內容),然後依序修正尺寸、顏色、字體排版、圓角半徑、陰影。在 spec.md 中查詢每個列出的圖層 ID 以取得精確數值。
  5. 重新執行檢查。 報告會顯示先前的分數,因此您可以查看進度。
  6. 在以下情況停止:不符比例 ≤ 3%(文字反鋸齒永遠不會達到 0),或連續兩次執行都沒有改善。然後回報最終分數以及您無法比對的項目及其原因(缺少字型、平台渲染差異、動態資料)。

規則:修正實際的程式碼,切勿欺騙差異比對(不要在應用程式內部使用設計稿的截圖或圖片)。檢查時請使用與設計稿相同的資料/文字(必要時使用模擬資料),否則文字差異將主導分數。

元件對應表

figma-lens.map.json(專案根目錄)將 Figma 元件和標記對應到此專案的程式碼:

{
  "components": {
    "Button": { "flutter": "lib/widgets/app_button.dart#AppButton", "web": "src/components/Button.tsx#Button", "props": { "Label": "label", "Type": "variant" } },
    "Icon/*": "SvgPicture.asset('assets/icons/<name>.svg')"
  },
  "tokens": { "color/primary": { "flutter": "AppColors.primary", "web": "var(--color-primary)" } }
}
  • 尚無對應表 → 執行 figma-lens map --design design。它會從匯出內容中新增每個元件和標記,並使用空值 ("")。
  • 自行填寫:在程式碼庫中搜尋每個元件(依名稱、外觀、屬性)和每個標記值;寫入 path#Symbol(或一個表達式)。僅在尚無任何內容時才保留 ""。"Prefix/*" 可匹配整個系列(例如圖示)。
  • 編輯對應表後,執行 figma-lens render design/<frame>,以便 spec.md 顯示 ⇒ USE 箭頭。橋接器也會在每次新匯出時套用該對應表。
  • 當您為未對應的元件建立新的可重複使用 widget 時,請將其新增至對應表。

閱讀 spec.md

  • 單位為設計像素,等同於 CSS px 和 Flutter 邏輯像素。切勿乘以截圖的縮放比例。
  • row|column gap G pad t,r,b,l main:X cross:Y 是自動佈局。pad 16 表示所有四個邊都是 16。gap auto 表示 space-between。
  • w:FILL h:HUG 表示每個軸的尺寸:FIXED(顯示精確尺寸)、HUG(包裹內容)或 FILL(佔用可用空間)。
  • @x,y 是父層級內的位置。absolute 表示自動佈局內絕對定位的子層級。pin H/V 給出約束條件(MIN = 左/上,MAX = 右/下,STRETCH = 兩者,CENTER,SCALE)。
  • bg A + B 從下到上列出填充。(name) 是 Figma 變數,[style name] 是 Figma 樣式。
  • 顏色為 #RRGGBB 或 #RRGGBBAA(Alpha 在後)。
  • 文字使用格式 "chars" · Family Style (weight) size/lineHeight color。lineHeight 為 px、% 或 auto。ls 是字母間距,單位為 px,或以字型大小的百分比表示。
  • radius 12 設定所有角落。radius tl,tr,br,bl 分別設定每個角落。smoothing 是 iOS 風格的角落平滑;請近似處理,或在 Flutter 中忽略(除非使用了 squircle 套件)。
  • drop-shadow x,y blur B spread S color、inner-shadow、layer-blur R、background-blur R。
  • → assets/x.svg 表示該圖層是一個圖示。使用指定尺寸的 SVG。
  • vars{itemSpacing=space/md} 表示該圖層屬性已繫結到該變數。請使用該標記。

Flutter 對應表

FigmaFlutter
column / rowColumn / Row(在 Flutter ≥ 3.27 上使用 spacing: G,否則使用 SizedBox 間距)
wrap, rowGap RWrap(spacing: G, runSpacing: R)
pad t,r,b,lPadding(padding: EdgeInsets.fromLTRB(l, t, r, b))。注意順序。
main MIN / CENTER / MAX / SPACE_BETWEENMainAxisAlignment.start / center / end / spaceBetween
cross MIN / CENTER / MAX / BASELINECrossAxisAlignment.start / center / end / baseline(baseline 需要 textBaseline)
HUG on main axismainAxisSize: MainAxisSize.min
FILL on parent's main axisExpanded(或 Flexible);grow N 設定 flex: N
FILL on parent's cross axis父層級的 CrossAxisAlignment.stretch,或 SizedBox(width: double.infinity)
FIXED w×hSizedBox(width: w, height: h)
@x,y / absoluteStack + Positioned(left: x, top: y);使用 pin 設定 right/bottom
bg solidBoxDecoration(color: Color(0xAARRGGBB))。將 Alpha 移到前面:#11223380 → 0x80112233。
gradient-linear from/toLinearGradient(begin: Alignment(fx*2-1, fy*2-1), end: Alignment(tx*2-1, ty*2-1), colors, stops),使用 spec.json 中的 from/to
radiusBorderRadius.circular(r) 或 BorderRadius.only(...)
border W color insideBorder.all(width: W, color: …)(inside 是 Flutter 的預設值;center/outside 需要 strokeAlign)
drop-shadow x,y blur B spread SBoxShadow(offset: Offset(x, y), blurRadius: B, spreadRadius: S, color: …)
background-blur RClipRRect + BackdropFilter(filter: ImageFilter.blur(sigmaX: R/2, sigmaY: R/2))
opacityOpacity(或顏色的 Alpha,適用於填充)
text size/lineHeightTextStyle(fontSize: size, height: lineHeight / size)。對於 %:height: pct/100。設定 leadingDistribution: TextLeadingDistribution.even 以匹配 Figma 的垂直置中。
weight 600FontWeight.w600
ls px / ls %letterSpacing: px / letterSpacing: size * pct / 100
ellipsis maxLines NmaxLines: N, overflow: TextOverflow.ellipsis
align CENTERtextAlign: TextAlign.center。對於由右至左的畫面,使用 TextAlign.start 和 EdgeInsetsDirectional。
assets/x.svgSvgPicture.asset('assets/…/x.svg', width:, height:)(flutter_svg)
image fill FILL / FITImage.asset(fit: BoxFit.cover / BoxFit.contain)

網頁(CSS / Tailwind / React)對應表

FigmaCSS
column / rowdisplay:flex; flex-direction: column / row; gap: Gpx
wrap, rowGap Rflex-wrap: wrap; column-gap: G; row-gap: R
pad t,r,b,lpadding: t r b l(順序與 CSS 相同)
main MIN / CENTER / MAX / SPACE_BETWEENjustify-content: flex-start / center / flex-end / space-between
cross MIN / CENTER / MAX / BASELINEalign-items: flex-start / center / flex-end / baseline
HUGwidth/height: fit-content(或直接 auto)
FILL(主軸)flex: 1 1 0; min-width: 0
FILL(交錯軸)align-self: stretch
FIXEDwidth: Wpx; height: Hpx; flex-shrink: 0
@x,y / absolute父層級 position: relative;子層級 position:absolute; left:x; top:y(使用 pin 設定 right/bottom)
顏色 #RRGGBBAA直接作為有效的 CSS
gradient-linear Ndeglinear-gradient(Ndeg, c1 p1%, c2 p2%)
drop-shadowbox-shadow: x y B S color(inner-shadow 加上 inset)
layer-blur / background-blur Rfilter: blur(R/2 px) / backdrop-filter: blur(R/2 px)
textfont: weight size/lineHeight family; letter-spacing(ls % → pct/100 em)
ellipsis maxLines Ndisplay:-webkit-box; -webkit-line-clamp:N; -webkit-box-orient:vertical; overflow:hidden
assets/x.svg<img src> 或內嵌 SVG;維持匯出的尺寸

spec.json 也包含 Figma 自身為大多數圖層產生的 CSS(css)。使用它來交叉檢查 CSS 數值;標記和佈局結構仍來自上方的樹狀結構。

規則

  • spec 中的數值優先於您在圖片中看到的內容。當兩者衝突時,請相信 spec 並提及此衝突。
  • 請勿四捨五入或「改善」數值(14 維持 14,而非 16),除非使用者要求正規化為標記。
  • 隱藏的圖層不會被匯出。請勿發明匯出中不存在的狀態(hover、error、empty);請要求那些框架的匯出。
  • 標記缺少的字型。如果字型家族未捆綁在專案中,請告知使用者並告訴他們需要新增什麼(pubspec fonts / @font-face)。
  • 對於多個斷點或狀態,請要求使用者匯出每個框架。每個框架都會變成自己的資料夾。

相關技能