From d378446f6c8f657b3d1a2d76ba2c5832a53ebd38 Mon Sep 17 00:00:00 2001 From: akhil Date: Wed, 30 Oct 2024 23:47:44 +0530 Subject: [PATCH 1/2] feature: auto scroll to the selected week in sidebar and closing sidebar on ESC --- src/components/Sidebar.tsx | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index c6ebfdf50..d1ec64ccf 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,24 @@ 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 +167,7 @@ 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 +184,7 @@ 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} >
@@ -217,7 +246,7 @@ export function Sidebar({
- + `item-${num}`)} className="w-full px-4 capitalize"> {memoizedContent} From 49159611d21abc36a30ad7b1d427b24d55c7b6f9 Mon Sep 17 00:00:00 2001 From: akhil Date: Thu, 31 Oct 2024 00:11:53 +0530 Subject: [PATCH 2/2] formatting --- src/components/Sidebar.tsx | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index d1ec64ccf..15f879d88 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -142,15 +142,21 @@ export function Sidebar({ useEffect(() => { if (sidebarOpen && activeItemRef.current) { - activeItemRef.current.scrollIntoView({ behavior: 'smooth', block: 'center' }); + 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'); + const firstFocusableElement = + activeItemRef.current.querySelector('button, a'); if (firstFocusableElement) { - (firstFocusableElement as HTMLButtonElement | HTMLAnchorElement).focus(); + ( + firstFocusableElement as HTMLButtonElement | HTMLAnchorElement + ).focus(); } } } @@ -167,7 +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} + ref={ + isActiveContent + ? (activeItemRef as React.RefObject) + : null + } > {content.title} @@ -184,7 +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} + ref={ + isActiveContent + ? (activeItemRef as React.RefObject) + : null + } >
@@ -215,7 +229,7 @@ export function Sidebar({ ); return ( -
+
- `item-${num}`)} className="w-full px-4 capitalize"> + `item-${num}`)} + className="w-full px-4 capitalize" + > {memoizedContent}