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.
This commit is contained in:
Emil Gulamov 2024-04-02 21:21:43 +04:00
parent 06e2222650
commit e896368f49
2 changed files with 50 additions and 59 deletions

View file

@ -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. - Serves as a UI demonstration with no live back-end integration.
- [x] **Starlight Documentation Theme Integration**: - [x] **Starlight Documentation Theme Integration**:
- A sleek, user-friendly, full-featured documentation theme, which enhances the readability and usability of our documentation. - 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. - 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. - 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. - 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**: - [x] **Icon Set Component**:
- Convenient and reusable Icon component that allows adding icons simply by providing a name prop. - Convenient and reusable Icon component that allows adding icons simply by providing a name prop.
- Render any pre-defined icon SVG using `<Icon name="iconName" />` in your Astro components. - Render any pre-defined icon SVG using `<Icon name="iconName" />` 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. - 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. - **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**: - [x] **Internationalization (i18n) Features**:
- Integrates [Astros internationalization (i18n) features](https://docs.astro.build/en/guides/internationalization/). - Integrates [Astros internationalization (i18n) features](https://docs.astro.build/en/guides/internationalization/).
- Additionally, a custom LanguagePicker component has been developed to facilitate language selection. - 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 ### 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 ### Bug Fixes

View file

@ -159,70 +159,57 @@ const pageTitle: string = `${post.data.title} | ${SITE.title}`;
}, },
}); });
document.addEventListener("DOMContentLoaded", function () { // Function to create and add an item to the ToC list
// The article element that contains the Markdown content function addToC(heading, tocList) {
const article: HTMLElement | null = document.querySelector("article"); const li = document.createElement("li");
li.className = "toc-level-" + heading.tagName.toLowerCase();
li.innerHTML =`
<svg class="w-0 h-0" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="#fa5a15">
<path stroke-linecap="round" stroke-linejoin="round" d="m12.75 15 3-3m0 0-3-3m3 3h-7.5M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z">
</path>
</svg>
<a href="#${heading.id}">${heading.textContent}</a>`;
tocList?.appendChild(li);
return li;
}
// The ToC container <ul> element function setActiveLink(id) {
const tocList: HTMLElement | null = document.querySelector("#toc ul"); document.querySelectorAll("#toc li").forEach((li) => {
li.classList.remove("selected");
// Function to create and add an item to the ToC list });
function addToC(heading: HTMLElement) { const activeLink = document.querySelector(`#toc a[href="#${id}"]`);
const li = document.createElement("li"); if (activeLink) {
li.className = "toc-level-" + heading.tagName.toLowerCase(); const li: HTMLElement | null = activeLink.parentElement;
li?.classList.add("selected");
const tempDiv = document.createElement("div");
tempDiv.innerHTML =
'<svg class="w-0 h-0" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="#fa5a15"><path stroke-linecap="round" stroke-linejoin="round" d="m12.75 15 3-3m0 0-3-3m3 3h-7.5M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"></svg>';
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 generateToC(article, tocList) {
// Observe headings and add them to the ToC // Observe headings and add them to the ToC
let headings: NodeListOf<HTMLElement> | [] = article let headings: NodeListOf<HTMLElement> | [] = article
? article.querySelectorAll("h1, h2, h3, h4, h5, h6") ? article.querySelectorAll("h1, h2, h3, h4, h5, h6")
: []; : [];
headings.forEach((heading: Element, i: number) => { headings.forEach((heading: Element, i: number) => {
if (heading instanceof HTMLElement) { if (heading instanceof HTMLElement) {
addToC(heading); addToC(heading, tocList);
gsap.timeline({ gsap.timeline({
scrollTrigger: { scrollTrigger: {
trigger: heading, trigger: heading,
start: "top 20%", start: "top 20%",
end: () => 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), 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 <ul> element
const tocList: HTMLElement | null = document.querySelector("#toc ul");
generateToC(article, tocList);
}); });
</script> </script>