diff --git a/components/WindowScrollListener/WindowScrollListener.tsx b/components/WindowScrollListener/WindowScrollListener.tsx new file mode 100644 index 00000000..71666e96 --- /dev/null +++ b/components/WindowScrollListener/WindowScrollListener.tsx @@ -0,0 +1,43 @@ +import { useEffect } from 'react'; + +type OnScrollMessage = { + type: 'onScroll'; + value: number; +}; + +type ScrollToMessage = { + type: 'scrollTo'; + value: number; +}; + +export function WindowScrollListener() { + useEffect(() => { + function onScroll() { + window.parent.postMessage( + { + type: 'onScroll', + value: window.scrollY, + } satisfies OnScrollMessage, + '*', + ); + } + + window.addEventListener('scroll', onScroll); + + return () => window.removeEventListener('scroll', onScroll); + }, []); + + useEffect(() => { + function onMessage(event: MessageEvent) { + if (event.data.type === 'scrollTo') { + window.scrollTo({ top: event.data.value }); + } + } + + window.addEventListener('message', onMessage); + + return () => window.removeEventListener('message', onMessage); + }, []); + + return null; +} diff --git a/components/WindowScrollListener/index.ts b/components/WindowScrollListener/index.ts new file mode 100644 index 00000000..57cdf423 --- /dev/null +++ b/components/WindowScrollListener/index.ts @@ -0,0 +1 @@ +export { WindowScrollListener } from './WindowScrollListener'; diff --git a/modules/Layout/Layout.tsx b/modules/Layout/Layout.tsx index 5aa0873a..45221fd5 100644 --- a/modules/Layout/Layout.tsx +++ b/modules/Layout/Layout.tsx @@ -14,6 +14,7 @@ import { useEffect, useMemo, useState } from 'react'; import { CategoriesBar, NotificationsBar } from '@/components'; import { PreviewPageMask } from '@/components/PreviewPageMask'; +import { WindowScrollListener } from '@/components/WindowScrollListener'; import { LoadingBar, ScrollToTopButton } from '@/ui'; import Boilerplate from './Boilerplate'; @@ -125,6 +126,7 @@ function Layout({ children, description, imageUrl, title, hasError }: PropsWithC {/* hide scroll to top on story page */} {!STORY_PAGE_PATHS.includes(pathname) && } + ); }