mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-11-29 18:50:00 +08:00
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:
parent
650cf96dbf
commit
953fe6fa7e
@ -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,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
@ -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]);
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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');
|
||||
});
|
||||
});
|
||||
|
7
components/image/demo/nested.md
Normal file
7
components/image/demo/nested.md
Normal file
@ -0,0 +1,7 @@
|
||||
## zh-CN
|
||||
|
||||
嵌套在弹框当中使用
|
||||
|
||||
## en-US
|
||||
|
||||
Nested in the modal
|
85
components/image/demo/nested.tsx
Normal file
85
components/image/demo/nested.tsx
Normal 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;
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user