前端组件库发展到了现在,功能已经非常完善,Ant Dedign 已经很久没有增加一个组件了,而竞争对手也做的越来越完善。用户也对前篇一律的界面感到懈怠。组件库本来是用标准化来解决业务问题,而到了现在我们又需要每个业务有自己的特色,虽然听起来很矛盾,但是随着技术的成熟,标准又富有业务特色的组件库也可以成为现实。
Material You 为「你」而来
“Material You, made for You” — Google.
自 2014 年推出以来,Material Design 作为 Google 官方的设计规范一直在跟随实际需要不断调整,从早年标志性的「汉堡菜单」到大屏时代对底栏标签的最终认可,从清一色的圆形 FAB 按钮到形状、配色多变的 Material Theming……化用 Google 的话来说,Material Design 的发展其实也是在不断应对各种变化对设计语言的需要。
而在去年 Material 发布了 Material You 功能,其中最亮眼的功能就是可以根据壁纸来对你的系统主色调进行改变,把原来标准化的系统变得更加个性化,更加的贴近用户。
Material You 以最能传达个性化特质的桌面壁纸为核心,通过基于色彩科学、交互设计与工程学的取色算法生成可以覆盖全局、所有应用的配色方案。
这个功能会让用户体验得到显著的提升,处处相同,但是处处不同。实现这个功能最重要的方案之一就是 《 Design Token》。
什么是 Design Token ?
Design Token 是设计系统中的视觉设计原子。它们是一组有着统一命名规则的实体,用于存储视觉设计部分的具体参数,比如 HEX 色值、间距、尺寸的像素等。使用它可以有帮助为 UI 开发工作维护一套具备可扩展性、一致性的视觉体系。
上面的引言是 Design Token 的官方说法,对于我们前端来说 Design Token 更像是 less 变量,每个 token 都是一个键值对。
@primary-color: #1890ff; // 全局主色
@link-color: #1890ff; // 链接色
@success-color: #52c41a; // 成功色
@warning-color: #faad14; // 警告色
@error-color: #f5222d; // 错误色
@font-size-base: 14px; // 主字号
@heading-color: rgba(0, 0, 0, 0.85); // 标题色
@text-color: rgba(0, 0, 0, 0.65); // 主文本色
@text-color-secondary: rgba(0, 0, 0, 0.45); // 次文本色
@disabled-color: rgba(0, 0, 0, 0.25); // 失效色
@border-radius-base: 2px; // 组件/浮层圆角
@border-color-base: #d9d9d9; // 边框色
@box-shadow-base: 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 6px 16px 0 rgba(0, 0, 0, 0.08),
0 9px 28px 8px rgba(0, 0, 0, 0.05); // 浮层阴影
记忆最深刻的就是 #1890ff
,这个变量在 antd 中到处都是。那么 antd 是不是已经实现了 Design Token 呢?当然不会这么简单,这个主要是因为 Ant Design 设计系统还没有经过 Design Token 的改造。
对于设计师来说 Design Token 的重要性不言而喻, Design Token 可以让设计师更方便的更新和维护设计系统,并且在多个平台和产品中混用。
「设计系统」是用来解决模块化和规模化的问题,对于 Ant Design 来说,虽然做了一些抽象,但是还远远没有到达完美。
比如我们设置 @primary-color
为一个浅色掉,那么 @text-color
就应该根据 @primary-color
计算得到。并且对于 Design Token 来说我们还有一个很重要的需求就是消费 Design Token,那么怎么做才算是一个好的基于 Design Token 的设计系统的组件库呢?
Material UI 是怎么做的?
Material UI 是基于 Material You 设计系统的 React 组件库,是现在最流行的 react 组件库。Material 比 antd 相比要前沿很多,很早之前 Material UI 就实现了一套设计系统,并且基于 css in js 的方案,让这套系统更加健壮和易用。
https://bareynol.github.io/mui-theme-creator/
https://mui.com/zh/customization/default-theme/?expand-path=$.palette
由于 js 的隔离性质,你甚至可以做到及其先进的嵌套主题,这个对于现在深受微前端困扰的我们来说,简直是太美好了。
当然你也可以用很简单的办法消费这些 token,这些都是跨平台的。
import { useTheme } from '@material-ui/core/styles';
function DeepChild() {
const theme = useTheme();
return <span>{`spacing ${theme.spacing}`}</span>;
}
作为最流行的组件库 Material UI 给我们打了一个样,让我们可以以更低的成本接入 Design Token, 那么对于业务开发前端来说,我们能获得什么?
对于开发者的收益
对于开发者来说 Design Token 也有不小的好处。由于基于js 的动态性和模块性最显而易见的好处就是样式隔离和覆盖变得更加简单了。
<Slider
defaultValue={30}
sx={{
width: 300,
color: 'success.main',
'& .MuiSlider-thumb': {
borderRadius: '1px',
},
}}
/>
我们再也不需要用 css 来覆盖组建的样式了,也不会因为这个页面覆盖导致影响了别的页面。并且我们可以不用担心两份 antd 冲突的问题。
同样的我们的样式也可以基于 token 来进行设定。
import { useTheme } from '@material-ui/core/styles';
function DeepChild() {
const theme = useTheme();
return <span>{`spacing ${theme.spacing}`}</span>;
}
<ThemeProvider<MyTheme>
theme={{
spacing: '8px',
}}
>
<DeepChild />
</ThemeProvider>
这样可以让我们的设计稿还原度变得更高,毕竟我们的设计稿也是基于 Design Token 来实现的。实现在项目中没有一行 css 简直 so easy。
代价是什么?
天下没有免费的午餐,作为一个新的方案,解决问题的同时一定会带来相应的成本。相比于传统的css 和 less 方案,Design Token 的方案必然缺少了很多的灵活性。而且还要略微学习一些新的语法。
body .ant-design-pro > .ant-layout {
min-height: 100vh;
}
<div
css={css`
padding: 32px;
background-color: hotpink;
font-size: 24px;
border-radius: 4px;
&:hover {
color: ${color};
}
`}
>
Hover to change color.
</div>
这种全局的写法虽然可以用,但是会带来很多优先级的问题,如果你是组件的开发者,那么你在写组件的时候同时也需要确定设计系统,成本会几乎加倍。
对于业务系统开发,最大的改变就是我们常见的 padding:13px
,这种写法可能要根据设计规范来进行处理,以后都需要改写成
function DeepChild() {
const theme = useTheme();
return <span style={{padding: theme.spacing }}>{`spacing ${theme.spacing}`}</span>;
}
当然对于想用 js 写一切的人来说这一切都是值得的。
一切都是为了五颜六色的中后台。