From 0c3a6ebf2fd911e61c89ec8341c2d1db99cfe857 Mon Sep 17 00:00:00 2001 From: Innei Date: Sun, 9 Jul 2023 23:01:26 +0800 Subject: [PATCH] fix: toc Signed-off-by: Innei --- global.d.ts | 11 +- .../widgets/shared/ArticleRightAside.tsx | 72 +++++++++-- src/components/widgets/toc/TocAside.tsx | 112 ++++++++++-------- src/components/widgets/toc/TocItem.tsx | 9 -- src/styles/theme.css | 26 +++- 5 files changed, 157 insertions(+), 73 deletions(-) diff --git a/global.d.ts b/global.d.ts index 5ac91e7b6a..19bb826ae7 100644 --- a/global.d.ts +++ b/global.d.ts @@ -11,12 +11,11 @@ declare global { } & Props > - export type Component

= FC< - { - className?: string - } & P & - PropsWithChildren - > + export type Component

= FC + + export type ComponentType = { + className?: string + } & PropsWithChildren // TODO should remove in next TypeScript version interface Document { diff --git a/src/components/widgets/shared/ArticleRightAside.tsx b/src/components/widgets/shared/ArticleRightAside.tsx index a56ae3efd0..c4d3df3bee 100644 --- a/src/components/widgets/shared/ArticleRightAside.tsx +++ b/src/components/widgets/shared/ArticleRightAside.tsx @@ -1,19 +1,73 @@ -import React from 'react' +'use client' + +import React, { useEffect, useRef, useState } from 'react' +import clsx from 'clsx' +import type { TocAsideRef } from '../toc' + +import { useViewport } from '~/atoms' import { TocAside } from '../toc' import { ReadIndicator } from './ReadIndicator' export const ArticleRightAside: Component = ({ children }) => { + const asideRef = useRef(null) + const [isScrollToBottom, setIsScrollToBottom] = useState(false) + const [isScrollToTop, setIsScrollToTop] = useState(false) + const [canScroll, setCanScroll] = useState(false) + const h = useViewport((v) => v.h) + useEffect(() => { + const $ = asideRef.current?.getContainer() + if (!$) return + + // if $ can not scroll, return null + if ($.scrollHeight <= $.clientHeight + 2) return + + setCanScroll(true) + + const handler = () => { + // to bottom + if ($.scrollTop + $.clientHeight + 20 > $.scrollHeight) { + setIsScrollToBottom(true) + setIsScrollToTop(false) + } + + // if scroll to top, + // set isScrollToTop to true + else if ($.scrollTop === 0) { + setIsScrollToTop(true) + setIsScrollToBottom(false) + } else { + setIsScrollToBottom(false) + setIsScrollToTop(false) + } + } + $.addEventListener('scroll', handler) + + handler() + + return () => { + $.removeEventListener('scroll', handler) + } + }, [h]) + return ( -