diff --git a/components/float-button/FloatButtonGroup.tsx b/components/float-button/FloatButtonGroup.tsx index a023cc4893..d67e3a6edf 100644 --- a/components/float-button/FloatButtonGroup.tsx +++ b/components/float-button/FloatButtonGroup.tsx @@ -1,4 +1,4 @@ -import React, { useRef, memo, useContext } from 'react'; +import React, { useRef, memo, useContext, useEffect, useCallback, useMemo } from 'react'; import CloseOutlined from '@ant-design/icons/CloseOutlined'; import FileTextOutlined from '@ant-design/icons/FileTextOutlined'; import classNames from 'classnames'; @@ -41,23 +41,11 @@ const FloatButtonGroup: React.FC = (props) => { const [open, setOpen] = useMergedState(false, { value: props.open }); - const clickAction = useRef>({}); + const floatButtonGroupRef = useRef(null); + const floatButtonRef = useRef(null); - const hoverAction = useRef>({}); - - if (trigger === 'click') { - clickAction.current = { - onClick() { - setOpen((prevState) => { - onOpenChange?.(!prevState); - return !prevState; - }); - }, - }; - } - - if (trigger === 'hover') { - hoverAction.current = { + const hoverAction = useMemo(() => { + const hoverTypeAction = { onMouseEnter() { setOpen(true); onOpenChange?.(true); @@ -67,11 +55,42 @@ const FloatButtonGroup: React.FC = (props) => { onOpenChange?.(false); }, }; - } + return trigger === 'hover' ? hoverTypeAction : {}; + }, [trigger]); + + const handleOpenChange = () => { + setOpen((prevState) => { + onOpenChange?.(!prevState); + return !prevState; + }); + }; + + const onClick = useCallback( + (e: MouseEvent) => { + if (floatButtonGroupRef.current!.contains(e.target as Node)) { + if (floatButtonRef.current!.contains(e.target as Node)) { + handleOpenChange(); + } + return; + } + setOpen(false); + onOpenChange?.(false); + }, + [trigger], + ); + + useEffect(() => { + if (trigger === 'click') { + document.addEventListener('click', onClick); + return () => { + document.removeEventListener('click', onClick); + }; + } + }, [trigger]); return wrapSSR( -
+
{trigger && ['click', 'hover'].includes(trigger) ? ( <> @@ -80,11 +99,11 @@ const FloatButtonGroup: React.FC = (props) => { )} ) : ( diff --git a/components/float-button/__tests__/group.test.tsx b/components/float-button/__tests__/group.test.tsx index 67ebf2001a..2458a146e9 100644 --- a/components/float-button/__tests__/group.test.tsx +++ b/components/float-button/__tests__/group.test.tsx @@ -58,4 +58,30 @@ describe('FloatButtonGroup', () => { fireEvent.mouseLeave(container.querySelector('.ant-float-btn-group')!); expect(onOpenChange).toHaveBeenCalled(); }); + it('support click floatButtonGroup not close', () => { + const onOpenChange = jest.fn(); + const { container } = render( + + + + + , + ); + fireEvent.click(container.querySelector('.ant-float-btn')!); + fireEvent.click(container.querySelector('.ant-float-btn-group')!); + expect(onOpenChange).toHaveBeenCalledTimes(1); + }); + it('support click out auto close', () => { + const onOpenChange = jest.fn(); + const { container } = render( + + + + + , + ); + fireEvent.click(container.querySelector('.ant-float-btn')!); + fireEvent.click(container); + expect(onOpenChange).toHaveBeenCalledTimes(2); + }); });