Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: content table #33

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/components/AboutMe.astro
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Text from "@/components/Text";
---

<section class="bg-background text-foreground" aria-label="About Ave Aristov">
<Text variant="heading" className="mb-6">
<Text variant="heading" className="mb-6" id="about-ave-aristov">
Meet <span class="neon-pulse-slow-text text-neon-pink">Ave Aristov</span>,
Navigating the Cyberspace
</Text>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Cyberware/Cyberware.astro
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import TechnologyLinks from "./TechnologyLinks";
---

<section class="flex flex-col gap-4" aria-label="Cyberware Loadout">
<Text variant="subheading">Cyberware Loadout</Text>
<Text variant="subheading" id="cyberware-loadout">Cyberware Loadout</Text>
<Text variant="body">
Dive into the eclectic array of cybernetic tools that fuel their odyssey
through the algorithmic maze of the digital underworld
Expand Down
11 changes: 9 additions & 2 deletions src/components/Experince/Experince.astro
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
import Text from "@/components/Text";
import { slugify } from "@/lib/utils";

const jobExperiences = [
{
Expand Down Expand Up @@ -27,7 +28,11 @@ const jobExperiences = [
];
---

<section class="flex flex-col gap-4" aria-label="Job Experience">
<section
class="flex flex-col gap-4"
aria-label="Job Experience"
id="job-experience"
>
<Text variant="subheading">Job Experience</Text>
<div class="relative pl-4">
<div
Expand All @@ -38,7 +43,9 @@ const jobExperiences = [
{
jobExperiences.map((job) => (
<div>
<Text variant="title">{job.title}</Text>
<Text variant="title" id={slugify(job.title)}>
{job.title}
</Text>
<Text variant="small" className="text-neon-pink">
{job.period}
</Text>
Expand Down
11 changes: 10 additions & 1 deletion src/components/Main.astro
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
import { cn } from "@/lib/utils";
import type { TransitionAnimationPair } from "astro";
import TableOfContents from "./TableOfContents";

const { class: additionalClasses } = Astro.props;

Expand Down Expand Up @@ -30,12 +31,20 @@ const viewTransition = {
id="main-content"
class={cn(
"container mx-auto px-4 py-4 sm:px-6 sm:py-6 md:px-8 md:py-8",
"flex flex-col lg:flex-row gap-8",
additionalClasses
)}
transition:animate={viewTransition}
transition:name="main"
>
<slot />
<div class="flex-grow">
<slot />
</div>
<aside
class="shrink-0 bg-card text-card-foreground rounded-lg shadow-md lg:w-64 lg:sticky lg:top-4 lg:self-start lg:max-h-[calc(100vh-2rem)] lg:overflow-y-auto hidden sm:block"
>
<TableOfContents client:load />
</aside>
</main>

<style>
Expand Down
4 changes: 3 additions & 1 deletion src/components/Portifillo/Contact.astro
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import { Button } from "../ui/button";
class="flex flex-col gap-4 text-foreground rounded-md text-pretty"
aria-label="Track Beyond the Blackwall"
>
<Text variant="subheading">Track Beyond the Blackwall</Text>
<Text variant="subheading" id="track-beyond-the-blackwall"
>Track Beyond the Blackwall</Text
>
<Text variant="body">
Penetrate the Blackwall and trace their digital signal through the enigmatic
void deep within cyberspace. Beyond the Blackwall, uncover the encrypted
Expand Down
4 changes: 3 additions & 1 deletion src/components/Portifillo/Profile.astro
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import Text from "@/components/Text";
---

<section aria-label="Profile">
<Text variant="heading">Netrunner Profile: Ave Aristov</Text>
<Text variant="heading" id="net-runner-profile"
>Netrunner Profile: Ave Aristov</Text
>
<Text variant="body">
Full Stack Developer with a Computer Science degree and a neural interface
optimized for cutting-edge web technologies. Proficient in modern web
Expand Down
6 changes: 5 additions & 1 deletion src/components/Portifillo/Project.astro
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Text from "@/components/Text";
import { Image } from "astro:assets";
import khmerBlog from "src/assets/pictures/khmerblog.png";
import { ExternalLink } from "lucide-react";
import { slugify } from "@/lib/utils";

interface VideoMedia {
type: "video";
Expand Down Expand Up @@ -58,7 +59,9 @@ const projects: Project[] = [
class="text-foreground grow h-full rounded-md"
aria-label="Open Source Chronicles"
>
<Text variant="subheading" className="mb-6">Open Source Chronicles</Text>
<Text variant="subheading" className="mb-6" id="open-source-chronicles"
>Open Source Chronicles</Text
>
<div class="space-y-6 text-pretty">
<Text variant="paragraph">
Jack into their open-source contributions, each project a chapter in the
Expand Down Expand Up @@ -89,6 +92,7 @@ const projects: Project[] = [
<Text
variant="title"
className="text-neon-pink scroll-m-20 text-xl font-semibold tracking-tight flex flex-row items-center gap-2"
id={slugify(project.title)}
>
<ExternalLink />
<a
Expand Down
72 changes: 72 additions & 0 deletions src/components/TableOfContents.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import type React from "react";
import { useState, useEffect } from "react";

interface TOCItem {
id: string;
text: string;
level: number;
}

const TableOfContents: React.FC = () => {
const [toc, setToc] = useState<TOCItem[]>([]);

useEffect(() => {
const generateTOC = () => {
const headings = document.querySelectorAll("h1, h2, h3, h4, h5, h6");
const tocItems: TOCItem[] = Array.from(headings)
.filter((heading) => heading.textContent !== "Table of Contents")
.map((heading) => ({
id: heading.id,
text: heading.textContent || "",
level: Number.parseInt(heading.tagName.charAt(1)),
}));
setToc(tocItems);
};

generateTOC();

// Optional: Re-generate TOC when content changes
const observer = new MutationObserver(generateTOC);
observer.observe(document.body, { childList: true, subtree: true });

return () => observer.disconnect();
}, []);

const handleClick = (e: React.MouseEvent<HTMLAnchorElement>, id: string) => {
e.preventDefault();
const targetElement = document.getElementById(id);
if (targetElement) {
targetElement.scrollIntoView({ behavior: "smooth" });
}
};

return (
<nav>
<h2 className="text-xl font-semibold mb-4">Table of Contents</h2>
<ul className="space-y-2">
{toc.map((item) => (
<li
key={item.id}
style={{ marginLeft: `${(item.level - 1) * 1}rem` }}
className={`
${item.level === 1 ? "font-bold" : ""}
${item.level === 2 ? "font-semibold" : ""}
${item.level > 2 ? "text-sm" : ""}
`}
>
<a
href={`#${item.id}`}
onClick={(e) => handleClick(e, item.id)}
className="hover:text-neon-pink transition-colors duration-200"
>
{item.text}
</a>
</li>
))}
</ul>
</nav>
);
};

export default TableOfContents;

3 changes: 2 additions & 1 deletion src/layouts/Layout.astro
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import Navbar from "@/components/Navbar.astro";
import "@/styles/globals.css";
import { ViewTransitions } from "astro:transitions";

import TableOfContents from "@/components/TableOfContents";

interface Props {
title: string;
description?: string;
Expand Down Expand Up @@ -99,7 +101,6 @@ const jsonLd = {
</header>

<slot />

<Footer />
</body>
</html>
16 changes: 13 additions & 3 deletions src/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
import { type ClassValue, clsx } from "clsx"
import { twMerge } from "tailwind-merge"
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";

export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
return twMerge(clsx(inputs));
}

export function slugify(text: string): string {
return text
.toLowerCase()
.trim()
.replace(/[^\w\s-]/g, "") // Remove non-word chars (except spaces and dashes)
.replace(/[\s_-]+/g, "-") // Replace spaces, underscores and dashes with a single dash
.replace(/^-+|-+$/g, ""); // Remove leading/trailing dashes
}

2 changes: 1 addition & 1 deletion tailwind.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default {
center: true,
padding: "2rem",
screens: {
"2xl": "1024px",
"2xl": "1280px",
},
},
extend: {
Expand Down
Loading