diff --git a/packages/design/src/tooltip/__tests__/index.test.tsx b/packages/design/src/tooltip/__tests__/index.test.tsx
index a974ea529..033a0ded2 100644
--- a/packages/design/src/tooltip/__tests__/index.test.tsx
+++ b/packages/design/src/tooltip/__tests__/index.test.tsx
@@ -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';
@@ -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 (
+ {
+ setOpen(false);
+ }}
+ >
+
+
+ );
+ };
+ const { container } = render();
+
+ // 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 (
+ {
+ setVisible(false);
+ }}
+ >
+
+
+ );
+ };
+ const { container } = render();
+
+ // 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();
+ });
});
diff --git a/packages/design/src/tooltip/demo/close-icon.tsx b/packages/design/src/tooltip/demo/close-icon.tsx
index ad29ef045..b3d5ed1f7 100644
--- a/packages/design/src/tooltip/demo/close-icon.tsx
+++ b/packages/design/src/tooltip/demo/close-icon.tsx
@@ -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) => {
- console.log(e);
- };
+ const [open1, setOpen1] = useState(true);
+ const [open2, setOpen2] = useState(true);
return (
-
-
-
-
-
+
{
- setOpen(false);
- }}
- onOpenChange={v => {
- setOpen(v);
+ setOpen1(false);
+ message.success('Default close icon is clicked');
}}
>
-
+
}
- onClose={log}
+ onClose={() => {
+ setOpen2(false);
+ message.success('Custom close icon is clicked');
+ }}
>
-
+
+ }
+ onClick={() => {
+ setOpen1(true);
+ setOpen2(true);
+ }}
+ >
+ Reset
+
);
};
+
export default App;
diff --git a/packages/design/src/tooltip/index.tsx b/packages/design/src/tooltip/index.tsx
index b9ff5ded3..f179dace5 100644
--- a/packages/design/src/tooltip/index.tsx
+++ b/packages/design/src/tooltip/index.tsx
@@ -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';
@@ -55,15 +55,20 @@ type CompoundedComponent = React.FC & {
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);
@@ -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) => {
e.stopPropagation();
@@ -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 ? (
) : (
{closeIcon}
- );
- }, [closeIcon]);
+ )
+ ) : null;
const titleNode = typeof title === 'function' ? title() : title;
- const titleWithCloseIcon = (
+ const newTitle = closeIcon ? (
{titleNode}
- {CloseIconNode}
+ {closeIconNode}
+ ) : (
+ titleNode
);
const typeList = getTooltipTypeList();
@@ -129,11 +139,14 @@ const Tooltip: CompoundedComponent = ({
) : (
{
- setInnerOpen(newOpen);
+ open={newOpen}
+ defaultOpen={defaultOpen}
+ onOpenChange={value => {
+ setInnerOpen(value);
+ onVisibleChange?.(value);
+ onOpenChange?.(value);
}}
overlayInnerStyle={{
color: typeItem?.color,