From c93400d375cb3a3ac188093d4d92e75d71b2800c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=81=8F=E5=8F=B3?= Date: Mon, 25 May 2020 17:43:59 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E2=8C=A8=EF=B8=8F=20Popconfirm=20can?= =?UTF-8?q?=20be=20closed=20by=20pressing=20ESC=20(#24420)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: support ESC to close Popconfirm close #15203 * add test case * fix focus in other element inside inner-content * no fit * fix snapshot * refactor it * use util cloneElement * fix test case --- components/popconfirm/__tests__/index.test.js | 19 ++++++++++++ components/popconfirm/index.tsx | 29 ++++++++++++++++--- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/components/popconfirm/__tests__/index.test.js b/components/popconfirm/__tests__/index.test.js index 4e930a12c0..78ce927c12 100644 --- a/components/popconfirm/__tests__/index.test.js +++ b/components/popconfirm/__tests__/index.test.js @@ -176,4 +176,23 @@ describe('Popconfirm', () => { triggerNode.simulate('click'); expect(ref.current.getPopupDomNode()).toBeFalsy(); }); + + it('should be closed by pressing ESC', () => { + const onVisibleChange = jest.fn(); + const wrapper = mount( + + Delete + , + ); + const triggerNode = wrapper.find('span').at(0); + triggerNode.simulate('click'); + expect(onVisibleChange).toHaveBeenLastCalledWith(true, undefined); + triggerNode.simulate('keydown', { key: 'Escape', keyCode: 27 }); + expect(onVisibleChange).toHaveBeenLastCalledWith(false, eventObject); + }); }); diff --git a/components/popconfirm/index.tsx b/components/popconfirm/index.tsx index 673d470f22..1462d1e133 100644 --- a/components/popconfirm/index.tsx +++ b/components/popconfirm/index.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; import ExclamationCircleFilled from '@ant-design/icons/ExclamationCircleFilled'; +import KeyCode from 'rc-util/lib/KeyCode'; import Tooltip, { AbstractTooltipProps } from '../tooltip'; import Button from '../button'; import { LegacyButtonType, NativeButtonProps, convertLegacyProps } from '../button/button'; @@ -7,6 +8,7 @@ import LocaleReceiver from '../locale-provider/LocaleReceiver'; import defaultLocale from '../locale/default'; import { ConfigContext } from '../config-provider'; import { getRenderPropValue, RenderFunction } from '../_util/getRenderPropValue'; +import { cloneElement } from '../_util/reactNode'; export interface PopconfirmProps extends AbstractTooltipProps { title: React.ReactNode | RenderFunction; @@ -19,7 +21,10 @@ export interface PopconfirmProps extends AbstractTooltipProps { okButtonProps?: NativeButtonProps; cancelButtonProps?: NativeButtonProps; icon?: React.ReactNode; - onVisibleChange?: (visible: boolean, e?: React.MouseEvent) => void; + onVisibleChange?: ( + visible: boolean, + e?: React.MouseEvent | React.KeyboardEvent, + ) => void; } export interface PopconfirmState { @@ -46,7 +51,10 @@ const Popconfirm = React.forwardRef((props, ref) => { } }, [props.defaultVisible]); - const settingVisible = (value: boolean, e?: React.MouseEvent) => { + const settingVisible = ( + value: boolean, + e?: React.MouseEvent | React.KeyboardEvent, + ) => { if (!('visible' in props)) { setVisible(value); } @@ -72,6 +80,12 @@ const Popconfirm = React.forwardRef((props, ref) => { } }; + const onKeyDown = (e: React.KeyboardEvent) => { + if (e.keyCode === KeyCode.ESC && visible) { + settingVisible(false, e); + } + }; + const onVisibleChange = (value: boolean) => { const { disabled } = props; if (disabled) { @@ -107,7 +121,7 @@ const Popconfirm = React.forwardRef((props, ref) => { const { getPrefixCls } = React.useContext(ConfigContext); - const { prefixCls: customizePrefixCls, placement, ...restProps } = props; + const { prefixCls: customizePrefixCls, placement, children, ...restProps } = props; const prefixCls = getPrefixCls('popover', customizePrefixCls); const overlay = ( @@ -125,7 +139,14 @@ const Popconfirm = React.forwardRef((props, ref) => { visible={visible} overlay={overlay} ref={ref as any} - /> + > + {cloneElement(children, { + onKeyDown: (e: React.KeyboardEvent) => { + children?.props.onKeyDown?.(e); + onKeyDown(e); + }, + })} + ); });