@basenative/combobox

中文文档
3.0.0发布于 2026/10/31Apache-2.0TypeScriptES Module零依赖构建来源已验证

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

中文使用文档
文档目录13 节
  1. 为什么
  2. 安装
  3. 快速开始-选择从现有的选项
  4. 允许创建新条目
  5. 带有选项提示
  6. 用信号控制
  7. 咏叹调模式
  8. 键盘
  9. 主题
  10. 过滤策略
  11. 移动测试笔记
  12. API
  13. 许可证

@basenative /组合框

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

部分 BaseNative 生态系统。

为什么

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

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

安装

pnpm add @basenative/combobox @basenative/runtime

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

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"]'));

允许创建新条目

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).

带有选项提示

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

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),
});

用信号控制

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组合框/列表框模式 准确地说应该是:

  • 输入有 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”永远不会清除用户键入的输入-键入的文本将成为新值。

主题

在任何祖先重写:

.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-bgCreate-option背景#ECFDF3
--cb-min-tap最小命中目标(WCAG 2.5.5 AA)44px

过滤策略

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

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 共发布 11 个版本,首次发布于 2026/10/18;过去 12 个月发布了 11 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
3.0.0latest2026/10/312 天前
2.4.02026/10/268 天前
2.3.22026/10/2212 天前
2.3.12026/10/2212 天前
2.3.02026/10/2212 天前
2.2.02026/10/2113 天前

关于 @basenative/combobox 的常见问题

@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 和提交记录判断。