From e896368f4971dc9dcd52c8d9bdfbf75773f88876 Mon Sep 17 00:00:00 2001
From: Emil Gulamov <125820963+mearashadowfax@users.noreply.github.com>
Date: Tue, 2 Apr 2024 21:21:43 +0400
Subject: [PATCH 1/4] Update README and refactor Table of Contents (ToC) code
This commit updates the README file to reflect the addition of a dynamic ToC with a scroll progress indicator in the insights posts. The code related to this functionality has also been refactored in the insights file to split the logic within event listeners into separate functions, leading to higher readability and cleaner code.
---
README.md | 26 ++++++----
src/pages/insights/[...slug].astro | 83 +++++++++++++-----------------
2 files changed, 50 insertions(+), 59 deletions(-)
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
element
+ const tocList: HTMLElement | null = document.querySelector("#toc ul");
+ generateToC(article, tocList);
});
From 332dd8f5ce5c7e41ec6afbb6df03769d99c74845 Mon Sep 17 00:00:00 2001
From: Emil Gulamov <125820963+mearashadowfax@users.noreply.github.com>
Date: Tue, 2 Apr 2024 21:33:55 +0400
Subject: [PATCH 2/4] Refine README and add typings to ToC functions
---
README.md | 1 -
src/pages/insights/[...slug].astro | 6 +++---
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index 9089e51..b5e4b2a 100644
--- a/README.md
+++ b/README.md
@@ -107,7 +107,6 @@ ScrewFast is an open-source template designed for quick and efficient web projec
### Planned Improvements
- Currently, there are no planned improvements. We'll update this section as plans develop.
-
### Bug Fixes
- Currently, there are no known bugs. If you encounter any issues, please report them on our [issues page](https://github.com/mearashadowfax/ScrewFast/issues).
diff --git a/src/pages/insights/[...slug].astro b/src/pages/insights/[...slug].astro
index 88e387f..70241b8 100644
--- a/src/pages/insights/[...slug].astro
+++ b/src/pages/insights/[...slug].astro
@@ -160,7 +160,7 @@ const pageTitle: string = `${post.data.title} | ${SITE.title}`;
});
// Function to create and add an item to the ToC list
- function addToC(heading, tocList) {
+ function addToC(heading: HTMLElement, tocList: HTMLElement | null) {
const li = document.createElement("li");
li.className = "toc-level-" + heading.tagName.toLowerCase();
li.innerHTML =`
@@ -173,7 +173,7 @@ const pageTitle: string = `${post.data.title} | ${SITE.title}`;
return li;
}
- function setActiveLink(id) {
+ function setActiveLink(id: string) {
document.querySelectorAll("#toc li").forEach((li) => {
li.classList.remove("selected");
});
@@ -184,7 +184,7 @@ const pageTitle: string = `${post.data.title} | ${SITE.title}`;
}
}
- function generateToC(article, tocList) {
+ function generateToC(article: HTMLElement | null, tocList: HTMLElement | null) {
// Observe headings and add them to the ToC
let headings: NodeListOf | [] = article
? article.querySelectorAll("h1, h2, h3, h4, h5, h6")
From 65037e910f01bf5bda3f7a384711eeb16145b5ba Mon Sep 17 00:00:00 2001
From: Emil Gulamov <125820963+mearashadowfax@users.noreply.github.com>
Date: Tue, 2 Apr 2024 21:43:50 +0400
Subject: [PATCH 3/4] Add spacing in CSS for improved readability
---
src/pages/insights/[...slug].astro | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/src/pages/insights/[...slug].astro b/src/pages/insights/[...slug].astro
index 70241b8..1d6bfcc 100644
--- a/src/pages/insights/[...slug].astro
+++ b/src/pages/insights/[...slug].astro
@@ -82,6 +82,7 @@ const pageTitle: string = `${post.data.title} | ${SITE.title}`;
html {
scroll-behavior: smooth;
}
+
article h2,
article h3,
article h4,
@@ -91,21 +92,26 @@ const pageTitle: string = `${post.data.title} | ${SITE.title}`;
margin-top: 2.5rem;
scroll-margin-top: 3rem;
}
+
h2 {
font-size: 1.5rem;
line-height: 2rem;
}
+
h3 {
font-size: 1.25rem;
line-height: 1.75rem;
}
+
h4 {
font-size: 1.125rem;
line-height: 1.75rem;
}
+
p {
margin-top: 1.5rem;
}
+
@keyframes grow-progress {
from {
transform: scaleX(0);
@@ -114,20 +120,24 @@ const pageTitle: string = `${post.data.title} | ${SITE.title}`;
transform: scaleX(1);
}
}
+
#progress {
transform-origin: 0 50%;
animation: grow-progress auto linear;
animation-timeline: scroll(block root);
}
+
#toc li {
display: flex;
align-items: center;
opacity: 0.8;
transition: all 300ms var(--transition-cubic);
}
+
#toc li.selected {
opacity: 1;
}
+
#toc li svg {
width: 0;
height: 0;
@@ -135,6 +145,7 @@ const pageTitle: string = `${post.data.title} | ${SITE.title}`;
height 400ms var(--transition-cubic),
width 400ms var(--transition-cubic);
}
+
#toc li.selected svg {
width: 1.25rem;
height: 1.25rem;
From 1fc42828b3717ac5b0e731228073bbce18d2609c Mon Sep 17 00:00:00 2001
From: Emil Gulamov <125820963+mearashadowfax@users.noreply.github.com>
Date: Tue, 2 Apr 2024 21:59:53 +0400
Subject: [PATCH 4/4] Refactor ToC generation and active link handling
The SVG HTML was moved into a constant for cleaner code.
---
src/pages/insights/[...slug].astro | 85 +++++++++++++++---------------
1 file changed, 43 insertions(+), 42 deletions(-)
diff --git a/src/pages/insights/[...slug].astro b/src/pages/insights/[...slug].astro
index 1d6bfcc..66b9921 100644
--- a/src/pages/insights/[...slug].astro
+++ b/src/pages/insights/[...slug].astro
@@ -170,50 +170,20 @@ const pageTitle: string = `${post.data.title} | ${SITE.title}`;
},
});
- // Function to create and add an item to the ToC list
- function addToC(heading: HTMLElement, tocList: HTMLElement | null) {
- const li = document.createElement("li");
- li.className = "toc-level-" + heading.tagName.toLowerCase();
- li.innerHTML =`
-
- ${heading.textContent}`;
- tocList?.appendChild(li);
- return li;
- }
+ const SVG_HTML_STRING = '';
+
+ function setActiveLinkById(id: string | null) {
+ const listItems = document.querySelectorAll("#toc li");
+ listItems.forEach(item => item.classList.remove("selected"));
+
+ if (!id) return;
- 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 generateToC(article: HTMLElement | null, tocList: HTMLElement | null) {
- // Observe headings and add them to the ToC
- let headings: NodeListOf | [] = article
- ? article.querySelectorAll("h1, h2, h3, h4, h5, h6")
- : [];
- headings.forEach((heading: Element, i: number) => {
- if (heading instanceof HTMLElement) {
- addToC(heading, tocList);
- gsap.timeline({
- scrollTrigger: {
- trigger: heading,
- start: "top 20%",
- end: () =>
- `bottom top+=${i === headings.length - 1 ? 0 : headings[i + 1].getBoundingClientRect().height}`,
- onEnter: () => setActiveLink(heading.id),
- },
- });
- }
- });
+ if (!activeLink) return;
+
+ const listItem = activeLink.parentElement;
+ listItem?.classList.add("selected");
}
document.addEventListener("DOMContentLoaded", function () {
@@ -221,6 +191,37 @@ const pageTitle: string = `${post.data.title} | ${SITE.title}`;
const article: HTMLElement | null = document.querySelector("article");
// The ToC container