diff --git a/src/components/page-container.tsx b/src/components/page-container.tsx index 9b9704ee..ad6a5f85 100644 --- a/src/components/page-container.tsx +++ b/src/components/page-container.tsx @@ -15,6 +15,7 @@ import Footer from 'components/footer' import Header from 'components/header' import SEO from 'components/seo' import TableOfContent from 'components/table-of-content' +import ScrollToTop from 'components/scroll-to-top' import { convertBackticksToInlineCode } from 'utils/convert-backticks-to-inline-code' import { t } from 'utils/i18n' import { FrontmatterHeading } from 'src/types/frontmatter' @@ -61,9 +62,9 @@ function PageContainer(props: PageContainerProps) { rightSidebar, pagination, hideToc, - maxWidth = '48rem', } = props + const bodyRef = React.useRef(null) useHeadingFocusOnRouteChange() if (!frontmatter) return <> @@ -101,6 +102,7 @@ function PageContainer(props: PageContainerProps) {
+ ) } diff --git a/src/components/scroll-to-top.tsx b/src/components/scroll-to-top.tsx new file mode 100644 index 00000000..b6b57fab --- /dev/null +++ b/src/components/scroll-to-top.tsx @@ -0,0 +1,50 @@ +import { IconButton } from '@chakra-ui/react' +import { useEffect, useState, RefObject } from 'react' +import { BsArrowUpCircleFill } from 'react-icons/bs' + +interface ScrollToTopProps { + scrollContainerRef: RefObject +} + +export function ScrollToTop({ scrollContainerRef }: ScrollToTopProps) { + const [isVisible, setIsVisible] = useState(false) + + useEffect(() => { + const container = scrollContainerRef.current + if (!container) return + + const handleScroll = () => { + setIsVisible(container.scrollTop > 300) + } + + container.addEventListener('scroll', handleScroll) + return () => container.removeEventListener('scroll', handleScroll) + }, [scrollContainerRef]) + + const scrollToTop = () => { + scrollContainerRef.current?.scrollTo({ top: 0, behavior: 'smooth' }) + } + + if (!isVisible) return null + + return ( + } + onClick={scrollToTop} + position='fixed' + bottom={{ base: '6', md: '8' }} + right={{ base: '4', md: '8' }} + zIndex='tooltip' + size='md' + colorScheme='blue' + rounded='full' + shadow='lg' + opacity={0.9} + _hover={{ opacity: 1, transform: 'translateY(-2px)', shadow: 'xl' }} + transition='all 0.2s ease' + /> + ) +} + +export default ScrollToTop