介绍 Catalyst:一款面向 React 的现代 UI 工具包
- 日期
- Adam Wathan
今天是激动人心的日子——我们刚刚发布了 Catalyst 的第一个开发预览版,正好赶上您的假期黑客马拉松。
Catalyst 是我们第一个完全组件化、包含电池的应用程序 UI 工具包——真正的 React 组件,具有经过精心设计的 API,这些 API 彼此构建以创建真正的组件架构,就像我们在实际应用程序中所做的那样。
查看 实时演示,阅读 文档,如果您是 Tailwind UI 全方位访问客户,请 下载 它并在新项目中试用。
Catalyst 目前处于开发预览阶段,还有很多内容即将推出,但我们今天发布它,以便您可以在我们继续构建新组件并寻找方法使其成为更佳体验的同时,立即体验它。
您的组件,而不是我们的
使用 Catalyst,我们着手构建一个 UI 工具包,明天的 Stripe 或 Linear 会很乐意使用它来构建他们的产品——设计痴迷的团队,他们希望拥有自己的 UI 组件,并且永远不会选择现成的库。
因此,它不是您安装的依赖项,而是您下载源代码并将组件复制到您自己的项目中,在那里它们成为您自己的组件系统的起点
想要更改按钮的边框半径?只需打开 button.tsx
并更改一些类。您无需打开 GitHub 问题并试图说服我们公开新的配置选项。
Catalyst 是一款“消失的 UI 工具包”—— 安装六个月后,你几乎会忘记这些原始组件不是你自己构建的。
设计在于细节
在这样的项目中,要获得正确的视觉风格很难。我们带着几个目标开始了这个项目
- 具有竞争力—— 我们想要设计出能够与当今网络上一些最漂亮的界面相媲美的产品。
- 经久耐用—— 我们不想设计出六个月后就会过时的产品,因为它过于依赖特定的趋势。
- 高效—— 无论我们设计了什么,都需要让真实用户感觉快速高效,而不仅仅是在 Dribbble 上看起来很棒。
这需要大量的努力,也需要权衡很多因素,但我真的很喜欢最终的结果
为了具有竞争力,我们在很多细节上投入了大量精力,比如下拉菜单上的微妙背景模糊、完善表单控件上阴影和边框的融合方式,以及在对话框和切换开关等方面巧妙地使用动画。
为了经久耐用,我们试图在扁平化设计和拟物化设计之间取得平衡,并加入适量的深度提示,即使趋势发生变化,我们的组件也能保持良好的外观。
我们还从浏览器中汲取了灵感,并使用了不带任何意见的蓝色焦点环,避免选择一种可能很快就会过时的处理方式。
为了高效,我们仔细地确保仍然有足够的空白区域,但 UI 仍然足够密集,可以在屏幕上容纳大量信息。
我们还限制了过渡和动画的使用,只在感觉重要的位置使用,即使在这些位置,我们也尽量保持速度,这样就不会让人感觉在等待 UI。
Catalyst 还附带完整的暗黑模式支持,你使用 Catalyst 组件构建的任何内容都会自动在亮色模式和暗色模式之间切换。
这并不明显,但为了让东西在暗黑模式下看起来最好,我们不得不改变很多细节,比如调整阴影、将外环改为内环以模拟光照变化等等。
以 HTML 为模型
我们花费了 *大量* 时间来开发组件 API,努力使它们易于使用,无需妥协灵活性即可立即使用。
UI 库通常使用这样的 API
function Example() {
return (
<TextField
name="product_name"
label="Product name"
description="Use the name you'd like people to see in their cart."
/>
)
}
但是,当所有 props 都位于同一个组件上时,添加一个仅针对 <input>
元素本身的类就变得很困难。
最终,这导致我们创建了与 HTML 非常相似的 API,在这些 API 中,单个组件很少渲染多个元素。
例如,使用 Catalyst 创建一个文本字段看起来像这样
import { Description, Field, Label } from '@/components/fieldset'
import { Input } from '@/components/input'
function Example() {
return (
<Field>
<Label>Product name</Label>
<Description>Use the name you'd like people to see in their cart.</Description>
<Input name="product_name" />
</Field>
)
}
通过保持这种可组合性,可以轻松地限制输入的宽度,而不会限制任何其他元素的宽度
import { Description, Field, Label } from '@/components/fieldset'
import { Input } from '@/components/input'
function Example() {
return (
<Field>
<Label>Product name</Label>
<Description>Use the name you'd like people to see in their cart.</Description>
<Input name="product_name" />
<Input name="product_name" className="max-w-sm" />
</Field>
)
}
它还使将描述移动到输入 *下方* 而不是上方变得很容易
import { Description, Field, Label } from '@/components/fieldset'
import { Input } from '@/components/input'
function Example() {
return (
<Field>
<Label>Product name</Label>
<Description>Use the name you'd like people to see in their cart.</Description>
<Input name="product_name" className="max-w-sm" />
<Description>Use the name you'd like people to see in their cart.</Description>
</Field>
)
}
我们进行了大量的实验,才找到了使这些 API 正常工作的正确方法,尤其是在将布局样式添加到正确的子元素等细节方面,但最终的回报是值得的,这些组件使用起来真的很愉快。
由下一代无头 UI 提供支持
我们在 2020 年夏季发布了 Headless UI 的第一个版本,但由于我们一直专注于 Tailwind CSS 本身的工作,所以自上一次重大功能发布以来已经过去了一年多。
Catalyst 是我们再次接触 Headless UI 的绝佳借口,我们很快发现了很多方法可以改进项目,从而简化 Catalyst 本身的代码。
我们刚刚发布了 Headless UI v2.0.0-alpha.1,其中包含大量新内容
- 内置锚点定位 — 使用 Floating UI,
Menu
、Listbox
等组件现在可以自动定位其弹出窗口,使其锚定到触发器,并根据视窗的变化进行调整。 - 无状态复选框组件 — 我们添加了一个无状态
Checkbox
组件来补充我们现有的RadioGroup
组件,使构建完全自定义的复选框控件变得容易。 - HTML 表单组件 — 我们添加了
Input
、Select
、Textarea
、Label
、Description
、Fieldset
和Legend
组件,这些组件处理所有 ID 生成和aria-*
属性映射,您需要将表单字段连接在一起。 - 改进的悬停和焦点可见检测 — 使用来自很棒的 React Aria 库的钩子,Headless UI 现在为您的控件添加了更智能的
data-hover
和data-focus
属性,这些属性在不同设备上的行为比本机伪类更一致。 - 组合框列表虚拟化 — 下一个版本的 Headless UI 现在可以处理巨大的组合框选项列表,而不会出现性能问题。
…还有许多其他改进即将推出,包括日期选择器、工具提示等等。
这些改进目前仅限于 React,在早期 alpha 阶段,但我们计划在标记 v2.0 之前将所有这些改进带到 Vue。
我们很快就会发布这些内容的文档,但忍不住在假期之前发布 Catalyst,即使这意味着要晚几天发布 Headless UI 文档。
试试看
Catalyst 是所有 Tailwind UI 全部访问 客户的免费更新,您可以 下载它 并立即开始使用这个第一个版本。
我们投入了大量工作来确保今天发布的所有内容都完美无缺,但我们渴望得到您的反馈和改进建议,所以请使用它构建一些东西,并告诉我们您的想法。
我们将花几周时间在假期里充电,但我们将在新年回到 Catalyst,开发新的组件,例如应用程序布局、组合框、命令面板、工具提示等等。