Skip to content

Commit

Permalink
feature: auto scroll to the selected week in sidebar and closing side…
Browse files Browse the repository at this point in the history
…bar on ESC (#1531)

* feature: auto scroll to the selected week in sidebar and closing sidebar on ESC

* formatting

---------

Co-authored-by: akhil <[email protected]>
Co-authored-by: Sargam <[email protected]>
  • Loading branch information
3 people authored and hkirat committed Dec 5, 2024
1 parent 454dc26 commit 9fb8a88
Showing 1 changed file with 49 additions and 7 deletions.
56 changes: 49 additions & 7 deletions src/components/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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]);

Expand Down Expand Up @@ -129,6 +138,30 @@ export function Sidebar({
[courseId, findPathToContent, fullCourseContent],
);

const activeItemRef = useRef<HTMLDivElement | HTMLAnchorElement | null>(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) => {
Expand All @@ -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<HTMLDivElement>)
: null
}
>
<AccordionTrigger className="rounded-md px-4 text-lg font-medium capitalize">
{content.title}
Expand All @@ -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<HTMLAnchorElement>)
: null
}
>
<div className="flex w-full items-center justify-between gap-2">
<div className="flex items-center gap-2">
Expand Down Expand Up @@ -186,10 +229,7 @@ export function Sidebar({
);

return (

<div className="sticky top-[55px] z-20 bg-background py-2">


<div className="sticky top-[72px] z-20 bg-background py-2">
<Button
ref={buttonRef}
onClick={() => setSidebarOpen((s) => !s)}
Expand All @@ -209,11 +249,9 @@ export function Sidebar({
variants={sidebarVariants}
className="fixed right-0 top-0 z-[99999] flex h-screen w-full flex-col gap-4 overflow-y-auto rounded-r-lg border-l border-primary/10 bg-neutral-50 dark:bg-neutral-900 md:max-w-[30vw]"
>

<div className="sticky top-0 z-10 flex items-center justify-between border-b border-primary/10 bg-neutral-50 p-5 dark:bg-neutral-900">
{' '}
<h4 className="text-xl font-bold tracking-tighter text-primary lg:text-2xl">

Course Content
</h4>
<Button
Expand All @@ -224,7 +262,11 @@ export function Sidebar({
<X className="size-5" />
</Button>
</div>
<Accordion type="multiple" className="w-full px-4 pb-20 capitalize">
<Accordion
type="multiple"
defaultValue={currentActiveContentIds.map((num) => `item-${num}`)}
className="w-full px-4 capitalize"
>
{memoizedContent}
</Accordion>
</motion.div>
Expand Down

0 comments on commit 9fb8a88

Please sign in to comment.