From f8f6e900e7fec5474c5d36c0b4d1f4ed25b76213 Mon Sep 17 00:00:00 2001 From: Akhil <60128585+Chityalaakhil@users.noreply.github.com> Date: Wed, 4 Dec 2024 00:47:05 +0530 Subject: [PATCH] feature: auto scroll to the selected week in sidebar and closing sidebar on ESC (#1531) * feature: auto scroll to the selected week in sidebar and closing sidebar on ESC * formatting --------- Co-authored-by: akhil Co-authored-by: Sargam --- src/components/Sidebar.tsx | 56 +++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 7 deletions(-) diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index 048cf00b..78751267 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -83,10 +83,19 @@ export function Sidebar({ } }; + // listen for ESC key and close the sidebar + const handleEscape = (event: KeyboardEvent) => { + if (event.key === 'Escape') { + closeSidebar(); + } + }; + document.addEventListener('mousedown', handleClickOutside); + document.addEventListener('keydown', handleEscape); return () => { document.removeEventListener('mousedown', handleClickOutside); + document.removeEventListener('keydown', handleEscape); }; }, [sidebarRef]); @@ -129,6 +138,30 @@ export function Sidebar({ [courseId, findPathToContent, fullCourseContent], ); + const activeItemRef = useRef(null); + + useEffect(() => { + if (sidebarOpen && activeItemRef.current) { + activeItemRef.current.scrollIntoView({ + behavior: 'smooth', + block: 'center', + }); + // focus on the active item + if (activeItemRef.current instanceof HTMLAnchorElement) { + activeItemRef.current.focus(); + } else if (activeItemRef.current instanceof HTMLDivElement) { + // check for the first focusable element and focus on it + const firstFocusableElement = + activeItemRef.current.querySelector('button, a'); + if (firstFocusableElement) { + ( + firstFocusableElement as HTMLButtonElement | HTMLAnchorElement + ).focus(); + } + } + } + }, [sidebarOpen]); + const renderContent = useCallback( (contents: FullCourseContent[]) => { return contents.map((content) => { @@ -140,6 +173,11 @@ export function Sidebar({ key={content.id} value={`item-${content.id}`} className={`rounded-md border-none ${isActiveContent ? 'bg-primary/5' : ''}`} + ref={ + isActiveContent + ? (activeItemRef as React.RefObject) + : null + } > {content.title} @@ -156,6 +194,11 @@ export function Sidebar({ key={content.id} href={navigateToContent(content.id) || '#'} className={`flex w-full cursor-pointer items-center rounded-md p-4 tracking-tight hover:bg-primary/10 ${isActiveContent ? 'bg-primary/10' : ''}`} + ref={ + isActiveContent + ? (activeItemRef as React.RefObject) + : null + } >
@@ -186,10 +229,7 @@ export function Sidebar({ ); return ( - -
- - +
- + `item-${num}`)} + className="w-full px-4 capitalize" + > {memoizedContent}