@ basenative/键盘
可访问的,移动优先的屏幕虚拟键盘原始-布局无关,信号驱动,主题。
部分 BaseNative 生态系统。
专为益智游戏,kiosk应用程序,可访问的输入,以及任何时候你需要一个屏幕上的键盘,不与移动Safari战斗。
为什么
移动浏览器对键盘有很多看法。本机不请自来地弹出,焦点跳来跳去,命中目标太小,动画中断了要求他们不要的用户。这个包是一个单一的原语:
- 呈现语义
<button>元素 (作品没有JS-SSR预画友好)。 - 通过信号感知处理程序调度轻击,使用硬件键镜像,因此蓝牙键盘会经过完全相同的调度路径。
- 从应用每个键的状态课程
stategetter (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