diff --git a/src/NoticeList.tsx b/src/NoticeList.tsx index 9b59be5..4fb9380 100644 --- a/src/NoticeList.tsx +++ b/src/NoticeList.tsx @@ -1,5 +1,5 @@ import type { CSSProperties, FC } from 'react'; -import React, { useContext, useRef, useState } from 'react'; +import React, { useContext, useEffect, useRef, useState } from 'react'; import clsx from 'classnames'; import type { CSSMotionProps } from 'rc-motion'; import { CSSMotionList } from 'rc-motion'; @@ -47,7 +47,7 @@ const NoticeList: FC = (props) => { const dictRef = useRef>({}); const [latestNotice, setLatestNotice] = useState(null); - const [hoverCount, setHoverCount] = useState(0); + const [hoverKeys, setHoverKeys] = useState([]); const keys = configList.map((config) => ({ config, @@ -56,10 +56,19 @@ const NoticeList: FC = (props) => { const [stack, { offset, threshold, gap }] = useStack(stackConfig); - const expanded = stack && (hoverCount > 0 || keys.length <= threshold); + const expanded = stack && (hoverKeys.length > 0 || keys.length <= threshold); const placementMotion = typeof motion === 'function' ? motion(placement) : motion; + // Clean hover key + useEffect(() => { + if (hoverKeys.length > 1) { + setHoverKeys((prev) => + prev.filter((key) => keys.some(({ key: dataKey }) => key === dataKey)), + ); + } + }, [hoverKeys, keys]); + return ( = (props) => { ...stackStyle, ...configStyle, }} - onMouseEnter={() => setHoverCount((c) => c + 1)} - onMouseLeave={() => setHoverCount((c) => c - 1)} + onMouseEnter={() => + setHoverKeys((prev) => (prev.includes(key) ? prev : [...prev, key])) + } + onMouseLeave={() => setHoverKeys((prev) => prev.filter((k) => k !== key))} > = (props) => { key={key} eventKey={key} onNoticeClose={onNoticeClose} - hovering={hoverCount > 0} + hovering={hoverKeys.length > 0} /> ); diff --git a/tests/stack.test.tsx b/tests/stack.test.tsx index abbe2b1..be6bc9e 100644 --- a/tests/stack.test.tsx +++ b/tests/stack.test.tsx @@ -43,4 +43,47 @@ describe('stack', () => { fireEvent.mouseEnter(document.querySelector('.rc-notification-notice')); expect(document.querySelector('.rc-notification-stack-expanded')).toBeTruthy(); }); + + it('should collapse when amount is less than threshold', () => { + const Demo = () => { + const [api, holder] = useNotification({ + stack: { threshold: 3 }, + }); + return ( + <> +