@basenative/keyboard

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

可访问的移动-第一个屏幕上的虚拟键盘原语-布局不可知,信号驱动的键状态着色,主题

中文使用文档
文档目录11 节
  1. 为什么
  2. 安装
  3. 快速开始-游戏键盘
  4. 数字键盘
  5. 自定义布局
  6. 主题
  7. 移动Safari焦点修复
  8. 硬件键盘奇偶校验
  9. 移动测试笔记
  10. API
  11. 许可证

@ basenative/键盘

可访问的,移动优先的屏幕虚拟键盘原始-布局无关,信号驱动,主题。

部分 BaseNative 生态系统。

专为益智游戏,kiosk应用程序,可访问的输入,以及任何时候你需要一个屏幕上的键盘,不与移动Safari战斗。

为什么

移动浏览器对键盘有很多看法。本机不请自来地弹出,焦点跳来跳去,命中目标太小,动画中断了要求他们不要的用户。这个包是一个单一的原语:

  • 呈现语义 <button> 元素 (作品没有JS-SSR预画友好)。
  • 通过信号感知处理程序调度轻击,使用硬件键镜像,因此蓝牙键盘会经过完全相同的调度路径。
  • 从应用每个键的状态课程 state getter (green / yellow / absent / staked) -完美的文字风格的游戏或任何反馈驱动的UI。
  • 主题贯穿始终 --kb-* CSS自定义属性。没有捆绑的调色板假设。
  • 是否有44pt min命中目标默认(WCAG 2.5.5 AA),默认调色板WCAG AA对比每个状态状态,和荣誉 prefers-reduced-motion.
  • 修复了mobile-Safari focus-steal bug (更多内容见下文)。

安装

pnpm add @basenative/keyboard @basenative/runtime

快速开始-游戏键盘

import { Keyboard, LAYOUTS } from '@basenative/keyboard';
import { signal, effect } from '@basenative/runtime';
import '@basenative/keyboard/css';

const keyStatus = signal({ A: 'green', E: 'yellow', X: 'absent' });

const kb = Keyboard({
  layout: LAYOUTS.qwerty,
  primary: 'ENTER',
  state: keyStatus.get,
  runtime: { effect },
  onKey:    (char) => guessSignal.update(g => g + char),
  onAction: (a) => {
    if (a === 'ENTER') submitGuess();
    if (a === 'BACKSPACE') guessSignal.update(g => g.slice(0, -1));
  },
});

document.querySelector('#kb-mount').innerHTML = kb.html;
kb.hydrate(document.querySelector('[data-bn="keyboard"]'));

数字键盘

import { Keyboard } from '@basenative/keyboard';

const pad = Keyboard({
  layout: 'numpad',
  primary: 'ENTER',
  onKey: (digit) => pin.update(s => s + digit),
  onAction: (a) => a === 'BACKSPACE' && pin.update(s => s.slice(0, -1)),
});

自定义布局

import { defineLayout, Keyboard } from '@basenative/keyboard';

const dvorak = defineLayout([
  ['1','2','3','4','5','6','7','8','9','0'],
  ["'", ',', '.', 'P', 'Y', 'F', 'G', 'C', 'R', 'L'],
  ['A', 'O', 'E', 'U', 'I', 'D', 'H', 'T', 'N', 'S'],
  [
    { type: 'action', label: '⌫', key: 'BACKSPACE', span: 1.5, variant: 'backspace' },
    ';', 'Q', 'J', 'K', 'X', 'B', 'M', 'W', 'V', 'Z',
    { type: 'action', label: 'GO', key: 'ENTER', span: 1.5, variant: 'enter' },
  ],
]);

const kb = Keyboard({ layout: dvorak, primary: 'ENTER', onKey, onAction });

主题

所有视觉对象都是CSS自定义属性。覆盖任何祖先:

.my-app [data-bn="keyboard"] {
  --kb-bg: #fff;
  --kb-key-bg: #f4f4f5;
  --kb-key-fg: #18181b;
  --kb-key-active: #d4d4d8;
  --kb-key-green:  #16a34a;
  --kb-key-yellow: #eab308;
  --kb-key-absent: #d4d4d8;
  --kb-key-radius: 8px;
  --kb-min-tap: 48px;
}
令牌目的默认的
--kb-bg键盘表面背景#0C0B09
--kb-key-bg默认键背景#3A3530
--kb-key-fg默认键文本#F0EDE4
--kb-key-active按下的背景#5A5550
--kb-key-green状态: 正确的位置#2E8B5A
--kb-key-yellow状态:正确的字母,错误的位置#D4B445
--kb-key-absent状态: 不在答案中#1E1C18
--kb-key-radius每键角半径6px
--kb-gap键间水平间隙4px
--kb-min-tap最小命中目标(WCAG 2.5.5 AA)44px

移动Safari焦点修复

当你点击一个键时,移动Safari会将焦点短暂地移到 <button>,这会模糊活动的文本输入。这种模糊会导致Safari关闭键盘-在下一个焦点上,它会引发 本地的 键盘在我们旁边。解决办法是打电话 preventDefault 在 mousedown / touchstart 所以注意力永远不会移动。

hydrateKeyboard 自动执行此操作。如果你需要钥匙的话 做 取焦点(很少-通常是通过本机语义提交表单的键),设置 data-bn-kb-focusable="true" 在按钮上。

硬件键盘奇偶校验

当 bindHardware 是 true (默认), keydown 事件 document 被翻译成相同的 onKey / onAction 呼叫为轻敲。因此,蓝牙键盘或桌面用户获得相同的行为-没有单独的输入管道。

要限制硬件侦听器转发的字符,请传递 charSet 通过较低的水平 bindHardwareKeys(...) API。

移动测试笔记

  • iOS 16/17 Safari (iPhone 12, 14 Pro,SE 3rd gen): 点击dispatch,无本机键盘弹出窗口,haptics fire。
  • Android 13/14 Chrome(像素6,7):点击调度, navigator.vibrate(8) 火灾,命中目标通过灯塔a11y审计。
  • 减少运动:测试与iOS“减少运动”和 prefers-reduced-motion: reduce 在DevTools中-按比例动画下降到平面颜色变化。

API

import {
  Keyboard,            // factory: { html, hydrate(rootEl) }
  renderKeyboard,      // SSR: returns HTML string
  hydrateKeyboard,     // wire reactivity to an existing root
  LAYOUTS,             // { qwerty, alphanumeric, numpad, phone }
  defineLayout,        // (rows, meta?) => Layout
  validateLayout,      // throw on shape mismatch
  keyState,            // single-letter status reader
  applyAriaAttributes,
  preventFocusSteal,
  bindHardwareKeys,
  haptic,
} from '@basenative/keyboard';

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

许可证

apache - 2.0

版本与发布记录

@basenative/keyboard 共发布 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/keyboard 的常见问题

@basenative/keyboard 是什么?

可访问的移动-第一个屏幕上的虚拟键盘原语-布局不可知,信号驱动的键状态着色,主题

如何安装 @basenative/keyboard?

在项目目录运行 npm install @basenative/keyboard,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@basenative/runtime(3.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@basenative/keyboard 支持 TypeScript 吗?

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

@basenative/keyboard 支持 ESM 还是 CommonJS?

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

@basenative/keyboard 可以商用吗?

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

@basenative/keyboard 还在维护吗?

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