Merge pull request #133 from mearashadowfax/add-insights-translation

Add insights translation and refactor 404 page
This commit is contained in:
Emil Gulamov 2024-07-04 16:21:09 +04:00 committed by GitHub
commit 5132a9b643
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 423 additions and 63 deletions

View file

@ -71,9 +71,13 @@ import Icon from "./icons/Icon.astro";
.split("/")
.filter((part) => part && !languages.includes(part as TLanguage));
// Disable the selection of the same language
if (lang === url.pathname.split("/")[1]) return;
if (url.pathname.includes("/post")) {
if (
url.pathname.includes("/post") ||
url.pathname.includes("/insight")
) {
if (url.pathname.includes("en")) {
pathParts.unshift(lang);
pathParts.splice(2, 0, lang);

View file

@ -4,16 +4,20 @@ import { Image } from "astro:assets";
import Icon from "@components/ui/icons/Icon.astro";
import type { CollectionEntry } from "astro:content";
const { insightEntry } = Astro.props;
const {
insightEntry,
label = Astro.currentLocale === "fr" ? "Lire plus" : "Read more",
} = Astro.props;
interface Props {
insightEntry: CollectionEntry<"insights">;
label?: string;
}
---
<!-- The anchor tag is the root container for the "Insight" card. It links to the insight detail page. -->
<a
class="group outline-none rounded-xl ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none"
class="group rounded-xl outline-none ring-zinc-500 transition duration-300 focus-visible:ring dark:ring-zinc-200 dark:focus:outline-none"
href={`/insights/${insightEntry.slug}/`}
>
<!-- This is the container for the insight's cover image. -->
@ -42,7 +46,7 @@ interface Props {
<p
class="mt-5 inline-flex items-center gap-x-1 font-medium text-orange-400 decoration-2 group-hover:underline dark:text-orange-300"
>
Read more
{label}
<Icon name="arrowRightStatic" />
</p>
</div>

View file

@ -0,0 +1,42 @@
---
title: "L'avenir de la technologie de la construction"
description: "Explorez le rôle pionnier de ScrewFast dans la révolution de la construction grâce à des technologies avancées et des solutions innovantes."
cardImage: "@/images/insights/insight-1.avif"
cardImageAlt: "Vue de dessus de l'agencement des outils mécaniques"
---
Dans le monde de la construction, où l'innovation rencontre la praticité, ScrewFast se dresse comme un phare d'avancées pionnières. Depuis des années, cette entreprise est à la pointe de la révolution de la construction grâce à son engagement indéfectible envers les technologies avancées et les solutions innovantes. Des gratte-ciels aux ponts, ScrewFast a laissé une marque indélébile sur l'industrie, façonnant l'avenir de la construction de manière inimaginable.
## Un héritage d'innovation
Fondée avec la vision de redéfinir les normes de la construction, ScrewFast s'est lancée dans un parcours marqué par une innovation incessante. Depuis sa création, l'entreprise n'a cessé de repousser les limites du possible, introduisant des technologies révolutionnaires qui ont transformé la manière dont les structures sont construites.
## Réinventer les systèmes de fondation
Au cœur du succès de ScrewFast se trouve son approche révolutionnaire des systèmes de fondation. Traditionnellement, le processus de pose des fondations est fastidieux et chronophage, nécessitant souvent des excavations importantes et une main-d'œuvre manuelle. Cependant, les solutions innovantes de ScrewFast ont totalement changé la donne.
En utilisant des techniques avancées telles que l'installation de pieux hélicoïdaux, ScrewFast a rationalisé le processus de fondation, réduisant considérablement le temps et les coûts. Ces pieux hélicoïdaux, avec leur conception en forme de vis, offrent une stabilité inégalée et peuvent être installés avec une efficacité remarquable, en faisant le choix privilégié pour des projets de toutes tailles.
## Adopter la digitalisation
À une époque dominée par la digitalisation, ScrewFast a pleinement embrassé la technologie, exploitant sa puissance pour améliorer l'efficacité et la précision. Grâce à l'utilisation de logiciels avancés et de techniques de modélisation, l'entreprise a révolutionné les phases de conception et de planification des projets de construction.
De la modélisation 3D à la modélisation de l'information du bâtiment (BIM), ScrewFast utilise des outils de pointe pour créer des simulations détaillées des structures, permettant une meilleure visualisation et optimisation. Cette approche numérique améliore non seulement la précision des plans de construction, mais permet également une collaboration sans faille entre architectes, ingénieurs et constructeurs.
## Des solutions durables pour un avenir plus vert
Dans un monde de plus en plus soucieux de durabilité, ScrewFast a pris des mesures proactives pour minimiser son empreinte environnementale. En donnant la priorité aux matériaux écologiques et aux pratiques de construction durables, l'entreprise mène la charge vers un avenir plus vert.
Un exemple notable est l'engagement de ScrewFast envers la construction modulaire, une méthode qui consiste à préfabricer des composants de bâtiment hors site et à les assembler sur site. Cette approche réduit non seulement les déchets de construction mais minimise également la perturbation des écosystèmes locaux, en faisant une solution gagnante pour les constructeurs et l'environnement.
## La route à venir : défis et opportunités
Alors que ScrewFast continue de repousser les limites de la technologie de la construction, elle fait face à une multitude de défis et d'opportunités à l'horizon. De la navigation dans les obstacles réglementaires à l'adaptation aux tendances de l'industrie en évolution, la route à venir est semée de complexités.
Cependant, avec son dévouement indéfectible à l'innovation et un bilan de succès, ScrewFast est bien positionnée pour surmonter ces obstacles et continuer à façonner l'avenir de la construction pour les générations à venir. Alors que l'industrie avance vers un avenir de plus en plus numérique et durable, ScrewFast se dresse comme un phare de progrès, ouvrant la voie vers un monde où la construction est non seulement efficace et rentable, mais aussi respectueuse de l'environnement.
## Conclusion
Dans le paysage en constante évolution de la technologie de la construction, ScrewFast reste un pionnier, repoussant constamment les limites du possible. Grâce à son engagement envers l'innovation, la digitalisation et la durabilité, l'entreprise a non seulement révolutionné la manière dont les structures sont construites, mais a également établi une nouvelle norme d'excellence dans l'industrie.
En regardant vers l'avenir, une chose est claire : l'héritage de ScrewFast continuera de façonner le monde de la construction pour les années à venir, inspirant des générations de constructeurs à rêver grand et à repousser les limites du possible. Avec ScrewFast à la tête, l'avenir de la construction n'a jamais été aussi prometteur.

View file

@ -0,0 +1,44 @@
---
title: "L'importance de la collaboration"
description: "Découvrez comment la collaboration est au cœur de l'approche de construction de ScrewFast, favorisant une communication efficace et un travail d'équipe pour atteindre des résultats exceptionnels."
cardImage: "@/images/insights/insight-2.avif"
cardImageAlt: "Vue de dessus de l'agencement des outils mécaniques"
---
Dans le domaine de la construction, où les projets impliquent souvent des conceptions complexes, des délais serrés et des défis logistiques compliqués, l'importance de la collaboration ne peut être sous-estimée. Une collaboration efficace n'est pas seulement un aspect souhaitable de la gestion de projet; c'est la pierre angulaire sur laquelle reposent les entreprises de construction réussies. Dans cet article, nous explorons comment la collaboration sert de force motrice à l'approche de construction de ScrewFast, facilitant une communication efficace et un travail d'équipe pour atteindre des résultats exceptionnels.
## Comprendre ScrewFast : Un aperçu
Avant d'approfondir les subtilités de la collaboration dans les projets de construction de ScrewFast, il est essentiel de comprendre les antécédents et l'éthique de l'entreprise. ScrewFast est une entreprise de construction renommée pour son approche innovante des solutions de fondation. Spécialisée dans les fondations à pieux hélicoïdaux, ScrewFast s'est imposée comme un leader dans l'industrie de la construction, offrant des solutions de haute qualité et rentables pour une large gamme de projets, des développements à petite échelle aux grandes infrastructures.
## La culture de collaboration chez ScrewFast
Au cœur du succès de ScrewFast se trouve une culture qui privilégie la collaboration à chaque étape du processus de construction. De l'initiation à l'achèvement du projet, la collaboration est intégrée dans le fonctionnement de l'entreprise. Contrairement aux modèles hiérarchiques traditionnels courants dans de nombreuses entreprises de construction, ScrewFast favorise un environnement où l'apport de chaque membre de l'équipe est valorisé, quel que soit son rôle ou son ancienneté.
### Briser les silos : la clé de la collaboration efficace
L'un des plus grands obstacles à la collaboration dans la construction est la présence de silos au sein des organisations. Les départements opèrent souvent de manière isolée, entraînant des problèmes de communication, des efforts dupliqués et un manque de synergie. ScrewFast relève ce défi de front en brisant les silos et en promouvant la collaboration interfonctionnelle.
#### Équipes interfonctionnelles : combler le fossé
ScrewFast forme des équipes interfonctionnelles composées de professionnels issus de divers horizons, y compris des ingénieurs, des architectes, des chefs de projet et des travailleurs de la construction. En réunissant des individus aux expertises et perspectives variées, ScrewFast garantit une résolution complète des problèmes et une prise de décision holistique tout au long du cycle de vie du projet.
#### Livraison de projet intégrée : une approche unifiée
La livraison de projet intégrée (IPD) est une autre pierre angulaire de l'éthique collaborative de ScrewFast. Contrairement aux méthodes traditionnelles de livraison de projet où les parties prenantes opèrent dans des silos séparés, l'IPD favorise une approche unifiée où toutes les parties travaillent ensemble dès le début. Cette approche intégrée favorise la transparence, l'efficacité et la responsabilité collective, conduisant finalement à des résultats de projet supérieurs.
## Stimuler l'innovation grâce à la collaboration
La collaboration ne consiste pas seulement à améliorer la communication et le travail d'équipe; elle sert également de catalyseur pour l'innovation. Chez ScrewFast, la collaboration alimente une culture d'amélioration continue et de pensée avant-gardiste, favorisant le développement de solutions révolutionnaires qui repoussent les limites de la technologie de la construction.
### Co-création avec les clients : transformer les idées en réalité
ScrewFast reconnaît l'importance d'impliquer les clients dans le processus de co-création. En collaborant étroitement avec les clients dès le début du projet, ScrewFast obtient des informations précieuses sur leurs besoins, préférences et défis. Cette approche collaborative permet à ScrewFast de personnaliser ses solutions pour répondre aux exigences spécifiques des clients, ce qui se traduit par une satisfaction client accrue et un succès du projet.
### Adopter les technologies émergentes
L'innovation prospère dans les environnements collaboratifs où se croisent des perspectives diverses. Chez ScrewFast, la collaboration s'étend au-delà des équipes internes pour inclure des partenaires externes, notamment des fournisseurs de technologies, des institutions de recherche et le monde universitaire. En forgeant des partenariats stratégiques avec des leaders de l'industrie, ScrewFast reste à la pointe des avancées technologiques, exploitant des outils et des techniques de pointe pour améliorer l'efficacité et les performances de ses projets.
## Conclusion
Dans le monde trépidant de la construction, la collaboration n'est pas qu'un mot à la mode; c'est un principe fondamental qui sous-tend le succès. L'approche de construction de ScrewFast illustre le pouvoir transformateur de la collaboration, démontrant comment une communication efficace, un travail d'équipe et une innovation peuvent produire des résultats exceptionnels. Alors que l'industrie de la construction continue d'évoluer, embrasser la collaboration sera essentiel pour relever les défis, saisir les opportunités et offrir des solutions durables qui résistent à l'épreuve du temps.

View file

@ -0,0 +1,37 @@
---
title: "L'impact des pratiques durables"
description: "Découvrez comment ScrewFast mène la charge en promouvant la durabilité dans l'industrie de la construction"
cardImage: "@/images/insights/insight-3.avif"
cardImageAlt: "Vue de dessus de l'agencement des outils mécaniques"
---
L'industrie de la construction projette une longue ombre. Bien qu'elle fournisse l'infrastructure essentielle à nos vies, son impact environnemental est indéniable. De l'épuisement des ressources et la pollution à la consommation d'énergie et à la génération de déchets, les pratiques de construction traditionnelles pèsent lourdement sur notre planète. Mais une révolution est en marche, et à l'avant-garde se trouve ScrewFast, une entreprise qui change la donne de manière démonstrative avec son engagement envers des pratiques durables.
## L'ampleur du défi
Imaginez ceci : l'industrie de la construction est responsable de 36 % de la consommation énergétique mondiale et de 40 % des émissions totales de CO2 [1]. Et ce n'est pas tout. Les bâtiments et la construction sont des contributeurs majeurs à la génération de déchets solides, représentant jusqu'à 40 %, et consomment 30 % des matières premières mondiales [1]. Ces statistiques dressent un tableau clair : continuer comme avant est tout simplement insoutenable.
## ScrewFast : construire avec responsabilité
ScrewFast est une entreprise fondée sur la responsabilité. Ils comprennent le coût environnemental de la construction et prennent des mesures décisives pour changer de cap. Leur engagement envers la durabilité imprègne tous les aspects de leurs opérations, des matériaux qu'ils utilisent aux processus de construction qu'ils mettent en œuvre.
* **Innovation matérielle :** ScrewFast privilégie l'utilisation de matériaux recyclés et recyclables. Cela réduit non seulement la dépendance aux ressources vierges, mais diminue également la charge environnementale associée à l'extraction des ressources.
* **Efficacité énergétique :** ScrewFast défend les méthodes de construction écoénergétiques. Cela peut impliquer l'incorporation de matériaux d'isolation haute performance, l'optimisation de la conception des bâtiments pour la lumière naturelle et la ventilation, ou même l'intégration de sources d'énergie renouvelable comme les panneaux solaires. Le résultat ? Des bâtiments nécessitant moins d'énergie pour fonctionner, entraînant une réduction significative des émissions de gaz à effet de serre.
* **Réduction des déchets :** ScrewFast planifie et exécute minutieusement des projets pour minimiser la génération de déchets. Cela peut impliquer l'utilisation de composants préfabriqués, l'emploi de techniques de construction modulaire et la mise en œuvre de programmes rigoureux de tri et de recyclage des déchets. En minimisant les déchets, ScrewFast conserve les ressources et réduit l'impact environnemental associé aux décharges.
* **Approvisionnement durable :** ScrewFast adopte une approche responsable de l'approvisionnement en matériaux. Ils privilégient les fournisseurs qui partagent leur engagement envers la durabilité. Cela garantit que l'empreinte environnementale est prise en compte tout au long de la chaîne d'approvisionnement.
## L'impact du changement
L'engagement de ScrewFast envers les pratiques durables s'étend bien au-delà des murs de leur entreprise. L'effet d'entraînement de leurs actions est substantiel :
* **Avantages environnementaux :** En promouvant la conservation des ressources, la réduction de la consommation d'énergie et la minimisation des déchets, ScrewFast contribue de manière significative à une planète plus saine. Cela se traduit par un air plus pur, un climat plus stable et la préservation des ressources naturelles pour les générations futures.
* **Avantages économiques :** Les pratiques de construction durables conduisent souvent à des avantages économiques à long terme. Les bâtiments écoénergétiques ont des coûts opérationnels plus bas, et les matériaux durables peuvent parfois être étonnamment compétitifs en termes de coûts. ScrewFast démontre qu'être vert peut aussi être bon pour les résultats financiers.
* **Responsabilité sociale :** ScrewFast reconnaît que la durabilité englobe plus que l'environnement. Ils s'engagent à créer des environnements de travail sûrs et sains pour leurs employés et à favoriser des relations positives avec les communautés dans lesquelles ils opèrent.
## Donner l'exemple
ScrewFast ne se contente pas de parler, ils agissent. Leur engagement envers la durabilité est évident dans chaque projet qu'ils entreprennent. En montrant les avantages tangibles de la construction durable, ScrewFast inspire un changement de paradigme au sein de l'industrie. Ils ouvrent la voie à un avenir où les bâtiments sont non seulement fonctionnels, mais aussi respectueux de l'environnement.
## La route à suivre
L'industrie de la construction est à la croisée des chemins. ScrewFast se dresse comme un phare, éclairant la voie vers un avenir plus durable. En adoptant des pratiques innovantes et en donnant la priorité à la responsabilité environnementale, ScrewFast ne se contente pas de construire des structures ; ils construisent un avenir meilleur. À mesure que de plus en plus d'entreprises emboîtent le pas, l'impact sera profond. Une industrie de la construction plus verte signifie une planète plus saine pour tous.

View file

@ -4,15 +4,20 @@ import MainLayout from "@/layouts/MainLayout.astro";
import Btn404 from "@components/ui/buttons/Btn404.astro";
import { SITE } from "@data/constants";
const pageTitle: string = `Page Not Found | ${SITE.title}`;
// Define variables for page content
const pageTitle: string = Astro.currentLocale === "fr" ? `Page Non Trouvée | ${SITE.title}` : `Page Not Found | ${SITE.title}`;
const title: string = "404";
const subTitle: string = "Oops, this isn't the tool you were looking for!";
const content: string =
"Don't let this hiccup slow you down. Let's get you back to building your masterpiece.";
const btnTitle: string = "Go Back";
const {
subTitle = Astro.currentLocale === "fr" ? "Oops, ce n'est pas l'outil que vous recherchiez!" : "Oops, this isn't the tool you were looking for!", content = Astro.currentLocale === "fr" ? "Ne laissez pas ce contretemps vous ralentir. Revenons à la construction de votre chef-d'œuvre." : "Don't let this hiccup slow you down. Let's get you back to building your masterpiece.", btnTitle = Astro.currentLocale === "fr" ? "Retournez" : "Go Back",
} = Astro.props;
interface Props {
subTitle?: string;
content?: string;
btnTitle?: string;
}
---
<MainLayout

View file

@ -115,7 +115,7 @@ const pageTitle: string = `${post.data.title} | ${SITE.title}`;
class="flex flex-wrap gap-x-2 gap-y-1 sm:flex-nowrap sm:items-center sm:gap-y-0"
>
{
post.data.tags?.map((tag: string, index) => (
post.data.tags?.map((tag: string) => (
<span class="inline-flex items-center gap-x-1.5 rounded-lg bg-neutral-400/30 px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:outline-none focus-visible:ring dark:bg-neutral-700/60 dark:text-neutral-300">
{capitalize(tag)}
</span>

View file

@ -14,13 +14,16 @@ const englishBlogEntries = await getCollection("blog", ({ id }) => {
return id.startsWith("en/");
});
const englishInsightsEntries = await getCollection("insights", ({ id }) => {
return id.startsWith("en/");
});
const blogPosts: CollectionEntry<"blog">[] = englishBlogEntries.sort(
(a: CollectionEntry<"blog">, b: CollectionEntry<"blog">) =>
b.data.pubDate.valueOf() - a.data.pubDate.valueOf()
);
// Get all insights posts
const insightPosts: CollectionEntry<"insights">[] =
await getCollection("insights");
const insightPosts: CollectionEntry<"insights">[] = englishInsightsEntries;
// Separate the most recent post from others
const mostRecentPost: CollectionEntry<"blog"> = blogPosts[0];

View file

@ -1,45 +0,0 @@
---
// Import section components
import MainLayout from "@/layouts/MainLayout.astro";
import Btn404 from "@components/ui/buttons/Btn404.astro";
// Define variables for page content
const title: string = "404";
const subTitle: string = "Oops, ce n'est pas l'outil que vous recherchiez !";
const content: string =
"Ne laissez pas ce contretemps vous ralentir. Revenons à la construction de votre chef-d'œuvre.";
const btnTitle: string = "Retournez";
---
<MainLayout title="Page Non Trouvée | ScrewFast" lang="fr">
<section class="grid h-svh place-content-center">
<div class="mx-auto max-w-screen-xl px-4 py-8 lg:px-6 lg:py-16">
<div class="mx-auto max-w-screen-sm text-center">
<h1
class="text-dark mb-4 text-7xl font-extrabold text-yellow-500 dark:text-yellow-400 lg:text-9xl"
>
{title}
</h1>
<p
class="mb-4 text-balance text-3xl font-bold tracking-tight text-neutral-700 dark:text-neutral-300 md:text-4xl"
>
{subTitle}
</p>
<p
class="mb-4 text-pretty text-lg text-neutral-600 dark:text-neutral-400"
>
{content}
</p>
<!--Display a button that navigates user back to the previous page-->
<Btn404 title={btnTitle} id="go-back" />
</div>
</div>
</section>
</MainLayout>
<!--JavaScript code that adds click event to the Button, resulting in going back to the previous page in history-->
<script>
document.getElementById("go-back")?.addEventListener("click", () => {
history.back();
});
</script>

View file

@ -14,13 +14,16 @@ const frenchBlogEntries = await getCollection("blog", ({ id }) => {
return id.startsWith("fr/");
});
const frenchInsightsEntries = await getCollection("insights", ({ id }) => {
return id.startsWith("fr/");
});
const blogPosts: CollectionEntry<"blog">[] = frenchBlogEntries.sort(
(a: CollectionEntry<"blog">, b: CollectionEntry<"blog">) =>
b.data.pubDate.valueOf() - a.data.pubDate.valueOf(),
);
// Get all insights posts
const insightPosts: CollectionEntry<"insights">[] =
await getCollection("insights");
const insightPosts: CollectionEntry<"insights">[] = frenchInsightsEntries;
// Separate the most recent post from others
const mostRecentPost: CollectionEntry<"blog"> = blogPosts[0];
@ -30,7 +33,7 @@ const otherPosts: CollectionEntry<"blog">[] = blogPosts.slice(1);
const title: string = "Votre Passerelle vers l'Excellence en Construction";
const subTitle: string =
"Explorez les dernières actualités, astuces et analyses de ScrewFast pour améliorer vos projets de construction. Des mises en avant de produits aux stratégies de gestion de projet, notre blog est votre ressource incontournable pour tout ce qui concerne les outils et la construction.";
const secondTitle: string = "Insights";
const secondTitle: string = "Perspectives";
const secondSubTitle: string =
"Restez à jour avec les dernières tendances et évolutions de l'industrie de la construction grâce aux analyses de l'équipe d'experts de ScrewFast.";

View file

@ -0,0 +1,263 @@
---
// Import section components
import { SITE } from "@data/constants";
import MainLayout from "@/layouts/MainLayout.astro";
import { Image } from "astro:assets";
import { getCollection } from "astro:content";
// Use `getStaticPaths` to generate static routes for generated pages on build
export async function getStaticPaths() {
const insightPosts = await getCollection("insights");
return insightPosts.map((post) => ({
params: { slug: post.slug },
props: { post },
}));
}
// Get the props for this page that define a specific insight post
const { post } = Astro.props;
const { Content } = await post.render();
const pageTitle: string = `${post.data.title} | ${SITE.title}`;
---
<MainLayout title={pageTitle}>
<section class="py-6 sm:py-8 lg:py-12">
<div class="mx-auto max-w-screen-xl px-4 md:px-8">
<div class="grid gap-8 md:grid-cols-2 lg:gap-12">
<div>
<div class="h-64 overflow-hidden rounded-lg shadow-lg md:h-auto">
<Image
class="h-full w-full object-cover object-center"
src={post.data.cardImage}
alt={post.data.cardImageAlt}
draggable={"false"}
format={"avif"}
/>
</div>
<div
id="progress-mobile"
class="fixed left-0 top-0 h-2 w-full bg-gradient-to-r from-orange-400/30 to-orange-400 md:hidden"
>
</div>
<div id="pin" class="mt-10 hidden space-y-4 md:block">
<div
class="h-px w-full overflow-hidden bg-neutral-300 dark:bg-neutral-700"
>
<div
id="progress"
class="h-px w-full bg-gradient-to-r from-orange-400/30 to-orange-400"
>
</div>
</div>
<p class="text-pretty text-sm font-light text-neutral-500">
Table of Contents:
</p>
<div id="toc" class="">
<ul
class="space-y-2 text-pretty text-base text-neutral-700 transition duration-300 dark:text-neutral-400"
>
</ul>
</div>
</div>
</div>
<div class="md:pt-8">
<h1
class="mb-4 text-balance text-center text-2xl font-bold text-neutral-800 dark:text-neutral-200 sm:text-3xl md:mb-6 md:text-left"
>
{post.data.title}
</h1>
<article
class="text-pretty text-lg text-neutral-700 dark:text-neutral-300"
>
<Content />
</article>
</div>
</div>
</div>
</section>
</MainLayout>
<style is:global>
:root {
--transition-cubic: cubic-bezier(0.165, 0.84, 0.44, 1);
}
html {
scroll-behavior: smooth;
}
article h2,
article h3,
article h4,
article h5,
article h6 {
font-weight: bold;
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;
}
#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;
transition:
height 400ms var(--transition-cubic),
width 400ms var(--transition-cubic);
}
#toc li.selected svg {
width: 1.25rem;
height: 1.25rem;
margin-right: 0.3rem;
}
</style>
<script>
const onScroll = (): void => {
const article = document.querySelector("article");
if (!article) return;
const articleHeight = article.offsetHeight;
const articleOffsetTop = article.offsetTop;
const scrollTop = window.scrollY || document.documentElement.scrollTop;
if (articleHeight && articleOffsetTop && scrollTop) {
const progress =
((scrollTop - articleOffsetTop) /
(articleHeight - window.innerHeight)) *
100;
const progressBar = document.getElementById("progress");
const progressBarMobile = document.getElementById("progress-mobile");
if (progressBar && progressBarMobile) {
progressBar.style.width = `${progress}%`;
progressBarMobile.style.width = `${progress}%`;
}
}
};
document.addEventListener("DOMContentLoaded", (event) => {
window.onscroll = onScroll;
// Set initial width of progress bar
const progressBar = document.getElementById("progress");
const progressBarMobile = document.getElementById("progress-mobile");
if (progressBar && progressBarMobile) {
progressBar.style.width = "0%";
progressBarMobile.style.width = "0%";
}
});
</script>
<script>
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger);
gsap.timeline({
scrollTrigger: {
scrub: 1,
pin: true,
trigger: "#pin",
start: "top 20%",
endTrigger: "footer",
end: "top bottom",
},
});
const SVG_HTML_STRING =
'<svg class="w-0 h-0 flex-none" 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>';
function setActiveLinkById(id: string | null) {
const listItems = document.querySelectorAll("#toc li");
listItems.forEach((item) => item.classList.remove("selected"));
if (!id) return;
const activeLink = document.querySelector(`#toc a[href="#${id}"]`);
if (!activeLink) return;
const listItem = activeLink.parentElement;
listItem?.classList.add("selected");
}
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");
const headings: NodeListOf<HTMLElement> | [] = article
? article.querySelectorAll("h1, h2, h3, h4, h5, h6")
: [];
headings.forEach((heading, i) => {
if (heading instanceof HTMLElement) {
const listItem = document.createElement("li");
listItem.className = "toc-level-" + heading.tagName.toLowerCase();
const tempDiv = document.createElement("div");
tempDiv.innerHTML = SVG_HTML_STRING;
const svg = tempDiv.firstChild;
listItem.appendChild(svg as Node);
const link = document.createElement("a");
link.href = "#" + heading.id;
link.textContent = heading.textContent;
listItem.appendChild(link);
tocList?.appendChild(listItem);
gsap.timeline({
scrollTrigger: {
trigger: heading,
start: "top 20%",
end: () =>
`bottom top+=${i === headings.length - 1 ? 0 : (headings[i + 1] as HTMLElement).getBoundingClientRect().height}`,
onEnter: () => setActiveLinkById(heading.id),
onLeaveBack: () =>
setActiveLinkById((headings[i - 1] as HTMLElement)?.id),
},
});
}
});
});
</script>