组件与区块 Components vs Blocks
@cloudflare/kumo

构建块谱系

并不是所有东西都适合放进设计系统库。Kumo 区分组件(共享的、有版本的原语) 和区块(你复制并据为己有的模式)。理解这一区别,能帮助你在保持恰当所有权层级的同时更快地构建应用。

这不只是组织偏好问题——它关乎职责。组件是我们维护、测试并管理版本的原语。区块则是有用的起点,由你扩展和改造以满足自身需求。

组件

组件是原子级、可复用的 UI 元素,构成你应用的基础。Button、Input、Dialog、Badge——这些是内容无关、上下文无关的构建块,为在任何产品中最大化复用而设计。

特点

  • 有版本且持续维护 —— API 由我们负责,修复缺陷并发布更新
  • 支持树摇 (tree-shaking) —— 只导入你用到的部分,没有冗余
  • 默认无障碍 —— 基于 Base UI 原语构建,具备完善的 ARIA 支持
  • 符合设计系统规范 —— 语义令牌、一致的变体、可预期的 API
  • 无预设假设 —— 不含业务逻辑,不预设任何产品场景

用法

直接从包中导入:

import { Button, Input, Dialog, Badge } from "@cloudflare/kumo";

// 也可以使用细粒度导入以获得更好的树摇效果
import { Button } from "@cloudflare/kumo/components/button";

当 Kumo 发布新版本时,你会自动获得缺陷修复和改进。你的代码无需改动——只需升级版本号。

区块

区块是组件的组合,用于解决常见模式,但通用性不足以进入核心库。PageHeader、ResourceList——这些是有价值的、可复用的模式,但它们可能只适用于某些产品,或需要针对具体产品做定制。

特点

  • 归你所有 —— 代码位于你的项目中,实现由你掌控
  • 完全可定制 —— 可以修改属性 (props) 允许范围之外的任何内容
  • 组合优先 —— 由 Kumo 组件构建,而非原始 HTML
  • 是起点而非限制 —— 是可扩展的模式,不是需要绕开的约束
  • 感知产品 —— 可以包含业务逻辑、布局假设和特定组合

用法

通过 CLI 安装,然后从你的项目中导入:


# 初始化配置(仅首次需要)

npx @cloudflare/kumo init

# 列出可用的区块

npx @cloudflare/kumo blocks

# 将区块安装到你的项目

npx @cloudflare/kumo add PageHeader

安装完成后,从本地路径导入:

// 路径取决于你的 kumo.json blocksDir 设置
// 默认:src/components/kumo/
import { PageHeader } from "./components/kumo/page-header/page-header";

区块代码现在归你所有。定制它、扩展它、把它拆散——你的产品需要什么就做什么。

一个实际例子

来看一个 ProductCard。它是针对特定用例的特定组件排布:

// 这是一个"区块"或"配方" —— 针对特定模式的
// 设计系统组件的特定组合

<Surface className="rounded-lg p-4">
  <img src={imgSrc} alt={imgAlt} className="rounded-md" />
  <div className="mt-3">
    <Text size="lg" weight="semibold">
      {title}
    </Text>
    <Text className="text-kumo-subtle">{description}</Text>
    <StarRating rating={rating} />
  </div>
  <div className="mt-4">
    <Button variant="primary">Add to cart</Button>
  </div>
</Surface>

所有这些组件 (Surface、Text、Button) 都来自 Kumo。但这种特定排布呢?那是你拥有并定制的模式。

决策框架

问”这是组件还是区块?“实际上是在问所有权与复用:

选择组件,当……

  • 它与内容无关 (适用于任何数据)
  • 它与上下文无关 (适用于任何布局)
  • 多个产品需要完全相同的东西
  • 无障碍和一致性最重要
  • 你希望获得自动更新与维护

选择区块,当……

  • 你需要在属性之外做定制
  • 该模式是特定于产品的
  • 它包含业务逻辑或布局假设
  • 你希望完全掌控实现
  • 你更倾向于复制粘贴而非包依赖

默认优先想”组件”。 即使在构建某个特定内容时,也问问自己:“我能用现有组件构建它吗?“答案通常是可以。组件可以组合成区块,而区块也随时可以再次拆解。

层级之间的流动

事物可以在这些类别之间流动。一个最初在应用中一次性使用的模式,可能因为被广泛使用而值得抽取为区块。一个被证明普遍有用的区块,也可能晋升为正式组件。

关键原则: 事物应当向_下_流入设计系统,而不是让过于具体的模式充斥其中、日后还需逐一清理。在把某样东西晋升为共享组件之前,先等待复用证明其价值。

这就是区块作为中间地带存在的原因。它们是值得分享的模式,但不必承担维护版本化 API 的承诺。你获得起点;演进归你所有。

总结

组件区块
交付方式npm 包导入CLI 复制到你的项目
所有权Kumo 维护你拥有并定制
更新升级版本号自动更新手动 (重新安装或合并)
定制仅限属性与 className完整源码访问
示例Button、Input、Dialog、BadgePageHeader、ResourceList
  • 安装 —— 开始使用 Kumo
  • CLI —— 安装区块并访问文档
  • 贡献指南 —— 添加新的组件和区块