fix: Fix image group preview z index in nested modal (#46035)

* fix: Fixed Image.PreviewGroup preview in a nested modal where z-index Settings did not meet expectations

* fix: Fixed Image.PreviewGroup preview in a nested modal where z-index Settings did not meet expectations

* fix: Fixed Image.PreviewGroup preview in a nested modal where z-index Settings did not meet expectations

* test: update test case

* test: update test case

* bump: rc-menu@7.5.1

* feat: optimize code

* feat: optimize code

* feat: optimize code
This commit is contained in:
kiner-tang(文辉) 2023-11-24 16:17:52 +08:00 committed by GitHub
parent 650cf96dbf
commit 953fe6fa7e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 228 additions and 12 deletions

View File

@ -180,13 +180,23 @@ const consumerComponent: Record<ZIndexConsumer, React.FC<{ rootClassName: string
),
Menu: (props) => <Menu {...props} items={items} defaultOpenKeys={['SubMenu']} />,
ImagePreview: ({ rootClassName }: ImageProps) => (
<Image
src="xxx"
preview={{
visible: true,
rootClassName: `${rootClassName} comp-item comp-ImagePreview`,
}}
/>
<>
<Image
src="xxx"
preview={{
visible: true,
rootClassName: `${rootClassName} comp-item comp-ImagePreview`,
}}
/>
<Image.PreviewGroup
preview={{
visible: true,
rootClassName: `${rootClassName} comp-item comp-ImagePreviewGroup`,
}}
>
<Image src="xxx" />
</Image.PreviewGroup>
</>
),
};
@ -207,7 +217,12 @@ function getConsumerSelector(baseSelector: string, consumer: ZIndexConsumer): st
} else if (['Menu'].includes(consumer)) {
selector = `${baseSelector}.ant-menu-submenu-placement-rightTop`;
} else if (consumer === 'ImagePreview') {
selector = `${baseSelector}.comp-ImagePreview`;
selector = ['ImagePreview', 'ImagePreviewGroup']
.map(
(item) =>
`${baseSelector}.comp-${item} .ant-image-preview-wrap, ${baseSelector}.comp-${item}.ant-image-preview-operations-wrapper`,
)
.join(',');
}
return selector;
}
@ -276,7 +291,7 @@ describe('Test useZIndex hooks', () => {
const selector2 = getConsumerSelector('.consumer2', key as ZIndexConsumer);
const selector3 = getConsumerSelector('.consumer3', key as ZIndexConsumer);
if (['SelectLike', 'DatePicker'].includes(key)) {
if (['SelectLike', 'DatePicker', 'ImagePreview'].includes(key)) {
let comps = document.querySelectorAll(selector1);
comps.forEach((comp) => {
expect((comp as HTMLDivElement).style.zIndex).toBeFalsy();
@ -287,11 +302,15 @@ describe('Test useZIndex hooks', () => {
const consumerOffset = isColorPicker
? containerBaseZIndexOffset.Popover
: consumerBaseZIndexOffset[key as ZIndexConsumer];
const operOffset = comp.classList.contains('ant-image-preview-operations-wrapper')
? 1
: 0;
expect((comp as HTMLDivElement).style.zIndex).toBe(
String(
1000 +
containerBaseZIndexOffset[containerKey as ZIndexContainer] +
consumerOffset,
consumerOffset +
operOffset,
),
);
});
@ -302,11 +321,15 @@ describe('Test useZIndex hooks', () => {
const consumerOffset = isColorPicker
? containerBaseZIndexOffset.Popover
: consumerBaseZIndexOffset[key as ZIndexConsumer];
const operOffset = comp.classList.contains('ant-image-preview-operations-wrapper')
? 1
: 0;
expect((comp as HTMLDivElement).style.zIndex).toBe(
String(
1000 +
containerBaseZIndexOffset[containerKey as ZIndexContainer] * 2 +
consumerOffset,
consumerOffset +
operOffset,
),
);
});

View File

@ -15,6 +15,7 @@ import { getTransitionName } from '../_util/motion';
// CSSINJS
import useStyle from './style';
import { useZIndex } from '../_util/hooks/useZIndex';
export const icons = {
rotateLeft: <RotateLeftOutlined />,
@ -40,6 +41,11 @@ const InternalPreviewGroup: React.FC<GroupConsumerProps> = ({
const [wrapSSR, hashId] = useStyle(prefixCls);
const [zIndex] = useZIndex(
'ImagePreview',
typeof preview === 'object' ? preview.zIndex : undefined,
);
const mergedPreview = React.useMemo(() => {
if (preview === false) {
return preview;
@ -52,6 +58,7 @@ const InternalPreviewGroup: React.FC<GroupConsumerProps> = ({
transitionName: getTransitionName(rootPrefixCls, 'zoom', _preview.transitionName),
maskTransitionName: getTransitionName(rootPrefixCls, 'fade', _preview.maskTransitionName),
rootClassName: mergedRootClassName,
zIndex,
};
}, [preview]);

View File

@ -349,6 +349,19 @@ exports[`renders components/image/demo/imageRender.tsx extend context correctly
exports[`renders components/image/demo/imageRender.tsx extend context correctly 2`] = `[]`;
exports[`renders components/image/demo/nested.tsx extend context correctly 1`] = `
<button
class="ant-btn ant-btn-default"
type="button"
>
<span>
showModal
</span>
</button>
`;
exports[`renders components/image/demo/nested.tsx extend context correctly 2`] = `[]`;
exports[`renders components/image/demo/placeholder.tsx extend context correctly 1`] = `
<div
class="ant-space ant-space-horizontal ant-space-align-center"

View File

@ -340,6 +340,17 @@ exports[`renders components/image/demo/imageRender.tsx correctly 1`] = `
</div>
`;
exports[`renders components/image/demo/nested.tsx correctly 1`] = `
<button
class="ant-btn ant-btn-default"
type="button"
>
<span>
showModal
</span>
</button>
`;
exports[`renders components/image/demo/placeholder.tsx correctly 1`] = `
<div
class="ant-space ant-space-horizontal ant-space-align-center"

View File

@ -1,4 +1,6 @@
import React from 'react';
import { Modal } from 'antd';
import Image from '..';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
@ -116,4 +118,70 @@ describe('Image', () => {
expect(baseElement.querySelector('.test-root-class')).toBeTruthy();
});
it('Image.PreviewGroup preview in a nested modal where z-index Settings should be correct', () => {
const App = () => (
<Modal open>
<Modal open>
<Modal open>
<Image
width={200}
src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg"
preview={{
rootClassName: 'test-image-preview-class',
}}
/>
<Image.PreviewGroup
preview={{
rootClassName: 'test-image-preview-group-class',
}}
>
<Image
width={200}
src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg"
/>
<Image
width={200}
src="https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg"
/>
</Image.PreviewGroup>
</Modal>
</Modal>
</Modal>
);
const { baseElement } = render(<App />);
fireEvent.click(baseElement.querySelector('.ant-image')!);
expect(
(
baseElement.querySelector(
'.test-image-preview-class .ant-image-preview-wrap',
) as HTMLElement
).style.zIndex,
).toBe('1301');
expect(
(
baseElement.querySelector(
'.test-image-preview-class.ant-image-preview-operations-wrapper',
) as HTMLElement
).style.zIndex,
).toBe('1302');
fireEvent.click(baseElement.querySelectorAll('.ant-image')[1]!);
expect(
(
baseElement.querySelector(
'.test-image-preview-group-class .ant-image-preview-wrap',
) as HTMLElement
).style.zIndex,
).toBe('1301');
expect(
(
baseElement.querySelector(
'.test-image-preview-group-class.ant-image-preview-operations-wrapper',
) as HTMLElement
).style.zIndex,
).toBe('1302');
});
});

View File

@ -0,0 +1,7 @@
## zh-CN
嵌套在弹框当中使用
## en-US
Nested in the modal

View File

@ -0,0 +1,85 @@
import React, { useState } from 'react';
import { Button, Divider, Image, Modal } from 'antd';
const App: React.FC = () => {
const [show1, setShow1] = useState(false);
const [show2, setShow2] = useState(false);
const [show3, setShow3] = useState(false);
return (
<>
<Button
onClick={() => {
setShow1(true);
}}
>
showModal
</Button>
<Modal
open={show1}
afterOpenChange={(open) => {
setShow1(open);
}}
onCancel={() => {
setShow1(false);
}}
>
<Button
onClick={() => {
setShow2(true);
}}
>
test2
</Button>
<Modal
open={show2}
afterOpenChange={(open) => {
setShow2(open);
}}
onCancel={() => {
setShow2(false);
}}
>
<Button
onClick={() => {
setShow3(true);
}}
>
test3
</Button>
<Modal
open={show3}
afterOpenChange={(open) => {
setShow3(open);
}}
onCancel={() => {
setShow3(false);
}}
>
<Image
width={200}
src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg"
/>
<Divider />
<Image.PreviewGroup
preview={{
onChange: (current, prev) =>
console.log(`current index: ${current}, prev index: ${prev}`),
}}
>
<Image
width={200}
src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg"
/>
<Image
width={200}
src="https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg"
/>
</Image.PreviewGroup>
</Modal>
</Modal>
</Modal>
</>
);
};
export default App;

View File

@ -27,6 +27,7 @@ Previewable image.
<code src="./demo/toolbarRender.tsx">Custom toolbar render</code>
<code src="./demo/imageRender.tsx">Custom preview render</code>
<code src="./demo/preview-mask.tsx" debug>Custom preview mask</code>
<code src="./demo/nested.tsx">nested</code>
<code src="./demo/preview-group-top-progress.tsx" debug>Top progress customization when previewing multiple images</code>
<code src="./demo/component-token.tsx" debug>Custom component token</code>

View File

@ -28,6 +28,7 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*LVQ3R5JjjJEAAA
<code src="./demo/toolbarRender.tsx">自定义工具栏</code>
<code src="./demo/imageRender.tsx">自定义预览内容</code>
<code src="./demo/preview-mask.tsx" debug>自定义预览文本</code>
<code src="./demo/nested.tsx">嵌套</code>
<code src="./demo/preview-group-top-progress.tsx" debug>多图预览时顶部进度自定义</code>
<code src="./demo/component-token.tsx" debug>自定义组件 Token</code>

View File

@ -133,7 +133,7 @@
"rc-drawer": "~6.5.2",
"rc-dropdown": "~4.1.0",
"rc-field-form": "~1.40.0",
"rc-image": "~7.5.0",
"rc-image": "~7.5.1",
"rc-input": "~1.3.6",
"rc-input-number": "~8.4.0",
"rc-mentions": "~2.9.1",