From 3e0c8157a67d90cf347e6bde8671280aa12670c8 Mon Sep 17 00:00:00 2001 From: Innei Date: Sun, 18 Jun 2023 11:00:44 +0800 Subject: [PATCH] feat: to top Signed-off-by: Innei --- src/app/notes/[id]/page.tsx | 5 ++++ src/components/ui/fab/BackToTopFAB.tsx | 2 +- src/components/widgets/toc/Toc.tsx | 27 +++++++++++++++---- src/components/widgets/toc/TocAutoScroll.tsx | 6 ++--- src/components/widgets/toc/TocItem.tsx | 12 ++++----- src/components/widgets/toc/escapeSelector.tsx | 3 +++ src/utils/{spring.ts => scroller.ts} | 12 +++++---- 7 files changed, 45 insertions(+), 22 deletions(-) create mode 100644 src/components/widgets/toc/escapeSelector.tsx rename src/utils/{spring.ts => scroller.ts} (81%) diff --git a/src/app/notes/[id]/page.tsx b/src/app/notes/[id]/page.tsx index a6032091b5..b61372a4e7 100644 --- a/src/app/notes/[id]/page.tsx +++ b/src/app/notes/[id]/page.tsx @@ -25,6 +25,7 @@ import { MarkdownImageRecordProvider } from '~/providers/article/markdown-image- import { useSetCurrentNoteId } from '~/providers/note/current-note-id-provider' import { NoteLayoutRightSidePortal } from '~/providers/note/right-side-provider' import { parseDate } from '~/utils/datetime' +import { springScrollToTop } from '~/utils/scroller' import styles from './page.module.css' @@ -162,5 +163,9 @@ const Markdownrenderers: { [name: string]: Partial } = { export default PageDataHolder(PageImpl, () => { const { id } = useParams() as { id: string } + + useEffect(() => { + springScrollToTop() + }, [id]) return useNoteByNidQuery(id) }) diff --git a/src/components/ui/fab/BackToTopFAB.tsx b/src/components/ui/fab/BackToTopFAB.tsx index 628e9f8395..3113871397 100644 --- a/src/components/ui/fab/BackToTopFAB.tsx +++ b/src/components/ui/fab/BackToTopFAB.tsx @@ -2,7 +2,7 @@ import { useViewport } from '~/atoms' import { usePageScrollLocationSelector } from '~/providers/root/page-scroll-info-provider' -import { springScrollToTop } from '~/utils/spring' +import { springScrollToTop } from '~/utils/scroller' import { FABBase } from './FABContainer' diff --git a/src/components/widgets/toc/Toc.tsx b/src/components/widgets/toc/Toc.tsx index 948ecbfc8f..af954e77f1 100644 --- a/src/components/widgets/toc/Toc.tsx +++ b/src/components/widgets/toc/Toc.tsx @@ -1,11 +1,13 @@ -import { memo, useEffect, useMemo, useRef, useState } from 'react' +import { memo, useCallback, useEffect, useMemo, useRef } from 'react' import { motion } from 'framer-motion' +import { atom, useAtom } from 'jotai' import type { ITocItem } from './TocItem' import { RightToLeftTransitionView } from '~/components/ui/transition/RightToLeftTransitionView' import { throttle } from '~/lib/_' import { useArticleElement } from '~/providers/article/article-element-provider' import { clsxm } from '~/utils/helper' +import { springScrollToElement } from '~/utils/scroller' import { TocItem } from './TocItem' @@ -28,6 +30,7 @@ export const Toc: Component = ({ useAsWeight, className }) => { ...$article.querySelectorAll('h1,h2,h3,h4,h5,h6'), ] as HTMLHeadingElement[] }, [$article]) + const toc: ITocItem[] = useMemo(() => { return Array.from($headings).map((el, idx) => { const depth = +el.tagName.slice(1) @@ -76,8 +79,18 @@ export const Toc: Component = ({ useAsWeight, className }) => { [toc], ) - const activeId = useActiveId($headings) + const [activeId, setActiveId] = useActiveId($headings) + const handleScrollTo = useCallback( + (i: number, $el: HTMLElement | null, anchorId: string) => { + if ($el) { + springScrollToElement($el, -100).then(() => { + setActiveId(anchorId) + }) + } + }, + [], + ) return (