diff --git a/README.md b/README.md
index 3778cc9..9089e51 100644
--- a/README.md
+++ b/README.md
@@ -85,23 +85,27 @@ ScrewFast is an open-source template designed for quick and efficient web projec
- Serves as a UI demonstration with no live back-end integration.
- [x] **Starlight Documentation Theme Integration**:
- - A sleek, user-friendly, full-featured documentation theme, which enhances the readability and usability of our documentation.
- - Offers a range of features such as site navigation, built-in search functionality, dark mode, syntax highlighting for code, and improved SEO.
- - Seamlessly integrates internationalization (i18n) to provide support for documentation in multiple languages, catering to a global audience.
- - Designed to facilitate ease of use while offering a modern aesthetic in both light and dark themes to accommodate user preferences.
+ - A sleek, user-friendly, full-featured documentation theme, which enhances the readability and usability of our documentation.
+ - Offers a range of features such as site navigation, built-in search functionality, dark mode, syntax highlighting for code, and improved SEO.
+ - Seamlessly integrates internationalization (i18n) to provide support for documentation in multiple languages, catering to a global audience.
+ - Designed to facilitate ease of use while offering a modern aesthetic in both light and dark themes to accommodate user preferences.
- [x] **Icon Set Component**:
- - Convenient and reusable Icon component that allows adding icons simply by providing a name prop.
- - Render any pre-defined icon SVG using `` in your Astro components.
- - The Icon Component offers a centralized location for all SVG Icons across the project in one TypeScript file - allowing unified updates and easy maintenance.
- - **Note:** Users have the option to use other community integrations like [astro-icons](https://github.com/natemoo-re/astro-icon). However, the author decided to create a custom icon set component for managing custom icons.
+ - Convenient and reusable Icon component that allows adding icons simply by providing a name prop.
+ - Render any pre-defined icon SVG using `` in your Astro components.
+ - The Icon Component offers a centralized location for all SVG Icons across the project in one TypeScript file - allowing unified updates and easy maintenance.
+ - **Note:** Developers have the option to use other community integrations like [astro-icons](https://github.com/natemoo-re/astro-icon). However, the author decided to create a custom icon set component for managing custom icons.
- [x] **Internationalization (i18n) Features**:
- - Integrates [Astro’s internationalization (i18n) features](https://docs.astro.build/en/guides/internationalization/).
- - Additionally, a custom LanguagePicker component has been developed to facilitate language selection.
+ - Integrates [Astro’s internationalization (i18n) features](https://docs.astro.build/en/guides/internationalization/).
+ - Additionally, a custom LanguagePicker component has been developed to facilitate language selection.
+
+- [x] **Dynamic Table of Contents (ToC) with Scroll Progress Indicator**:
+ - Enhances ease of navigation in insight posts by highlighting the relevant section in the ToC, and includes a progress indicator to visually represent scroll progress.
+ - Developers seeking alternatives might consider the [remark-toc](https://github.com/remarkjs/remark-toc) plugin.
### Planned Improvements
-- [ ] Implement a table of contents (ToC) sidebar for blog articles.
+- Currently, there are no planned improvements. We'll update this section as plans develop.
### Bug Fixes
diff --git a/src/pages/insights/[...slug].astro b/src/pages/insights/[...slug].astro
index 95cb1a0..88e387f 100644
--- a/src/pages/insights/[...slug].astro
+++ b/src/pages/insights/[...slug].astro
@@ -159,70 +159,57 @@ const pageTitle: string = `${post.data.title} | ${SITE.title}`;
},
});
- document.addEventListener("DOMContentLoaded", function () {
- // The article element that contains the Markdown content
- const article: HTMLElement | null = document.querySelector("article");
+ // Function to create and add an item to the ToC list
+ function addToC(heading, tocList) {
+ const li = document.createElement("li");
+ li.className = "toc-level-" + heading.tagName.toLowerCase();
+ li.innerHTML =`
+
+ ${heading.textContent}`;
+ tocList?.appendChild(li);
+ return li;
+ }
- // The ToC container
element
- const tocList: HTMLElement | null = document.querySelector("#toc ul");
-
- // Function to create and add an item to the ToC list
- function addToC(heading: HTMLElement) {
- const li = document.createElement("li");
- li.className = "toc-level-" + heading.tagName.toLowerCase();
-
- const tempDiv = document.createElement("div");
- tempDiv.innerHTML =
- '';
- const svg = tempDiv.firstChild;
-
- li.appendChild(svg as Node);
-
- const link = document.createElement("a");
- link.href = "#" + heading.id;
- link.textContent = heading.textContent;
-
- li.appendChild(link);
-
- tocList?.appendChild(li);
-
- return li;
- }
-
- // Helper function to toggle the 'selected' class
- function setActiveLink(id: string) {
- document.querySelectorAll("#toc li").forEach((li) => {
- li.classList.remove("selected");
- });
-
- const activeLink = document.querySelector(`#toc a[href="#${id}"]`);
- if (activeLink) {
- const li: HTMLElement | null = activeLink.parentElement;
- li?.classList.add("selected");
- }
+ function setActiveLink(id) {
+ document.querySelectorAll("#toc li").forEach((li) => {
+ li.classList.remove("selected");
+ });
+ const activeLink = document.querySelector(`#toc a[href="#${id}"]`);
+ if (activeLink) {
+ const li: HTMLElement | null = activeLink.parentElement;
+ li?.classList.add("selected");
}
+ }
+ function generateToC(article, tocList) {
// Observe headings and add them to the ToC
let headings: NodeListOf | [] = article
- ? article.querySelectorAll("h1, h2, h3, h4, h5, h6")
- : [];
-
+ ? article.querySelectorAll("h1, h2, h3, h4, h5, h6")
+ : [];
headings.forEach((heading: Element, i: number) => {
if (heading instanceof HTMLElement) {
- addToC(heading);
-
+ addToC(heading, tocList);
gsap.timeline({
scrollTrigger: {
trigger: heading,
start: "top 20%",
end: () =>
- `bottom top+=${i === headings.length - 1 ? 0 : headings[i + 1].getBoundingClientRect().height}`,
+ `bottom top+=${i === headings.length - 1 ? 0 : headings[i + 1].getBoundingClientRect().height}`,
onEnter: () => setActiveLink(heading.id),
- onLeaveBack: () =>
- setActiveLink((headings[i - 1] || { id: null }).id),
},
});
}
});
+ }
+
+ document.addEventListener("DOMContentLoaded", function () {
+ // The article element that contains the Markdown content
+ const article: HTMLElement | null = document.querySelector("article");
+ // The ToC container