# @codefusion-cc/ui 中文文档

规范地址：https://npmcn.com/package/%40codefusion-cc/ui/

版本：0\.2\.9
npm 元数据更新时间：2026-11-09T08:31:05.736Z
中文译文更新时间：2026-11-10T08:09:21.775Z
软件包许可：MIT

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

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

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

- 包体积（解压后）：412 kB，70 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=20
- 运行依赖：0 个
- peer 依赖：vite \>=8，react \>=19，react-dom \>=19，tailwindcss \>=4\.1，tailwind-merge \>=3
- 首次发布：2026-10-13T05:59:27.827Z
- 最新版本发布：2026-11-09T08:31:05.495Z
- 近 30 天下载量：2150（2026-10-10 至 2026-11-08，npm 官方下载统计）
- 已发布版本数：11（近 12 个月 11 个）

## 中文简介

符号契约 每一个代码融合的外观都填满了, 套件建在它上:打出的角色(颜色、字体、光线、阴影、控制高度、运动), 定义在编译时间检查, WCAG 2.2 AA的外观问题和光和暗中的目标大小, C

## 安装

```sh
npm install @codefusion-cc/ui
```

也可以使用：`pnpm add @codefusion-cc/ui`、`yarn add @codefusion-cc/ui`、`bun add @codefusion-cc/ui`

## README

# @ codamunation-cc/ ui

设计标志每个CodeFusion app 都建立在它之上,其组件也建立在它之上: 一个角色契约(page, page, p, 墨水、口音、状态颜色、6个图表颜色、字体、弧度、阴影、控制高度、运动等 它,一个在构建时将外观变成一个样式表的Vite插件,以及一个用 Tailwind 绘制的套件 角色。 。 。 在写时检查一个外观: TypeScript 拒绝一个被排除在外的角色,或者合同没有一个角色,以及 根据WCAG 2.2 AA,在任何一对颜色上,建筑都失败了.

```sh
npm install @codefusion-cc/ui
```

| 条目 | 它所持有的 |
| --- | --- |
| `@codefusion-cc/ui/looks` | `defineLook`, (中文(简体) ), `defineAppTokens`, (中文(简体) ), `lookProblems`, (中文(简体) ), `looksCss`, (中文(简体) ), `lookTokens`合同(`ROLES`, (中文(简体) ), `PAIRS`及其类型 |
| `@codefusion-cc/ui/vite` | `uiLooks()`: 外观为 CSS, 而 `/__looks` 开发中的预览; `uiButtons()`数字 : `data-button="secondary"` 在静态 HTML 中变为 `buttonClass`班级( 空白) `data-button` (b) 小学; `expandClassAttribute` 用于其它此类属性 |
| `@codefusion-cc/ui/button-class` | `buttonClass` 用于页面和构建工具 |
| `@codefusion-cc/ui/react` | 工具包 : `Button`, (中文(简体) ), `buttonClass`, (中文(简体) ), `buttonSizeClass`, (中文(简体) ), `Loading`, (中文(简体) ), `ErrorState`, (中文(简体) ), `Spinner`, (中文(简体) ), `UiProvider`, (中文(简体) ), `usePageLock` |
| `@codefusion-cc/ui/words` | 工具包用波兰语、英语和德语写成`pl`, (中文(简体) ), `en`, (中文(简体) ), `de`(中文(简体) ) |
| `@codefusion-cc/ui/tailwind.css` | 作为 Tailwind 主题的角色, 和工具箱的源头 Tailwind 扫描 |
| `@codefusion-cc/ui/tailwind-merge` | `createCx`: 应用程序 `cx`, 尾风- 相接而来, 了解工具包的主题值 (`tailwindMergeConfig`(中文(简体) ) |
| `@codefusion-cc/ui/react/states` | 工具包的状态列表,用于 `/__looks` 和视觉测试 |
| `@codefusion-cc/ui/page-lock` | `lockPageBehind`, (中文(简体) ), `pageScrollY`: 模式对话框或抽屉后面的页面仍保留在iOS Safari上,键盘也打开 |
| `@codefusion-cc/ui/testing` | `assertLook`, (中文(简体) ), `assertLookComplete`三个固定的外观, `defineStates` 和州登记处,合成接触`drag`, (中文(简体) ), `touch`(中文(简体) ) |
| `@codefusion-cc/ui/client` | 类型 `virtual:codefusion-ui/looks.css`,用于应用程序的 tsconfig |
| `@codefusion-cc/ui/tokens.css` | 合同本身的倒置, 对于一个没有自己的外观的页面 |
| `@codefusion-cc/ui/tokens.json` | 作为设计托肯斯的合同(DTCG 2025.10) |

## 看看这个

外观模块默认导出 `defineLook(...)`: 其名称( `data-look`),每一色和光的阴影 而对于黑暗, 和价值一样 在两者.

```ts
// src/looks/kuznia.ts
import { defineLook } from '@codefusion-cc/ui/looks'

export default defineLook({
  name: 'kuznia',
  light: {
    page: 'oklch(0.965 0.012 85)',
    surface: 'oklch(0.99 0.006 85)',
    raised: 'oklch(0.93 0.016 85)',
    ink: 'oklch(0.2 0.012 60)',
    muted: 'oklch(0.45 0.02 60)',
    line: 'oklch(0.86 0.016 80)',
    accent: 'oklch(0.5 0.19 35)',
    'accent-2': 'oklch(0.42 0.09 250)',
    'on-accent': 'oklch(0.99 0.006 85)',
    inverse: 'oklch(0.2 0.012 60)',
    'on-inverse': 'oklch(0.965 0.012 85)',
    media: 'oklch(0.9 0.012 85)',
    focus: 'var(--cf-accent)',
    ok: 'oklch(0.48 0.11 150)',
    warn: 'oklch(0.52 0.12 65)',
    danger: 'oklch(0.5 0.19 27)',
    info: 'oklch(0.45 0.12 250)',
    'chart-1': 'oklch(0.5 0.19 35)',
    'chart-2': 'oklch(0.42 0.09 250)',
    'chart-3': 'oklch(0.5 0.1 150)',
    'chart-4': 'oklch(0.55 0.13 65)',
    'chart-5': 'oklch(0.45 0.13 320)',
    'chart-6': 'oklch(0.35 0.02 60)',
    'shadow-card': '0 1px 2px oklch(0.2 0.012 60 / 0.08), 0 6px 20px -8px oklch(0.2 0.012 60 / 0.18)',
    'shadow-lift': '0 2px 4px oklch(0.2 0.012 60 / 0.1), 0 18px 40px -12px oklch(0.2 0.012 60 / 0.3)',
  },
  dark: {
    page: 'oklch(0.17 0.008 60)',
    surface: 'oklch(0.21 0.01 60)',
    raised: 'oklch(0.26 0.012 60)',
    ink: 'oklch(0.94 0.014 85)',
    muted: 'oklch(0.74 0.018 80)',
    line: 'oklch(0.34 0.014 60)',
    accent: 'oklch(0.74 0.15 40)',
    'accent-2': 'oklch(0.76 0.09 250)',
    'on-accent': 'oklch(0.17 0.008 60)',
    inverse: 'oklch(0.94 0.014 85)',
    'on-inverse': 'oklch(0.17 0.008 60)',
    media: 'oklch(0.3 0.012 60)',
    focus: 'var(--cf-accent)',
    ok: 'oklch(0.78 0.13 150)',
    warn: 'oklch(0.82 0.13 80)',
    danger: 'oklch(0.72 0.15 27)',
    info: 'oklch(0.76 0.1 250)',
    'chart-1': 'oklch(0.74 0.15 40)',
    'chart-2': 'oklch(0.76 0.09 250)',
    'chart-3': 'oklch(0.78 0.12 150)',
    'chart-4': 'oklch(0.82 0.13 80)',
    'chart-5': 'oklch(0.74 0.13 320)',
    'chart-6': 'oklch(0.85 0.02 85)',
    'shadow-card': '0 0 0 1px oklch(1 0 0 / 0.06), 0 6px 20px -8px oklch(0 0 0 / 0.6)',
    'shadow-lift': '0 0 0 1px oklch(1 0 0 / 0.08), 0 18px 40px -12px oklch(0 0 0 / 0.75)',
  },
  both: {
    'font-display': '"Fraunces", "Iowan Old Style", Georgia, serif',
    'font-body': '"Inter", system-ui, sans-serif',
    'font-mono': '"JetBrains Mono", ui-monospace, monospace',
    'radius-card': '14px',
    'radius-ctl': '10px',
    'control-touch': '44px',
    'control-mouse': '32px',
    'duration-press': '90ms',
    'duration-quick': '160ms',
    'duration-move': '280ms',
    'duration-settle': '480ms',
    'ease-out': 'cubic-bezier(0.2, 0.8, 0.2, 1)',
    'ease-in': 'cubic-bezier(0.4, 0, 1, 1)',
    'ease-state': 'cubic-bezier(0.34, 1.3, 0.5, 1)',
  },
})
```

-   **颜色** 可能出现在任何CSS标记中(oklch, hex, rgb, hsl, 实验室, `color(display-p3 …)`, (中文(简体) ), `var(--cf-<role>)` 联 合 国 其他角色,或 `color-mix()` 这些。 它们被写成OKLCH, 所测量的是书面值 读回,如Chrimium、Firefox和WebKit所画的(通过屏幕剪接频道的颜色),所以 四舍五入从不移动一对穿过它的一线;一对完全按照它的比例通过. 拒绝了,因为浏览器画它们 不同或无法测量:混合于hsl或hwb, `none` 混凝土内部,一个颜色过去 OKLCH染色体1, `light-dark()` (一个表情给出了每个模式自己的价值), `currentColor`,系统颜色和相对颜色。 互相称呼的颜色 因为CSS读作一体 `light-dark()`。 。 。 .
-   **字体** 在普通家庭中结束(`serif`, (中文(简体) ), `sans-serif`, (中文(简体) ), `system-ui`, 和单字体 `monospace`A级 家庭名称有字母、数字、空格和 `. _ & + -`。 。 。 .
-   **控制高度** 在 px 中, 鼠标至少需要44px 和 24px , 应用设定的,而不是外观. `--cf-control` 是用来指针的.
-   **会期** 变成 `0s` 当系统要求减少运动.
-   **边界**:一个值和一个app角色的描述最多有4,000个字符,一个外观的名字,一个角色的名字和 a app的前缀 64,而彩相( ) 最多可打入 8 个深. 长度在一万px或雷姆以两种方式,a 目标分钟也一样,所以一个宣布的分钟总是可以满足的. 持续时间可长达一分钟, 放松的y值将停留 10-10范围内。 一个应用最多有200个角色和400对对 `looksProblems` 最多100个外观 这个 界限适用于一个外观或应用程序给予的,一次:从中写入的CSS可能更长(一种颜色写作: (原始内容存档于2018-09-13). oklch (). 超过约束的事物在按照比例进行工作之前被拒绝,只有一个例外:在检查之前 可以计算一个对象的密钥, JavaScript 引擎列出了全部的密钥, 所以一个百万个密钥的密钥成本 但很快就会被拒绝列入清单.
-   **工作**: 一张支票(`lookProblems`, (中文(简体) ), `looksProblems`, (中文(简体) ), `appTokensProblems`, (中文(简体) ), `defineAppTokens`拥有一个工作预算, `WORK_BUDGET` 步骤,每个步骤都是有限度的工作量:经过的元素,发现的问题,a 字符读取,计算出一种颜色。 在预算之后,它回答说,投入太大无法衡量,这是一个问题 这阻止了表情被写。 每一个值都写过一次,尽管它经常被问到,而两者 花在预算的一分之一上 看上去是十倍 检查答案最多100个问题,那些停止 从被写到最后 说还有多少人 有多少人挡住.
-   **可选角色** 与众不同的是 测量方式为: `<tone>-tint` (在地上洗个澡), `<tone>-ink` (语气)和 `<tone>-line` (数量) 边缘)用于口音,ok,警告,危险和信息; `accent-hover`, (中文(简体) ), `inverse-hover` 财务报告和审定财务报表 `hover`;二级按钮的 `control-fill`, (中文(简体) ), `control-line`, (中文(简体) ), `control-ink` 联合国 `-hover`安静的那个 `ghost-ink` (在指针下,它保留了文字,取出 `hover` 纱布, 连结者 `link-ink` (口音的墨迹); `shadow-control` (无);和 `both`, (中文(简体) ), `control-pad` (20px), (中文(简体) ), `control-case` (单位:千美元)`none`,或 `uppercase` 用于按钮 设于首都, `control-tracking` (0)和 `control-disabled` (0.6,残疾或繁忙控制显示多少, 0.25改为1. 外观组合的颜色角色在两种模式或两种模式中都设置.

### 只有一个模式

一个模式的外表是这么说的。 页面将保留在该模式中,即使主题要求另一个;另一个 模式永远不会从中补齐.

```ts
export default defineLook({ name: 'papier', only: 'light', light: { … }, both: { … } })
```

类型脚本拒绝 `dark` 参与其中,和 `/__looks` 显示缺少的模式.

## 一个应用它

```ts
// vite.config.ts
import { defineConfig } from 'vite'
import { prePaintTheme } from '@codefusion-cc/theme/vite'
import { uiLooks } from '@codefusion-cc/ui/vite'
import { themeConfig } from './src/themeConfig.ts'

export default defineConfig({
  plugins: [
    prePaintTheme(themeConfig),
    uiLooks({ looks: ['./src/looks/kuznia.ts', './src/looks/noc.ts'], default: 'kuznia' }),
  ],
})
```

```ts
// src/main.ts, before anything else: the contract and every look, as CSS. No look code reaches the page.
import 'virtual:codefusion-ui/looks.css'
```

从脚本导入它, 而不是用 `@import` 从样式表另一个工具的后处理。 内容 `light-dark()` 必须到达 已写入的浏览器, 插件可以确保 Vite 的自定义将它单独保存 .

TypeScript从包的客户端类型中学习出模块,紧接Vite:

```json
// tsconfig.json
{ "compilerOptions": { "types": ["vite/client", "@codefusion-cc/ui/client"] } }
```

主题包选择外观和模式. 它设置 `data-look` 财务报告和审定财务报表 `color-scheme` 打开 `<html>`,CSS读取 都一样 默认的外观显示在页面中, 任何地方 `data-look` 在主题设定前 当它命名一个外观 应用程序不再有, 像游客的老选择.

```ts
// src/themeConfig.ts
import { defineTheme } from '@codefusion-cc/theme'

export const themeConfig = defineTheme({
  storageKey: 'myapp-theme',
  html: { class: 'dark' },
  choices: { look: { storageKey: 'myapp-look', values: ['kuznia', 'noc'], default: 'kuznia', attribute: 'data-look' } },
})
```

然后在任何地方使用角色:

```css
.card {
  background: var(--cf-surface);
  color: var(--cf-ink);
  border-radius: var(--cf-radius-card);
  box-shadow: var(--cf-shadow-card);
}
.card:hover { background: color-mix(in oklab, var(--cf-surface), var(--cf-hover)); }
button { min-height: var(--cf-control); transition: background var(--cf-duration-quick) var(--cf-ease-out); }
:focus-visible { outline: 2px solid var(--cf-focus); outline-offset: 2px; }
```

使用 Tailwind 4.1 或 稍后, 导入角色为 Tailwind 的主题, 在 Tailwind 之后, 并写入 `bg-surface`, (中文(简体) ), `text-muted`, (中文(简体) ), `border-danger-line`, (中文(简体) ), `rounded-card`, (中文(简体) ), `min-h-control`, (中文(简体) ), `shadow-lift`, (中文(简体) ), `ease-state`数字 :

```css
/* src/index.css */
@import "tailwindcss";
@import "@codefusion-cc/ui/tailwind.css";
```

每个颜色角色都是一种颜色(`bg-<role>`, (中文(简体) ), `text-<role>`, (中文(简体) ), `border-<role>`, (中文(简体) ), `bg-accent/40`),而阴也 (单位:千美元)`rounded-card`, (中文(简体) ), `rounded-ctl`),字体(`font-display`, (中文(简体) ), `font-body`, (中文(简体) ), `min-h-control`, (中文(简体) ), `px-control-pad`, (中文(简体) ), `tracking-control` 财务报告和审定财务报表 `ease-state` 这里也有 每个班都读过自己的定制地产 所以是页面的一部分 换个角度 泰尔温德没有重新定义: `font-sans`, (中文(简体) ), `shadow-sm` 财务报告和审定财务报表 `rounded-xl` 保持不变 他们是。 文件还指向了Tailwind的源头,所以工具的班级在app的样式表上降落过一次, 与它的屏幕共享.

### 级联

样式表宣布一层, `cf.tokens`外观也在里面 角色是自定义属性,所以图层 只决定谁设定它们:一个应用程序自己的 `--cf-*` 胜过任何造物主的外表.

### 再看一页

彩色角色计算地点 `data-look` 已经设定。 以其他外观或模式显示的部分页面设置在 同一元素:

```html
<section data-look="noc" style="color-scheme: dark">…</section>
```

## 应用程序的自有标志

只有一个应用程序(对话的两面,所画的作品的大小)在应用程序的前缀下,键入和 检查像合同的:

```ts
// src/looks/tokens.ts
import { defineAppTokens } from '@codefusion-cc/ui/looks'

export const hh = defineAppTokens(
  'hh',
  {
    me: { type: 'color', description: 'Your side of a conversation.', fallback: { light: '#b8460f', dark: '#f19359' } },
    ring: { type: 'dimension', description: 'The width of the speaking ring.', fallback: '3px' },
  },
  { pairs: [{ fg: '--hh-me', bg: '--cf-page', kind: 'ui' }] },
)

// in a look: app: { tokens: hh, light: { me: '#b8460f' }, dark: { me: '#f19359' }, both: { ring: '3px' } }
```

他们写成: `--hh-me` 财务报告和审定财务报表 `--hh-ring`,注册和给他们的倒扣 像合同的。 每个表情 设定它们,一个没有自身价值的视角 来回顾它们的倒数, 所以另一个的视角 没有任何东西从它。 A 类 倒置被检查为一个外观值是定义了符号时(其类型,目标分数,它所在的对数, 建造措施 互相看 应用的倒置.

## 正在检查

构建在任何问题上都失败了,无论应用程序是否导入了样式表,而dev服务器会警告它们. `looksProblems(looks)` 返回同一列表,并 `lookProblems(look)` 一张相看(不扔),因为相看满了 从任何地方。 在应用测试中:

```ts
import { assertLook } from '@codefusion-cc/ui/testing'
import kuznia from '../src/looks/kuznia.ts'

test('kuznia passes', () => assertLook(kuznia))
```

它检查两种模式中的每个角色;每个文本对(在页面、表面和高高处连接和变音;在重音上连接; 每个音调都用墨水指着它的音色,...)相对4.5:1,界面的每个部分(角,焦点,状态和图表颜色) 第3:1条。 透明颜色混合在所绘的颜色和外表 sRGB在SRGB和显示P3屏幕上同时被测量. `line` 是装饰性的,没有测量.

## 装备

在外观角色中回放组件,以 Tailwind 类为样式,应用自己的 Tailwind 生成(上面的导入). 他们需要回放19 和回放DOM, 和Tailwind 4.1 和它的飞行前.

```tsx
import { Button, ErrorState, Loading, UiProvider, buttonClass } from '@codefusion-cc/ui/react'
import { pl } from '@codefusion-cc/ui/words'

<UiProvider words={pl}>
  <Button pending={saving} pendingLabel="Zapisywanie…" onClick={save}>Zapisz</Button>
  <Link to="/koszyk" className={buttonClass({ tone: 'secondary' })}>Koszyk</Link>
  {orders.failed ? <ErrorState onRetry={reload}>Nie udało się wczytać zamówień.</ErrorState> : <Loading />}
</UiProvider>
```

-   **`Button`**数字 : `tone` 实值 `primary` (口音,屏幕的一个动作), `inverse`, (中文(简体) ), `secondary` (表列), `ghost` (没有填满,直到徘徊), `link` 或者说 `plain` (单是外形). `size` 实值 `md` (单位:千美元)`--cf-control` 高:44px at (中文(简体) ) 至少接触一下, `sm` 或者说 `icon` (40px;仅限图标按钮需要 `aria-label`) (中文(简体) ). 没错 `type="button"` 除非告诉 否则。 虽然 `pending` 它保持其焦点和在标签顺序中的位置,但不单击,也不提交表单 (第二次按下,或输入一字段,无所事事) `icon` 或显示旋转器,并告诉屏幕阅读器 它在起作用. `disabled` 是浏览器本身的:没有焦点,没有按键。 已禁用 或待决; 盘旋的应用程序添加到 `plain` 以同样的戒备, `not-disabled:not-aria-disabled:hover:…`按钮 灯光照亮,好像可以按住它.
-   **`link`**:在单词之间静静地动作("再试"在失败后,一行"取出""取出"),被划为链接. 没有填满, 边缘、 粘贴或文本大小: 它与周围的文本一样大, 并坐落在基线上, 以 `link-ink`, (中文(简体) ), 半粗体, 在指针下划线。 它仍然是键盘和屏幕读取器的按钮,焦点 并用强迫颜色保持下划线。 这需要不 `size` 或者说 `height`。另一种颜色是应用程序的: `cx(buttonClass({ tone: 'link' }), 'text-muted')`。 。 。 .
-   **大小**数字 : `sm` 财务报告和审定财务报表 `icon` 保持40px的触摸屏太。 WCAG 2.2 AA(2.5.8,最小目标尺寸)要求24px; 2; 44px为AAA. 应用软件的小按钮是今天的40px, 让他们在手机上44px会改变他们的外观 包不能这样 在没有每个应用程序的所有人同意的情况下,不要把它们提高到44px.
-   **`height="padding"`**: 对于一个按钮和标签一样高的应用程序来说 `md` 带行 `text-sm`, 36px 为 `sm`无论指示者是什么,默认的, `control`,给出 `md` 外观 控制高度和 `sm` 起码40px. 与 `padding` 应用程序对目标大小本身的答案.
-   **`buttonClass({ tone, size, height })`**: 链接的同一类课程或任何应该看起来像 按钮. **`buttonSizeClass(size, { height })`**:一个大小的类单,因为一个大小增加了应用自己的基调.
-   **`Loading`**:一个旋转器和"走失"(或) `label`),以礼貌方式宣布(`role="status"`) (中文(简体) ).
-   **`ErrorState`**:危险语气的失败,一并宣布(`role="alert"`),带有"再试"按钮 给定 `onRetry`时 `onRetry` 返回按键等待、完成或拒绝的许诺; `retrying` 是一个 重新测试应用程序的轨迹 。 它需要一个 `div`属性和 `ref` 也: 一个 `id` 为田地 `aria-describedby`, (中文(简体) ), `tabIndex={-1}` 用于将焦点移动到其信件(显示无环)的窗体.
-   **单词**数字 : `UiProvider words={pl | en | de}` 设置套件本身的几个单词; 没有英文.
-   **`className`** 设置组件(边距、宽度、网格或弹性项目)。 它不重排一个:两个班 一种财产适用Tailwind的顺序,而不是按照书写的顺序。 要重写 `buttonClass()` 一个 软件本身的元素, 将类与尾风相融合( app's, 3 或后期), 这需要知道 工具包的主题值: `export const cx = createCx()` 从 `@codefusion-cc/ui/tailwind-merge`,则 `cx(buttonClass({ size: 'sm' }), 'min-h-11 px-5')`。 。 。 . `createCx({ extend: { theme: { radius: ['panel'] } } })` 添加 应用本身的值,作为尾风相接的值 `extendTailwindMerge` 带他们走.
-   一个字太长了,整行都断了 而不是推倒页面;在拥挤的一行中,按钮保留它 整个词,就像它旁边的文字一样。 这代表着一个纯文本的标签(`Cart ({count})` 图标 结束 `icon` 而不是在话语中。 旋转器在运动减少的地方慢慢地转动 被迫 每个按钮的颜色都保持边缘(链接其下划线).

### 窗口列表

`WindowedList` 仅挂载窗口中固定高的行并加 `overscan` (默认为4个)和焦点行. 它与页面相滚动,没有内卷盒. 浏览器在页面中查找时不包含行, 因此为大型收藏提供搜索或过滤。 每行是一条 `li` 及其位置和完整列表大小. `rowClassName` 提供其角色类别; `as="ol"` 使用命令列表。 其他属性在列表中本身 : `aria-label` 说吧, `aria-busy` 说一个页面正在装入。 稳定而独特的密钥使阅读器的第一可见行在行的位置 上方插入或去除,或断点高度变化。 附页不需要滚动更正 。 期间a 列表已挂载,浏览器本身的滚动锁定已关闭(`overflow-anchor: none` 打开 `<html>`it: 将锁定清单后面的内容,并在末尾随附每一页附上一个读取器.

```tsx
import { useCallback } from 'react'
import { WindowedList } from '@codefusion-cc/ui/react'

const getKey = useCallback((index: number) => orders[index].id, [orders])

<WindowedList
  aria-label="Orders"
  count={orders.length}
  getKey={getKey}
  className="[--row-height:56px] sm:[--row-height:64px]"
  renderRow={index => <a href={`/orders/${orders[index].id}`}>{orders[index].number}</a>}
/>
```

使用正数 `rowHeight` 以像素表示,或仅使用正式 px `--row-height` 在名单上。 虽然 `--row-height` 无法是 读取(它的样式表仍在装入),第一行保留,一个错误被记录,下一个调整度量。 CSS每页读取一次 `ResizeObserver` 回调; 内容必须符合固定行高。 内容包裹到不同高度的列表 需要不同的布局或可变高度执行。 该清单拥有其定位和总高度; 保持零分的自备状态 将行贴在固定高度内,通过 `rowClassName` 或内容. 一个卷轴,一个跳动,一个Tab步骤或一个断点变化,使得它的新行在浏览器画出框架之前, 所以继续 `renderRow` 便宜点.

`useWindowedList({ count, rowHeight?, overscan?, getKey })` 曝光情况 `{ listProps, rows, scrollToIndex }` 列表 提供自己的行属性。 展开 `listProps` 编辑 `ul` 或者说 `ol`; 每个 `li` 它们的行 `key` 财务报告和审定财务报表 `style`, (中文(简体) ), `aria-setsize={count}`,以及 `aria-posinset={index + 1}`。保持密钥的稳定,并保持各种更新的独特性. 每把钥匙都是在 `getKey` 更改,所以记住 `useCallback`钩子和部件都一样. 标签和 Shift+ 标签在窗口边界上挂起相邻一行, 焦点则会在它离开后挂起一行 观地道. `scrollToIndex(i)` 卷轴平稳地滚动,除非运动减少,当它跳出(`behavior: 'instant'`, (中文(简体) ), 哪一页 `scroll-behavior: smooth` 不动静). 在服务器上,第一个多扫描行在不测量CSS的情况下渲染;第一个涂料之前的水分测量. `windowRange({ scrollY, listTop, viewport, rowHeight, count, overscan? })` 返回纯半开放范围. 无效的几何,重复的密钥,或外向滚动索引是编程错误并丢出.

## 对话框后面的页面

`overflow: hidden` 在正文上不持有iOS Safari:键盘打开后,对话框上拖动页面 后面是那个. `lockPageBehind(dialog)` 将正文标注在其卷轴上, 并取消任何一指拖动 最上面的对话框可以滚动,除非它降落在滑动器或带有 `touch-action: none`二、导 言 手指还缩放。 锁巢:上个解锁将身体的样式和卷轴相抵消回. 每一份副本 软件包在页面上共享一个锁.

```tsx
import { usePageLock } from '@codefusion-cc/ui/react'

usePageLock(dialogRef, open)
```

外接回话 `lockPageBehind(element)` 联 合 国 `@codefusion-cc/ui/page-lock` 并返回函数. 被钉住的身体保持粘性元素的位置(Firefox随页移动),但 `window.scrollY` 读取 0 被绑定 : 页面滚动后改变外观的页眉读取 `pageScrollY()` 联 合 国 `@codefusion-cc/ui/page-lock` 换句话说,所以对话之后保持不变. `usePageLock` 插入页后 对话框的第一张油漆,所以解答水龙头的相框不等待它,在布局效果中还给它,所以一个 被导航关闭的对话框在路由器的卷轴恢复运行前会让页面返回.

一个测试驱动它 `drag(target, from, to)` 从 `@codefusion-cc/ui/testing`,这是正确的 当移动是 已取消 。 无头引擎没有触摸屏,所以iOS本身所做的都是在手机上检查.

## 预览

`npm run dev`,然后打开 `/__looks`: 符号表和每个已注册状态列表, 在每个外观中, 光和暗 相并相并相并相并相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相 外观文件已更改 . `?look=kuznia` 显示一个表情; `?list=button&look=kuznia&mode=dark` 以一个外观和模式显示一个列表, 里面的整页, 周围没有 : 如何是观想所摄.

国家列表是共享组件(以及一个app的自有)如何显示它们可以进入的每个状态. 将模块命名于 `uiLooks({ states: ['./src/states/buttons.ts'] })`,对于用应用程序的类绘制的州,它的样式表在 `styles`。工具包自己的名单是: `@codefusion-cc/ui/react/states`数字 :

```ts
uiLooks({ looks: ['./src/looks/kuznia.ts'], states: ['@codefusion-cc/ui/react/states', './src/states/buttons.ts'], styles: ['./src/index.css'] })
```

页面列表名称 `widths` 它的视觉测试拍摄它( 默认) `[390]`,电话;添加 `1280` 在布局中 页:1.

```ts
// src/states/buttons.ts
import { defineStates } from '@codefusion-cc/ui/testing'

export default defineStates({
  id: 'buttons',
  title: 'Buttons',
  states: [
    { name: 'Idle', props: { label: 'Save' } },
    { name: 'Busy', props: { label: 'Saving', busy: true } },
  ],
  render(target, props) {
    const button = document.createElement('button')
    button.textContent = props.label
    button.disabled = Boolean(props.busy)
    target.append(button)
  },
})
```

## 视觉测试

`packages/web/ui/visual/` 是三个固定的外观和工具箱的状态清单的应用。 它的套房拍摄 每一个列表 每张相片,光和暗,每张相片的宽度, 一张硬色的相片, 一张相片, 一张相片的相片 模式给予屏幕读取器相同的树。 图片仅在被绑的 Playwright 图像中比较 (单位:千美元)`@codefusion-cc/testing`),通过容器:

```sh
pnpm visual
```

视觉工作流程运行在每一个牵引请求上 `packages/web/ui`在Tenki的Linux上 运行(仓库变量) `CI_RUNNER_DOCKER` 我们自己的跑者不给多克和GitHub的工作 东道主在本组织的0美元支出限额内被拒绝。 在换相机之前 在当地运行它. 在Mac上它需要一个运行的容器运行时间 `linux/amd64` 图片, 如 Colima 与 Rosetta (单位:千美元)`colima start --vm-type vz --vz-rosetta`) (中文(简体) ).

改变工具箱的外观的改变 `pnpm visual:update` 承诺 它们;拉动请求显示每个都改变了. 没有容器运行时间, 也没有新的 Playwright 图像, 视觉 工作流程采用 CI : `gh workflow run visual.yml --ref <branch> -f update=true`,然后执行 视觉底线 文物持有.

## 设计符号

`@codefusion-cc/ui/tokens.json` 是 DTCG 格式的合同,并且 `lookTokens(look)` 变回一模一样 格式,用于设计工具。 颜色是 OKLCH 组件及其六进制. 只命名另一个角色的颜色仍为 化名 (`{color.accent}`) (中文(简体) ). 模式和自定义属性都在 `$extensions["cc.codefusion"]`和应用程序 符号下 `app.<prefix>.<type>` (单位:千美元)`app.hh.color.me`) (中文(简体) ).

## 常见问题

### @codefusion-cc/ui 是什么？

符号契约 每一个代码融合的外观都填满了, 套件建在它上:打出的角色\(颜色、字体、光线、阴影、控制高度、运动\), 定义在编译时间检查, WCAG 2\.2 AA的外观问题和光和暗中的目标大小, C

### 如何安装 @codefusion-cc/ui？

在项目目录运行 npm install @codefusion-cc/ui，或使用 pnpm add / yarn add / bun add。

### @codefusion-cc/ui 支持 TypeScript 吗？

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

### @codefusion-cc/ui 支持 ESM 还是 CommonJS？

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

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

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

### @codefusion-cc/ui 可以商用吗？

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

### @codefusion-cc/ui 的下载量有多少？

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

### @codefusion-cc/ui 还在维护吗？

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

