fix: Popover display empty div when title and content is null (#42229)

* fix: Popover display empty div when title and content is null (#42217)

* fix: Popover display empty div when title and content is null

* test: Popover add test

* lint: remove useless block statement

---------

Co-authored-by: MaHui <mahuiyoung@cmbchina.com>
(cherry picked from commit 4271ff0976)

* lint: fix Popover test lint error

* lint: fix Popover test lint error

* improvement: Popover overlay

* lint: fix Popover test lint error

* Update package.json

---------

Co-authored-by: MaHui <mahuiyoung@cmbchina.com>
Co-authored-by: afc163 <afc163@gmail.com>
This commit is contained in:
MaHui 2023-05-10 11:04:45 +08:00 committed by GitHub
parent 0371a933bf
commit 19f8505d0c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 33 deletions

View File

@ -8,38 +8,34 @@ describe('Popover', () => {
mountTest(Popover);
it('should show overlay when trigger is clicked', () => {
const ref = React.createRef<any>();
const popover = render(
<Popover ref={ref} content="console.log('hello world')" title="code" trigger="click">
<Popover content="console.log('hello world')" title="code" trigger="click">
<span>show me your code</span>
</Popover>,
);
expect(ref.current.getPopupDomNode()).toBe(null);
expect(popover.container.querySelector('.ant-popover-inner-content')).toBeFalsy();
expect(document.querySelector('.ant-popover')).toBe(null);
fireEvent.click(popover.container.querySelector('span')!);
expect(popover.container.querySelector('.ant-popover-inner-content')).toBeTruthy();
const popup = document.querySelector('.ant-popover');
expect(popup?.querySelector?.('.ant-popover-inner-content')).toBeTruthy();
});
it('shows content for render functions', () => {
const renderTitle = () => 'some-title';
const renderContent = () => 'some-content';
const ref = React.createRef<any>();
const popover = render(
<Popover ref={ref} content={renderContent} title={renderTitle} trigger="click">
<Popover content={renderContent} title={renderTitle} trigger="click">
<span>show me your code </span>
</Popover>,
);
fireEvent.click(popover.container.querySelector('span')!);
const popup = ref.current.getPopupDomNode();
const popup = document.querySelector('.ant-popover');
expect(popup).not.toBe(null);
expect(popup.innerHTML).toContain('some-title');
expect(popup.innerHTML).toContain('some-content');
expect(popup.innerHTML).toMatchSnapshot();
expect(popup?.innerHTML).toContain('some-title');
expect(popup?.innerHTML).toContain('some-content');
expect(popup?.innerHTML).toMatchSnapshot();
});
it('handles empty title/content props safely', () => {
@ -50,8 +46,8 @@ describe('Popover', () => {
);
fireEvent.click(container.querySelector('span')!);
expect(container.querySelector('.ant-popover-title')?.textContent).toBeFalsy();
expect(container.querySelector('.ant-popover-inner-content')?.textContent).toBeFalsy();
const popup = document.querySelector('.ant-popover');
expect(popup).toBe(null);
});
it('should not render popover when the title & content props is empty', () => {
@ -62,8 +58,8 @@ describe('Popover', () => {
);
fireEvent.click(container.querySelector('span')!);
expect(container.querySelector('.ant-popover-title')?.textContent).toBeFalsy();
expect(container.querySelector('.ant-popover-inner-content')?.textContent).toBeFalsy();
const popup = document.querySelector('.ant-popover');
expect(popup).toBe(null);
});
it('props#overlay do not warn anymore', () => {

View File

@ -1,10 +1,10 @@
import * as React from 'react';
import { ConfigContext } from '../config-provider';
import type { AbstractTooltipProps } from '../tooltip';
import Tooltip from '../tooltip';
import type { RenderFunction } from '../_util/getRenderPropValue';
import { getRenderPropValue } from '../_util/getRenderPropValue';
import { getTransitionName } from '../_util/motion';
import { ConfigContext } from '../config-provider';
import type { AbstractTooltipProps } from '../tooltip';
import Tooltip from '../tooltip';
export interface PopoverProps extends AbstractTooltipProps {
title?: React.ReactNode | RenderFunction;
@ -19,17 +19,12 @@ interface OverlayPorps {
content?: PopoverProps['content'];
}
const Overlay: React.FC<OverlayPorps> = ({ title, content, prefixCls }) => {
if (!title && !content) {
return null;
}
return (
const Overlay: React.FC<OverlayPorps> = ({ title, content, prefixCls }) => (
<>
{title && <div className={`${prefixCls}-title`}>{getRenderPropValue(title)}</div>}
<div className={`${prefixCls}-inner-content`}>{getRenderPropValue(content)}</div>
</>
);
};
const Popover = React.forwardRef<unknown, PopoverProps>((props, ref) => {
const {
@ -49,6 +44,16 @@ const Popover = React.forwardRef<unknown, PopoverProps>((props, ref) => {
const prefixCls = getPrefixCls('popover', customizePrefixCls);
const rootPrefixCls = getPrefixCls();
const mergedOverlay = React.useMemo<React.ReactNode>(() => {
if (_overlay) {
return _overlay;
}
if (!title && !content) {
return null;
}
return <Overlay prefixCls={prefixCls} title={title} content={content} />;
}, [_overlay, title, content, prefixCls]);
return (
<Tooltip
placement={placement}
@ -59,7 +64,7 @@ const Popover = React.forwardRef<unknown, PopoverProps>((props, ref) => {
{...otherProps}
prefixCls={prefixCls}
ref={ref}
overlay={_overlay || <Overlay prefixCls={prefixCls} title={title} content={content} />}
overlay={mergedOverlay}
transitionName={getTransitionName(rootPrefixCls, 'zoom-big', otherProps.transitionName)}
/>
);

View File

@ -223,7 +223,7 @@
"eslint-plugin-markdown": "^3.0.0",
"eslint-plugin-react": "^7.31.8",
"eslint-plugin-react-hooks": "^4.1.2",
"eslint-plugin-unicorn": "^44.0.0",
"eslint-plugin-unicorn": "^47.0.0",
"fast-glob": "^3.2.11",
"fetch-jsonp": "^1.1.3",
"fs-extra": "^10.0.0",