Skip to content
Lenso UI

v3.0.3

升级到 RAC 1.17(依赖减少 90%)、Table 支持可展开行、采用 Apache 2.0 协议、新增 useTheme Hook、DOM 多态 render-prop API,以及若干 bug 修复。

2026 年 4 月 17 日

补丁版本:升级到 React Aria Components 1.17(依赖数量减少 90%)、Table 支持可展开行、采用 Apache 2.0 协议,为 Vite 与 CRA 应用提供 useTheme Hook、新增可在 render prop 中替换元素的 DOM 多态工具函数,以及若干 bug 修复。

安装

升级到最新版本:

npm i @lenso/tokens@latest @lenso/ui@latest

正在使用 AI 助手? 只需对它说一句「Hey Cursor,把 HeroUI 升级到最新版本」,AI 助手就会自动对比版本并应用必要的变更。了解更多请参阅 HeroUI MCP 服务器。

新增功能

React Aria Components 1.17

本次发布将 React Aria Components 升级到 v1.17.0。最大亮点是依赖整合:RAC 的传递依赖减少了 90%,安装与构建都更快。详情请查看完整的 RAC 1.17 发布说明。

Table 可展开行

Table 现在支持以可展开行的形式呈现树形数据。设置 treeColumn 并在对应单元格中渲染一个 chevron 图标即可展开 / 折叠子行——非常适合用于文件浏览器、嵌套分类以及层级数据。

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";// HeroUI v3.2.6 expandable-rows adaptation (Apache-2.0).import { useState, type Key } from "react";import * as stylex from "@stylexjs/stylex";import { Icon } from "@iconify/react";import { Table } from "@lenso/ui";type Row = { key: string; title: string; type: string; date: string; children: Row[] };const file = (key: string, title: string, date: string, children: Row[] = []): Row => ({  key,  title,  date,  children,  type: children.length ? "Directory" : "File",});const rows = [  file("1", "Documents", "10/20/2025", [    file("2", "Project", "8/2/2025", [      file("3", "Weekly Report", "7/10/2025"),      file("4", "Budget", "8/20/2025"),    ]),  ]),  file("5", "Photos", "2/3/2026", [    file("6", "Image 1", "1/23/2026"),    file("7", "Image 2", "2/3/2026"),  ]),];const styles = stylex.create({  content: { minWidth: 520 },  title: { display: "flex", alignItems: "center", gap: 4 },  chevron: { transform: "rotate(90deg)" },  collapsed: { transform: { default: "none", ":dir(rtl)": "rotate(180deg)" } },});export function ExpandableRows() {  const [expanded, setExpanded] = useState<Set<Key>>(new Set(["1"]));  const renderRow = (item: Row): React.ReactNode => (    <Table.Row itemKey={item.key} textValue={item.title}>      <Table.Cell columnKey="name">        {({ hasChildItems, isExpanded, isTreeColumn }) => (          <span {...stylex.props(styles.title)}>            {hasChildItems && isTreeColumn && (              <Table.ExpandButton aria-label={`Toggle ${item.title}`}>                <Icon                  icon="gravity-ui:chevron-right"                  width={16}                  aria-hidden="true"                  {...stylex.props(isExpanded ? styles.chevron : styles.collapsed)}                />              </Table.ExpandButton>            )}            <span>{item.title}</span>          </span>        )}      </Table.Cell>      <Table.Cell>{item.type}</Table.Cell>      <Table.Cell>{item.date}</Table.Cell>      <Table.Collection items={item.children}>{renderRow}</Table.Collection>    </Table.Row>  );  return (    <Table>      <Table.ScrollContainer>        <Table.Content          aria-label="Files"          xstyle={styles.content}          treeColumn="name"          expandedKeys={expanded}          onExpandedChange={setExpanded}        >          <Table.Header>            <Table.Column columnKey="name">Name</Table.Column>            <Table.Column columnKey="type">Type</Table.Column>            <Table.Column columnKey="date">Date Modified</Table.Column>          </Table.Header>          <Table.Body items={rows}>{renderRow}</Table.Body>        </Table.Content>      </Table.ScrollContainer>    </Table>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

useTheme Hook

对于使用 Vite 或 Create React App 搭建(没有 Next.js 主题 Provider)的纯 React 应用,可以从 @lenso/ui 中引入 useTheme。它接受任意主题名("light"、"dark"、"brutalism-light" 等),传入 "system" 则会跟随操作系统偏好。useTheme 会将主题值持久化到 localStorage,并在 <html> 元素上同步设置 data-theme 与 class,二者均为解析后的主题名。

"use client";
import { Button, useTheme } from "@lenso/ui";
export function ThemeSwitch() {  const { theme, setTheme } = useTheme("light");
  return (    <div className="flex gap-2">      <Button onPress={() => setTheme("light")}>        Light      </Button>      <Button onPress={() => setTheme("dark")}>        Dark      </Button>      <Button onPress={() => setTheme("system")}>        System      </Button>      <Button onPress={() => setTheme("brutalism-light")}>        Brutalism Light      </Button>      <span className="text-sm opacity-70">Current: {theme}</span>    </div>  );}

DOM 多态工具

DOM 多态辅助工具让那些没有基于 React Aria 基元构建的轻量级组件,也能通过 render prop 切换其宿主元素。

示例: 将 Card 组件渲染为 <button />

<Card<"button"> render={(props) => <button {...props} />} />

协议变更

HeroUI 现已采用 Apache License 2.0 协议,取代此前的 MIT 协议。Apache 2.0 同样提供宽松的使用自由,并在此基础上增加了显式的专利授权,提供更进一步的法律保护。现有用户无需进行任何操作。

Bug 修复

  • Tabs:限定 secondary 变体样式的作用范围,嵌套的 tab 组将不再继承父级变体(#6384)

依赖更新

  • React Aria Components:从 1.16.0 升级到 1.17.0
  • @react-aria/utils:从 3.33.1 升级到 3.34.0
  • @react-types/shared:从 3.33.1 升级到 3.34.0
  • @internationalized/date:从 3.12.0 升级到 3.12.1

链接

贡献者

感谢每一位为本次发布做出贡献的开发者!

HeroUI contributors