今天是个大日子 —— 我们刚刚发布了 Catalyst 的首个开发预览版,正好赶上您的节日编程时光。

Catalyst 是我们首个完全组件化、开箱即用的应用程序 UI 工具包 —— 真正的 React 组件,具有经过深思熟虑设计的 API,它们相互构建,创建真正的组件架构,就像我们在实际应用程序中所做的那样。
查看 在线演示,阅读 文档,如果您是 Tailwind UI All-Access 客户,立即下载 并在新项目中试用。
Catalyst 目前处于开发预览阶段,未来还有更多内容,但我们今天发布它,以便您可以在我们继续构建新组件并寻找使其成为更好体验的方法时立即试用。
您的组件,而非我们的
通过 Catalyst,我们着手构建一个 UI 工具包,让未来的 Stripe 或 Linear 团队在用它构建产品时会感到满意 —— 那些对设计痴迷的团队,他们希望拥有自己的 UI 组件,并且永远不会选择现成的库。
因此,它不是您安装的依赖项,而是您下载源代码并将组件复制到您自己的项目中,在那里它们成为您自己的组件系统的起点

想要更改按钮的边框半径?只需打开 button.tsx
并更改一些类。您无需打开 GitHub issue 并试图说服我们公开新的配置选项。
Catalyst 是一个“消失的 UI 工具包” —— 在您安装它六个月后,您应该几乎忘记最初的组件不是您构建的。
设计在于细节
在一个像这样的项目中,把视觉风格做好是很难的。我们带着几个目标开始了这项工作
- 保持竞争力 —— 我们想设计一些可以与当今网络上一些最精美的界面相媲美的产品。
- 保持永恒 —— 我们不想设计一些在 6 个月后看起来会过时的东西,因为它过于依赖特定的趋势。
- 保持高效 —— 无论我们设计什么,都需要让真实用户感到快速和高效,而不仅仅是在 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,在 HTML 中,单个组件很少渲染多个元素。
例如,使用 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 工作的正确方法,我们进行了大量的实验,尤其是在诸如向正确的子元素添加布局样式之类的细节方面,但是付出是值得的,这些组件使用起来真的很愉快。
由下一代 Headless UI 驱动
我们在 2020 年夏天发布了第一个版本的 Headless UI,但自从上次重大功能发布以来已经过去一年多了,因为我们一直专注于 Tailwind CSS 本身的工作。
Catalyst 是让我们再次着手 Headless UI 的完美借口,我们很快找到了许多改进项目的方法,以简化 Catalyst 本身的代码。
我们刚刚发布了 Headless UI v2.0.0-alpha.1,其中包含大量新内容
- 内置锚点定位 —— 使用 Floating UI,
Menu
、Listbox
等组件现在可以自动将其弹出窗口定位到其触发器,并根据需要在视口变化时进行调整。 - Headless 复选框组件 —— 我们添加了一个 headless
Checkbox
组件来补充我们现有的RadioGroup
组件,使其易于构建完全自定义的复选框控件。 - HTML 表单组件 —— 我们添加了
Input
、Select
、Textarea
、Label
、Description
、Fieldset
和Legend
组件,它们处理将表单字段连接在一起所需的所有 ID 生成和aria-*
属性映射。 - 改进的悬停和焦点可见检测 —— 在底层使用了来自出色的 React Aria 库的 hooks,Headless UI 现在为您的控件添加了更智能的
data-hover
和data-focus
属性,这些属性在不同设备上的行为比原生伪类更一致。 - Combobox 列表虚拟化 —— 下一个版本的 Headless UI 现在可以处理大量的 combobox 选项列表,而不会出现性能问题。
......以及更多其他改进,包括日期选择器、工具提示等等。
这些改进目前在此早期 alpha 阶段仅适用于 React,但我们计划在标记 v2.0 之前将所有这些改进也带到 Vue。
我们很快就会发布有关这些内容的文档,但我们忍不住想在假期前发布 Catalyst,即使这意味着晚几天发布 Headless UI 文档。
试用一下
Catalyst 是所有 Tailwind UI All-Access 客户的免费更新,您可以 立即下载 并开始试用这个首个版本。
为了使我们今天发布的所有内容都恰到好处,我们投入了比您想象的还要多的工作,但我们渴望获得反馈以及可以改进的方法,因此请使用它构建一些东西,并告诉我们您的想法。
我们将在假期期间花几周时间充电,但我们将在新的一年立即回到 Catalyst,致力于开发新的组件,例如应用程序布局、comboboxes、命令面板、工具提示等等。