diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/components/DocEditor.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/components/DocEditor.tsx index 1562070e..d8070664 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-editor/components/DocEditor.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/components/DocEditor.tsx @@ -1,6 +1,5 @@ import clsx from 'clsx'; import { useEffect } from 'react'; -import { css } from 'styled-components'; import { Box, Loading } from '@/components'; import { DocHeader } from '@/docs/doc-header/'; @@ -97,18 +96,7 @@ export const DocEditor = ({ doc }: DocEditorProps) => { return ( <> - {isDesktop && ( - - - - )} + {isDesktop && } } docEditor={ diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/hook/useHeadings.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/hook/useHeadings.tsx index 6d89a8aa..a84626c3 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-editor/hook/useHeadings.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/hook/useHeadings.tsx @@ -9,11 +9,33 @@ export const useHeadings = (editor: DocsBlockNoteEditor) => { useEffect(() => { setHeadings(editor); - const unsubscribe = editor?.onChange(() => { - setHeadings(editor); + let timeoutId: NodeJS.Timeout; + const DEBOUNCE_DELAY = 500; + const unsubscribe = editor?.onChange((_, context) => { + clearTimeout(timeoutId); + + timeoutId = setTimeout(() => { + const blocksChanges = context.getChanges(); + + if (!blocksChanges.length) { + return; + } + + const blockChanges = blocksChanges[0]; + + if ( + blockChanges.type !== 'update' || + blockChanges.block.type !== 'heading' + ) { + return; + } + + setHeadings(editor); + }, DEBOUNCE_DELAY); }); return () => { + clearTimeout(timeoutId); resetHeadings(); unsubscribe(); }; diff --git a/src/frontend/apps/impress/src/features/docs/doc-table-content/components/TableContent.tsx b/src/frontend/apps/impress/src/features/docs/doc-table-content/components/TableContent.tsx index 8fdd946e..febdf0ab 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-table-content/components/TableContent.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-table-content/components/TableContent.tsx @@ -10,15 +10,112 @@ import { MAIN_LAYOUT_ID } from '@/layouts/conf'; import { Heading } from './Heading'; export const TableContent = () => { + const { spacingsTokens, colorsTokens } = useCunninghamTheme(); + const [containerHeight, setContainerHeight] = useState('100vh'); + + const { t } = useTranslation(); + const [isOpen, setIsOpen] = useState(false); + + /** + * Calculate container height based on the scrollable content + */ + useEffect(() => { + const mainLayout = document.getElementById(MAIN_LAYOUT_ID); + if (mainLayout) { + setContainerHeight(`${mainLayout.scrollHeight}px`); + } + }, []); + + const onOpen = () => { + setIsOpen(true); + }; + + return ( + + + {!isOpen && ( + + + + )} + {isOpen && } + + + ); +}; + +const TableContentOpened = ({ + setIsOpen, +}: { + setIsOpen: (isOpen: boolean) => void; +}) => { const { headings } = useHeadingStore(); const { editor } = useEditorStore(); const { spacingsTokens, colorsTokens } = useCunninghamTheme(); - const [headingIdHighlight, setHeadingIdHighlight] = useState(); - const { t } = useTranslation(); - const [isHover, setIsHover] = useState(false); + /** + * Handle scroll to highlight the current heading in the table of content + */ useEffect(() => { const handleScroll = () => { if (!headings) { @@ -69,23 +166,10 @@ export const TableContent = () => { .getElementById(MAIN_LAYOUT_ID) ?.removeEventListener('scroll', scrollFn); }; - }, [headings, setHeadingIdHighlight]); - - const onOpen = () => { - setIsHover(true); - setTimeout(() => { - const element = document.getElementById(`heading-${headingIdHighlight}`); - - element?.scrollIntoView({ - behavior: 'instant', - inline: 'center', - block: 'center', - }); - }, 0); // 300ms is the transition time of the box - }; + }, [headings]); const onClose = () => { - setIsHover(false); + setIsOpen(false); }; if ( @@ -99,129 +183,69 @@ export const TableContent = () => { return ( - {!isHover && ( + + + {t('Summary')} + - + - )} - {isHover && ( - - - - {t('Summary')} - - - - - - - {headings?.map( - (heading) => - heading.contentText && ( - - - - ), - )} - - - )} + + + {headings?.map( + (heading) => + heading.contentText && ( + + + + ), + )} + ); };