Day 13 我們把一個會員頁一路拆成:
App
↓
MemberPage
↓
MemberCard
也第一次真的用到 props:
<MemberCard user={user} />
原本我以為下一步大概就是繼續往 React 裡面鑽。
結果今天碰到一個更實際的問題:
如果真的要做一個會員系統,畫面到底從哪裡來?工程師會自己打開 Figma,從空白頁開始畫嗎?
我比較想知道的其實不是「Figma 的 Rectangle 怎麼畫」,而是一般工程師拿到一個需求時,怎麼找現成範例、怎麼看設計稿,最後又怎麼把它變成 React。
所以今天先不寫新功能,第一次認真看 Figma。
打開 Figma 之後,我第一個想法很單純:
建立 Frame
→ 畫 Header
→ 畫 Sidebar
→ 畫按鈕
→ 自己慢慢排
這當然做得到。
但如果我是工程師,而且今天只是想快速做一個 SaaS / 會員系統介面,真的每次都要從空白開始嗎?
所以我跑去 Figma Community,直接搜尋:
saas dashboard
很快就看到很多現成的 Dashboard、CRM、Admin UI Kit。
今天選的是一份 CRM UI Kit。
這時候我才第一次分清楚兩個以前常常混在一起的東西:
UI Kit
= 零件庫
Template / 完整頁面
= 已經把零件組好的畫面
例如 UI Kit 裡面會看到:
Icons
Typography
Color Palette
Buttons
Forms
Form Elements
它比較像前端專案裡的:
Button
Input
Icon
Typography
Design tokens
而不是一張已經完成的網站。
這份範例裡另外有一頁:
Login & Register
打開之後,畫面不是只有一張 Login,而是:
Sign Up
Sign In
Recover
Details
Finish
這時候就比較像一個真的 user flow。
也就是使用者不是只看到「登入頁」這張圖而已,而是可能一路經過:
註冊
↓
填資料
↓
完成
或:
登入
↓
忘記密碼
↓
Recover
我以前比較容易把 Figma 想成「一張張漂亮的圖」,但這裡開始發現,它其實也在表達:
畫面彼此怎麼連起來,以及一個產品有哪些重複的結構。
一開始點整張 Sign In,只看到最外層:
Sign In
再往裡面點,Layers 開始展開:
Sign In
├─ Field title
├─ Icon
├─ Start typing...
├─ bg
├─ Frame 10
├─ Frame 13
├─ Buttons / Plain / Primary / Active
│ ├─ Label
│ └─ bg
├─ Buttons / Plain / Primary / Resting
├─ Frame 18
├─ Image
└─ Gradient bg
看到這裡,我原本很自然會想:
左邊每一個 Layer,是不是都要變成 React Component?
答案顯然不是。
例如一顆 Sign In 按鈕裡面有:
Buttons / Plain / Primary / Active
├─ Label
└─ bg
Label 只是裡面的文字,bg 只是背景圖層。
如果照 Figma Layer 一比一拆 React,可能會變成:
<Button>
<Label />
<Background />
</Button>
但這通常完全沒必要。
真正比較合理的 React Component 反而可能只是:
<Button>
Sign In
</Button>
所以今天第一個很重要的理解是:
Figma Layer 不等於 React Component。
Figma 的 Layer 是在描述畫面怎麼組成;React Component 則還要考慮責任、重複使用、資料和互動。
這份 UI Kit 裡,同一種 Button 有:
Buttons / Plain / Primary / Active
Buttons / Plain / Primary / Resting
它不是做一顆 SignInButton、再做一顆 SignUpButton。
它比較像先定義:
Button
├─ Primary
├─ Active
└─ Resting
然後實際使用時,裡面的文字才是:
Sign In
Sign Up
Save
Continue
這突然讓我想到 Day 13 的 props。
React 裡也不一定要這樣做:
<SignInButton />
<SignUpButton />
<SaveButton />
比較可能是同一個:
<Button variant="primary">
Sign In
</Button>
換地方使用:
<Button variant="primary">
Save
</Button>
所以 Figma 的 Component / Variant,和 React 的 Component / props 雖然不是同一個東西,但它們都在處理一個很像的問題:
哪些結構應該重複使用?哪些差異只需要用設定或資料傳進去?
昨天的 props 到今天第一次開始有「設計系統」的味道。
接著我點到包住 Sign In 和 Sign Up 兩顆按鈕的 Frame 13。
Figma 右邊顯示:
Auto layout
Flow: Horizontal
Width: 365 / Fill
Height: 46 / Hug
Gap: 9
Padding: 0
這一段比「按鈕是幾 px」有意思多了。
因為它其實在告訴我這個 layout 的規則。
裡面的兩個東西橫著排:
[ Sign In ] [ Sign Up ]
放到 CSS 的心智模型,很接近:
display: flex;
flex-direction: row;
之後 Tailwind 可能會看到:
<div className="flex">
代表兩個子元素之間有間距:
gap: 9px;
Tailwind 如果真的需要精準 9px,可以寫成:
<div className="flex gap-[9px]">
但實務上還要先看看整個 design system 的 spacing,不一定每次都照著畫面硬塞任意 px。
這個我一開始很容易直接翻成:
Fill = width: 100%
但這樣其實太快了。
比較好的理解是:
Fill 是「尺寸策略」:父容器能給多少空間,我就去填那個空間。
最後在 CSS 裡可能用:
width: 100%
也可能是在 flex 裡用:
flex: 1
要看父層怎麼排。
所以不能死背:
Figma Fill = Tailwind w-full
Hug contents 則比較像:
我的尺寸跟著內容長,不先把高度寫死。
例如一顆按鈕可以由文字加上 padding 自然形成高度,而不是每一顆都硬寫:
height: 46px;
這時候我才開始理解,Figma 右邊那些設定不是單純在報尺寸。
它其實是在描述:
父容器怎麼排子元素
子元素怎麼取得空間
內容改變時尺寸怎麼跟著變
如果只看今天的 Frame 13,可以先把它概念化成:
<div className="flex w-full gap-[9px]">
<Button variant="active">
Sign In
</Button>
<Button variant="resting">
Sign Up
</Button>
</div>
但這不是說看到 Figma 就要把每個數字直接翻成 Tailwind。
真正重要的是先讀懂:
Horizontal Auto Layout
↓
兩個子元素橫向排列
↓
CSS Flexbox
Gap
↓
子元素之間的距離
Fill / Hug
↓
尺寸不是只有固定 px
而是有「怎麼跟父層、內容互動」的規則
所以今天最大的修正是:
Figma 對工程師來說,不只是看一張漂亮的圖,更重要的是讀出 layout、重複結構和狀態規則。
今天沒有真的把這個登入頁寫成 React,也沒有開始背 Tailwind class。
但至少下一次再看到設計稿,不會只剩下:
這裡 365px
那裡 46px
這顆按鈕是藍色
而會開始問:
這是不是一個可重複的 Component?
這兩顆按鈕是不是同一個元件的不同狀態?
誰是父 Frame?
它是不是 Auto Layout?
是 Horizontal 還是 Vertical?
尺寸是 Fixed、Fill 還是 Hug?
這些問題其實已經很接近前端工程師真正需要從設計稿讀出的資訊。