From 94dcda55a4f3880c9e66f0b6979c47a21895df5d Mon Sep 17 00:00:00 2001 From: kiner-tang <1127031143@qq.com> Date: Thu, 29 Feb 2024 14:45:24 +0800 Subject: [PATCH] feat: Dialog support aria-* in closable (#403) * feat: Dialog support aria-* in closable * feat: Dialog support aria-* in closable * feat: Dialog support aria-* in closable * feat: Dialog support aria-* in closable * feat: optimize code * feat: optimize code --- src/Dialog/Content/Panel.tsx | 20 +++++++++++++++--- src/IDialogPropTypes.tsx | 2 +- tests/index.spec.tsx | 40 ++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/Dialog/Content/Panel.tsx b/src/Dialog/Content/Panel.tsx index 2be44237..afea6a4f 100644 --- a/src/Dialog/Content/Panel.tsx +++ b/src/Dialog/Content/Panel.tsx @@ -1,9 +1,10 @@ import classNames from 'classnames'; import { useComposeRef } from 'rc-util/lib/ref'; -import React, { useRef } from 'react'; +import React, { useMemo, useRef } from 'react'; import { RefContext } from '../../context'; import type { IDialogPropTypes } from '../../IDialogPropTypes'; import MemoChildren from './MemoChildren'; +import pickAttrs from 'rc-util/lib/pickAttrs'; const sentinelStyle = { width: 0, height: 0, overflow: 'hidden', outline: 'none' }; const entityStyle = { outline: 'none' }; @@ -96,11 +97,24 @@ const Panel = React.forwardRef((props, ref) => { ); } + + const closableObj = useMemo(() => { + if (typeof closable === 'object' && closable !== null) { + return closable; + } + if (closable) { + return { closeIcon: closeIcon ?? }; + } + return {}; + }, [closable, closeIcon]); + + const ariaProps = pickAttrs(closableObj, true); + let closer: React.ReactNode; if (closable) { closer = ( - ); } diff --git a/src/IDialogPropTypes.tsx b/src/IDialogPropTypes.tsx index ac64ac33..2d9bf12c 100644 --- a/src/IDialogPropTypes.tsx +++ b/src/IDialogPropTypes.tsx @@ -28,7 +28,7 @@ export type IDialogPropTypes = { afterClose?: () => any; afterOpenChange?: (open: boolean) => void; onClose?: (e: SyntheticEvent) => any; - closable?: boolean; + closable?: boolean | ({ closeIcon?: React.ReactNode } & React.AriaAttributes); maskClosable?: boolean; visible?: boolean; destroyOnClose?: boolean; diff --git a/tests/index.spec.tsx b/tests/index.spec.tsx index 39ee9f17..c79dd88f 100644 --- a/tests/index.spec.tsx +++ b/tests/index.spec.tsx @@ -640,4 +640,44 @@ describe('dialog', () => { ); spy.mockRestore(); }); + + it('support aria-* in closable', () => { + const onClose = jest.fn(); + const wrapper = mount( + + ); + jest.runAllTimers(); + wrapper.update(); + + const btn = wrapper.find('.rc-dialog-close'); + expect(btn.text()).toBe('test'); + expect(btn.getDOMNode().getAttribute('aria-label')).toBe('test aria-label'); + btn.simulate('click'); + + jest.runAllTimers(); + wrapper.update(); + expect(onClose).toHaveBeenCalledTimes(1); + }); + it('should not display closeIcon when closable is false', () => { + const onClose = jest.fn(); + const wrapper = mount( + + ); + jest.runAllTimers(); + wrapper.update(); + + const btn = wrapper.find('.rc-dialog-close'); + expect(btn.find('.rc-dialog-close-x')).not.toBeNull(); + }); });