mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-11-29 18:50:00 +08:00
feat(modal): Ingested changes from rc-dialog to disable modal close button (#50522)
Co-authored-by: Alina Andrieieva <Alina_Andrieieva@epam.com> Co-authored-by: afc163 <afc163@gmail.com>
This commit is contained in:
parent
b5b0918970
commit
a75c481ddf
@ -1,10 +1,10 @@
|
||||
import type { ReactNode } from 'react';
|
||||
import React from 'react';
|
||||
import CloseOutlined from '@ant-design/icons/CloseOutlined';
|
||||
import type { DialogProps } from 'rc-dialog';
|
||||
import pickAttrs from 'rc-util/lib/pickAttrs';
|
||||
|
||||
export type BaseClosableType = { closeIcon?: React.ReactNode } & React.AriaAttributes;
|
||||
export type ClosableType = boolean | BaseClosableType;
|
||||
export type ClosableType = DialogProps['closable'];
|
||||
|
||||
export type BaseContextClosable = { closable?: ClosableType; closeIcon?: ReactNode };
|
||||
export type ContextClosable<T extends BaseContextClosable = any> = Partial<
|
||||
@ -49,7 +49,7 @@ function useClosableConfig(closableCollection?: ClosableCollection | null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let closableConfig: BaseClosableType = {
|
||||
let closableConfig: ClosableType = {
|
||||
closeIcon: typeof closeIcon !== 'boolean' && closeIcon !== null ? closeIcon : undefined,
|
||||
};
|
||||
if (closable && typeof closable === 'object') {
|
||||
@ -104,10 +104,12 @@ export default function useClosable(
|
||||
*/
|
||||
closeIconRender?: (closeIcon: ReactNode) => ReactNode;
|
||||
} = EmptyFallbackCloseCollection,
|
||||
): [closable: boolean, closeIcon: React.ReactNode | null] {
|
||||
): [closable: boolean, closeIcon: React.ReactNode, closeBtnIsDisabled: boolean] {
|
||||
// Align the `props`, `context` `fallback` to config object first
|
||||
const propCloseConfig = useClosableConfig(propCloseCollection);
|
||||
const contextCloseConfig = useClosableConfig(contextCloseCollection);
|
||||
const closeBtnIsDisabled =
|
||||
typeof propCloseConfig !== 'boolean' ? !!propCloseConfig?.disabled : false;
|
||||
const mergedFallbackCloseCollection = React.useMemo(
|
||||
() => ({
|
||||
closeIcon: <CloseOutlined />,
|
||||
@ -149,7 +151,7 @@ export default function useClosable(
|
||||
// Calculate the final closeIcon
|
||||
return React.useMemo(() => {
|
||||
if (mergedClosableConfig === false) {
|
||||
return [false, null];
|
||||
return [false, null, closeBtnIsDisabled];
|
||||
}
|
||||
|
||||
const { closeIconRender } = mergedFallbackCloseCollection;
|
||||
@ -173,6 +175,6 @@ export default function useClosable(
|
||||
}
|
||||
}
|
||||
|
||||
return [true, mergedCloseIcon];
|
||||
return [true, mergedCloseIcon, closeBtnIsDisabled];
|
||||
}, [mergedClosableConfig, mergedFallbackCloseCollection]);
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ const Modal: React.FC<ModalProps> = (props) => {
|
||||
<Footer {...props} onOk={handleOk} onCancel={handleCancel} />
|
||||
) : null;
|
||||
|
||||
const [mergedClosable, mergedCloseIcon] = useClosable(
|
||||
const [mergedClosable, mergedCloseIcon, closeBtnIsDisabled] = useClosable(
|
||||
pickClosable(props),
|
||||
pickClosable(modalContext),
|
||||
{
|
||||
@ -139,7 +139,11 @@ const Modal: React.FC<ModalProps> = (props) => {
|
||||
visible={open ?? visible}
|
||||
mousePosition={restProps.mousePosition ?? mousePosition}
|
||||
onClose={handleCancel as any}
|
||||
closable={mergedClosable}
|
||||
closable={
|
||||
mergedClosable
|
||||
? { disabled: closeBtnIsDisabled, closeIcon: mergedCloseIcon }
|
||||
: mergedClosable
|
||||
}
|
||||
closeIcon={mergedCloseIcon}
|
||||
focusTriggerAfterClose={focusTriggerAfterClose}
|
||||
transitionName={getTransitionName(rootPrefixCls, 'zoom', props.transitionName)}
|
||||
|
@ -41,6 +41,11 @@ describe('Modal', () => {
|
||||
expect(baseElement.querySelector('.ant-modal-close')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('support disable close button when setting disable to true', () => {
|
||||
const { baseElement } = render(<Modal open closable={{ disabled: true }} />);
|
||||
expect(baseElement.querySelector('.ant-modal-close')).toHaveAttribute('disabled');
|
||||
});
|
||||
|
||||
it('render correctly', () => {
|
||||
const { asFragment } = render(<ModalTester />);
|
||||
expect(asFragment().firstChild).toMatchSnapshot();
|
||||
|
@ -53,7 +53,7 @@ Common props ref:[Common props](/docs/react/common-props)
|
||||
| cancelButtonProps | The cancel button props | [ButtonProps](/components/button/#api) | - | |
|
||||
| cancelText | Text of the Cancel button | ReactNode | `Cancel` | |
|
||||
| centered | Centered Modal | boolean | false | |
|
||||
| closable | Whether a close (x) button is visible on top right or not | boolean \| { closeIcon?: React.ReactNode } | true | |
|
||||
| closable | Whether a close (x) button is visible on top right or not | boolean \| { closeIcon?: React.ReactNode; disabled?: boolean; } | true | |
|
||||
| closeIcon | Custom close icon. 5.7.0: close button will be hidden when setting to `null` or `false` | ReactNode | <CloseOutlined /> | |
|
||||
| confirmLoading | Whether to apply loading visual effect for OK button or not | boolean | false | |
|
||||
| destroyOnClose | Whether to unmount child components on onClose | boolean | false | |
|
||||
|
@ -54,7 +54,7 @@ demo:
|
||||
| cancelButtonProps | cancel 按钮 props | [ButtonProps](/components/button-cn#api) | - | |
|
||||
| cancelText | 取消按钮文字 | ReactNode | `取消` | |
|
||||
| centered | 垂直居中展示 Modal | boolean | false | |
|
||||
| closable | 是否显示右上角的关闭按钮 | boolean \| { closeIcon?: React.ReactNode } | true | |
|
||||
| closable | 是否显示右上角的关闭按钮 | boolean \| { closeIcon?: React.ReactNode; disabled?: boolean; } | true | |
|
||||
| closeIcon | 自定义关闭图标。5.7.0:设置为 `null` 或 `false` 时隐藏关闭按钮 | ReactNode | <CloseOutlined /> | |
|
||||
| confirmLoading | 确定按钮 loading | boolean | false | |
|
||||
| destroyOnClose | 关闭时销毁 Modal 里的子元素 | boolean | false | |
|
||||
|
@ -1,7 +1,6 @@
|
||||
import type React from 'react';
|
||||
import type { DialogProps } from 'rc-dialog';
|
||||
|
||||
import type { ClosableType } from '../_util/hooks/useClosable';
|
||||
import type { ButtonProps, LegacyButtonType } from '../button/button';
|
||||
import type { DirectionType } from '../config-provider';
|
||||
|
||||
@ -21,8 +20,6 @@ export interface ModalProps extends ModalCommonProps {
|
||||
confirmLoading?: boolean;
|
||||
/** The modal dialog's title */
|
||||
title?: React.ReactNode;
|
||||
/** Whether a close (x) button is visible on top right of the modal dialog or not. Recommend to use closeIcon instead. */
|
||||
closable?: ClosableType;
|
||||
/** Specify a function that will be called when a user clicks the OK button */
|
||||
onOk?: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
||||
/** Specify a function that will be called when a user clicks mask, close button on top right or Cancel button */
|
||||
@ -89,7 +86,6 @@ export interface ModalFuncProps extends ModalCommonProps {
|
||||
/** @deprecated Please use `open` instead. */
|
||||
visible?: boolean;
|
||||
title?: React.ReactNode;
|
||||
closable?: ClosableType;
|
||||
content?: React.ReactNode;
|
||||
// TODO: find out exact types
|
||||
onOk?: (...args: any[]) => any;
|
||||
|
@ -287,6 +287,10 @@ const genModalStyle: GenerateStyle<ModalToken> = (token) => {
|
||||
textRendering: 'auto',
|
||||
},
|
||||
|
||||
'&:disabled': {
|
||||
pointerEvents: 'none',
|
||||
},
|
||||
|
||||
'&:hover': {
|
||||
color: token.modalCloseIconHoverColor,
|
||||
backgroundColor: token.colorBgTextHover,
|
||||
|
Loading…
Reference in New Issue
Block a user