Skip to content

Instantly share code, notes, and snippets.

@Boettner-eric
Created May 1, 2023 21:00
Show Gist options
  • Save Boettner-eric/2fb7bf111d4b1f1b87a2415435cb86d5 to your computer and use it in GitHub Desktop.
Save Boettner-eric/2fb7bf111d4b1f1b87a2415435cb86d5 to your computer and use it in GitHub Desktop.
React scrollable table of contents
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