# @aoctech/ui 中文文档

规范地址：https://npmcn.com/package/%40aoctech/ui/

版本：0\.11\.0
npm 元数据更新时间：2026-10-25T20:19:45.263Z
中文译文更新时间：2026-11-08T09:26:04.198Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40aoctech/ui
原文对照：https://npmcn.com/package/%40aoctech/ui/?lang=original
项目主页：https://github.com/artur-oliveira/ctech-ui#readme
源码仓库：https://github.com/artur-oliveira/ctech-ui

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：221 kB，82 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=24
- 运行依赖：4 个
- peer 依赖：react \>=18，react-dom \>=18，@base-ui/react \>=1\.7\.0
- 首次发布：2026-08-16T16:31:51.121Z
- 最新版本发布：2026-10-25T20:19:44.878Z
- 近 30 天下载量：1838（2026-10-06 至 2026-11-04，npm 官方下载统计）
- 已发布版本数：19（近 12 个月 19 个）

## 中文简介

共享 CTech UI 原始: Base UI行为,tailwind class,无自有颜色. 完全通过消费应用的 CSS 变量.

## 安装

```sh
npm install @aoctech/ui
```

也可以使用：`pnpm add @aoctech/ui`、`yarn add @aoctech/ui`、`bun add @aoctech/ui`

## README

# @aoctech/ ui (英语)

CTech组件词汇,位于一地. Base UI 提供无障碍行为; 此软件包 拥有语义符号合同和船舶官方主题,用于账户、DFE、钱包、扑克和 计费. 每种产品都保持其特性,而不会产生相互作用或无障碍性.

```sh
npm i @aoctech/ui
```

## 消费者供应两样东西

### 1\. 官方主题合同

导入共享符牌一次并范围为产品根上的官方主题. 申请可以 扩展主题,但不能重新定义语义状态的含义.

```css
@import "tailwindcss";
@import "@aoctech/ui/styles.css";

@theme inline {
  --color-background: var(--background);
  --color-surface: var(--surface);
  --color-foreground: var(--foreground);
  --color-muted-foreground: var(--muted-foreground);
  --color-border: var(--border);
  --color-ring: var(--ring);
  --color-brand-50: var(--brand-50);
  --color-brand-600: var(--brand-600);
  --color-brand-700: var(--brand-700);
  --color-success: var(--success);
  --color-warning: var(--warning);
  --color-danger: var(--danger);
  --color-danger-strong: var(--danger-strong);
  --shadow-modal: var(--shadow-modal);
}
```

```tsx
import {ThemeProvider} from "@aoctech/ui"

export function App() {
  return <ThemeProvider theme="billing"><BillingApp /></ThemeProvider>
}
```

#### 通过您自己的 CSS 变量进行拼接: 导入 `touch.css` 仅限

`styles.css` 停车 `tokens.css` 财务报告和审定财务报表 `themes.css`,以及软件包的出入口(Drawer, Modal, 选择, RowMenu, UserMenu) 携带 `data-ctech-theme`。定义自己的应用程序 `--background`, (中文(简体) ), `--brand-600`,则使否 `ThemeProvider` 将会看到这些传送门重新漆成一个包 主题。 此类应用程序仅进口触摸规则,自0.4.1起稳定出口:

```css
@import "tailwindcss";
@import "@aoctech/ui/touch.css";
```

`touch.css` 是自成一体的(它定义了自身的 `--touch-*` 变量和输入无)。 这个 `@source` 下面的行仍然需要.

### 2\. 决 议 `@source` 线条

Tailwind v4只发出它能看到的类. 它不会扫描 `node_modules` 默认,所以不 这艘没有风格的船 是最有可能先出错的 安装.

```css
@source "../node_modules/@aoctech/ui/dist";
```

## 主题和地位是单独的合同

`account`, (中文(简体) ), `dfe`, (中文(简体) ), `wallet`, (中文(简体) ), `poker` 财务报告和审定财务报表 `billing` 改变动作,聚焦,表面和品牌花花. 这个 `success`, (中文(简体) ), `warning` 财务报告和审定财务报表 `danger` 角色保持不变。 只添加一个新产品主题 在它的调色板和对比状态之后,记录在"故事书"中.

## 密度是地表的一部分

控制默认为触摸大小(44px). 密集的地表选择通过设置一个属性来下移 它的根, 和内部的每个控制如下:

```tsx
<div data-density="compact">…</div>   {/* 32px controls */}
```

这就是为什么 `Button` 没有 `size="console"`:高度由按钮所在位置决定,而不是由每个按钮决定 呼叫网站 记得它在哪屏幕上.

舒适的应用软件内部的紧凑表面是 `DensityScope`与赤裸的属性不同,它也 到达从里面打开的封面: `Drawer`, (中文(简体) ), `Modal`, (中文(简体) ), `Select` 财务报告和审定财务报表 `RowMenu` 提交日期: 传送门,载体外 `data-density`,并遵循最近的距离 `ThemeProvider`) (中文(简体) ). 因此,一个紧凑的控制台在桌面上也有紧凑的抽屉. `Drawer`, (中文(简体) ), `Modal` 财务报告和审定财务报表 `Select` 还要一个 `density` 这个道具能超越两者.

```tsx
<ThemeProvider theme="billing">          {/* the portal: comfortable */}
  <DensityScope density="compact">       {/* the console */}
    <Drawer …/>                          {/* compact as well */}
  </DensityScope>
</ThemeProvider>
```

### 触摸:外观紧凑,44px目标

指下(粗指指下取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取 `sm`),紧凑的控制是: **抽签** 在36px和 **击出** at 44px: 一个隐形 `::after` 以它为中心 `styles.css` (也单独导出为: `@aoctech/ui/touch.css`)并按键于每个控件的 `data-slot`没有什么可以窃听的 规则:

-   目标只生长在控制短于44px的轴上,最多靠边 4px (英语). **保留 8px ()`gap-2`相邻控制之间**,在行或堆栈中:两个扩展 然后相会而永不相重叠(用更少的,后期控制会赢得共享边缘).
-   图标按钮保持正方形(36×36所取出,44×44所打出).
-   `Segmented` 片段触碰,所以它们的垂直生长 在每个密度.
-   通过其 `Field` 标签,目标位于字段内容后面:a 链接或按钮在提示或错误中保留自己的自带.
-   选择选项和菜单项是接触中的44px行.
-   其它任意绘制为控件( 以按钮为样式的链接、 标签) 的选项选择加入类 `touch-target`控制呼叫者的位置(`absolute`, (中文(简体) ), `fixed`, (中文(简体) ), `sticky`保持其立场.

## 品牌颜色和状态颜色从未相遇

`Button variant="brand"` 是唯一一个品牌颜色出现的地方. `Badge` 带有四个状态 吨数 - `neutral`, (中文(简体) ), `positive`, (中文(简体) ), `attention`, (中文(简体) ), `urgent` - 他们是 **已固定**: 从未重新注册到 和表面的口音吻合.

原因是整个家庭都看得出来 一个知道绿色徽章意味着定居的操作员 必须在每台CTech应用程序的每个屏幕上读取;音调随地表变化 声音需要每个应用程序重新学习。 也保持了温和的品牌应用程序的诚实性——账单 特拉科塔坐落在红色的危险附近 规则就是阻止两人在一地上 组件。 (按角色分列是必要的,但还不够:开账单也必须收回。) 品牌染色体下降,直到 `danger` 是屏幕上唯一饱和的颜色。 )

4个音符是同一套闭合的 CTech API 与人类可读状态字符串同时发射, 因此,徽章使服务器所说的话,而不是客户端对一个内部谜团的映射.

## 这是什么

| 构成部分 | 页:1 |
| --- | --- |
| `Button` | 备选案文 `brand` • 妇女 `outline` • 妇女 `ghost` • 妇女 `danger` • 妇女 `link`密度意识. |
| `Input` + 键 `Field` | 可见标签,提示/错误复制和无效的状态词汇. |
| `Alert` | 信息、成功、警告和危险反馈. |
| `Badge` | 四个状态 与一格相配——永远不独有颜色. |
| `Modal` | 基础UI `Dialog`:真正的焦点陷阱,滚动锁,恢复焦点,出逃. 自0.1.0起(另见 `Drawer`: `initialFocus`, (中文(简体) ), `dismissible`, (中文(简体) ), `hideClose`, (中文(简体) ), `aria`; 莫达尔也 `footer`, (中文(简体) ), `hideCancel`货币/删除确认书见 `docs/confirmation-dialogs.md`。 。 。 . |
| `PageHeader` | 一个h1,一个可选行,一个可选动作. |
| `EmptyState` | 标题,描述,可选行动. |
| `Skeleton` | 荣誉 `prefers-reduced-motion`。 。 。 . |
| `Separator` | 水平与垂直. |
| `Checkbox` | 基础UI `Checkbox`。 。 。 . |
| `Radio` + 键 `RadioGroup` | 基础UI `Radio`。 。 。 . |
| `Switch` | 基础UI `Switch`。 。 。 . |
| `DatePicker` + 键 `Calendar` | 建造在 `react-day-picker`。 。 。 . `locale` (BCP-47,默认) `"pt-BR"`· ; `"en"` 驱动日历名称,第一个工作日,显示日期(Intl)和aria副本; `labels` 覆盖单个字符串. `Modal` 财务报告和审定财务报表 `ErrorState` 一样 `locale` (莫达尔也) `labels`从0.2.0起. |
| `BottomNav` | 仅限电话主导航(隐藏于 `md`: 最多四个标签, 一个可选的中央动作, 一个可选的打开底页的“ 更多” 标签( Base UI) `Drawer`从0.3.0起. |
| `UserMenu` | Avatar( 初始或图像) 打开 Base UI `Menu`:全名和电子邮件,可选取取景切换器,额外项目,签出. 从0.3.0. |
| `CommandPalette` + 键 `CommandPaletteTrigger` + 键 `useCommandPaletteShortcut` | QQK / Ctrl+K 搜索屏幕, 操作应用程序将它当作 `entries` (单位:千美元)`{id, label, group, kind: "page" | "action", keywords?, icon?, href?, onSelect?}`) (中文(简体) ). 应用程序拥有 `entries` 财务报告和审定财务报表 `open`; 匹配为重音不敏感 (`matchEntries`,标签 > 关键词 > 组;页面通过 `renderLink` (真正的链接),动作运行 `onSelect` 对话框关闭后 . `labels` `dialog`, (中文(简体) ), `placeholder`, (中文(简体) ), `empty`, (中文(简体) ), `action`, (中文(简体) ), `trigger`, (中文(简体) ), `results`. 自0.8.0. |
| `Select` | 基础UI `Select`显示选中的标签, 永远不显示值; 可选的装饰选项 `icon`s,可选 `none` 选项,以及 `actions` ("+"Novo espaço"),只从公开列表中的媒体运行. 从0.4.0. |
| `Segmented` | 关于切换按钮的2至4个相互排斥的选择(`aria-pressed`; 有全名的文本或图标标签; `fill` 电话的全宽。 从0.4.0. |
| `RowMenu` | 一行可见"QQ"菜单( Base UI) `Menu`),默认名称"Mais ações"/"更多动作". 从0.4.0. |
| `SwipeRow` + 键 `useSwipeReveal` | 斯威普留下来透露一行的动作,在电话上. 总是配对 `RowMenu`。自0.4.0起;0.4.1 修正在行中孩子开始时取消的触摸刷. |
| `Steps` | 指导清单:目前步骤为 `aria-current="step"`;每个步骤的状态是说(`stateLabel`),而只有当前和等待步骤显示其内容. 其本无相. 从0.5.0. |
| `FileDrop` | 一个文件, 已丢弃或选中: 检查 `accept` (对照名称、MIME类型和 `type/*` 针对文件类型; 偏好 PEM 扩展名)和 `maxBytes` 在此之前 `onFile`,从不读取内容。 文件输入是键盘控件及其描述名称所选文件; 删除返回焦点到它. 44个px控制器,每个字符串一个道具. 从0.5.0. |
| `DensityScope` | 一个紧凑(或舒适)的表面,它的上覆随它而来。 从0.4.0. |

| `NetworkProvider` + 键 `OfflineBanner` + 键 `UnavailableScreen` + 键 `useNetwork` QQ网络韧性:一个健康探测器,一个可访问的下行/降级条形,以及一个完整的503页,可以自行返回. 加上无框架 `createLiveness`, (中文(简体) ), `withRetry` 财务报告和审定财务报表 `useOnlineStatus`。见 [文件/网络抗御能力](https://npmcn.com/package/%40aoctech/ui/docs/network-resilience.md). 自0.9.0

### 导航 : `BottomNav` 财务报告和审定财务报表 `UserMenu`

也不知道路线 打电话的人说哪件东西 `active` (或 `current`从 它自己的路由器,和通过 `renderLink` 因此链接导航客户端; 没有它是一个平面 `<a>` 实值 已经完成。 项目取用 `href` (链接)或 `onClick` (一个按钮).

```tsx
import Link from "next/link"
import {BottomNav, BottomNavSpacer, UserMenu, type RenderLink} from "@aoctech/ui"

const renderLink: RenderLink = props => <Link {...props} />

<UserMenu
  name={session.name}
  email={session.email}
  imageUrl={session.avatarUrl}
  views={[
    {label: "Portal", href: "/dashboard", current: !inConsole},
    {label: "Console", href: "/console/overview", current: inConsole},
  ]}
  onSignOut={logout}
  renderLink={renderLink}
/>

<main>
  {children}
  <BottomNavSpacer />   {/* keeps the page's end clear of the bar; gone from md up */}
</main>
<BottomNav
  renderLink={renderLink}
  action={{label: "Novo", icon: <Plus />, onClick: openCreate}}   // or null on screens without one
  items={[
    {label: "Resumo", icon: <Home />, href: "/console/finance", active: pathname === "/console/finance"},
    {label: "A pagar/receber", icon: <Receipt />, href: "/console/finance/bills", active: is("/bills")},
    {label: "Extrato", icon: <List />, href: "/console/finance/statement", active: is("/statement")},
    {type: "more", label: "Mais", icon: <Menu />, items: [
      {label: "Recorrências", icon: <Repeat />, href: "/console/finance/recurrences", active: is("/recurrences")},
      {label: "Cartões", icon: <CreditCard />, href: "/console/finance/cards", active: is("/cards")},
      {label: "Importar", icon: <Upload />, href: "/console/finance/import", active: is("/import")},
      {label: "Relatórios", icon: <Chart />, href: "/console/finance/reports", active: is("/reports"), group: "Análise"},
      {label: "Configuração", icon: <Settings />, href: "/console/finance/accounts", active: is("/accounts"), group: "Análise"},
    ]},
  ]}
/>
```

-   **最多四个分页**{\\fn黑体\\fs22\\bord1\\shad0\\3aHBE\\4aH00\\fscx67\\fscy66\\2cHFFFFFF\\3cH808080}行动都平分了 {\\fn黑体\\fs22\\bord1\\shad0\\3aHBE\\4aH00\\fscx67\\fscy66\\2cHFFFFFF\\3cH808080}行动是死中心 标签包成两个 线条(a后) `/` 首先,不要截断;反正要缩短.
-   **"多"标签** 当任何工作表项目是( ) 时显示活动`active` (原始内容存档于2017-03-25). overse. 工作表项目 同样的 `group` 列在该标题下。 选择一个关闭工作表; 逃离,关闭 按钮并刷新并关闭,焦点返回标签.
-   **安全区域 :** 栏杆本身由 `env(safe-area-inset-bottom)` ——应用需要 `viewport-fit=cover` 在它的视门元中, 设置非零。 清除页面的结尾 与 `<BottomNavSpacer />`,或与 `bottomNavInset` 类字符串在拥有它的容器上 垫底.
-   **总是触摸大小**随便 `data-density` 说:台上紧凑的操纵台仍然是 拇指在电话。 栏标高为72px,并有320px屏幕上至少60px宽;平板行高为48px.
-   **复制 :** `locale` (默认) `"pt-BR"`和 `labels` 与 `Modal` —— 说 `BottomNav` 标签 `nav`, (中文(简体) ), `close`· ; `UserMenu` 标签 `trigger`, (中文(简体) ), `views`, (中文(简体) ), `signOut`。 。 。 .

### 相互作用: `Segmented`, (中文(简体) ), `Select`, (中文(简体) ), `RowMenu`, (中文(简体) ), `SwipeRow`

```tsx
import {RowMenu, Segmented, Select, SwipeRow, type RowMenuItem} from "@aoctech/ui"

<Segmented
  label="Período"                       // names the group
  value={period}
  onValueChange={setPeriod}
  options={[
    {value: "6m", label: "6 m", name: "6 meses"},   // a short label carries its full name
    {value: "chart", label: <ChartIcon />, name: "Gráfico"},
  ]}
  fill                                  // share a phone's full width
/>

<Field label="Bandeira" htmlFor="brand">
  <Select
    id="brand"
    value={brand}                       // "" is "nothing chosen"
    onValueChange={setBrand}
    options={[{value: "visa", label: "Visa", icon: <VisaMark />}]}   // icons are decoration
    none="Nenhuma"                      // or `none` for the catalogue's "Nenhum" / "None"
    actions={[{label: "Nova bandeira", icon: <Plus />, onSelect: openCreate}]}
  />
</Field>
```

`Select`其动作只在开放列表中的媒体上运行(`reason === "item-press"`: 基准UI类型 “n”不能开始“Novo espaço”并离开页面.

**刷子从来都不是唯一的入口.** `SwipeRow` 在手指下显示一行的次要动作; 同样的行动也必须是一个新闻媒介,在 `RowMenu` 在行上(或者在行中插入按钮) 这儿有房间). 所揭示的条是惰性的,直到被揭发,所以键盘或屏幕读取器使用 菜单.

```tsx
const actions: RowMenuItem[] = [
  {key: "edit", label: "Editar", onSelect: openEdit},
  {key: "del", label: "Excluir", destructive: true, onSelect: confirmDelete},   // open a confirmation
]

<li>
  <SwipeRow actions={actions}>                {/* the front: opaque, it covers the actions */}
    <div className="flex items-center gap-3 py-2.5">
      <span className="flex-1">Aluguel</span>
      <RowMenu label="Mais ações: Aluguel" items={actions} />
    </div>
  </SwipeRow>
</li>
```

-   8px后手势锁定到轴上( 行集) `touch-action: pan-y`垂直拖动 保存页面的滚动,打开所显示的宽度的35%,然后反转,保存 每页打开一行,然后关闭在别处或逃逸的报刊上。 接下来 `prefers-reduced-motion`。 。 。 .
-   拖曳从不吃下个自拍; 第二指头、 取消的手势、 丢失的指针抓取或 窗口失去焦点返回行休息.
-   仅默认电话( E)`media="(max-width: 39.999rem)"`(三); `media={null}` 到处打扫.
-   对于自定义的布局, `useSwipeReveal(width, {enabled, media})` 返回时 `{open, active, rowId, offset, dragging, close, bind}`设置 : `data-swipe-row={rowId}` 在行的根并传播 `bind` 在滑动的部分.

故意地小取来. 当第二个应用需要时, 组件到达, 而不是在预期中—— 整个 取出这一点是停止 保存四份, 和一个消费者的组件是 还是一份.

提取队列和非域边界均位于 [文件/部件库存](https://npmcn.com/package/%40aoctech/ui/docs/component-inventory.md)。源调色板参考文献和添加产品的规则存在于 [文件/主题登记.md](https://npmcn.com/package/%40aoctech/ui/docs/theme-registry.md)。 。 。 .

## 测试

```sh
npm test   # node:test for pure logic, vitest + jsdom for component behaviour, then the build
```

## 故事书

```sh
npm run storybook
```

该目录包括一个主题登记册和一个覆盖国家的网页。 它的工具栏开关全部五个 主题和密度模式,使视觉漂移在组件释放前可见.

## 同伴

`react >=18`, (中文(简体) ), `react-dom >=18`, (中文(简体) ), `@base-ui/react >=1.7`和Tailwind v4 在消费应用程序.

## 常见问题

### @aoctech/ui 是什么？

共享 CTech UI 原始: Base UI行为,tailwind class,无自有颜色\. 完全通过消费应用的 CSS 变量\.

### 如何安装 @aoctech/ui？

在项目目录运行 npm install @aoctech/ui，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：react（\>=18）、react-dom（\>=18）、@base-ui/react（\>=1\.7\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @aoctech/ui 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @aoctech/ui 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @aoctech/ui 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=24。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @aoctech/ui 可以商用吗？

@aoctech/ui 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @aoctech/ui 的下载量有多少？

根据 npm 官方下载统计，@aoctech/ui 在 2026/10/06 – 2026/11/04 这 30 天内被下载 1,838 次，日均约 61 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @aoctech/ui 还在维护吗？

最新版本 0\.11\.0 发布于 2026/10/26（13 天前）；至今共发布 19 个版本，其中过去 12 个月发布了 19 个；首次发布于 2026/08/17。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

