From 3d8ba2e808803ca6d9e752b9e927e95228997dff Mon Sep 17 00:00:00 2001 From: jeffvli Date: Mon, 2 Jan 2023 16:59:21 -0800 Subject: [PATCH] Add native scroll area component --- src/renderer/components/scroll-area/index.tsx | 111 +++++++++++++++++- 1 file changed, 110 insertions(+), 1 deletion(-) diff --git a/src/renderer/components/scroll-area/index.tsx b/src/renderer/components/scroll-area/index.tsx index 4b673230..ff8a88d2 100644 --- a/src/renderer/components/scroll-area/index.tsx +++ b/src/renderer/components/scroll-area/index.tsx @@ -1,7 +1,10 @@ -import { forwardRef, Ref } from 'react'; +import { forwardRef, Ref, useEffect, useRef, useState } from 'react'; import type { ScrollAreaProps as MantineScrollAreaProps } from '@mantine/core'; import { ScrollArea as MantineScrollArea } from '@mantine/core'; +import { useMergedRef, useTimeout } from '@mantine/hooks'; +import { motion, useScroll } from 'framer-motion'; import styled from 'styled-components'; +import { PageHeader, PageHeaderProps } from '/@/renderer/components/page-header'; interface ScrollAreaProps extends MantineScrollAreaProps { children: React.ReactNode; @@ -19,6 +22,19 @@ const StyledScrollArea = styled(MantineScrollArea)` } `; +const StyledNativeScrollArea = styled.div` + height: 100%; + overflow-y: overlay; + + &::-webkit-scrollbar-track { + margin-top: 35px; + } + + &::-webkit-scrollbar-thumb { + margin-top: 35px; + } +`; + export const ScrollArea = forwardRef(({ children, ...props }: ScrollAreaProps, ref: Ref) => { return ( ); }); + +interface NativeScrollAreaProps { + children: React.ReactNode; + debugScrollPosition?: boolean; + pageHeaderProps?: PageHeaderProps & { offset?: any; target: any }; +} + +export const NativeScrollArea = forwardRef( + ( + { children, pageHeaderProps, debugScrollPosition, ...props }: NativeScrollAreaProps, + ref: Ref, + ) => { + const [hideScrollbar, setHideScrollbar] = useState(false); + const [hideHeader, setHideHeader] = useState(true); + const { start, clear } = useTimeout(() => setHideScrollbar(true), 1000); + + const containerRef = useRef(null); + const mergedRef = useMergedRef(ref, containerRef); + + const { scrollYProgress } = useScroll({ + container: containerRef, + offset: pageHeaderProps?.offset || ['center start', 'end start'], + target: pageHeaderProps?.target, + }); + + // Automatically hide the scrollbar after the timeout duration + useEffect(() => { + start(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + useEffect(() => { + const setHeaderVisibility = (v: number) => { + if (v === 1) { + return setHideHeader(false); + } + + if (hideHeader === false) { + return setHideHeader(true); + } + + return undefined; + }; + + const unsubscribe = scrollYProgress.on('change', setHeaderVisibility); + + return () => { + unsubscribe(); + }; + }, [hideHeader, scrollYProgress]); + + return ( + <> + + { + setHideScrollbar(false); + clear(); + }} + onMouseLeave={() => { + start(); + }} + {...props} + > + {children} + + {debugScrollPosition && ( + + )} + + ); + }, +);