diff --git a/src/NotificationList/Content.tsx b/src/NotificationList/Content.tsx index 700fd2f..159dc51 100644 --- a/src/NotificationList/Content.tsx +++ b/src/NotificationList/Content.tsx @@ -4,10 +4,20 @@ import * as React from 'react'; export interface ContentProps extends React.HTMLAttributes { listPrefixCls: string; height: number; + topNoticeHeight?: number; + topNoticeWidth?: number; } const Content = React.forwardRef((props, ref) => { - const { listPrefixCls, height, className, style, ...restProps } = props; + const { + listPrefixCls, + height, + topNoticeHeight = 0, + topNoticeWidth = 0, + className, + style, + ...restProps + } = props; const contentPrefixCls = `${listPrefixCls}-content`; @@ -18,15 +28,23 @@ const Content = React.forwardRef((props, ref) => { prevHeightRef.current = height; + // ========================= Style ========================== + const contentStyle: React.CSSProperties & { + '--top-notificiation-height': string; + '--top-notificiation-width': string; + } = { + ...style, + height, + '--top-notificiation-height': `${topNoticeHeight}px`, + '--top-notificiation-width': `${topNoticeWidth}px`, + }; + // ========================= Render ========================= return (
); diff --git a/src/NotificationList/index.tsx b/src/NotificationList/index.tsx index 08c3d68..2063828 100644 --- a/src/NotificationList/index.tsx +++ b/src/NotificationList/index.tsx @@ -210,11 +210,8 @@ const NotificationList: React.FC = (props) => { // ====================== List Measure ====================== const [gap, setGap] = React.useState(0); const contentRef = React.useRef(null); - const [notificationPosition, setNodeSize, totalHeight] = useListPosition( - configList, - stackPosition, - gap, - ); + const [notificationPosition, setNodeSize, totalHeight, topNoticeHeight, topNoticeWidth] = + useListPosition(configList, stackPosition, gap); const hasConfigList = !!configList.length; React.useEffect(() => { @@ -259,6 +256,8 @@ const NotificationList: React.FC = (props) => { { + const [notificationPosition, totalHeight, topNoticeHeight, topNoticeWidth] = React.useMemo(() => { let offsetY = 0; let nextTotalHeight = 0; const stackThreshold = stack?.threshold ?? 0; const nextNotificationPosition = new Map(); + let nextTopNoticeHeight: number | undefined; + let nextTopNoticeWidth: number | undefined; configList .slice() @@ -29,6 +31,11 @@ export default function useListPosition( nextNotificationPosition.set(key, y); + if (index === 0) { + nextTopNoticeHeight = height; + nextTopNoticeWidth = sizeMap[key]?.width ?? 0; + } + if (!stack || index < stackThreshold) { nextTotalHeight = Math.max(nextTotalHeight, y + height); } @@ -40,8 +47,13 @@ export default function useListPosition( } }); - return [nextNotificationPosition, nextTotalHeight] as const; + return [ + nextNotificationPosition, + nextTotalHeight, + nextTopNoticeHeight, + nextTopNoticeWidth, + ] as const; }, [configList, gap, sizeMap, stack]); - return [notificationPosition, setNodeSize, totalHeight] as const; + return [notificationPosition, setNodeSize, totalHeight, topNoticeHeight, topNoticeWidth] as const; } diff --git a/tests/index.test.tsx b/tests/index.test.tsx index e45e5d5..8de40c7 100644 --- a/tests/index.test.tsx +++ b/tests/index.test.tsx @@ -866,6 +866,48 @@ describe('Notification.Basic', () => { expect(document.querySelector('.rc-notification-list-content')).toHaveClass('bamboo'); }); + it('should expose top notice size on listContent', () => { + const offsetHeightSpy = vi + .spyOn(HTMLElement.prototype, 'offsetHeight', 'get') + .mockImplementation(function offsetHeight(this: HTMLElement) { + if (this.classList.contains('rc-notification-notice')) { + return this.textContent === 'second' ? 18 : 10; + } + + return 0; + }); + const offsetWidthSpy = vi + .spyOn(HTMLElement.prototype, 'offsetWidth', 'get') + .mockImplementation(function offsetWidth(this: HTMLElement) { + if (this.classList.contains('rc-notification-notice')) { + return this.textContent === 'second' ? 28 : 20; + } + + return 0; + }); + + const { instance } = renderDemo(); + + act(() => { + instance.open({ + description: 'first', + duration: false, + }); + instance.open({ + description: 'second', + duration: false, + }); + }); + + expect(document.querySelector('.rc-notification-list-content')).toHaveStyle({ + '--top-notificiation-height': '18px', + '--top-notificiation-width': '28px', + }); + + offsetHeightSpy.mockRestore(); + offsetWidthSpy.mockRestore(); + }); + it('placement', () => { const { instance } = renderDemo();