Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(editor): fix accessibility issues with editor tabs and close buttons #3916

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

lilangtop
Copy link
Contributor

@lilangtop lilangtop commented Aug 7, 2024

Types

  • 🎉 New Features

Background or solution

关联issuse #3900
为编辑器的选项卡和关闭按钮添加键盘操作支持、适配屏幕阅读器
改造后的编辑器tab代码

Changelog

  • 选项卡支持键盘聚焦
  • 选项卡聚焦后支持按左光彪和上光标移动到上一个选项卡、按下光标或右光标移动到后一个选项卡、按home移动到第一个选项卡、按end移动到最后一个选项卡。
  • 选项卡支持回车键或空格键执行点击操作、支持按菜单键Application弹出菜单。
  • 选项卡添加aria无障碍展开状态属性,支持屏幕阅读器朗读选项卡是否展开的状态。
  • 选项卡的关闭按钮添加键盘焦点、添加无障碍属性适配屏幕阅读器。

Summary by CodeRabbit

  • 新功能

    • 增强了编辑器中标签组件的键盘导航和交互处理,支持使用方向键、Home、End、空格和回车键进行标签导航。
    • 引入了程序化触发鼠标事件的功能,提高了用户交互体验。
  • 可访问性

    • 为每个标签添加了ARIA角色和属性,改善了对键盘用户和辅助技术用户的支持。

- Add role="tab" to tabs
- Add aria-expanded attribute to indicate the active tab
- Enable keyboard focus on tabs
- Support arrow keys: left or up arrow moves to the previous tab, right or down arrow
  moves to the next tab, end key moves to the last tab, home key moves to the first tab
- Support Enter or Space key to activate the focused tab, and Menu key to open the
  context menu
- Add role="button", aria-label, and keyboard shortcut hints to all tab close buttons
- Add keyboard focus to the close button of the active tab, support Space or Enter key
  to activate the close button

Closes opensumi#3900
@CLAassistant
Copy link

CLAassistant commented Aug 7, 2024

CLA assistant check
All committers have signed the CLA.

Copy link
Contributor

coderabbitai bot commented Aug 7, 2024

Walkthrough

此次更改显著提升了编辑器中 Tabs 组件的键盘导航和交互处理。新增的 handleKeyDown 函数允许用户通过方向键和其他键进行标签导航,同时引入了 simulateClicksimulateContextMenu 函数以支持通过键盘模拟鼠标事件。这些更改不仅提高了功能性,还增强了无障碍访问性,确保所有用户都能更便捷地使用标签导航系统。

Changes

文件路径 更改摘要
packages/editor/src/browser/tab.view.tsx 增强键盘导航功能,新增事件处理函数,改进可访问性特性,包括ARIA角色和属性,同时支持用键盘模拟鼠标点击。

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Keyboard
    participant TabsComponent

    User->>Keyboard: 按下方向键
    Keyboard->>TabsComponent: 触发 handleKeyDown
    TabsComponent->>TabsComponent: 处理导航 (移动焦点)
    TabsComponent->>User: 更新高亮状态

    User->>Keyboard: 按下 Space 或 Enter
    Keyboard->>TabsComponent: 触发 simulateClick
    TabsComponent->>TabsComponent: 执行当前标签的点击操作
Loading

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@opensumi opensumi bot added the 🐞 bug Something isn't working label Aug 7, 2024
Copy link

codecov bot commented Aug 7, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 54.83%. Comparing base (6c1122d) to head (660b2dd).
Report is 136 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3916      +/-   ##
==========================================
- Coverage   54.84%   54.83%   -0.01%     
==========================================
  Files        1559     1559              
  Lines       95181    95181              
  Branches    19497    19497              
==========================================
- Hits        52198    52195       -3     
- Misses      35707    35709       +2     
- Partials     7276     7277       +1     
Flag Coverage Δ
jsdom 50.28% <ø> (-0.01%) ⬇️
node 15.53% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@@ -370,15 +371,91 @@ export const Tabs = ({ group }: ITabsProps) => {
[editorService],
);

// 处理选项卡键盘事件
const handleKeyDown = (e: React.KeyboardEvent) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

在 OpenSumi 中目前针对快捷键有统一实现,不建议通过这种方式绑定键盘事件处理,可以通过 keybindingService 去注册快捷键方式实现,而选项卡是否聚焦,应该设定相应的 when 来控制,相关可参考的代码见:

registerKeybindings(keybindings: KeybindingRegistry) {

注册与前端组件绑定的 contextKey(when):

initContextKey(dom: HTMLDivElement) {

当前实现后续可能会出现快捷键冲突问题

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

收到
请问a给组件添加aria、role、tabIndex属性这些可以直接加在组件上吗,有没有统一处理机制。我们先加常规的无障碍属性和tabIndex。键盘的单独提交

@erha19
Copy link
Member

erha19 commented Aug 9, 2024

单个 PR 内容可以简化一下,例如本次可以先把部分属性状态的更新提交 @lilangtop

@lilangtop
Copy link
Contributor Author

单个 PR 内容可以简化一下,例如本次可以先把部分属性状态的更新提交 @lilangtop

请问给组件添加键盘点击的支持是否可以使用这种方式呢。
给组件添加 onKeyDown={handleKeyDown}

const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.key === ' ' || e.key === 'Enter') {
e.currentTarget.click();
e.preventDefault();
}
};

tabIndex={isCurrent ? 0 : -1}
role='button'
aria-label={editorCloseTabButtonAriaLabel}
aria-description={isMacintosh ? '⌘W' : 'Ctrl+W'}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里的快捷键 ⌘W 是跟随着快捷键配置走的,不一定一直是 ⌘W。
你可以通过 keybindingRegistry 来获取 EDITOR_COMMANDS.CLOSE.id 所绑定的快捷键信息,并将其转为文案显示。可以参考这里
https://github.com/opensumi/core/blob/v3.2/packages/ai-native/src/browser/widget/inline-hint/inline-hint-line-widget.tsx#L38-L45

e.stopPropagation();
e.preventDefault();
// 模拟鼠标左键点击事件
const mouseDownEvent = new window.MouseEvent('mousedown', { bubbles: true, button: 0 });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

直接调用 group.close(resource.uri) 吧。和 onMouseDown 的事件一样,不需要通过 MouseEvent 去模拟

}
};

if (['ArrowLeft', 'ArrowUp'].includes(e.key)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里的硬编码都使用 packages/core-browser/src/keyboard/keys.ts 文件里的变量吧

const currentElement = e.currentTarget;
const parentNode = currentElement.parentElement?.parentElement?.parentElement;
if (parentNode) {
const tabs = Array.from(parentNode.querySelectorAll('[role="tab"][aria-expanded]')) as HTMLElement[];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里通过 react 的 ref 去访问 role='tab' 的元素吧,不要通过 querySelectorAll 的方式。

};

const simulateContextMenu = (element: HTMLElement) => {
const mouseDownEvent = new window.MouseEvent('contextmenu', { bubbles: true, button: 2 });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里的 simulateContextMenu 可以直接调用 tabTitleMenuService.show 方法,和 onContextMenu 的事件处理一致就行

};

const simulateClick = (element: HTMLElement) => {
const mouseDownEvent = new window.MouseEvent('mousedown', { bubbles: true, button: 0 });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

同理,可以和 onMousedown 事件的处理方式一样

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

收到,谢谢

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐞 bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants