Skip to content
Snippets Groups Projects
Commit 224940c4 authored by Toavina's avatar Toavina
Browse files

toc component, manage typesense error

parent 98b8f124
No related branches found
No related tags found
No related merge requests found
......@@ -83,7 +83,7 @@ module.exports = {
},
},
},
{
/*{
resolve: `gatsby-plugin-typesense`,
options: {
publicDir: `./public`, // Required
......@@ -144,7 +144,7 @@ module.exports = {
],
},
},
},
}, */
// this (optional) plugin enables Progressive Web App + Offline functionality
// To learn more, visit: https://gatsby.dev/offline
......
......@@ -43,6 +43,12 @@ interface CardProps {
}
export function Card(props: CardProps): JSX.Element;
interface TocProps {
children?: React.ReactNode;
className?: string;
}
export function Toc(props: TocProps): JSX.Element;
interface LinkProps {
children?: React.ReactNode;
to: string;
......
......@@ -9,6 +9,7 @@ export { default as Button } from "./src/components/core/Button";
export { default as Card } from "./src/components/core/Card";
export { default as Link } from "./src/components/core/Link";
export { default as Search } from "./src/components/core/Search";
export {default as Toc} from "./src/components/core/Toc";
// Feature components
export { default as Hero } from "./src/components/Hero";
import React from "react";
import { useEffect, useState } from "react";
import { useHeadsObserver } from "./utils/hook";
const navStyle = {
position: "sticky -webkit-sticky",
top: "24px",
maxHeight: "calc(100vh - 40px)",
overflow: "auto",
} as unknown as React.CSSProperties;
let navulliStyle = {
marginBottom: "15px",
} as React.CSSProperties;
const getClassName = (level) => {
switch (level) {
case 1:
navulliStyle = {
...navulliStyle,
marginLeft: "0px",
};
return "head1";
case 2:
navulliStyle = {
...navulliStyle,
marginLeft: "10px",
};
return "head2";
case 3:
navulliStyle = {
...navulliStyle,
marginLeft: "20px",
};
return "head3";
case 4:
navulliStyle = {
...navulliStyle,
marginLeft: "30px",
};
return "head4";
default:
return undefined;
}
};
interface Props {
className?: string;
}
const Toc = (props: Props) => {
const { className = "" } = props;
const [headings, setHeadings] = useState<any>([]);
const { activeId } = useHeadsObserver();
useEffect(() => {
const elements = Array.from(
document.querySelectorAll("h1, h2, h3, h4")
).map((elem) => ({
id: elem.id ? elem.id : console.log("Please set the id of the element"),
text: elem.textContent,
level: Number(elem.nodeName.charAt(1)),
}));
setHeadings(elements);
}, []);
return (
<aside
className={`w-[20%] fixed right-0 top-auto h-screen bg-slate-50 p-5 ${className}`}
>
<div className="text-2xl pb-5 flex flex-row">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
className="w-6 h-6 mt-2"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M8.25 6.75h12M8.25 12h12m-12 5.25h12M3.75 6.75h.007v.008H3.75V6.75zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0zM3.75 12h.007v.008H3.75V12zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0zm-.375 5.25h.007v.008H3.75v-.008zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0z"
/>
</svg>
<p className="px-2 mt-0.5"> Menu interne </p>
</div>
<nav style={navStyle}>
<ul style={navulliStyle}>
{headings.map((heading) => (
<li
key={heading.id}
className={getClassName(heading.level)}
style={navulliStyle}
>
<a
href={`#${heading.id}`}
onClick={(e) => {
e.preventDefault();
const element = document.querySelector(`#${heading.id}`);
if(element) {
element?.scrollIntoView({
behavior: "smooth",
});
}
else {
console.log("Please set the id of the element");
}
}}
style={{
fontWeight: activeId == heading.id ? "bold" : "normal",
fontFamily: "Georgia, serif",
}}
>
{heading.text}
</a>
</li>
))}
</ul>
</nav>
</aside>
);
};
export default Toc;
import { useRef, useState, useEffect } from "react";
export function useHeadsObserver() {
const observer = useRef<any>();
const [activeId, setActiveId] = useState<any>("");
useEffect(() => {
const handleObsever = (entries) => {
entries.forEach((entry) => {
if (entry?.isIntersecting) {
setActiveId(entry.target.id);
}
});
};
observer.current = new IntersectionObserver(handleObsever, {
rootMargin: "20% 0% -35% 0%",
});
const elements = document.querySelectorAll("h1, h2, h3, h4");
elements.forEach((elem) => observer.current.observe(elem));
return () => observer.current?.disconnect();
}, []);
return { activeId };
}
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment