Skip to content

Conversation

@aojunhao123
Copy link
Contributor

@aojunhao123 aojunhao123 commented Dec 24, 2025

Summary by CodeRabbit

发布说明

  • 改进
    • 增强了抽屉组件的键盘事件处理,支持通过 Esc 键关闭抽屉。
    • 优化了键盘交互逻辑,简化了事件处理流程。

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link

vercel bot commented Dec 24, 2025

@aojunhao123 is attempting to deploy a commit to the React Component Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link

coderabbitai bot commented Dec 24, 2025

概述

本次变更重构了抽屉组件的键盘事件处理机制。将 ESC 键关闭功能从 DrawerPopup 内部处理转移到 Portal 层级,同时扩展了 onClose 回调的事件类型支持,并相应更新了相关测试用例以验证新的事件流。

变更清单

结群 / 文件 变更摘要
抽屉组件核心逻辑重构
src/Drawer.tsx
扩展 DrawerProps.onClose 事件类型,新增原生 KeyboardEvent 支持(原有 React.MouseEventReact.KeyboardEvent 保留);新增 onEsc 处理器,将 ESC 键事件委托至 Portal 组件处理
抽屉弹窗简化
src/DrawerPopup.tsx
移除 keyboard 属性的解构使用;删除面板 keydown 逻辑中的 ESC 键处理(移除 KeyCode.ESC 分支),仅保留 TAB 导航逻辑;调整接口声明格式为单行形式
测试用例更新
tests/index.spec.tsx
修改 ESC 关闭行为的测试:改用在 window 上分派 keyDown 事件(key: 'Escape')替代原有的特定元素内部 KeyCode.ESC 方式;更新两个相关测试用例的事件源和按键表示方法

代码审查工作量评估

🎯 2 (简单) | ⏱️ ~12 分钟

建议审查者

  • zombieJ

🐰 ESC 键旅行新去处,
从弹窗深处到 Portal 驻,
事件类型更宽广,
测试窗口听传唱,
键盘舞步更流畅。

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main changes: moving ESC key handling from DrawerPopup to Portal with adjusted event type signatures.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @aojunhao123, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request refactors the keyboard event handling for the drawer component, specifically for closing the drawer with the ESC key. The change centralizes the ESC key logic within the main Drawer component, leveraging a Portal component for event management, and updates the onClose callback signature to accommodate native keyboard events. This improves the consistency and maintainability of keyboard interactions.

Highlights

  • Refactored ESC Key Handling: The logic for closing the drawer using the ESC key has been moved from the DrawerPopup component to the Drawer component, utilizing a Portal component's onEsc prop for more centralized and robust handling.
  • Updated onClose Event Type: The onClose callback now explicitly supports receiving a native KeyboardEvent object, aligning with the new keyboard event handling mechanism.
  • Modernized Keyboard Event Tests: Existing tests for ESC key functionality have been updated to simulate window-level keyboard events and use the modern key: 'Escape' property instead of keyCode.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@codecov
Copy link

codecov bot commented Dec 24, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (5f1e192) to head (e7931df).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff            @@
##            master      #558   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            6         6           
  Lines          218       217    -1     
  Branches        80        79    -1     
=========================================
- Hits           218       217    -1     

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

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the keyboard event handling for closing the drawer with the Escape key. The logic has been moved from DrawerPopup to the main Drawer component, utilizing the onEsc prop from the Portal component. This is a good improvement, as it centralizes the logic and makes the behavior more robust (e.g., it's no longer dependent on the drawer panel having focus). The tests have been updated accordingly to reflect this change. I've found one minor typing inconsistency that should be addressed to ensure type safety across components.

prefixCls?: string;
open?: boolean;
onClose?: (e: React.MouseEvent | React.KeyboardEvent) => void;
onClose?: (e: React.MouseEvent | React.KeyboardEvent | KeyboardEvent) => void;
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

You've correctly updated the onClose type here to include KeyboardEvent. However, the onClose prop in the DrawerPopupProps interface (defined in src/DrawerPopup.tsx) was not updated to reflect this change. This creates a type inconsistency between the Drawer and DrawerPopup components, which can lead to type errors under stricter TypeScript configurations (like strictFunctionTypes). To ensure type safety, DrawerPopupProps['onClose'] should also be updated to accept a native KeyboardEvent.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
src/Drawer.tsx (1)

143-162: 建议清理未使用的属性传递。

keyboard 属性被传递给 DrawerPopup(行 149),但根据 src/DrawerPopup.tsx 的更改,该组件不再使用此属性(ESC 处理已移至 Portal 层)。

如果 DrawerPopup 确实不再需要 keyboard 属性,建议:

  1. 从传递给 DrawerPopup 的 props 中移除 keyboard
  2. 或在 DrawerPopup.tsx 中从接口定义中移除该属性

这有助于保持代码清晰并避免混淆。

src/DrawerPopup.tsx (2)

41-41: 考虑从接口中移除未使用的 keyboard 属性。

keyboard 属性仍在 DrawerPopupProps 接口中定义,但组件内部不再使用它(ESC 处理已移至 Drawer.tsx)。

建议:

  • 如果不需要保持向后兼容性,从 DrawerPopupProps 接口中移除 keyboard 属性
  • 如果需要保留,添加注释说明该属性由父组件使用

这有助于明确接口的意图并避免混淆。


157-176: LGTM!正确移除了 ESC 键处理逻辑。

onPanelKeyDown 现在只处理 TAB 键导航,ESC 键处理已移至 Drawer.tsxonEsc 处理器。这使得职责分离更清晰。

可选建议:由于现在只有一个键码需要处理,可以考虑将 switch 语句简化为 if 语句,但保持 switch 结构也便于将来扩展。

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5f1e192 and e7931df.

📒 Files selected for processing (3)
  • src/Drawer.tsx
  • src/DrawerPopup.tsx
  • tests/index.spec.tsx
🧰 Additional context used
🧬 Code graph analysis (2)
src/Drawer.tsx (3)
src/DrawerPopup.tsx (1)
  • DrawerPopupProps (33-94)
src/DrawerPanel.tsx (2)
  • DrawerPanelEvents (11-18)
  • DrawerPanelAccessibility (20-23)
src/context.ts (1)
  • RefContext (15-15)
src/DrawerPopup.tsx (1)
src/DrawerPanel.tsx (2)
  • DrawerPanelEvents (11-18)
  • DrawerPanelAccessibility (20-23)
🔇 Additional comments (3)
tests/index.spec.tsx (2)

300-307: LGTM!测试更新与新的 ESC 处理机制对齐。

测试从元素级别的 ESC 事件改为窗口级别的 Escape 键事件,这与 Portal 组件的 onEsc 处理器行为一致。


309-318: LGTM!禁用 ESC 的测试正确更新。

测试验证了当 keyboard={false} 时,窗口级别的 Escape 键事件不会触发 onClose,符合预期行为。

src/Drawer.tsx (1)

24-24: LGTM!正确扩展了 onClose 的类型签名。

添加 KeyboardEvent(原生事件类型)是必要的,因为新的 onEsc 处理器会传递 Portal 提供的原生键盘事件。

Comment on lines +164 to +169
const onEsc: PortalProps['onEsc'] = ({ top, event }) => {
if (top && keyboard) {
event.stopPropagation();
onClose?.(event);
}
};
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# 查找 src/Drawer.tsx 文件并查看目标行
fd -type f "Drawer.tsx" -path "*/src/*" | head -5

Repository: react-component/drawer

Length of output: 236


🏁 Script executed:

# 检查 @rc-component/portal 包是否存在及其结构
ls -la node_modules/@rc-component/portal 2>/dev/null | head -20

Repository: react-component/drawer

Length of output: 48


🏁 Script executed:

# 正确的查找命令 - 查找 Drawer.tsx
fd "Drawer.tsx" src/

Repository: react-component/drawer

Length of output: 80


🏁 Script executed:

# 查看项目结构
ls -la src/ | head -20

Repository: react-component/drawer

Length of output: 675


🏁 Script executed:

# 查找所有 TypeScript 文件中 onEsc 的引用
rg "onEsc" --type ts --type tsx

Repository: react-component/drawer

Length of output: 93


🏁 Script executed:

# 查看 Drawer.tsx 的内容,特别关注行 164-169
cat -n src/Drawer.tsx | sed -n '150,180p'

Repository: react-component/drawer

Length of output: 1000


🏁 Script executed:

# 搜索 onEsc 的使用(不指定文件类型)
rg "onEsc" -A 5 -B 2

Repository: react-component/drawer

Length of output: 686


🏁 Script executed:

# 查看 Drawer.tsx 的导入部分
head -40 src/Drawer.tsx

Repository: react-component/drawer

Length of output: 1501


🏁 Script executed:

# 搜索 PortalProps 的定义或使用
rg "PortalProps" -B 2 -A 5

Repository: react-component/drawer

Length of output: 1158


🏁 Script executed:

# 查看 package.json 了解依赖信息
cat package.json | grep -A 2 -B 2 "portal\|Portal"

Repository: react-component/drawer

Length of output: 218


🏁 Script executed:

# 查找项目中所有的 d.ts 或 TypeScript 定义文件
find . -name "*.d.ts" -o -name "*.ts" | grep -i portal | head -10

Repository: react-component/drawer

Length of output: 48


🏁 Script executed:

# 查看是否有 node_modules,并检查 @rc-component/portal 的类型文件
find . -path "*/node_modules/@rc-component/portal*" -name "*.d.ts" 2>/dev/null | head -5

Repository: react-component/drawer

Length of output: 48


🌐 Web query:

@rc-component/portal onEsc API documentation

💡 Result:

Short answer: @rc-component/portal does not expose an onEsc prop. Its documented props are getContainer, open, and autoLock; it provides no built‑in Escape-key handler — handle Escape yourself (e.g., add a keydown listener in your portal content or use a higher-level component like rc-dialog that supports onClose). [1][2]

Sources:

  • @rc-component/portal npm README (props list: getContainer, open, autoLock). [1]
  • Package overview / API listing (no onEsc in API). [2]

🌐 Web query:

@rc-component/portal version 2.0 onEsc escape key handler support

💡 Result:

Short answer: No — @rc-component/portal v2.x does not include a built-in onEsc/escape-key prop. The published API shows only props like getContainer, open and autoLock (no onEsc/close-on-esc). See the package README/API. [1][2]

If you need ESC-to-close behavior, add a keydown listener in your component that wraps Portal (or use a higher-level rc component that provides built-in close-on-esc). [1]

Sources:

  • @rc-component/portal README / API (props list: getContainer, open, autoLock). [1]
  • jsDelivr/npm listing for @rc-component/portal (v2.x metadata). [2]

🌐 Web query:

rc-component/portal GitHub releases 2024 onEsc feature

💡 Result:

Do you mean the GitHub repo react-component/portal (or the npm package @rc-component/portal)? Do you want to know whether a 2024 release added an onEsc (escape-key) prop/feature?


🏁 Script executed:

# 查找是否有其他 Portal 使用的例子
rg "Portal" src/ -B 2 -A 5 | head -50

Repository: react-component/drawer

Length of output: 2096


🏁 Script executed:

# 查看项目的 tsconfig 或相关配置,检查是否有类型覆盖
cat tsconfig.json 2>/dev/null || echo "No tsconfig.json"

Repository: react-component/drawer

Length of output: 450


Portal 不支持 onEsc 属性,此实现将无法工作。

根据官方文档,@rc-component/portal v2.x 仅暴露以下属性:getContaineropenautoLock,不包含 onEsc 属性。当前代码将 onEsc 处理器传给 Portal(行 178),但该属性会被忽略,导致 ESC 键无法关闭 Drawer。

建议采用以下替代方案之一:

  • 在 DrawerPopup 或 DrawerPanel 组件内部添加 keydown 事件监听器
  • 检查 @rc-component/portal 是否计划添加此功能
  • 使用其他支持 escape-key 处理的高级组件

@zombieJ zombieJ merged commit d42dc89 into react-component:master Dec 25, 2025
7 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants