Add back to top component

Remove event after unmount
This commit is contained in:
DefectingCat
2022-11-28 17:46:43 +08:00
parent 5419c78944
commit 37c7105026
4 changed files with 61 additions and 10 deletions

View File

@ -9,6 +9,8 @@ export type ButtonProps = {
>;
const Button = ({ children, ...rest }: ButtonProps) => {
const { className, ...props } = rest;
return (
<>
<button
@ -23,9 +25,10 @@ const Button = ({ children, ...rest }: ButtonProps) => {
'disabled:hover:border-transparent',
'text-lg disabled:bg-gray-200 disabled:text-gray-500',
'dark:disabled:bg-gray-700 dark:disabled:text-gray-300',
'disabled:dark:hover:border-transparent'
'disabled:dark:hover:border-transparent',
className
)}
{...rest}
{...props}
>
{children}
</button>

View File

@ -0,0 +1,29 @@
import clsx from 'clsx';
import Button from 'components/RUA/Button';
import { FiChevronUp } from 'react-icons/fi';
const BackToTop = () => {
const handleBack = () => {
const target = document.documentElement || document.body;
target.scrollTo({
top: 0,
});
};
return (
<>
<Button
onClick={handleBack}
className={clsx(
'!px-3 fixed',
'right-4 bottom-4',
'lg:right-8 lg:bottom-8'
)}
>
<FiChevronUp className="w-6 h-6" />
</Button>
</>
);
};
export default BackToTop;

View File

@ -1,18 +1,37 @@
import dynamic from 'next/dynamic';
import { useCallback, useEffect, useState } from 'react';
const Footer = dynamic(() => import('components/Footer'));
const HeadBar = dynamic(() => import('components/NavBar'));
const BackToTop = dynamic(() => import('components/common/BackToTop'));
type Props = {
children: React.ReactNode;
};
const MainLayout = ({ children }: Props) => {
const [showTop, setShowTop] = useState(false);
const handleScroll = useCallback(() => {
const target = document.documentElement || document.body;
const scrollableHeight = target.scrollHeight - target.clientHeight;
const scrollHeight = target.scrollTop;
if (scrollHeight / scrollableHeight >= 0.1) {
setShowTop(true);
} else {
setShowTop(false);
}
}, []);
useEffect(() => {
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, [handleScroll]);
return (
<>
<HeadBar />
{children}
<Footer />
{showTop && <BackToTop />}
</>
);
};

View File

@ -8,11 +8,11 @@ import { GetStaticPaths, GetStaticProps, InferGetStaticPropsType } from 'next';
import { MDXRemote, MDXRemoteSerializeResult } from 'next-mdx-remote';
import { serialize } from 'next-mdx-remote/serialize';
import dynamic from 'next/dynamic';
import { ReactElement } from 'react';
import rehypeSlug from 'rehype-slug';
import remarkGfm from 'remark-gfm';
const Footer = dynamic(() => import('components/Footer'));
const HeadBar = dynamic(() => import('components/NavBar'));
const MainLayout = dynamic(() => import('layouts/MainLayout'));
const PostComment = dynamic(() => import('components/post/PostComment'));
const Slug = ({
@ -22,8 +22,6 @@ const Slug = ({
}: InferGetStaticPropsType<typeof getStaticProps>) => {
return (
<>
<HeadBar />
<main id="article" className="relative max-w-4xl px-4 mx-auto my-10">
<h1>{mdxSource.frontmatter?.title}</h1>
<time>{mdxSource.frontmatter?.date}</time>
@ -34,8 +32,6 @@ const Slug = ({
<PostComment />
</article>
</main>
<Footer />
</>
);
};
@ -89,4 +85,8 @@ export const getStaticProps: GetStaticProps<{
};
};
Slug.getLayout = function getLayout(page: ReactElement) {
return <MainLayout>{page}</MainLayout>;
};
export default Slug;