diff --git a/packages/core/src/components/Modal/layouts/ModalBasicLayout/ModalBasicLayout.tsx b/packages/core/src/components/Modal/layouts/ModalBasicLayout/ModalBasicLayout.tsx index 87879e9716..961443f1eb 100644 --- a/packages/core/src/components/Modal/layouts/ModalBasicLayout/ModalBasicLayout.tsx +++ b/packages/core/src/components/Modal/layouts/ModalBasicLayout/ModalBasicLayout.tsx @@ -15,7 +15,7 @@ const ModalBasicLayout = forwardRef( { children, className, id, "data-testid": dataTestId }: ModalBasicLayoutProps, ref: React.ForwardedRef ) => { - const { isContentScrolled, onScroll } = useLayoutScrolledContent(); + const { ref: contentRef, isContentScrolled, isScrollable, isScrolledToEnd, onScroll } = useLayoutScrolledContent(); const [header, content] = React.Children.toArray(children); return ( @@ -30,11 +30,11 @@ const ModalBasicLayout = forwardRef( >
{header}
- + {content} - + {isScrollable && } ); } diff --git a/packages/core/src/components/Modal/layouts/ModalLayoutScrollableContent.tsx b/packages/core/src/components/Modal/layouts/ModalLayoutScrollableContent.tsx index b989c995ca..aec09d085a 100644 --- a/packages/core/src/components/Modal/layouts/ModalLayoutScrollableContent.tsx +++ b/packages/core/src/components/Modal/layouts/ModalLayoutScrollableContent.tsx @@ -1,14 +1,16 @@ -import React from "react"; +import React, { ForwardedRef, forwardRef } from "react"; import cx from "classnames"; import styles from "./ModalLayoutScrollableContent.module.scss"; import { ModalLayoutScrollableContentProps } from "./ModalLayoutScrollableContent.types"; -const ModalLayoutScrollableContent = ({ onScroll, className, children }: ModalLayoutScrollableContentProps) => { - return ( -
- {children} -
- ); -}; +const ModalLayoutScrollableContent = forwardRef( + ({ onScroll, className, children }: ModalLayoutScrollableContentProps, ref: ForwardedRef) => { + return ( +
+ {children} +
+ ); + } +); export default ModalLayoutScrollableContent; diff --git a/packages/core/src/components/Modal/layouts/useLayoutScrolledContent.ts b/packages/core/src/components/Modal/layouts/useLayoutScrolledContent.ts index 63cae6d323..d393351609 100644 --- a/packages/core/src/components/Modal/layouts/useLayoutScrolledContent.ts +++ b/packages/core/src/components/Modal/layouts/useLayoutScrolledContent.ts @@ -1,16 +1,44 @@ -import { UIEventHandler, useCallback, useState } from "react"; +import { UIEventHandler, useCallback, useEffect, useRef, useState } from "react"; const useLayoutScrolledContent = () => { const [isContentScrolled, setContentScrolled] = useState(false); + const [isScrollable, setScrollable] = useState(false); + const [isScrolledToEnd, setScrolledToEnd] = useState(false); - const onScroll: UIEventHandler = useCallback( - e => { - setContentScrolled(e.currentTarget?.scrollTop > 0); - }, - [setContentScrolled] - ); + const ref = useRef(null); - return { isContentScrolled, onScroll }; + const checkScroll = useCallback(() => { + const element = ref.current; + if (element) { + const { scrollTop, scrollHeight, clientHeight } = element; + setScrollable(scrollHeight > clientHeight); + setContentScrolled(scrollTop > 0); + setScrolledToEnd(scrollTop + clientHeight >= scrollHeight); + } + }, []); + + const onScroll: UIEventHandler = useCallback(() => { + checkScroll(); + }, [checkScroll]); + + useEffect(() => { + const element = ref.current; + if (!element) return; + + const resizeObserver = new ResizeObserver(() => { + checkScroll(); + }); + + resizeObserver.observe(element); + + checkScroll(); + + return () => { + resizeObserver.disconnect(); + }; + }, [checkScroll]); + + return { ref, isContentScrolled, isScrollable, isScrolledToEnd, onScroll }; }; export default useLayoutScrolledContent;