今天是大日子 — 我们刚刚发布了 Catalyst 的第一个开发预览,正好适合您假期的动手项目。

Catalyst 是我们第一个全组件化、包含全部功能的应用 UI 套件 — 真正的 React 组件,设计精良的 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="产品名称" description="使用您希望人们在购物车中看到的名称。" /> );}
但是由于所有的属性都在同一个组件上,开始变得困难,比如仅向 <input>
元素添加一个类。
最终这引导我们使用了与 HTML 密切相似的 API,在这种情况下,单个组件渲染多个元素是很少见的。
使用 Catalyst 创建文本字段,例如看起来像这样:
import { Description, Field, Label } from "@/components/fieldset";import { Input } from "@/components/input";function Example() { return ( <Field> <Label>产品名称</Label> <Description>使用您希望人们在购物车中看到的名称。</Description> <Input name="product_name" /> </Field> );}
通过保持组件可组合,这使得在不约束其他元素宽度的情况下,轻松地限制输入的宽度:
import { Description, Field, Label } from "@/components/fieldset";import { Input } from "@/components/input";function Example() { return ( <Field> <Label>产品名称</Label> <Description>使用您希望人们在购物车中看到的名称。</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>产品名称</Label> <Description>使用您希望人们在购物车中看到的名称。</Description> <Input name="product_name" className="max-w-sm" /> <Description>使用您希望人们在购物车中看到的名称。</Description> </Field> )}
经过大量实验,我们找到了让这些 API 正常工作的正确方法,特别是在给正确的子元素添加布局样式等细节方面,但 payoff 是值得的,这些组件确实是使用的乐趣。
由下一代 Headless 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 现在可以处理巨大的组合框选项列表,而不会出现性能问题。
...还有许多其他改进即将到来,包括日期选择器、工具提示等。
在早期 alpha 阶段,这些改进目前仅针对 React,但我们计划在标记 v2.0 之前将所有这些改进也带到 Vue。
我们将很快发布这些内容的文档,但在假期前迫不及待地想将 Catalyst 发布出去,尽管这意味着要在几天后发布 Headless UI 文档。
尝试一下
Catalyst 是所有 Tailwind UI 全访问 客户的免费更新,您可以 下载它,并开始尝试这个第一个版本。
为了确保我们今天发布的每一项内容都完美无缺,我们付出了您无法想象的努力,但我们渴望反馈以及改善建议,因此使用它构建一些项目并告诉我们您的想法。
假期我们将花几周时间补充精力,但新的一年里我们将立即回归 Catalyst,继续致力于新的组件,如应用布局、组合框、命令面板、工具提示等。