# @basenative/combobox 中文文档

规范地址：https://npmcn.com/package/%40basenative/combobox/

版本：3\.0\.0
npm 元数据更新时间：2026-10-31T13:48:07.394Z
中文译文更新时间：2026-10-31T16:09:37.564Z
软件包许可：Apache-2\.0

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

原始 npm 页面：https://www.npmjs.com/package/%40basenative/combobox
原文对照：https://npmcn.com/package/%40basenative/combobox/?lang=original
项目主页：https://github.com/DuganLabs/BaseNative/tree/main/packages/combobox#readme
源码仓库：https://github.com/DuganLabs/BaseNative

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

- 包体积（解压后）：47.5 kB，9 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：0 个
- peer 依赖：@basenative/runtime 3\.0\.0
- 首次发布：2026-10-18T05:29:05.653Z
- 最新版本发布：2026-10-31T13:48:07.075Z
- 已发布版本数：11（近 12 个月 11 个）

## 中文简介

可访问的组合框原语——预先输入过滤现有列表并允许用户创建新条目的输入。WAI-ARIA组合框列表框模式。

## 安装

```sh
npm install @basenative/combobox
```

也可以使用：`pnpm add @basenative/combobox`、`yarn add @basenative/combobox`、`bun add @basenative/combobox`

## README

# @basenative /组合框

> 可访问的预输入组合框原语-从现有列表中选择，或创建新条目。WAI-ARIA APG组合框+列表框模式，ssr优先，信号驱动，可选。

部分 [BaseNative](https://github.com/DuganLabs/basenative) 生态系统。

## 为什么

大多数组合框库都是巨大的（40+ KB），特定于框架，并且带有您必须与之抗争的固执己见的风格。这个正好相反：

-   呈现语义HTML服务器端。没有JS，你会得到一个plain `<input>` + `<datalist>` 提前输入（对于表单足够好）。
-   使用JS，它会变成一个完整的apg模式组合框，具有虚拟焦点、键盘导航和内置的“+ Create”功能。
-   主题贯穿始终 `--cb-*` CSS自定义属性。零捆绑调色板假设。
-   Layout-shift-free：打开列表框永远不会刷新页面。
-   信号互操作通道 `runtime.effect` -传递 `@basenative/runtime` 信号和输入镜像它。

## 安装

```bash
pnpm add @basenative/combobox @basenative/runtime
```

## 快速开始-选择从现有的选项

```js
import { Combobox } from '@basenative/combobox';
import '@basenative/combobox/css';

const cb = Combobox({
  id: 'fruit',
  name: 'fruit',
  label: 'Pick a fruit',
  options: ['Apple', 'Banana', 'Cherry'],
  onChange: (value) => console.log('selected', value),
});

document.querySelector('#mount').innerHTML = cb.html;
const handle = cb.hydrate(document.querySelector('[data-bn="combobox"]'));
```

## 允许创建新条目

```js
const cb = Combobox({
  id: 'tag',
  label: 'Tag',
  options: existingTags,
  allowCreate: true,
  createLabel: (input) => `+ New tag "${input}"`,
  onChange: (value) => setTag(value),
  onCreate: (label) => {
    addTag(label);   // persist somewhere
    setTag(label);
  },
});
```

如果你不及格 `onCreate`， BaseNative将把用户键入的文本作为值并调用 `onChange(typed)`.

## 带有选项提示

用于内联显示键盘快捷键、排序元数据或上下文信息：

```js
const cb = Combobox({
  options: [
    { value: 'today',     label: 'Today',          hint: 'T' },
    { value: 'this-week', label: 'This week',      hint: 'W' },
    { value: 'all',       label: 'All time',       hint: 'A' },
  ],
  onChange: (v) => setRange(v),
});
```

## 用信号控制

```js
import { signal, effect } from '@basenative/runtime';
import { Combobox } from '@basenative/combobox';

const category = signal('books');

const cb = Combobox({
  options: ['books', 'movies', 'music'],
  value: category,            // function-shape signal accessor
  onChange: (v) => category.set(v),
  runtime: { effect },        // mirrors signal -> input on every change
});
```

## 咏叹调模式

这个包实现了 [W3C APG组合框/列表框模式](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/) 准确地说应该是:

-   输入有 `role="combobox"`， `aria-autocomplete="list"`， `aria-expanded`， `aria-controls=<listbox id>`.
-   弹出框中有 `role="listbox"`． 每一行都有 `role="option"` 和 `aria-selected`.
-   焦点停留在输入。高亮显示的行通过 `aria-activedescendant` (虚拟聚焦)。
    -   这在手机平台上是很重要的：将真正的焦点移到弹出窗口将关闭软键盘。
-   有礼貌的居住地区(`aria-live="polite"`)在每次过滤器更改后宣布选项计数，并单独宣布创建选项提示，以便屏幕阅读器用户知道这是一个不同的操作。
-   create-选项使用不同的颜色标记(`--cb-create-fg`), `data-bn-cb-create="true"` 用于SR /造型。

### 键盘

| 关键 | 行为 |
| --- | --- |
| ArrowDown | 打开弹出窗口（如果关闭）并向下移动活动选项 |
| ArrowUp | 打开弹出窗口（如果关闭）并向上移动活动选项 |
| 首页 | 主动移动到第一个选项 |
| 结束 | 移动到最后一个选项 |
| 输入 | 提交活动选项（或者，如果没有活动行，则提交类型化查询） |
| 逃避 | 关闭弹出窗口，保持输入值不变 |
| 选项卡 | 提交活动选项（如果有的话），然后按自然选项卡顺序移动焦点 |

选择“+ Create”永远不会清除用户键入的输入-键入的文本将成为新值。

## 主题

在任何祖先重写：

```css
.dark [data-bn="combobox"] {
  --cb-bg: #18181b;
  --cb-fg: #f4f4f5;
  --cb-border: #3f3f46;
  --cb-border-focus: #f59e0b;
  --cb-listbox-bg: #18181b;
  --cb-listbox-border: #3f3f46;
  --cb-option-bg-hover: #27272a;
  --cb-option-bg-active: #3f3f46;
  --cb-create-fg: #fbbf24;
  --cb-create-bg: #422006;
}
```

| 令牌 | 目的 | 默认的 |
| --- | --- | --- |
| `--cb-bg` | 输入域背景 | `#ffffff` |
| `--cb-fg` | 默认文本 | `#111111` |
| `--cb-border` | 场边界 | `#c8c6bf` |
| `--cb-border-focus` | 现场边界聚焦 | `#2E5BFF` |
| `--cb-radius` | 场角半径 | `6px` |
| `--cb-input-h` | 场的高度 | `44px` |
| `--cb-listbox-bg` | 弹出的背景 | `#ffffff` |
| `--cb-listbox-border` | 弹出边境 | `#c8c6bf` |
| `--cb-option-bg-hover` | 选项悬停背景 | `#f1efe9` |
| `--cb-option-bg-active` | 选项激活（键盘）背景 | `#e6e4dc` |
| `--cb-option-fg` | 选择文本 | `#111111` |
| `--cb-create-fg` | 创建选项文本（故意区分） | `#0F5132` |
| `--cb-create-bg` | Create-option背景 | `#ECFDF3` |
| `--cb-min-tap` | 最小命中目标（WCAG 2.5.5 AA） | `44px` |

## 过滤策略

```js
import { Combobox, defaultFilter, prefixFilter, fuzzyFilter } from '@basenative/combobox';

Combobox({ options, filter: prefixFilter });    // type "ap" → "Apple"
Combobox({ options, filter: fuzzyFilter });     // type "apl" → "Apple"
Combobox({ options, filter: (o, q) => o.value.startsWith(q.toUpperCase()) });
```

## 移动测试笔记

-   iOS 16/17 Safari：在iPhone 12 / 14 Pro上测试。点击选项不会关闭软键盘（我们取消了） `mousedown` 在列表框上)。
-   `inputmode="text"` 保持系统键盘布局的文本形状 (不是数字键盘)。
-   `font-size: 16px` 最小阻止iOS变焦对焦。
-   每个选项的44pt min命中目标。

## API

```ts
import {
  Combobox,            // factory: { html, hydrate(rootEl) }
  renderCombobox,      // SSR: returns HTML string
  hydrateCombobox,     // wire reactivity to an existing root
  normalizeOption,     // (raw) => { value, label, hint? }
  defaultFilter,
  prefixFilter,
  fuzzyFilter,
  applyAriaAttributes,
  escapeOnKeydown,
  announce,
} from '@basenative/combobox';
```

看到 `types/index.d.ts` 完整签名。

## 许可证

apache - 2.0

## 常见问题

### @basenative/combobox 是什么？

可访问的组合框原语——预先输入过滤现有列表并允许用户创建新条目的输入。WAI-ARIA组合框列表框模式。

### 如何安装 @basenative/combobox？

在项目目录运行 npm install @basenative/combobox，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：@basenative/runtime（3\.0\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @basenative/combobox 支持 TypeScript 吗？

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

### @basenative/combobox 支持 ESM 还是 CommonJS？

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

### @basenative/combobox 可以商用吗？

@basenative/combobox 使用 Apache-2\.0 许可。宽松许可：允许商业使用、修改和再分发，并附带明确的专利授权；分发时需保留许可与 NOTICE 文件，修改过的文件要注明改动。以上为概括，不构成法律意见，请以许可原文为准。

### @basenative/combobox 还在维护吗？

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

