diff --git a/components/float-button/FloatButtonGroup.tsx b/components/float-button/FloatButtonGroup.tsx index a023cc4893ca..61bc105d8468 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, useState } from 'react'; import CloseOutlined from '@ant-design/icons/CloseOutlined'; import FileTextOutlined from '@ant-design/icons/FileTextOutlined'; import classNames from 'classnames'; @@ -23,6 +23,7 @@ const FloatButtonGroup: React.FC = (props) => { description, trigger, children, + clickOutAutoClose, onOpenChange, } = props; @@ -41,37 +42,82 @@ 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>({}); + const [clickAction, setClickAction] = useState({}); - if (trigger === 'click') { - clickAction.current = { - onClick() { - setOpen((prevState) => { - onOpenChange?.(!prevState); - return !prevState; - }); - }, - }; - } + const [hoverAction, setHoverAction] = useState({}); - if (trigger === 'hover') { - hoverAction.current = { - onMouseEnter() { - setOpen(true); - onOpenChange?.(true); - }, - onMouseLeave() { - setOpen(false); - onOpenChange?.(false); - }, - }; - } + const openChange = () => { + setOpen((prevState) => { + onOpenChange?.(!prevState); + return !prevState; + }); + }; + + const clickTypeAction = { + onClick() { + openChange(); + }, + }; + + const hoverTypeAction = { + onMouseEnter() { + setOpen(true); + onOpenChange?.(true); + }, + onMouseLeave() { + setOpen(false); + onOpenChange?.(false); + }, + }; + + useEffect(() => { + if (trigger === 'click') { + if (clickOutAutoClose) { + const BigestEl = document; + const clickFn = (e: MouseEvent) => { + let clickTarget = e.target as Node; + let clickWhich = null; + // Distinguish between clicking a button and expanding it in a group + const clickMap: Record = { + clickButton: openChange, + clickOther: () => {}, + }; + while (clickTarget) { + if (clickTarget === floatButtonRef.current) { + clickWhich = 'clickButton'; + break; + } + if (clickTarget === floatButtonGroupRef.current) { + clickWhich = 'clickOther'; + } + clickTarget = clickTarget.parentNode!; + } + if (clickWhich) { + clickMap[clickWhich](); + return; + } + setOpen(false); + }; + BigestEl?.addEventListener('click', clickFn); + } else { + setClickAction(clickTypeAction); + } + } + if (trigger === 'hover') { + setHoverAction(hoverTypeAction); + } + // 非严格模式下 会在组件卸载时自动 remove ,在合并前取消注释 + // return ( + // BigestEl?.removeEventListener('click', clickFn) + // ) + }, []); return wrapSSR( -
+
{trigger && ['click', 'hover'].includes(trigger) ? ( <> @@ -80,11 +126,12 @@ const FloatButtonGroup: React.FC = (props) => { )} ) : ( diff --git a/components/float-button/demo/group-menu.md b/components/float-button/demo/group-menu.md index e1d563dbf4c5..6c73b12239be 100644 --- a/components/float-button/demo/group-menu.md +++ b/components/float-button/demo/group-menu.md @@ -1,7 +1,7 @@ ## zh-CN -设置 `trigger` 属性即可开启菜单模式。提供 `hover` 和 `click` 两种触发方式 +设置 `trigger` 属性即可开启菜单模式。提供 `hover` 和 `click` 两种触发方式。若设置为 `click`,可通过 `clickOutAutoClose` 选择是否开启点击外侧自动关闭 ## en-US -Open menu mode with `trigger`, which could be `hover` or `click`. +Open menu mode with `trigger`, which could be `hover` or `click`. if set to `click`, you can choose whether to open by clicking `clickOutAutoClose` diff --git a/components/float-button/demo/group-menu.tsx b/components/float-button/demo/group-menu.tsx index 29d04d509342..69ac99a5bca7 100644 --- a/components/float-button/demo/group-menu.tsx +++ b/components/float-button/demo/group-menu.tsx @@ -3,7 +3,12 @@ import { FloatButton } from 'antd'; import { CustomerServiceOutlined, CommentOutlined } from '@ant-design/icons'; const App: React.FC = () => ( - } type="primary" trigger="click"> + } + type="primary" + trigger='click' + clickOutAutoClose + > } /> diff --git a/components/float-button/interface.ts b/components/float-button/interface.ts index 26216be0e36f..eb17d2b1566c 100644 --- a/components/float-button/interface.ts +++ b/components/float-button/interface.ts @@ -36,6 +36,8 @@ export interface FloatButtonGroupProps extends FloatButtonProps { children: React.ReactNode; // 触发方式 (有触发方式为菜单模式) trigger?: FloatButtonGroupTrigger; + // 触发方式为 click 时,是否开启点击外侧自动关闭 + clickOutAutoClose?: boolean; // 受控展开 open?: boolean; // 关闭按钮自定义图标