用 Figma 搭建可裝配設(shè)計(jì)系統(tǒng)
點(diǎn)擊 ▲ 三分設(shè) 關(guān)注,和 10 萬設(shè)計(jì)師一起成長
三分設(shè) x 閱文體驗(yàn)設(shè)計(jì)YUX
隨著產(chǎn)品的不斷迭代更新,我們已使用近兩年的舊設(shè)計(jì)組件庫逐漸顯露出自由度受限、無法靈活拓展的問題。大量使用補(bǔ)丁解決方案導(dǎo)致組件體量越來越龐大,這已經(jīng)嚴(yán)重阻礙了產(chǎn)品的創(chuàng)新與升級。如今,我們認(rèn)為有必要重新規(guī)劃和構(gòu)建一套新的設(shè)計(jì)系統(tǒng),以滿足當(dāng)前和未來產(chǎn)品的需求。

這套全新的設(shè)計(jì)系統(tǒng),我們將在 Figma 中從零開始搭建。通過汲取舊系統(tǒng)的經(jīng)驗(yàn)教訓(xùn),我們將在組件的可復(fù)用性、可擴(kuò)展性和自由度等方面進(jìn)行優(yōu)化。同時,組件的職責(zé)也將被明確定義,避免功能混亂和臃腫。
在組件化開發(fā)中,有一個概念——可裝配組件思路(Composable Components),也被稱為組件復(fù)合思想。它通過將多個組件組合成一個更高層次的組件來實(shí)現(xiàn)復(fù)雜界面的構(gòu)建。核心思想是將復(fù)雜的組件分解成多個小組件,然后再將這些小組件通過組合的方式構(gòu)建成一個更高層次的組件。這樣做的好處是,可以將復(fù)雜的組件分解成多個小組件,更好地管理組件庫,降低了組件庫的復(fù)雜度,提高了組件的靈活性、復(fù)用性和可維護(hù)性。
可裝配組件思路有兩種實(shí)現(xiàn)方式:嵌套組件和插槽組件。Figma 的組件集變體(Variants)、組件屬性(Component Properties)讓這個思路在 UI 設(shè)計(jì)中變得可行。“可裝配組件”思路加上 Figma 的功能支持,使我們能夠以全新的方式思考和構(gòu)建組件庫,最終提升界面設(shè)計(jì)的質(zhì)量和效率。它是我們起點(diǎn)讀書App在組件庫建設(shè)中所采用的核心設(shè)計(jì)之道。
一個高質(zhì)量的設(shè)計(jì)系統(tǒng)可以最大限度提高產(chǎn)品交付效率,減少重復(fù)工作,保證視覺與交互的一致性,這使其成為設(shè)計(jì)團(tuán)隊(duì)必不可少的基礎(chǔ)設(shè)施與工具。如果在初期構(gòu)建設(shè)計(jì)系統(tǒng)時采用單一龐大組件的方式,這雖在早期可以迅速滿足需求,但隨產(chǎn)品發(fā)展與業(yè)務(wù)變化,這類組件難以擴(kuò)展,最終導(dǎo)致系統(tǒng)難以維護(hù)甚至完全失效,無法實(shí)際發(fā)揮其作用。
要構(gòu)建一套全面高可用的設(shè)計(jì)系統(tǒng),我們需要從多角度進(jìn)行思考與規(guī)劃。這不僅需要考慮到組件的拆分與設(shè)計(jì),也需要結(jié)合產(chǎn)品需求與實(shí)際使用場景,只有深入理解使用者的真實(shí)需求,才能構(gòu)建一套可持續(xù)維護(hù)、拓展的設(shè)計(jì)系統(tǒng)。
對組件進(jìn)行合理地拆分并抽象化,避免單一龐大組件的設(shè)計(jì)。原組件拆分為相對獨(dú)立的子組件,可以自由組合生成完整的組件,并實(shí)現(xiàn)跨”父組件“使用,這不但提高了組件的靈活性與擴(kuò)展性,也方便后續(xù)的替換與維護(hù)。
采用”子組件“架構(gòu),我們需要考慮好組件拆分的粒度,避免子組件過于細(xì)碎導(dǎo)致系統(tǒng)復(fù)雜度提高。同時,子組件與父組件的組合關(guān)系也需要設(shè)計(jì)得當(dāng),確保其自由組合與靈活變化。只有在設(shè)計(jì)框架層面實(shí)現(xiàn)組件的模塊化,才能構(gòu)建一套真正靈活可擴(kuò)展的設(shè)計(jì)系統(tǒng)。
復(fù)雜組件由多個層級組成,每個層有它特定的功能,組件粒度分離的同時也需要屬性分離,這有助于提高復(fù)雜組件的可維護(hù)性。屬性分層是通過更改實(shí)例(Instance Swap)來分層化管理不同模塊,在同一組件中,我們可以通過更改實(shí)例來更改文本、圖像和其他元素,而不必每次創(chuàng)建新的組件。
以 NavBar 組件為例,向下的子組件包括了 NavBarRight,它是通過多個 Swap 子組件組成,Swap 可以置換為 Button、CheckBoxes 等子組件,Button 再向下拆分還包含 IconBtn、TextBtn 等,IconBtn 作為基礎(chǔ)原子組件還可以進(jìn)行 Size、Style、Badge 等信息的切換,搭配 Dropdown 組件還可以封裝為 More、Sort 等,理論上可以一直往下拓展。
使用及維護(hù)舊組件庫的過程中,擴(kuò)展性是我們?nèi)粘5龅阶畲蟮碾y題,一是父組件的橫向擴(kuò)展困難,往往一個新的需求就需要擴(kuò)展多個父組件;二是子組件的垂直擴(kuò)展能力,原本的子組件抽象程度低、鏈接關(guān)系單一,只能通過增加量級來適配各種需求環(huán)境。而新的設(shè)計(jì)系統(tǒng)可以通過 Variants(變體)、Instance Swap(更改實(shí)例) 來對組件的屬性、類型進(jìn)行擴(kuò)展,以此來承載更高的負(fù)荷。
以新版 Dialog 為例,決定 Dialog 屬性的子組件為 DialogBody ,它通過 Swap 子組件(這套設(shè)計(jì)系統(tǒng)中命名為 Swap 都被歸為置換組件)組成,Swap 子組件可以與預(yù)設(shè)好的封裝組件形成置換關(guān)系,在 DialogBody 組件這一層就可以調(diào)用到最底層的 Swap 組件的預(yù)設(shè),因此只需要增加 Swap 下的封裝組件類型并整理好鏈接關(guān)系即可完成 Dialog 組件的更新。而且所有子組件的覆蓋率極高,即使不增加預(yù)設(shè),也可以通過檢索置換來完成新樣式的搭建,總之新組件的拓展方式多、自由度很高。
利用嵌套實(shí)例(Nested Instances)來實(shí)現(xiàn)屬性傳遞,讓結(jié)構(gòu)自由變換僅在側(cè)邊欄即可完成裝配。如下所示,通過側(cè)邊欄裝配即可完成從 Dialog 基礎(chǔ)組件到不同類型組件的構(gòu)建。
Dialog組件裝配演示
設(shè)計(jì)系統(tǒng)要有一定的容錯及恢復(fù)能力,盡管我們是單人進(jìn)行管理維護(hù),但拓展是很多設(shè)計(jì)伙伴來共同完成,日常的拓展主要集中在豐富子組件中,這種拓展方式讓容錯率提高很多;即使組件庫出現(xiàn)錯誤,F(xiàn)igma 也擁有較為完善的版本回溯能力。
在構(gòu)建新設(shè)計(jì)系統(tǒng)時,子組件的可開發(fā)性和可還原性非常重要,應(yīng)作為前提考量。不建議僅為追求組件結(jié)構(gòu)的美觀而設(shè)置不合理的變體(Variants),這會導(dǎo)致開發(fā)實(shí)現(xiàn)困難。
此外,API(應(yīng)用程序接口)也被我們納入了設(shè)計(jì)系統(tǒng)的構(gòu)建流程,特別是在原子組件的設(shè)計(jì)中發(fā)揮著關(guān)鍵作用。組件的接口需要清晰定義,以保證后續(xù)開發(fā)過程中能夠順利實(shí)現(xiàn)組件的功能。
簡而言之,新設(shè)計(jì)系統(tǒng)在追求美觀的同時,也注重實(shí)用性,確保組件可靠地映射到產(chǎn)品功能,可被開發(fā)人員優(yōu)雅地還原實(shí)現(xiàn)。我們通過合理的變體設(shè)定和精心設(shè)計(jì)的API,來實(shí)現(xiàn)組件的可開發(fā)性,使設(shè)計(jì)系統(tǒng)能夠真正地指導(dǎo)產(chǎn)品開發(fā)。
在構(gòu)建設(shè)計(jì)系統(tǒng)的原子組件時,如 Icon、Book、Image、Avatar、Checkboxes、Button 等,設(shè)計(jì)師會同步輸出一份 API ,并在設(shè)計(jì)稿中表達(dá)組件全部的 API 屬性。API 的建立一般是通過參考相關(guān)的開源設(shè)計(jì)系統(tǒng)的做法,結(jié)合我們產(chǎn)品的具體需求進(jìn)行提取和調(diào)整,最終輸出適合我們產(chǎn)品的API定義。同時也會預(yù)留一些屬性作為擴(kuò)展預(yù)案。當(dāng)然組件構(gòu)建過程中我們也會考慮未來的擴(kuò)展需求,避免將組件的框架結(jié)構(gòu)設(shè)計(jì)得過于死板。
組件的API屬性及Badge組件動態(tài)演示
以 Badge(氣泡) 原子組件為例,它主要用于展示一些數(shù)字或文本信息。它可以用于展示未讀通知、消息數(shù)量、狀態(tài)點(diǎn)等。組件包含以下屬性:
參數(shù)
type:氣泡類型,可選值包括text、count、icon、dot、image。
badgeLayout:數(shù)字的顯示方式,可選值包括overflow、limit、custom。
bgColor:氣泡背景顏色,可選值為顏色代碼。
border:氣泡邊框,可選值為顏色代碼。
badgeText:氣泡文字,用于展示文本信息。
badgeCount:氣泡數(shù)值,用于展示數(shù)字信息。
badgeMaxCount:氣泡最大數(shù)字,用于限制數(shù)字的最大值。
屬性
count:展示的數(shù)字,大于overflowCount時顯示為${overflowCount}+,為0時隱藏。
dot:不展示數(shù)字,只有一個小紅點(diǎn)。
overflowCount:展示封頂?shù)臄?shù)字值。
showZero:count為0時是否展示。
offset:設(shè)置狀態(tài)點(diǎn)的偏移量,格式為[水平方向, 垂直方向]。
以上信息僅展示設(shè)計(jì)能力范圍內(nèi)可整理出來的API,并不代表開發(fā)實(shí)現(xiàn)后的最終結(jié)果;開發(fā)可以通過文檔或者 Figma 查看該組件的設(shè)計(jì)結(jié)構(gòu)。
我們舊的組件庫雖然在封裝形式上比較全面,但是在使用過程中也存在一些問題:
首先,繁雜的修改項(xiàng)經(jīng)常會讓人感到困惑和混亂。另外,每當(dāng)新增一個組件類型時,父組件的 Variant 數(shù)量就會無限增長,這會導(dǎo)致組件庫最終臃腫??到無法維護(hù)的地步。
為了避免這種情況,在新設(shè)計(jì)系統(tǒng)中,我們將所有的組件都視為可重復(fù)使用的子組件。不同的界面通過調(diào)用基礎(chǔ)的原子組件并進(jìn)行組合,就可以構(gòu)建出所需的較高層次子組件。
這樣一來,子組件的粒度更小,職責(zé)更單一,也更具備可復(fù)用性。同時,組件之間的組合方式也更加靈活合理。這種新的設(shè)計(jì)思路能夠有效避免組件庫的無限膨脹,讓我們的設(shè)計(jì)系統(tǒng)繼續(xù)保持簡潔和可維護(hù)性。
Comments組件Header區(qū)演示
新的設(shè)計(jì)系統(tǒng)中以 Comments 為例,將它劃分為五個同級子組件 CommentAvatar、CommentsHeader、CommentBody、CommentToolbar、CommentsReply;以 CommentsHeader 為例,它是通過 CommentsHeaderUser、CommentsHeaderAction 組成,CommentsHeaderAction 再往下細(xì)分是通過 Button、Tag 等原子組件及預(yù)設(shè)類型再組合而成,以此層層嵌套組合。
我們可以通過組合多個子組件的方式完成書章評頁面的構(gòu)建:
1. Comments 組件與具體業(yè)務(wù)深度綁定后,封裝為 ParagraphComments 子組件。
2. 將多個 ParagraphComments 子組件進(jìn)行陣列排列組合,形成一個 List 組件。
3. 再將 List 組件與 Header 組件組合,最終構(gòu)成完整的 ParagraphCommentsPage 組件。
ParagraphCommentsPage封裝演示
當(dāng)然在實(shí)際的項(xiàng)目中,界面組件的復(fù)雜度通常會更高。例如 ParagraphComments 組件的狀態(tài)還會有多種狀態(tài),這里就不做詳細(xì)演示。
我們采用的組件命名方式有助于設(shè)計(jì)師和開發(fā)人員更好地理解組件之間的關(guān)系:
父組件負(fù)責(zé)規(guī)范約束、風(fēng)格統(tǒng)一、模塊控制等穩(wěn)定工作。
子組件用于功能擴(kuò)展、場景切換、狀態(tài)替換等變化工作。
這使不同職能的工作更加明確和便捷:
使用更少的子組件支持更多場景。
設(shè)計(jì)師可更好掌控組件,適應(yīng)產(chǎn)品需求。
減少依賴不斷新增父組件,避免添加無關(guān)功能。
更鼓勵設(shè)計(jì)師創(chuàng)造性思考,應(yīng)對不同需求。
總之,合理的組件命名有助于提高組件的可維護(hù)性、擴(kuò)展性和創(chuàng)造性,使設(shè)計(jì)系統(tǒng)更好地服務(wù)于產(chǎn)品設(shè)計(jì)。它是我們實(shí)現(xiàn)高效協(xié)作的重要一環(huán)。
同一個父組件下的子組件,也可以按類型進(jìn)行區(qū)分:
核心子組件:決定組件類型和基本樣式,樣式相對穩(wěn)定,如 CommentAvatar、CommentsHeader。
業(yè)務(wù)子組件:需要根據(jù)不同業(yè)務(wù)場景調(diào)整樣式,如 CommentBody。
動作子組件:決定組件的交互功能,如 CommentAction。
以 Comments 組件為例,它包含多種類型的子組件。核心子組件定型了組件的基本樣式;業(yè)務(wù)子組件實(shí)現(xiàn)不同場景的樣式擴(kuò)展;動作子組件提供交互功能。
當(dāng)然,并不是所有的組件都需要這么復(fù)雜的子組件結(jié)構(gòu)。只有較高復(fù)雜度的組件才需要進(jìn)行這種劃分,以保持結(jié)構(gòu)的清晰和可維護(hù)性。
合理地對子組件進(jìn)行類型區(qū)分,有助于設(shè)計(jì)師更好地思考組件的職責(zé)劃分,提高組件系統(tǒng)的彈性與擴(kuò)展性。這是構(gòu)建可擴(kuò)展設(shè)計(jì)系統(tǒng)的重要方法之一。
在構(gòu)建子組件時,我們可以通過對原子組件進(jìn)行約束,來實(shí)現(xiàn)更好的樣式控制。假設(shè)一個原子組件理論上支持100種樣式變化,但在具體應(yīng)用場景中,我們只需要使用其中5種左右的樣式。此時子組件在調(diào)用原子組件進(jìn)行封裝時,可以對其進(jìn)行條件約束,只預(yù)設(shè)封裝需要的那幾種接口(樣式)。
以 CommentToolbarAction-Right 子組件為例,它封裝了以 IconBtn 為基礎(chǔ)的動作子組件,同時還預(yù)設(shè)了該動作組件的狀態(tài)變體,如 Initial、Active、Succeed 等。這種封裝提高了調(diào)用效率,子組件只暴露必要的接口(樣式),而非原子組件全部能力,這樣既提高了復(fù)用性,也使樣式更加一致。
Comments組件中Actions的演示
在新的設(shè)計(jì)系統(tǒng)中,父組件的主要作用是提供可選模塊,而不是限定組合方式。父組件需提供足夠豐富的可選模塊,允許使用者自由組合,以適應(yīng)不同的使用場景和需求。這既保證了系統(tǒng)的規(guī)范性,也不失靈活性。
父組件要預(yù)設(shè)通用的布局結(jié)構(gòu),但不應(yīng)固定模塊的具體搭配。如 List 組件預(yù)設(shè)了 ListHeader、ListBody、ListActions 三層結(jié)構(gòu),但模塊組合可自由調(diào)整。
模板上可以預(yù)設(shè)常見的組合布局,如 List 提供了通欄布局、混排布局、卡片布局。使用者可以根據(jù)需要選擇。通過提供可選模塊與靈活布局,父組件可以最大限度地適應(yīng)不同場景下的組合需求。規(guī)范性與創(chuàng)造性并重,是新設(shè)計(jì)系統(tǒng)的核心思路。這有助于在滿足產(chǎn)品多樣性的同時,也保證系統(tǒng)的一致性。
List組件的布局演示
未來借助 Figma 新的 Variables(變量)功能,在此基礎(chǔ)上還可以輕易的實(shí)現(xiàn)柵格、主題等變量控制,達(dá)成更多的場景適配。
與預(yù)設(shè)布局相比,開放式布局給予設(shè)計(jì)更多自由空間。設(shè)計(jì)師不再局限于組件的當(dāng)前框架,可以進(jìn)行更多發(fā)散性思考。組件組合不再僵化,設(shè)計(jì)和創(chuàng)意不再反相關(guān)。如 Header 和 BookView 可以自由組合出不同形式的 BookCard。
以 BookCard 組件為例,通過 List、BookView、Toolbar 組合方案,也可以在此基礎(chǔ)上插入 Subtitle 子組件來進(jìn)行不同方案的嘗試,還可以通過結(jié)構(gòu)的調(diào)整來組合更具差異化的 Card 組件,可以通過 Subtitle、BookViewItem、Toolbar 組合成宮格排列的推薦卡片。
這種方式避免了在前期預(yù)設(shè)好的固定布局結(jié)構(gòu),無法滿足后續(xù)新的業(yè)務(wù)與功能需求的情形。相比預(yù)置布局,開放布局可以實(shí)現(xiàn)真正的積木式設(shè)計(jì),帶來更高的覆蓋面與擴(kuò)展性。以往我們更看重父組件的覆蓋率,而反推設(shè)計(jì)師不停的去拓展父組件;開放布局的新設(shè)計(jì)思路,組件的覆蓋率不僅得到提高,設(shè)計(jì)的多樣性也得到質(zhì)的提升,最重要的是再也不用頻繁的去維護(hù)組件庫了,設(shè)計(jì)效率的提升是筆者深刻感知到的。
雖然開放布局提高了覆蓋率,但也增加了設(shè)計(jì)系統(tǒng)的復(fù)雜度,我們需要進(jìn)行合理的模塊粒度劃分,既滿足靈活性需求又不致過于繁雜。同時提供清晰直觀的模塊分類與組合規(guī)則,引導(dǎo)正確使用。
開放布局是構(gòu)建可擴(kuò)展設(shè)計(jì)系統(tǒng)的有效手段之一,但其真正價(jià)值還在于能否合理引導(dǎo)使用與推動標(biāo)準(zhǔn)化,兩者缺一不可。我們需要在靈活性與統(tǒng)一性間找到平衡,我們還需要不斷學(xué)習(xí)與實(shí)踐,讓可裝配設(shè)計(jì)系統(tǒng)更強(qiáng)大。
新的設(shè)計(jì)系統(tǒng)是一個打散重組的過程,將原本一體化程度較高的大型組件從多個維度進(jìn)行抽象化、層級化剝離、拆分為帶有 API 屬性的原子組件,和封裝了業(yè)務(wù)屬性的子組件;同時充分開放設(shè)計(jì)布局給到設(shè)計(jì)師,讓設(shè)計(jì)師既可以擁有一定的設(shè)計(jì)自由度,又能確保設(shè)計(jì)規(guī)則得到有效落實(shí);置換與預(yù)設(shè)讓組件庫的拓展不再是牽一發(fā)動全身的危險(xiǎn)操作,合理劃分出預(yù)設(shè)區(qū)域和開放的置換組件,可以應(yīng)對更多不可預(yù)測的業(yè)務(wù)需求。
Figma 最大的不同在于它并不單單只是輔助 UI 做設(shè)計(jì),更多的是推進(jìn) UI 設(shè)計(jì)的變革,倒推設(shè)計(jì)師做出改變、提升自己。Figma 最開始以組件為突破口迅速搶占 Sketch 的市場,到后續(xù)的自動布局(AutoLayout)、組件集變體(Variants)、組件屬性(Component Properties),再到最新的變量(Variables),它對組件的一步步增強(qiáng),讓我們在組件的學(xué)習(xí)跟依賴上越來越高。
就拿新構(gòu)建的設(shè)計(jì)系統(tǒng)來說,它也是有時效性的,隨著設(shè)計(jì)工具的更新迭代,組件庫還有更多的可能性。未來我還將繼續(xù)探索更完善的設(shè)計(jì)系統(tǒng),也很樂意持續(xù)進(jìn)行構(gòu)建細(xì)節(jié)的整理與分享。
索引(相關(guān)名詞官方教程):
AutoLayout:自動布局
https://help.figma.com/hc/en-us/articles/360040451373-Explore-auto-layout-properties
Component Properties:組件屬性
https://help.figma.com/hc/en-us/articles/5579474826519-Explore-component-properties
Variants:變體
https://help.figma.com/hc/en-us/articles/360056440594-Create-and-use-variants
Instance Swap:更改實(shí)例
Nested Instances:嵌套實(shí)例
https://help.figma.com/hc/en-us/articles/360039150413-Swap-components-and-instances
Variables:變量
https://help.figma.com/hc/en-us/articles/14506821864087-Overview-of-variables-collections-and-modes
參考文獻(xiàn):
https://medium.com/bytebytego-system-design-alliance/system-design-blueprint-the-ultimate-guide-e27b914bf8f1
https://medium.com/eightshapes-llc/subcomponents-753ce9f6600a
https://legacy.reactjs.org/docs/components-and-props.html#composing-components
https://www.youtube.com/watch?v=Cpc9H4GLEno









