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}