[Dialog] 支持焦点落点可配置、Enter 键确认与焦点循环(含 DialogPlugin 对齐)
Maintainer thường phản hồi trong vòng 1 ngày
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức phù hợp với người mới
- 18/100
- Loại issue
- Tính năng
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- react, typescript
- Lĩnh vực
- frontend
Hướng nghiên cứu
Start with dialog/hooks/useDialogEsc.js, where activateDialog() currently focuses only the .t-dialog__ctx container, then dialog/DialogCard.js (renderConfirmBtn hardcodes the primary theme and renderFooter passes custom footers through unchanged), and config-provider/ConfigContext.js for the dialog defaults. Done means defaultFocus, Enter-to-confirm with its textarea, IME and confirmLoading guards, and Tab focus trap work the same for Dialog and DialogPlugin, with a stable data-role="confirm" marker on the primary button.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
这个功能解决了什么问题
环境
- tdesign-react: 1.18.2
- React: 18
- 浏览器: Chrome 140 / Safari 18(均复现)
背景与诉求
- 不同弹窗诉求不同:二次确认希望焦点落「确定」,危险操作(删除/锁定)希望落「取消」,表单类弹窗希望落输入框。落点应由参数决定,并支持全站默认值。
- 可配置的键盘确认:只要弹窗打开,按 Enter 就应等同于点击「确定」。当前焦点默认落在弹窗容器上,回车完全无响应,键盘链路断裂。
期望行为
- 焦点落点可配置:提供
defaultFocus,支持'confirm' | 'cancel' | 'none' | (() => HTMLElement | null);组件默认值建议保持现状('none')以兼容存量,但通过globalConfig.dialog.defaultFocus可全站统一策略。 - Enter 触发确认,与焦点解耦:弹窗打开期间按 Enter 等同于点击「确定」,不要求焦点位于主按钮;Esc 仍关闭。需内置边界:焦点在
textarea/可换行输入控件、IME 组合输入过程中不触发,confirmLoading期间不重复触发。可用confirmOnEnter开关。 - Tab 焦点循环:Tab / Shift+Tab 在弹窗内循环,不逃逸;关闭后焦点归还触发元素(
restoreFocus)。 - 上述能力在声明式
Dialog与命令式DialogPlugin上行为一致。
你建议的方案是什么
建议 API(P0,其余能力可另开 issue)
interface DialogProps {
/** 打开后焦点落点;组件默认建议保持现状('none'),由业务按需指定 */
defaultFocus?: 'confirm' | 'cancel' | 'none' | (() => HTMLElement | null);
/** Enter 触发确认,默认 true */
confirmOnEnter?: boolean;
/** 焦点循环,默认 true */
focusTrap?: boolean;
/** 关闭后焦点归还触发元素,默认 true */
restoreFocus?: boolean;
}
配套要求:
globalConfig.dialog暴露defaultFocus/confirmOnEnter/focusTrap的默认值,便于全站统一;- 为「主操作按钮」提供稳定语义标记(例如统一
data-role="confirm",自定义 footer 下由业务显式声明),让defaultFocus: 'confirm'与 Enter 确认在任何 footer 形态下都能命中,而不是靠类名匹配。
根因(源码定位)
dialog/hooks/useDialogEsc.js的activateDialog()只做lastDialog.current.focus(),把焦点交给容器.t-dialog__ctx,既不涉及按钮,也没有任何落点配置。- 组件层只监听 Esc,无 Enter、无 focus trap;
autofocus在 Dialog 内不生效(参考 #2794),消费方只能在onOpened里补刀,且开场动画期间 TDesign 会抢焦点,时序脆弱。 dialog/DialogCard.js的renderConfirmBtn硬编码theme: "primary"(theme="danger"弹窗也渲染 primary),renderFooter对自定义footer直接parseTNode,不提供「主操作按钮」语义标记。于是:- 默认 footer:主按钮是
.t-button--theme-primary; - 自定义 footer:业务常用
<Button theme="danger">,类名是.t-button--theme-danger。
我们的补丁只认--theme-primary时,一批自定义 footer 弹窗(如分支锁定)主按钮依然拿不到焦点——只要组件不给语义,消费方就只能不断猜选择器。
- 默认 footer:主按钮是
config-provider/ConfigContext.js中dialog.confirmBtnTheme已声明默认值,但全量检索es/无任何消费方,属未生效配置。
我们当前的 workaround(供参考,非长期方案)
在业务封装层:① onOpened 里按类名猜主按钮并 focus();② 在 document 上挂 keydown 捕获实现 Tab 循环;③ 用 :focus 补焦点环(程序化 focus 不命中 :focus-visible,Button 无可见焦点);④ 对 DialogPlugin.confirm 做同构包装复制同一套逻辑。
Enter 确认目前只能自己绑,还得自行判断 textarea、IME 组合输入、confirmLoading 等边界,规则与组件内部(如 Esc 的 dialogStack)不同步就会出现误触发或漏触发。这套补丁必须随组件实现变化持续维护,因此希望能力下沉到组件层。
- Ngôn ngữ chính
- TypeScript
- Star
- 973
- Fork
- 379
- Merge trung bình
- 4 ngày 7 giờ
- Pull request đã merge (30 ngày)
- 15
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của Tencent/tdesign-react
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
Tencent/tdesign-react#4465 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[Table] reserveSelectedRowOnPaginate=false 时表头全选包含其他页数据Có thể đã có người làm @dvd233 đã nhận 33 ngày trước. Đang mở🐞 bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
Tencent/tdesign-react#4416 · 4 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[Chatbot] 似乎不支持ag-ui中的interruptsCó thể làm lại được @LzhengH đã nhận 52 ngày trước và không có pull request nào đang mở. Đang mở💪🏻 enhancement
Tencent/tdesign-react#4400 · 1 bình luận · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
-
💪🏻 enhancement
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 58/100
Tencent/tdesign-react#4253 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
💪🏻 enhancement
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 35/100
Tencent/tdesign-react#4246 · 3 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của Tencent/tdesign-react
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
earendil-works/pi-claude-code#36 ·
Maintainer thường phản hồi trong vòng 6 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Resources: New work of jabodetabekCó thể đã có người làm @rmt-svc đã nhận hôm nay. Đang mởresources
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
railmapgen/rmp-gallery#4167 ·
Maintainer thường phản hồi trong vòng 2 ngày
-
documentation p1
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 83/100
microsoft/monaco-editor#5577 ·
Maintainer thường phản hồi trong vòng 1 ngày