【React】How to create a table of contents with highlighting
2022/08/23
Hello, I'm Nono.
I would like to show you how to create a table of contents with highlighting.
It is surprisingly easy to create it by using a library called react-scroll.
How to create a highlighted table of contents
Add react-scroll
react-scroll
https://github.com/fisshy/react-scroll
yarn add react-scroll
for TypeScript
yarn add react-scroll @types/react-scroll
Source Code and Description
// component/Layout/SideMenu.tsx
import { Dispatch, FC, SetStateAction } from "react";
import { Link as ScrollLink } from "react-scroll";
import { menuList } from "src/utils/const";
type SideMenuProps = {
isActiveScroll: string;
setIsActiveScroll: Dispatch<SetStateAction<string>>;
};
const SideMenu: FC<SideMenuProps> = ({ isActiveScroll, setIsActiveScroll }) => {
return (
<nav>
<ul className="list-none font-main text-gray-300">
{menuList.map((menu) => {
const active = isActiveScroll === menu;
return (
<ScrollLink
to={menu}
smooth
duration={400}
offset={-40}
onSetActive={(id) => setIsActiveScroll(id)}
spy={true}
key={menu}
>
<li className="flex items-center transition">
<div className={active ? "diamond mr-2" : "w-[5.5px]"}></div>
<div
className={`${
active
? "cursor-default font-bold text-light"
: "cursor-pointer rounded-lg px-3 hover:bg-gray-50/10"
} py-1.5`}
>
{menu.charAt(0).toUpperCase() + menu.slice(1)} {/* Capitalize the first letter */}
</div>
</li>
</ScrollLink>
);
})}
</ul>
</nav>
);
};
export default SideMenu;
utils/const.ts
export const menuList = [
"home",
"about",
"skill",
"work",
"blog",
"github",
"twitter",
"contact",
];
// pages/index.tsx
// ~~~~~~~~~~~~~~~~~~~~~~~
<Container>
<div className="headline-wrapper">
<Headline title="About" id="about" /> //scroll to id
</div>
...
About onSetActive in react-scroll
<ScrollLink
to={menu}
smooth
duration={400}
offset={-40}
onSetActive={(id) => setIsActiveScroll(id)}
spy={true}
key={menu}
>
</ScrollLink>
The onSetActive
will pass the id of the target (the target with the id) when it passes over the top of the currently displayed screen.
For example, when the target passes the About section, it will send the id "about".
This is managed by the state with onSetActive={(id) => setIsActiveScroll(id)}
This will toggle the active table of contents each time the target passes by.
(Although quick scrolling may not be detected ^^;