@baukit/a11y-core

中文文档
0.18.3发布于 2026/11/07MITTypeScriptES Module零依赖构建来源已验证近 30 天下载 8727

网络和回放原生产品共享的无障碍行为:覆盖焦点,惰性背景内容,公告,减少运动,和键盘运动.

中文使用文档
文档目录8 节
  1. 两个切入点
  2. 重叠
  3. 菜单
  4. 路线焦点
  5. 原生到 DOM 边界
  6. 通知
  7. 运动、团体和形式减少
  8. 边界

@baukit/a11y-core

@baukit/a11y-core 持有网络和反应原生产品共享的无障碍行为: 覆盖焦点、惰性背景内容、公告、减少运动和键盘移动 通过团体和形式。 产品将其组件,复制品,外观设计保存在本地.

软件包导入 React and React Industrial 而不另作选择. 两者都是同伴的依赖关系,所以 产品的"Expo SDK"决定了这些版本,"React Introduction"是可选的.

两个切入点

反应原生产品进口包根并获得一切. 纯 React 网络应用程序导入 @baukit/a11y-core/web 获得 announce, (中文(简体) ), useFocusTrap, (中文(简体) ), useInert, (中文(简体) ), useAriaHiddenInert, (中文(简体) ), useReducedMotion, (中文(简体) ), useReducedMotionPreference, (中文(简体) ), useRovingMenu, (中文(简体) ), nextEnabledMenuIndex, (中文(简体) ), useSingleFlight, (中文(简体) ), createRouteFocusController,则 dom-boundary 帮手 无所可及 进口商品 react-native,在运行时或其类型,所以应用程序不需要反应 原生于其依附树上. react-native 是一个可选的对等关系, 确切地说 理由,你觉得呢.

DOM 钩子询问文档是否存在而不是询问 Platform 这是哪一个OS。 这个 两个问题在这里有相同的答案: 每个分支的钩子守卫 读或写DOM, React Introduct Web给他们一个真正的文档,React Introduct也没有. 有真爱的钩子 平台拆分, 例如 useOverlayA11y继续阅读 Platform 并停留在根入后. announce 财务报告和审定财务报表 useReducedMotion 两个条目上都存在: 根版本为 Platform,则 /web 版本是其DOM的一半.

重叠

useOverlayA11y 是两个平台上的一个合同 行为不一.

const { backgroundProps, containerProps } = useOverlayA11y({
  active: visible,
  containerRef: panelRef,
  inertContainerRef: overlayRootRef,
  initialFocusRef,
  onEscape: onClose,
  triggerRef,
});

在网络上将焦点移动到覆盖中, 包含 Tab 和 Shift+ 标签,电话 onEscape,并制作 外面的东西 inertContainerRef 惰性。 关上它检查 专注于下一个任务 所以 useInert 可以首先释放背景。 它把注意力集中在连接在外的元素上 关闭容器,除非该元素在 inert, (中文(简体) ), hidden,或 aria-hidden="true" 亚树. 否则会恢复开口器,如果开口器仍然连接. 任务前重新打开 运行取消待决恢复.

两者 useFocusTrap 财务报告和审定财务报表 useOverlayA11y 接受两个可选的回调:

  • restoreFocus?: () => boolean 决定是否恢复打开器。 它默认为真实.
  • returnFocus?: () => FocusTarget | null 当打开器断开时提供倒数 或者说 restoreFocus 返回错误。 A 类 FocusTarget 有一个 focus() 方法,因此是元素或原生元素 视图可以直接返回。 Web 只关注连接倒计时.

在需要恢复时,在网络外部焦点检查后,调用会运行。 变动至 要么回调不重新启动陷阱。 专注,通过 restoreFocus: () => false 没有退后。 在动作移除打开器时返回路径:

useFocusTrap({
  active: visible,
  containerRef: panelRef,
  restoreFocus: () => !navigatingRef.current,
  returnFocus: () => headingRef.current,
});

在本土,它等待才要求关注无障碍环境,因此在布局之前没有焦点土地。 打开 关闭它返回焦点 triggerRef土著无法发现以前拥有的无障碍环境 专注,所以呼叫者拥有该 ref. 钩子在关闭时再次解开反射器并使用 returnFocus 如果触发器已卸载或 restoreFocus 返回错误。 本地无法检查 当前访问焦点, 因此无法应用网络外聚焦检查 。 过 triggerHandle 当节点标记已经解决时; 调用者必须保持该标记有效直至关闭 .

等待默认为 InteractionManager.runAfterInteractions,该反应的原生0.86贬值 而不提供“在提交上下文之后”的替换。 真实产品 演示活动应当通过 deferFocus 并推动其重点要求:

const deferFocus = (task: () => void) => {
  layoutTasks.push(task);
  return { cancel: () => remove(task) };
};

展开 backgroundProps 输入内容 后面 盖子,从来不是盖子本身。 它设置 accessibilityElementsHidden 财务报告和审定财务报表 importantForAccessibility 以打开的、 在网络和关闭时空出。 展开 containerProps 在覆盖容器上.

useFocusTrap 财务报告和审定财务报表 useInert 是网络本身的一分之一, 对于组成自己的产品 重叠. useAriaHiddenInert 覆盖另一个问题: 路由器标记不活跃的网络场景 aria-hidden在键盘焦点顺序中留下他们的后人。 骑一次去 应用根. 打开 ARIA_HIDDEN_INERT_OPT_OUT ,但必须保持焦点.

菜单

useRovingMenu 持有动作菜单的键盘状态。 它给菜单一个分页 启用项目,在跳过已禁用项目时随箭头键移动焦点,在两端包入, ,然后将 Home 和 End 发送给第一个和最后一个启用的项目。 它一文不值 而且从未援引过 行动。 逃逸 Tab 封存 惰性背景 和焦点恢复 与 useOverlayA11y,所以打电话 useRovingMenu 先通过它 initialFocusRef 关于:

const menu = useRovingMenu({ active: visible, options: items });
const overlay = useOverlayA11y({
  active: visible,
  containerRef: panelRef,
  initialFocusRef: menu.initialFocusRef,
  onEscape: onClose,
  triggerRef,
});

items.map((item, index) => (
  <Pressable key={item.id} {...menu.itemProps(index)} disabled={item.disabled} />
));

options 仅需 disabled 财务报告和审定财务报表 selected,因此产品的项目阵列符合原样。 标签 停止开始于第一个选中的启用项目, 否则第一个启用的项目, 返回到那里 每次菜单打开时. itemProps(index) 返回时 tabIndex, (中文(简体) ), ref,以及 onKeyDown 一个 项目; activeIndex 将控取标签站的项目命名.

  • 没有启用的项目, activeIndex 无效, 每件物品都有 tabIndex: -1箭头键 没什么,和 initialFocusRef.current 无效. useOverlayA11y 然后聚焦第一个可聚焦 元素在容器中,所以在物品之前设置紧密的控制.
  • 当活动项在菜单打开时被禁用或删除时,制表站移动到 如果启用,则项目现在处于该位置,否则回到初始项目。 如果删除 控件的焦点和焦点落在文件正文上,钩子聚焦新的活动项.
  • 键出自一个项目内嵌入的宿主,如文本字段,则被放出.
  • initialFocusRef 是一个稳定回转的部件的生命。 钩子指着它 当菜单打开时, 覆盖会以稍后的效果读取, 所以两者都 钩子必须在相同的组件中运行 useRovingMenu 先说 不要把它换成另一个裁判 当菜单打开时:网络陷阱会再入并忘记它恢复的触发器.

nextEnabledMenuIndex(key, currentIndex, options) 对于一个产品来说,就是在钩子后面的纯粹一步 处理菜单容器上的密钥。 它返回除箭头以外的密钥为无效, 家和端,以及没有启用项目的菜单。 它移动相对 currentIndex 连 当该项被禁用或丢失时:一个索引通过结尾移动到第一个启用的项目并 直到最后,同样 -1。 。 。 .

动作命令,动作前或动作后关闭,同步故障恢复,选择含义,以及 复制留在产品.

路线焦点

WebKit 可以模糊启动控制到 body 当路由器使即将离开的场景惰性. 创建一个 createRouteFocusController 在应用程序启动时, 它可以记住最后可达到的 重点元素。 输入带有目标获取器的路由, 然后在路由时运行返回的清理 变为不活动 :

const routeFocus = createRouteFocusController();

const leaveRoute = routeFocus.enterRoute(() =>
  document.querySelector<HTMLElement>('[data-route-heading]'),
);

leaveRoute();
routeFocus.dispose();

控制器等待目的地目标在动画框上挂载并重试最多 1.5秒钟。 它等待惰性或隐藏的返回目标能够被达到. 如果用户停止 将焦点移动到另一个可达到的元素, 它从不将目标聚焦到下面 inert, (中文(简体) ), aria-hidden="true",或 hidden。 。 。 .

React Industrial没有文档,因此控制器不会在那里应用. 移动语音或 回到目的地,呼叫 focusAccessibilityElement(headingRef) 从根 条目,在标题确定后,例如,在路由增加焦点之后,有一个动画框架. 在原地上它解决了视图标签和呼叫 AccessibilityInfo.setAccessibilityFocus在网络上 将元素聚焦于 preventScroll。当裁判员空出时,它会返回假的,视图是 未挂载, 否则网络元素无法集中 .

import { focusAccessibilityElement } from '@baukit/a11y-core';

const frame = requestAnimationFrame(() => {
  focusAccessibilityElement(headingRef);
});

原生到 DOM 边界

反应原生网络 View 作为DOM元素,但 View 字型从不这么说。 每个 过关 dom-boundary,用于检查它所需要的方法并返回无效 否则. asFocusTarget, (中文(简体) ), asFocusContainer,以及 asTreeElement 带一个 HostRef 和窄处 它;一个没有DOM能力的本土宿主只产生无效,而不是投掷. HostRef 实值 RefObject<object | null>,它接受 View 参考书目和元素参考书目均没有命名 类型.

通知

announce(message, options) 说一个结果,没有明显的活区成分。 土著 电话 announceForAccessibility。Web将文字写入一个可视化隐藏区域,清除文本和 首先强制重回流, 所以同一消息要重复两次 。 空信被丢弃 .

该区域的 DOM ID 默认为 baukit-announcer。通过 liveRegionId 把它放在一个 产品自有标识,以及 assertive: true 打断而不是等待暂停.

announce 从 @baukit/a11y-core/web 取同样的论据 和网络半单独,所以 plain React app 获得没有React Introduct的活区. 它创造了第一个区域 调用,或采用该产品已经根据该标识制成的元素,且不需要组件或 供养. 过滤产品中哪些消息值得发言:呼叫 announce 仅限 做这些的.

运动、团体和形式减少

useReducedMotionPreference 返回时 { reducedMotion, resolved } 并跟踪偏好变化 在两个平台上。 第一次渲染时Web解决. 本地查询是同步的, 所以 resolved 开始为 false 变成 true 查询是否成功。 不要开始 非必要的动议,直到是 true。 。 。 . useReducedMotion 仍然是已存在的布尔形式 召来者.

网络条目导出相同名称的钩子和返回形状 matchMedia 财务报告和审定财务报表 useSyncExternalStore 一个人 在第一个客户端的翻译过程中,他们读到媒体的询问并跟踪 联合国 change 事件。 在服务器渲染和水合过程中,它们会报告 { reducedMotion: false, resolved: false },然后确定客户端。 没有主机 matchMedia 报告没有优先,解决.

useRovingRadioGroup 给无线电组一个单个制表符和箭键移动 选项,在两端包裹并尊重家和家. radioProps(index) 返回时 tabIndex, (中文(简体) ), ref,以及 onKeyDown 一个选项.

useEnterToNext 让 Enter 按字段行走一个网络表单字段,并从上一个字段提交. 多行字段保持其新行行为并沿途被跳出. 在本地时返回 仅限 ref键盘.

useSingleFlight 是Async UI突变的同步突变. 反应状态不能锁定在其中 单声道,双声道将两次提交。 一个被拒绝的呼叫决定 undefined,则 即使操作抛出,锁也会被放出.

边界

这套软件包没有任何部件、样式或副本。 它不决定哪一个 结果值得宣布,哪些动议至关重要,或覆盖是什么样子。 版式 断点算术生活在 @baukit/ui-tokens不在这里.

版本与发布记录

@baukit/a11y-core 共发布 67 个版本,首次发布于 2026/08/26;过去 12 个月发布了 67 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.18.3latest2026/11/07今天
0.18.22026/11/061 天前
0.18.12026/11/062 天前
0.18.02026/11/052 天前
0.17.12026/11/034 天前
0.17.02026/11/025 天前

关于 @baukit/a11y-core 的常见问题

@baukit/a11y-core 是什么?

网络和回放原生产品共享的无障碍行为:覆盖焦点,惰性背景内容,公告,减少运动,和键盘运动.

如何安装 @baukit/a11y-core?

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

@baukit/a11y-core 支持 TypeScript 吗?

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

@baukit/a11y-core 支持 ESM 还是 CommonJS?

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

@baukit/a11y-core 需要什么版本的 Node.js?

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

@baukit/a11y-core 可以商用吗?

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

@baukit/a11y-core 的下载量有多少?

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

@baukit/a11y-core 还在维护吗?

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