用 Figma 搭建可装配设计系统

三分设

共 11688字,需浏览 24分钟

 ·

2023-08-08 17:47


点击 ▲ 三分设 关注,和 10 万设计师一起成长

三分设 x 阅文体验设计YUX

正文共:1460 字 24 图 预计阅读时间:4 分钟


随着产品的不断迭代更新,我们已使用近两年的旧设计组件库逐渐显露出自由度受限、无法灵活拓展的问题。大量使用补丁解决方案导致组件体量越来越庞大,这已经严重阻碍了产品的创新与升级。如今,我们认为有必要重新规划和构建一套新的设计系统,以满足当前和未来产品的需求。


这套全新的设计系统,我们将在 Figma 中从零开始搭建。通过汲取旧系统的经验教训,我们将在组件的可复用性、可扩展性和自由度等方面进行优化。同时,组件的职责也将被明确定义,避免功能混乱和臃肿。

在组件化开发中,有一个概念——可装配组件思路(Composable Components),也被称为组件复合思想。它通过将多个组件组合成一个更高层次的组件来实现复杂界面的构建。核心思想是将复杂的组件分解成多个小组件,然后再将这些小组件通过组合的方式构建成一个更高层次的组件。这样做的好处是,可以将复杂的组件分解成多个小组件,更好地管理组件库,降低了组件库的复杂度,提高了组件的灵活性、复用性和可维护性。

可装配组件思路有两种实现方式:嵌套组件和插槽组件。Figma 的组件集变体(Variants)、组件属性(Component Properties)让这个思路在 UI 设计中变得可行。“可装配组件”思路加上 Figma 的功能支持,使我们能够以全新的方式思考和构建组件库,最终提升界面设计的质量和效率。它是我们起点读书App在组件库建设中所采用的核心设计之道。


一个高质量的设计系统可以最大限度提高产品交付效率,减少重复工作,保证视觉与交互的一致性,这使其成为设计团队必不可少的基础设施与工具。如果在初期构建设计系统时采用单一庞大组件的方式,这虽在早期可以迅速满足需求,但随产品发展与业务变化,这类组件难以扩展,最终导致系统难以维护甚至完全失效,无法实际发挥其作用。

要构建一套全面高可用的设计系统,我们需要从多角度进行思考与规划。这不仅需要考虑到组件的拆分与设计,也需要结合产品需求与实际使用场景,只有深入理解使用者的真实需求,才能构建一套可持续维护、拓展的设计系统。


对组件进行合理地拆分并抽象化,避免单一庞大组件的设计。原组件拆分为相对独立的子组件,可以自由组合生成完整的组件,并实现跨”父组件“使用,这不但提高了组件的灵活性与扩展性,也方便后续的替换与维护。

采用”子组件“架构,我们需要考虑好组件拆分的粒度,避免子组件过于细碎导致系统复杂度提高。同时,子组件与父组件的组合关系也需要设计得当,确保其自由组合与灵活变化。只有在设计框架层面实现组件的模块化,才能构建一套真正灵活可扩展的设计系统。

复杂组件由多个层级组成,每个层有它特定的功能,组件粒度分离的同时也需要属性分离,这有助于提高复杂组件的可维护性。属性分层是通过更改实例(Instance Swap)来分层化管理不同模块,在同一组件中,我们可以通过更改实例来更改文本、图像和其他元素,而不必每次创建新的组件。


NavBar层级演示


以 NavBar 组件为例,向下的子组件包括了 NavBarRight,它是通过多个 Swap 子组件组成,Swap 可以置换为 Button、CheckBoxes 等子组件,Button 再向下拆分还包含 IconBtn、TextBtn 等,IconBtn 作为基础原子组件还可以进行 Size、Style、Badge 等信息的切换,搭配 Dropdown 组件还可以封装为 More、Sort 等,理论上可以一直往下拓展。

使用及维护旧组件库的过程中,扩展性是我们日常迭代遇到最大的难题,一是父组件的横向扩展困难,往往一个新的需求就需要扩展多个父组件;二是子组件的垂直扩展能力,原本的子组件抽象程度低、链接关系单一,只能通过增加量级来适配各种需求环境。而新的设计系统可以通过 Variants(变体)、Instance Swap(更改实例) 来对组件的属性、类型进行扩展,以此来承载更高的负荷。

以新版 Dialog 为例,决定 Dialog 属性的子组件为 DialogBody ,它通过 Swap 子组件(这套设计系统中命名为 Swap 都被归为置换组件)组成,Swap 子组件可以与预设好的封装组件形成置换关系,在 DialogBody 组件这一层就可以调用到最底层的 Swap 组件的预设,因此只需要增加 Swap 下的封装组件类型并整理好链接关系即可完成 Dialog 组件的更新。而且所有子组件的覆盖率极高,即使不增加预设,也可以通过检索置换来完成新样式的搭建,总之新组件的拓展方式多、自由度很高。

利用嵌套实例(Nested Instances)来实现属性传递,让结构自由变换仅在侧边栏即可完成装配。如下所示,通过侧边栏装配即可完成从 Dialog 基础组件到不同类型组件的构建。


Dialog组件装配演示


设计系统要有一定的容错及恢复能力,尽管我们是单人进行管理维护,但拓展是很多设计伙伴来共同完成,日常的拓展主要集中在丰富子组件中,这种拓展方式让容错率提高很多;即使组件库出现错误,Figma 也拥有较为完善的版本回溯能力。


在构建新设计系统时,子组件的可开发性和可还原性非常重要,应作为前提考量。不建议仅为追求组件结构的美观而设置不合理的变体(Variants),这会导致开发实现困难。

此外,API(应用程序接口)也被我们纳入了设计系统的构建流程,特别是在原子组件的设计中发挥着关键作用。组件的接口需要清晰定义,以保证后续开发过程中能够顺利实现组件的功能。

简而言之,新设计系统在追求美观的同时,也注重实用性,确保组件可靠地映射到产品功能,可被开发人员优雅地还原实现。我们通过合理的变体设定和精心设计的API,来实现组件的可开发性,使设计系统能够真正地指导产品开发。

在构建设计系统的原子组件时,如 Icon、Book、Image、Avatar、Checkboxes、Button 等,设计师会同步输出一份 API ,并在设计稿中表达组件全部的 API 属性。API 的建立一般是通过参考相关的开源设计系统的做法,结合我们产品的具体需求进行提取和调整,最终输出适合我们产品的API定义。同时也会预留一些属性作为扩展预案。当然组件构建过程中我们也会考虑未来的扩展需求,避免将组件的框架结构设计得过于死板。

组件的API属性及Badge组件动态演示


以 Badge(气泡) 原子组件为例,它主要用于展示一些数字或文本信息。它可以用于展示未读通知、消息数量、状态点等。组件包含以下属性:

  1. 参数

  2. type:气泡类型,可选值包括text、count、icon、dot、image。

  3. badgeLayout:数字的显示方式,可选值包括overflow、limit、custom。

  4. bgColor:气泡背景颜色,可选值为颜色代码。

  5. border:气泡边框,可选值为颜色代码。

  6. badgeText:气泡文字,用于展示文本信息。

  7. badgeCount:气泡数值,用于展示数字信息。

  8. badgeMaxCount:气泡最大数字,用于限制数字的最大值。

  9. 属性

  10. count:展示的数字,大于overflowCount时显示为${overflowCount}+,为0时隐藏。

  11. dot:不展示数字,只有一个小红点。

  12. overflowCount:展示封顶的数字值。

  13. showZero:count为0时是否展示。

  14. offset:设置状态点的偏移量,格式为[水平方向, 垂直方向]。

以上信息仅展示设计能力范围内可整理出来的API,并不代表开发实现后的最终结果;开发可以通过文档或者 Figma 查看该组件的设计结构。

我们旧的组件库虽然在封装形式上比较全面,但是在使用过程中也存在一些问题:

首先,繁杂的修改项经常会让人感到困惑和混乱。另外,每当新增一个组件类型时,父组件的 Variant 数量就会无限增长,这会导致组件库最终臃肿💥到无法维护的地步。

为了避免这种情况,在新设计系统中,我们将所有的组件都视为可重复使用的子组件。不同的界面通过调用基础的原子组件并进行组合,就可以构建出所需的较高层次子组件。

这样一来,子组件的粒度更小,职责更单一,也更具备可复用性。同时,组件之间的组合方式也更加灵活合理。这种新的设计思路能够有效避免组件库的无限膨胀,让我们的设计系统继续保持简洁和可维护性。


Comments组件Header区演示


新的设计系统中以 Comments 为例,将它划分为五个同级子组件 CommentAvatar、CommentsHeader、CommentBody、CommentToolbar、CommentsReply;以 CommentsHeader 为例,它是通过 CommentsHeaderUser、CommentsHeaderAction 组成,CommentsHeaderAction 再往下细分是通过 Button、Tag 等原子组件及预设类型再组合而成,以此层层嵌套组合。

我们可以通过组合多个子组件的方式完成书章评页面的构建:

1.  Comments 组件与具体业务深度绑定后,封装为 ParagraphComments 子组件。

2.  将多个 ParagraphComments 子组件进行阵列排列组合,形成一个 List 组件。

3.  再将 List 组件与 Header 组件组合,最终构成完整的 ParagraphCommentsPage 组件。

ParagraphCommentsPage封装演示


当然在实际的项目中,界面组件的复杂度通常会更高。例如 ParagraphComments 组件的状态还会有多种状态,这里就不做详细演示。

我们采用的组件命名方式有助于设计师和开发人员更好地理解组件之间的关系:

  • 父组件负责规范约束、风格统一、模块控制等稳定工作。

  • 子组件用于功能扩展、场景切换、状态替换等变化工作。

这使不同职能的工作更加明确和便捷:

  • 使用更少的子组件支持更多场景。

  • 设计师可更好掌控组件,适应产品需求。

  • 减少依赖不断新增父组件,避免添加无关功能。

  • 更鼓励设计师创造性思考,应对不同需求。

总之,合理的组件命名有助于提高组件的可维护性、扩展性和创造性,使设计系统更好地服务于产品设计。它是我们实现高效协作的重要一环。

同一个父组件下的子组件,也可以按类型进行区分:

核心子组件:决定组件类型和基本样式,样式相对稳定,如 CommentAvatar、CommentsHeader。

业务子组件需要根据不同业务场景调整样式,如 CommentBody。

动作子组件:决定组件的交互功能,如 CommentAction。

以 Comments 组件为例,它包含多种类型的子组件。核心子组件定型了组件的基本样式;业务子组件实现不同场景的样式扩展;动作子组件提供交互功能。

当然,并不是所有的组件都需要这么复杂的子组件结构。只有较高复杂度的组件才需要进行这种划分,以保持结构的清晰和可维护性。

合理地对子组件进行类型区分,有助于设计师更好地思考组件的职责划分,提高组件系统的弹性与扩展性。这是构建可扩展设计系统的重要方法之一。

在构建子组件时,我们可以通过对原子组件进行约束,来实现更好的样式控制。假设一个原子组件理论上支持100种样式变化,但在具体应用场景中,我们只需要使用其中5种左右的样式。此时子组件在调用原子组件进行封装时,可以对其进行条件约束,只预设封装需要的那几种接口(样式)。

以 CommentToolbarAction-Right 子组件为例,它封装了以 IconBtn 为基础的动作子组件,同时还预设了该动作组件的状态变体,如 Initial、Active、Succeed 等。这种封装提高了调用效率,子组件只暴露必要的接口(样式),而非原子组件全部能力,这样既提高了复用性,也使样式更加一致。


Comments组件中Actions的演示



在新的设计系统中,父组件的主要作用是提供可选模块,而不是限定组合方式。父组件需提供足够丰富的可选模块,允许使用者自由组合,以适应不同的使用场景和需求。这既保证了系统的规范性,也不失灵活性。

父组件要预设通用的布局结构,但不应固定模块的具体搭配。如 List 组件预设了 ListHeader、ListBody、ListActions 三层结构,但模块组合可自由调整。

模板上可以预设常见的组合布局,如 List 提供了通栏布局、混排布局、卡片布局。使用者可以根据需要选择。通过提供可选模块与灵活布局,父组件可以最大限度地适应不同场景下的组合需求。规范性与创造性并重,是新设计系统的核心思路。这有助于在满足产品多样性的同时,也保证系统的一致性。

List组件的布局演示


未来借助 Figma 新的 Variables(变量)功能,在此基础上还可以轻易的实现栅格、主题等变量控制,达成更多的场景适配。

与预设布局相比,开放式布局给予设计更多自由空间。设计师不再局限于组件的当前框架,可以进行更多发散性思考。组件组合不再僵化,设计和创意不再反相关。如 Header 和 BookView 可以自由组合出不同形式的 BookCard。

以 BookCard 组件为例,通过 List、BookView、Toolbar 组合方案,也可以在此基础上插入 Subtitle 子组件来进行不同方案的尝试,还可以通过结构的调整来组合更具差异化的 Card 组件,可以通过 Subtitle、BookViewItem、Toolbar 组合成宫格排列的推荐卡片。

这种方式避免了在前期预设好的固定布局结构,无法满足后续新的业务与功能需求的情形。相比预置布局,开放布局可以实现真正的积木式设计,带来更高的覆盖面与扩展性。以往我们更看重父组件的覆盖率,而反推设计师不停的去拓展父组件;开放布局的新设计思路,组件的覆盖率不仅得到提高,设计的多样性也得到质的提升,最重要的是再也不用频繁的去维护组件库了,设计效率的提升是笔者深刻感知到的。

虽然开放布局提高了覆盖率,但也增加了设计系统的复杂度,我们需要进行合理的模块粒度划分,既满足灵活性需求又不致过于繁杂。同时提供清晰直观的模块分类与组合规则,引导正确使用。

开放布局是构建可扩展设计系统的有效手段之一,但其真正价值还在于能否合理引导使用与推动标准化,两者缺一不可。我们需要在灵活性与统一性间找到平衡,我们还需要不断学习与实践,让可装配设计系统更强大。


新的设计系统是一个打散重组的过程,将原本一体化程度较高的大型组件从多个维度进行抽象化、层级化剥离、拆分为带有 API 属性的原子组件,和封装了业务属性的子组件;同时充分开放设计布局给到设计师,让设计师既可以拥有一定的设计自由度,又能确保设计规则得到有效落实;置换与预设让组件库的拓展不再是牵一发动全身的危险操作,合理划分出预设区域和开放的置换组件,可以应对更多不可预测的业务需求。

Figma 最大的不同在于它并不单单只是辅助 UI 做设计,更多的是推进 UI 设计的变革,倒推设计师做出改变、提升自己。Figma 最开始以组件为突破口迅速抢占 Sketch 的市场,到后续的自动布局(AutoLayout)、组件集变体(Variants)、组件属性(Component Properties),再到最新的变量(Variables),它对组件的一步步增强,让我们在组件的学习跟依赖上越来越高。

就拿新构建的设计系统来说,它也是有时效性的,随着设计工具的更新迭代,组件库还有更多的可能性。未来我还将继续探索更完善的设计系统,也很乐意持续进行构建细节的整理与分享。


索引(相关名词官方教程):

  • 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:更改实例

  • Nested Instances:嵌套实例

    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


参考文献:

  • 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



—— END ——

我们相信设计师和创造者一样是思想家

一个开放的共创学习型产品设计社区
助力全球 1 亿设计师成长

欢迎添加 ⭐️  星标 · 获取每天推荐知识分享
每天阅读充电 · 养成终身学习
「资讯」「文章」「活动」「招聘」「课程」



期待与更多优秀产品设计师一起成长
👇👇👇
扫码进群

全年住主力设友建立设计知识体系
「体系化知识研讨」
「设计·管理书籍共读」「线上职场讨论」
「实战项目共创」「大会活动交流」
分享设计/管理/职场/心得,定期直播,答疑解惑


↓↓↓点开『阅读原文』,关注星球资料库

浏览 296
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报