From 11b2f1237b9320e0402e1619e62607d12738fd6d Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Wed, 27 Sep 2023 19:17:04 +0300 Subject: [PATCH] docs: fix irregular scrolling in code tabs (#5239) * docs: fix blocking scroll util * remove unnecessary util methods --- www/apps/api-reference/providers/index.tsx | 2 +- www/apps/ui/src/app/layout.tsx | 5 +- www/apps/ui/src/providers/index.tsx | 2 +- .../src/hooks/use-scroll-utils/index.tsx | 91 ++++--------------- 4 files changed, 22 insertions(+), 78 deletions(-) diff --git a/www/apps/api-reference/providers/index.tsx b/www/apps/api-reference/providers/index.tsx index 5cf435f12e..b6e1ec2f39 100644 --- a/www/apps/api-reference/providers/index.tsx +++ b/www/apps/api-reference/providers/index.tsx @@ -26,7 +26,7 @@ const Providers = ({ children }: ProvidersProps) => { - + {children} diff --git a/www/apps/ui/src/app/layout.tsx b/www/apps/ui/src/app/layout.tsx index d9b32f6ea8..28c80a2f35 100644 --- a/www/apps/ui/src/app/layout.tsx +++ b/www/apps/ui/src/app/layout.tsx @@ -35,7 +35,10 @@ export default function RootLayout({ > -
+
diff --git a/www/apps/ui/src/providers/index.tsx b/www/apps/ui/src/providers/index.tsx index f54558145b..afb2cf2f47 100644 --- a/www/apps/ui/src/providers/index.tsx +++ b/www/apps/ui/src/providers/index.tsx @@ -24,7 +24,7 @@ const Providers = ({ children }: ProvidersProps) => { - + {children} diff --git a/www/packages/docs-ui/src/hooks/use-scroll-utils/index.tsx b/www/packages/docs-ui/src/hooks/use-scroll-utils/index.tsx index 6d4a3247d9..73805c19f9 100644 --- a/www/packages/docs-ui/src/hooks/use-scroll-utils/index.tsx +++ b/www/packages/docs-ui/src/hooks/use-scroll-utils/index.tsx @@ -53,11 +53,19 @@ type ScrollController = { enableScrollEvents: () => void /** Disable scroll events in `useScrollPosition`. */ disableScrollEvents: () => void + /** Retrieves the scrollable element. By default, it's window. */ + getScrollableElement: () => Element | Window } -function useScrollControllerContextValue(): ScrollController { +function useScrollControllerContextValue( + scrollableSelector: string +): ScrollController { const scrollEventsEnabledRef = useRef(true) + const getScrollableElement = useCallback(() => { + return (document.querySelector(scrollableSelector) as Element) || window + }, [scrollableSelector]) + return useMemo( () => ({ scrollEventsEnabledRef, @@ -67,8 +75,9 @@ function useScrollControllerContextValue(): ScrollController { disableScrollEvents: () => { scrollEventsEnabledRef.current = false }, + getScrollableElement, }), - [] + [getScrollableElement] ) } @@ -78,10 +87,12 @@ const ScrollMonitorContext = React.createContext( export function ScrollControllerProvider({ children, + scrollableSelector = "", }: { children: ReactNode + scrollableSelector?: string }): JSX.Element { - const value = useScrollControllerContextValue() + const value = useScrollControllerContextValue(scrollableSelector) return ( {children} @@ -165,6 +176,7 @@ type UseScrollPositionSaver = { } function useScrollPositionSaver(): UseScrollPositionSaver { + const { getScrollableElement } = useScrollController() const lastElementRef = useRef<{ elem: HTMLElement | null; top: number }>({ elem: null, top: 0, @@ -187,7 +199,7 @@ function useScrollPositionSaver(): UseScrollPositionSaver { const newTop = elem.getBoundingClientRect().top const heightDiff = newTop - top if (heightDiff) { - window.scrollBy({ left: 0, top: heightDiff }) + getScrollableElement().scrollBy({ left: 0, top: heightDiff }) } lastElementRef.current = { elem: null, top: 0 } @@ -258,74 +270,3 @@ export function useScrollPositionBlocker(): { blockElementScrollPositionUntilNextRender, } } - -type CancelScrollTop = () => void - -function smoothScrollNative(top: number): CancelScrollTop { - window.scrollTo({ top, behavior: "smooth" }) - return () => { - // Nothing to cancel, it's natively cancelled if user tries to scroll down - } -} - -function smoothScrollPolyfill(top: number): CancelScrollTop { - let raf: number | null = null - const isUpScroll = document.documentElement.scrollTop > top - function rafRecursion() { - const currentScroll = document.documentElement.scrollTop - if ( - (isUpScroll && currentScroll > top) || - (!isUpScroll && currentScroll < top) - ) { - raf = requestAnimationFrame(rafRecursion) - window.scrollTo(0, Math.floor((currentScroll - top) * 0.85) + top) - } - } - rafRecursion() - - // Break the recursion. Prevents the user from "fighting" against that - // recursion producing a weird UX - return () => raf && cancelAnimationFrame(raf) -} - -/** - * A "smart polyfill" of `window.scrollTo({ top, behavior: "smooth" })`. - * This currently always uses a polyfilled implementation unless - * `scroll-behavior: smooth` has been set in CSS, because native support - * detection for scroll behavior seems unreliable. - * - * This hook does not do anything by itself: it returns a start and a stop - * handle. You can execute either handle at any time. - */ -export function useSmoothScrollTo(): { - /** - * Start the scroll. - * - * @param top The final scroll top position. - */ - startScroll: (top: number) => void - /** - * A cancel function, because the non-native smooth scroll-top - * implementation must be interrupted if user scrolls down. If there's no - * existing animation or the scroll is using native behavior, this is a no-op. - */ - cancelScroll: CancelScrollTop -} { - const cancelRef = useRef(null) - // Not all have support for smooth scrolling (particularly Safari mobile iOS) - // TODO proper detection is currently unreliable! - // see https://github.com/wessberg/scroll-behavior-polyfill/issues/16 - // For now, we only use native scroll behavior if smooth is already set, - // because otherwise the polyfill produces a weird UX when both CSS and JS try - // to scroll a page, and they cancel each other. - const supportsNativeSmoothScrolling = - getComputedStyle(document.documentElement).scrollBehavior === "smooth" - return { - startScroll: (top: number) => { - cancelRef.current = supportsNativeSmoothScrolling - ? smoothScrollNative(top) - : smoothScrollPolyfill(top) - }, - cancelScroll: () => cancelRef.current?.(), - } -}