过去五年来,我一直致力于Chakra UI的工作,同时非常自豪我们所共同取得的成绩。在增长团队的帮助下,我们每月获得超过1.9M的下载和 2M 次独立访问,同时获得超过 31K 的 Github的 Stars,这些已经成为我最有成就感的项目。
对于一个起步于单个维护开发者到成为一个面向多个框架的团队,这都是这是一次让人紧张不安、同时又令人兴奋的旅程。发展和管理核心团队是一次非常棒的旅程,我还想要再来一次。
这也就是说,我们一起来看看Chakra UI将要发生的变化,我非常兴奋想要与你分享。
快速回顾
在Chakra UI的理念中,我们的目标是创造许多易于访问的UI组件,这些组件可以被组装成复杂的 UI。我想要打造一个组件系统,任何人都可以使用,不需要掌握高级的 React 技能。
在这个过程中,样式系统、样式组件和表情是最常见。受到Brent Jackson在类型系统上的启发,我实现了很多想法来构建Chakra UI的类型基础。
// Here's a box
<Box>I'm a box</Box>
// if you want to its background red, you pass `background=red`. Feels intuitive!
<Box background="red">I'm a red box</Box>
// if you want to change the background on hover
<Box background="red" _hover={{ background: 'blue' }}> I'm a red box that turns blue on hover </Box>
符合直觉且富于弹性的类型系统是Chakra UI框架中最喜欢的一个功能,每次我使用这个功能,我都感到庆幸有Chakra这样的工具的存在(尽管是我开发的)。
根据最新围绕着Headless组件、设计语言和服务组件的趋势看,对于组件库的预期有了一个跃升,而且环境正在发生改变。
我一直在思考如何融合到Chakra中,同时最重要的一个想法是让Chakra成为设计系统的架构,让我们一起投入吧。
挑战
Chakra UI 的最大技术不足是其通过@emotion/styled
依赖实现的CSS-in-JS的运行时。对Chakra来说这不是特别的,其他类似的流程框架例如Material UI, Mantine和 Theme UI也面临相似的问题。
摆脱运行时的CSS-in-JS是我们从用户那里获得的最常见诉求,因为其限制更好的性能,减少初始化JS的负担,还能促进在React Server Components (RSC)中使用Chakra。
我可能被很多人问及,你要如何摆脱 CSS-in-JS的运行时?
另一个常见的诉求是增加更多复杂组件,例如日历、自定义选择和嵌套的菜单等等。今天,我们已经有很多 React Hooks 可以去放大,而且我们发现伴随着新的特性或者修复,对于组件如何工作的理解认知负担正在显著增加。
插播一句,我们正在致力于开发日历和自定义选择组件
当和更大的拥有更多资深和富有天赋的团队合作后,我们发现构建更鲁棒的主题解决方案,只有 light 和 dark 模式的需求,而且这将对多个解决方案有效。
最常见的诉求例如,我们如何对token平台例如 Figma 或者类型词典整合到Chakra的主题系统
需求
考虑到这些挑战,可以非常容易地说“好吧,我可以开始啦”,然后花费几个小时去构建 React 的方案。如今 ChakraUI 是一个多框架的组件库,这意味着在 Vue 中也需要花费同样的努力。我们在过去尝试过,这不是一个明智的选择,因为这导致精疲力尽和不一致的 DX。
我发现应对这些挑战的最好办法是把这些切碎成更小且更易于管理的。从工程师哲学来说,正确地定义需求是解决问题的第一步。
下文就是一些我们将要在 ChakraUI 获取的特性
- 框架无关。ChakraUI 是面相多种框架的,可以在 React、Vue、Angular、Svelete 和 Solid 中使用。这意味着任何的解决方案都必须是框架无关的。
- 设计原语。Chakra 的主题系统非常轻巧,而且在大多数用户场景下都工作良好。然而,这并不足以支持复杂的用户场景。
- 类型属性。Chakra UI的类型属性非常复合直觉且易于使用,我们需要保持这个体验,同时移除 CSS-in-JS 的运行时。
- 减少维护成本。如果架构正确的话,我们可以通过拆分指责到更小且更易于管理的模块来减少维护成本。
以上就是需求,让我见识下我们正在如何实现
实现
在 2022 年中,我注意到状态机和 XState,因为他们提供令人信服的承诺。你可以一次定义任意复杂的系统,在其他地方重复使用。他们同样提供很棒的方式去可视化和调试状态图。
这让我坠入好奇之洞,我返回来使用新的库叫做 Zag.js,其提供底层的状态机用来构建 UI 组件。
我和 Lee Robinson制作一期视频专门讨论 Chakra 的未来和我们即将做的事情。你可以从这里获取到www.youtube.com/watch?v=I5x…
那时候,我完全不知道我们将如何实现这一目标,但当我使用XState为Chakra UI的一些组件构建了一个概念验证时,情况变得更加清晰了。
破除巨石
当前,我把 Chakra 当做不同概念的巨石。我们有 React 的 hooks、组件、主题系统、样式系统以及多变的类型,这些都紧密地结合在一起。
过去一段时间,这提升了理解或者给代码库做贡献的门槛。这需要花费时间去完全理解每个部分是如何组合,导致修复 bug 比预期付出更多。
为了减少复杂性,我们把 Chakra 拆分为更小更容易管理的独立项目。
- 样式系统:零运行时 CSS-in-JS 的系统支持样式属性
- 设计标注:统一的编辑、文档和自动化的设计语言
- 状态机:一次定义组件的逻辑,在其他地方可以复用
- Headless 的 UI 组件:包装状态机的框架,所有框架的根 UI
零运行时 CSS-in-JS(Panda)
这是最常见也是最具挑战的用户诉求。
运行时 CSS-in-JS 和样式属性是功能强大的特性,使得开发者可以构建动态的 UI 组件,这些组件是可组合可预测而且易于使用。然而,这需要付出性能和运行时成本。
伴随着 React Server Components 的发布,提供编写 Chakra 组件在服务端的实现变得越来越具有决定意义。这将是性能、开发和用户体验的巨大胜利。
我们正在构建新的,与框架无关的样式解决方案,其将保持最重要的 Chakra 样式系统特性,还能在编译时导出样式,还有一个 PostCSS 插件提供导出在开发编译时导出样式。
Panda 将会对新的系统例如 CSS变量、层叠样式表以及其他 W3C 规范产生影响。
这个项目当前还在开发早期。如果你希望参与测试并帮助我们改进,请通过Twitter上联系我们或者发邮件到segun@chakra-ui.com。
组件的状态机(Zag)
在 Chakra UI 的每个组件交互都会通过状态机类型化。我们的核心目标是大多数组件应该保持函数状态,并与框架无关。
状态机使得我们可以谨慎地架构组件逻辑的状态和转换,这种方式将会带来更易于调试、易于预测和维护的组件库。
Zag.js是ChakraUI 组件的底层的状态机,我们希望去开发一个稳健的应用以及可商用的组件,这些可以在大多数框架下工作。
想要获取更多关于Zag.js信息,请访问zagjs.com,或者可以观看我和 Jason 一起学习的DEMO,www.youtube.com/watch?v=l8H…
下面是一个快速的例子,展示使用 React+Zag.js构建数字输入组件
// 1. Import the state machine
import * as numberInput from '@zag-js/number-input';
// 2. Import the React bindings
import { useMachine, normalizeProps } from '@zag-js/react';
export function NumberInput() {
// 3. Consume the machine
const [state, send] = useMachine(numberInput.machine({ id: '1', max: 50, min: -50 }));
// 4. Convert machine to a user friendly API
const api = numberInput.connect(state, send, normalizeProps);
// 5. Render the component
return (
<div {...api.rootProps}>
<label {...api.labelProps}>Enter number:</label>
<div>
<button {...api.decrementButtonProps}>DEC</button>
<input {...api.inputProps} />
<button {...api.incrementButtonProps}>INC</button>
</div>
</div>
);
}
迁移到Headless组件系统(Ark)
使用状态机来构建 UI 组件听起来是令人兴奋的,但是有时意味着复杂和恐慌。有时带来一种印象,在你开始使用之前,你需要知道或者至少学习过有关状态机。事实并非如此。
为了提升接受度,我们将 Zag.js的组件逻辑包装进 Headless 组件库,这样你就可以构建应用和设计系统。
import { NumberInput } from '@ark-ui/react';
export function Demo() {
return (
<NumberInput min={-50} max={50}
<NumberInput.Label>Label</NumberInput.Label>
<NumberInput.Field />
<NumberInput.Control>
<NumberInput.DecrementTrigger>
<button>-1</button>
</NumberInput.DecrementTrigger>
<NumberInput.IncrementTrigger>
<button>+1</button>
</NumberInput.IncrementTrigger>
</NumberInput.Control>
</NumberInput>
);
}
我们创建新的库成为 Ark,其将作为 Chakra UI 的 Headless 组件基础。
Ark 如何满足 Chakra UI
- Zag.js:UI 组件库的底层状态机
- Ark:基于Zag.js的Headless组件库
- Chakra:Ark + runtime CSS-in-JS
当 Panda 满足生产需求时,我们建议新项目从 Ark 迁移到 Panda。
设计标注平台(Ultra)
设计标注正在快速成为在产品或者web 站点的管理设计策略的标准。他们有强大的概念,帮助你构建富有弹性、可扩展和易于维护的设计系统。
Chakra UI 提供主题系统,其允许你在任意颗粒度下自定义设计标注和组件。我们还提供对语义化支持帮助开发者在应用中自动化实现 light 和暗黑模式。大多数企业级应用都需要 light 和暗黑模式。
对于大多数设计系统,除了定义,转换和分发到不同的平台和项目也是一个巨大的痛点。
我们正在构建一个 Saas 平台允许产品团队实现以下特性
- 可视化创建核心语义设计标注(并不认为是个大工程)
- 定义最佳实践,跨项目共享层和文字样式
- 根据你的标注提供自动化的文档,实现 GPT接口的查询和过滤
- 针对不同平台和项目分发设计标注
如果你希望了解更多,或者投资和捐赠项目,可以在Twitter上联系我们或者发邮件到segun@chakra-ui.com。
我如何在项目中使用
- 如果你正在构建设计系统,想要控制 API 设计、样式和包体积,请使用 Zag.js
- 如果你正在构建设计系统,想要专注在设计和体验,请使用 Ark
- 如果你正在构建应用,想要使用默认样式预定的 UI 组件,使用 Chakra 可以随着时间得到增强。
- 如果你对 CSS-in-JS的运行时满意,可以使用 Chakra UI
- 如果你对CSS-in-JS的运行时不满意,请使用 Ark 和 Panda
结语
我们仍有许多工作在进展中,而且会非常高兴与大家分享。我们的愿景是构建一套为产品团队设计系统的架构。
如果你对贡献代码、投资或者捐赠 Chakra 感兴趣,请在Twitter上联系我们或者发邮件到segun@chakra-ui.com。