Created
May 1, 2023 21:00
-
-
Save Boettner-eric/2fb7bf111d4b1f1b87a2415435cb86d5 to your computer and use it in GitHub Desktop.
React scrollable table of contents
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useRef } from 'react'; | |
enum ExampleEnum { | |
One = 'One', | |
Two = 'Two', | |
Three = 'Three', | |
} | |
export function ExampleComponent(props) { | |
const itemsRef = useRef<Map<ExampleEnum, HTMLDivElement>>(null); | |
function scrollToSection(item: ExampleEnum) { | |
return function () { | |
const map = getMap(); | |
const node = map.get(item); | |
parentRef.current?.scrollTo({ behavior: 'smooth', top: node.offsetTop - 75 }); | |
}; | |
} | |
function getMap() { | |
if (!itemsRef.current) { | |
itemsRef.current = new Map<ExampleEnum, HTMLDivElement>(); | |
} | |
return itemsRef.current; | |
} | |
function getRef(item: ExampleEnum) { | |
return function (node: HTMLDivElement) { | |
const map = getMap(); | |
if (node) { | |
map.set(item, node); | |
} else { | |
map.delete(item); | |
} | |
}; | |
} | |
const parentRef = useRef<HTMLDivElement>(null); | |
const enumValues = Object.values(ExampleEnum); | |
return ( | |
<div className="col-span-7 bg-gray-50 p-6 flex flex-col gap-4 overflow-y-scroll" ref={parentRef}> | |
{enumValues.map((enumVal, i) => ( | |
<div key={`${enumVal}-${i}`} className="flex flex-col gap-6 pt-4" ref={getRef(enumVal)}> | |
<div className="grid grid-cols-2 gap-4"> | |
<p>{enumVal}</p> | |
</div> | |
</div> | |
))} | |
<div className="flex flex-col gap-4 pl-4"> | |
<p className="text-base font-medium text-gray-600">Table of Contents</p> | |
<div className="flex flex-col gap-4 pl-2"> | |
{enumValues.map((category, j) => ( | |
<li | |
className="text-gray-600 text-base font-medium cursor-pointer" | |
key={`${category}-${j}-search`} | |
onClick={scrollToSection(category)} | |
> | |
category | |
</li> | |
))} | |
</div> | |
</div> | |
</div> | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment