Skip to content

Commit

Permalink
Merge pull request #231 from oceanbase/dengfuping-dev
Browse files Browse the repository at this point in the history
fix(design): Tooltip closeIcon should consider visible prop
  • Loading branch information
dengfuping authored Oct 29, 2023
2 parents fb3e9ad + 51cf96f commit 928a436
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 42 deletions.
70 changes: 69 additions & 1 deletion packages/design/src/tooltip/__tests__/index.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useState } from 'react';
import { render, fireEvent } from '@testing-library/react';
import { Tooltip } from '@oceanbase/design';
import { waitFakeTimer } from '../../../../../tests/util';
Expand Down Expand Up @@ -68,4 +68,72 @@ describe('Tooltip', () => {
await waitFakeTimer();
expect(container.querySelector('.ant-tooltip-open')).toBeNull();
});

it('close icon should work correctly for open', async () => {
const Demo = () => {
const [open, setOpen] = useState(true);
return (
<Tooltip
title="This is prompt text"
open={open}
closeIcon={true}
onClose={() => {
setOpen(false);
}}
>
<button id="button">Button</button>
</Tooltip>
);
};
const { container } = render(<Demo />);

// tooltip is open by default
expect(container.querySelector('.ant-tooltip-open')).not.toBeNull();

// click close icon => tooltip close
const closeIconElement = document.querySelector('.ant-tooltip-close-icon');
fireEvent.click(closeIconElement!);
await waitFakeTimer();
expect(container.querySelector('.ant-tooltip-open')).toBeNull();

// mouse enter div => tooltip is still closed
const buttonElement = container.querySelector('#button');
fireEvent.mouseEnter(buttonElement!);
await waitFakeTimer();
expect(container.querySelector('.ant-tooltip-open')).toBeNull();
});

it('close icon should work correctly for visible', async () => {
const Demo = () => {
const [visible, setVisible] = useState(true);
return (
<Tooltip
title="This is prompt text"
visible={visible}
closeIcon={true}
onClose={() => {
setVisible(false);
}}
>
<button id="button">Button</button>
</Tooltip>
);
};
const { container } = render(<Demo />);

// tooltip is open by default
expect(container.querySelector('.ant-tooltip-open')).not.toBeNull();

// click close icon => tooltip close
const closeIconElement = document.querySelector('.ant-tooltip-close-icon');
fireEvent.click(closeIconElement!);
await waitFakeTimer();
expect(container.querySelector('.ant-tooltip-open')).toBeNull();

// mouse enter div => tooltip is still closed
const buttonElement = container.querySelector('#button');
fireEvent.mouseEnter(buttonElement!);
await waitFakeTimer();
expect(container.querySelector('.ant-tooltip-open')).toBeNull();
});
});
46 changes: 26 additions & 20 deletions packages/design/src/tooltip/demo/close-icon.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,46 @@
import { Space, Tooltip, Button } from '@oceanbase/design';
import { CloseCircleOutlined } from '@oceanbase/icons';
import { Button, Space, Tooltip, message } from '@oceanbase/design';
import { CloseCircleOutlined, ReloadOutlined, SyncOutlined } from '@oceanbase/icons';
import React, { useState } from 'react';

const App: React.FC = () => {
const [open, setOpen] = useState(true);
const log = (e: React.MouseEvent<HTMLElement>) => {
console.log(e);
};
const [open1, setOpen1] = useState(true);
const [open2, setOpen2] = useState(true);

return (
<Space>
<Tooltip title="This is prompt text" closeIcon={true}>
<Button>Default Close Tooltip</Button>
</Tooltip>

<Space size={24}>
<Tooltip
title="This is prompt text"
open={open}
open={open1}
closeIcon={true}
onClose={() => {
setOpen(false);
}}
onOpenChange={v => {
setOpen(v);
setOpen1(false);
message.success('Default close icon is clicked');
}}
>
<Button>Set open</Button>
<Button>Default close icon</Button>
</Tooltip>
<Tooltip
title="This is prompt text This is prompt text This is prompt text This is prompt text"
title="This is prompt text"
open={open2}
closeIcon={<CloseCircleOutlined />}
onClose={log}
onClose={() => {
setOpen2(false);
message.success('Custom close icon is clicked');
}}
>
<Button>Customize closeIcon</Button>
<Button>Custom close icon</Button>
</Tooltip>
<Button
icon={<ReloadOutlined />}
onClick={() => {
setOpen1(true);
setOpen2(true);
}}
>
Reset
</Button>
</Space>
);
};

export default App;
55 changes: 34 additions & 21 deletions packages/design/src/tooltip/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Tooltip as AntTooltip, Space } from 'antd';
import type { TooltipPropsWithTitle as AntTooltipPropsWithTitle } from 'antd/es/tooltip';
import React, { useContext, useMemo, useState } from 'react';
import React, { useContext, useEffect, useState } from 'react';
import { CloseOutlined } from '@oceanbase/icons';
import { isNil } from 'lodash';
import { token } from '../static-function';
Expand Down Expand Up @@ -55,15 +55,20 @@ type CompoundedComponent = React.FC<TooltipProps> & {

const Tooltip: CompoundedComponent = ({
children,
title,
type = 'default',
color,
overlayInnerStyle,
mouseFollow,
closeIcon = false,
onClose,
title,
open,
defaultOpen,
onOpenChange,
visible,
defaultVisible,
onVisibleChange,
overlayInnerStyle,
className,
open: propOpen,
...restProps
}) => {
const { getPrefixCls } = useContext(ConfigProvider.ConfigContext);
Expand All @@ -73,9 +78,17 @@ const Tooltip: CompoundedComponent = ({
const { wrapSSR, hashId } = useStyle(prefixCls);

const tooltipCls = classNames(className, hashId);
const [innerOpen, setInnerOpen] = useState(undefined);
const [innerOpen, setInnerOpen] = useState(open ?? visible ?? defaultOpen ?? defaultVisible);

const open = isNil(propOpen) ? innerOpen : propOpen;
const newOpen = open ?? visible ?? innerOpen;

useEffect(() => {
if (!isNil(open)) {
setInnerOpen(open);
} else if (!isNil(visible)) {
setInnerOpen(visible);
}
}, [open, visible]);

const handleCloseClick = (e: React.MouseEvent<HTMLElement>) => {
e.stopPropagation();
Expand All @@ -88,27 +101,24 @@ const Tooltip: CompoundedComponent = ({
setInnerOpen(false);
};

const hasCloseIcon = !!closeIcon;

const CloseIconNode = useMemo(() => {
if (!hasCloseIcon) {
return null;
}
return closeIcon === true ? (
const closeIconNode = closeIcon ? (
closeIcon === true ? (
<CloseOutlined className={`${prefixCls}-close-icon`} onClick={handleCloseClick} />
) : (
<span className={`${prefixCls}-close-icon`} onClick={handleCloseClick}>
{closeIcon}
</span>
);
}, [closeIcon]);
)
) : null;

const titleNode = typeof title === 'function' ? title() : title;
const titleWithCloseIcon = (
const newTitle = closeIcon ? (
<Space className={`${prefixCls}-close-icon-wrap`}>
{titleNode}
{CloseIconNode}
{closeIconNode}
</Space>
) : (
titleNode
);

const typeList = getTooltipTypeList();
Expand All @@ -129,11 +139,14 @@ const Tooltip: CompoundedComponent = ({
</MouseTooltip>
) : (
<AntTooltip
title={hasCloseIcon ? titleWithCloseIcon : title}
title={newTitle}
color={color || typeItem?.backgroundColor}
open={open}
onOpenChange={newOpen => {
setInnerOpen(newOpen);
open={newOpen}
defaultOpen={defaultOpen}
onOpenChange={value => {
setInnerOpen(value);
onVisibleChange?.(value);
onOpenChange?.(value);
}}
overlayInnerStyle={{
color: typeItem?.color,
Expand Down

0 comments on commit 928a436

Please sign in to comment.