From 9c2a7cb269241775c86a3e7dcc68e4f83475a9a8 Mon Sep 17 00:00:00 2001
From: liyunze <50455574+liyunze-coding@users.noreply.github.com>
Date: Mon, 1 Dec 2025 14:48:03 +0800
Subject: [PATCH] fixed gradient animation
---
bun.lock | 31 +++
package.json | 1 +
.../experience/ExperienceComponent.astro | 13 +-
.../experience/ExperienceComponent.tsx | 242 ++++++++++++++++++
.../experience/MoreExperience.astro | 35 ---
src/components/global/Card.astro | 1 -
src/components/global/NavBar.astro | 10 +-
src/components/projects/MoreProjects.astro | 31 +--
src/components/projects/Project.astro | 10 +-
.../projects/ProjectsComponent.astro | 67 +----
src/components/projects/VideoProject.svelte | 10 +-
src/components/skills/Skill.astro | 14 +-
src/components/skills/SkillsComponent.astro | 137 ++--------
src/components/ui/NavigationBar.tsx | 57 +----
src/components/ui/moving-border.tsx | 141 ++++++++++
src/components/ui/tabs.tsx | 66 +++++
src/pages/experience.astro | 18 --
src/pages/index.astro | 30 ++-
src/styles/global.css | 23 +-
19 files changed, 559 insertions(+), 378 deletions(-)
create mode 100644 src/components/experience/ExperienceComponent.tsx
delete mode 100644 src/components/experience/MoreExperience.astro
create mode 100644 src/components/ui/moving-border.tsx
create mode 100644 src/components/ui/tabs.tsx
delete mode 100644 src/pages/experience.astro
diff --git a/bun.lock b/bun.lock
index 2ac9715..73e6146 100644
--- a/bun.lock
+++ b/bun.lock
@@ -7,6 +7,7 @@
"@astrojs/mdx": "^4.3.0",
"@astrojs/react": "^4.3.0",
"@astrojs/svelte": "^7.1.0",
+ "@radix-ui/react-tabs": "^1.1.13",
"@tailwindcss/vite": "^4.1.8",
"@types/react": "^19.1.9",
"@types/react-dom": "^19.1.7",
@@ -197,6 +198,36 @@
"@oslojs/encoding": ["@oslojs/encoding@1.1.0", "", {}, "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ=="],
+ "@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="],
+
+ "@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw=="],
+
+ "@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg=="],
+
+ "@radix-ui/react-context": ["@radix-ui/react-context@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA=="],
+
+ "@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw=="],
+
+ "@radix-ui/react-id": ["@radix-ui/react-id@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg=="],
+
+ "@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.5", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ=="],
+
+ "@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
+
+ "@radix-ui/react-roving-focus": ["@radix-ui/react-roving-focus@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA=="],
+
+ "@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
+
+ "@radix-ui/react-tabs": ["@radix-ui/react-tabs@1.1.13", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A=="],
+
+ "@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg=="],
+
+ "@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.2.2", "", { "dependencies": { "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg=="],
+
+ "@radix-ui/react-use-effect-event": ["@radix-ui/react-use-effect-event@0.0.2", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA=="],
+
+ "@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="],
+
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.27", "", {}, "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA=="],
"@rollup/pluginutils": ["@rollup/pluginutils@5.2.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw=="],
diff --git a/package.json b/package.json
index 4f36a09..bf6b7de 100644
--- a/package.json
+++ b/package.json
@@ -13,6 +13,7 @@
"@astrojs/mdx": "^4.3.0",
"@astrojs/react": "^4.3.0",
"@astrojs/svelte": "^7.1.0",
+ "@radix-ui/react-tabs": "^1.1.13",
"@tailwindcss/vite": "^4.1.8",
"@types/react": "^19.1.9",
"@types/react-dom": "^19.1.7",
diff --git a/src/components/experience/ExperienceComponent.astro b/src/components/experience/ExperienceComponent.astro
index 876cacb..c31d66d 100644
--- a/src/components/experience/ExperienceComponent.astro
+++ b/src/components/experience/ExperienceComponent.astro
@@ -16,10 +16,9 @@ import Line from "../global/NetworkLine.astro";
- Led implementation of frontend development, while also
- developing and intergating a CMS on the backend for
- website development. Actively contributing to LLM
- product research and development.
+ Led development of Astro websites with Payload CMS
+ backend implementation, manage Github Actions CI/CD and
+ deployments.
Relevant skills:
- Awarded a 50% Vice-Chancellor Scholarship to study
- Bachelor's in Computer Science.
+ Awarded 50% Vice-Chancellor Scholarship to study
+ Bachelor's in Computer Science. Active committee member
+ in cybersecurity association and software engineering
+ club.
Relevant skills:
+
+ Experience
+ Education
+
+ Extracurricular
+
+
+
+ {ExperienceTabContent()}
+
+
+ {EducationTabContent()}
+
+
+ {ExtracurricularTabContent()}
+
+
+ );
+}
+
+function ExperienceTabContent() {
+ return (
+ <>
+ {Position({
+ title: "Lead Full Stack Developer",
+ institution: "Hyson Horizon",
+ dateRange: "Dec 2024 - Now",
+ country: "Malaysia",
+ summary:
+ "Led development of clients' Astro websites with Payload CMS backend implementation, managed Github Actions CI/CD and deployments.",
+ className: "pb-5",
+ })}
+ {Position({
+ title: "Frontend Web Developer Intern",
+ institution: "Studio20",
+ dateRange: "Jan 2024 - Apr 2024",
+ country: "Malaysia",
+ summary:
+ "Developed WordPress sites and NextJS apps for clients. Used lazy-loading to optimise page load speeds. Ensured CMS allowed easy yet flexible customisations for clients.",
+ })}
+ >
+ );
+}
+
+function EducationTabContent() {
+ return (
+ <>
+ {Position({
+ title: "Bachelors of Computer Science",
+ dateRange: "June 2024 - Now",
+ country: "Australia",
+ summary: `Awarded 50% Vice-Chancellor Scholarship to study
+ Bachelor's in Computer Science, minoring in Full Stack Development. Active committee member in cybersecurity association and software engineering club.`,
+ className: "pb-5",
+ })}
+ {Position({
+ title: "Diploma in Computer Science",
+ dateRange: "Jan 2022 - Apr 2024",
+ country: "Malaysia",
+ summary: `Focused in Data Science, took on role as President of Computer Programming Club and Vice President of Diploma Student Union.`,
+ })}
+ >
+ );
+}
+
+function ExtracurricularTabContent() {
+ return (
+ <>
+ {Position({
+ title: "University Cybersecurity Association, Development Committee",
+ dateRange: "Nov 2025 - Now",
+ country: "Australia",
+ summary: `Leading frontend development club's revamped website using Astro framework with Svelte components.`,
+ className: "pb-5",
+ })}
+ {Position({
+ title: "University Software Engineering Club Committee",
+ dateRange: "Sep 2025 - Now",
+ country: "Australia",
+ summary: `Leading and contributing to various club projects:`,
+ className: "pb-5",
+ highlights: [
+ `Rust Discord Bot, includes club membership verification feature using Supabase.`,
+ `Python web scraping AI project, using BeautifulSoup4 and Gemini API.`,
+ ],
+ })}
+ {Position({
+ title: "Malaysian Association, Marketing Officer",
+ dateRange: "Mar 2025 - Oct 2025",
+ country: "Australia",
+ summary: `Contributed to marketing strategy through video ideation, execution (including on-screen presence and filming), and video editing.`,
+ })}
+ >
+ );
+}
+
+// ICONS AND SUBCOMPONENTS
+
+function LocationIcon() {
+ return (
+
+
+
+
+ );
+}
+
+function CalendarIcon() {
+ return (
+
+
+
+ );
+}
+
+function BriefCaseIcon() {
+ return (
+
+
+
+ );
+}
+
+const lineMoveCSS = `
+ @keyframes line-move {
+ 0% { background-position: 0% 50%; }
+ 100% { background-position: 0% -100%; }
+ }
+ .animate-line-move {
+ animation: line-move 2s linear infinite;
+ background-size: 100% 200%;
+ }
+`;
+
+function Position({
+ title,
+ institution,
+ dateRange,
+ country,
+ summary,
+ className = "",
+ highlights = [],
+}: {
+ title: string;
+ institution?: string;
+ dateRange: string;
+ country: string;
+ summary: string;
+ className?: string;
+ highlights?: Array
;
+}) {
+ return (
+ <>
+
+
+
+
+
{title}
+
+
+ {CalendarIcon()} {dateRange}
+
+
+ {institution && (
+
+ {BriefCaseIcon()} {institution}
+
+ )}
+
+
+ {LocationIcon()} {country}
+
+
+
+
{summary}
+
+ {highlights.map((highlight) => (
+ {highlight}
+ ))}
+
+
+
+ >
+ );
+}
diff --git a/src/components/experience/MoreExperience.astro b/src/components/experience/MoreExperience.astro
deleted file mode 100644
index f650f6f..0000000
--- a/src/components/experience/MoreExperience.astro
+++ /dev/null
@@ -1,35 +0,0 @@
----
-import Card from "../global/Card.astro";
-import Line from "../global/NetworkLine.astro";
----
-
-
-
-
-
-
-
-
-
- Diploma in Computer Science student
-
-
- @ Methodist College Kuala Lumpur
-
- Jan 2022 - June 2024
-
-
-
Achievements
-
-
- 4-time Dean's List Award recipient (>3.5 GPA)
-
- 3.8 CGPA
- President of Computer Programming Club
- Vice President of Diploma Union
-
-
-
-
-
-
diff --git a/src/components/global/Card.astro b/src/components/global/Card.astro
index 039b4bc..ea126e1 100644
--- a/src/components/global/Card.astro
+++ b/src/components/global/Card.astro
@@ -11,7 +11,6 @@ type Props = {
const {
href,
- primaryColor,
shadowColor = "rgb(12,12,12)",
bgColor = "var(--color-secondary)",
scaleOnHover = false,
diff --git a/src/components/global/NavBar.astro b/src/components/global/NavBar.astro
index c1965af..437c7e9 100644
--- a/src/components/global/NavBar.astro
+++ b/src/components/global/NavBar.astro
@@ -4,23 +4,23 @@ import { HoverNavigation } from "@/components/ui/NavigationBar";
const navLinks = [
{
label: "Home",
- link: "/",
+ link: "/#home",
},
{
label: "Experience",
- link: "/experience",
+ link: "/#experience",
},
{
label: "Projects",
- link: "/projects",
+ link: "/#projects",
},
{
label: "Skills",
- link: "/skills",
+ link: "/#skills",
},
{
label: "Contact",
- link: "/contact",
+ link: "/#contact",
},
];
---
diff --git a/src/components/projects/MoreProjects.astro b/src/components/projects/MoreProjects.astro
index 7f9b6c7..1950255 100644
--- a/src/components/projects/MoreProjects.astro
+++ b/src/components/projects/MoreProjects.astro
@@ -18,23 +18,7 @@ import TwitchPlays from "../images/projects/twitchplays.webp";
chess engine to determine the best moves. Then uses
PyAutoGUI to play the moves on the browser.
`}
- tags={[
- {
- text: "Python",
- textColor: "white",
- bgColor: "var(--color-python)",
- },
- {
- text: "OpenCV",
- textColor: "white",
- bgColor: "var(--color-opencv)",
- },
- {
- text: "PyAutoGUI",
- textColor: "white",
- bgColor: "black",
- },
- ]}
+ tags={["Python", "OpenCV", "PyAutoGUI"]}
client:visible
/>
diff --git a/src/components/projects/Project.astro b/src/components/projects/Project.astro
index fb70b0d..75e3a0a 100644
--- a/src/components/projects/Project.astro
+++ b/src/components/projects/Project.astro
@@ -1,12 +1,6 @@
---
import { Image } from "astro:assets";
-interface Tag {
- text: string;
- textColor: string;
- bgColor: string;
-}
-
interface Props {
position?: "left" | "right";
image?: ImageMetadata;
@@ -15,7 +9,7 @@ interface Props {
title: string;
description: string;
label?: string;
- tags?: Tag[];
+ tags?: Array;
}
const {
@@ -117,7 +111,7 @@ const leftProject = position == "left";
- {tag.text}
+ {tag}
))
}
diff --git a/src/components/projects/ProjectsComponent.astro b/src/components/projects/ProjectsComponent.astro
index f04e8f0..28f1e90 100644
--- a/src/components/projects/ProjectsComponent.astro
+++ b/src/components/projects/ProjectsComponent.astro
@@ -19,23 +19,7 @@ import Project from "./Project.astro";
title="Coworking Guide"
label="Visit Site"
description="A guide to coworking streams for streamers, covers wide range of topics from tips on how to get started with setting up stream to how to grow your audience!"
- tags={[
- {
- text: "Astro",
- bgColor: "white",
- textColor: "black",
- },
- {
- text: "TypeScript",
- bgColor: "#3178C6",
- textColor: "white",
- },
- {
- text: "Markdown",
- bgColor: "black",
- textColor: "white",
- },
- ]}
+ tags={["Astro", "Typescript", "Markdown"]}
/>
import { onMount } from "svelte";
- interface Tag {
- text: string;
- textColor: string;
- bgColor: string;
- }
-
interface Props {
position?: "left" | "right";
image_src: string;
@@ -14,7 +8,7 @@
video_src: string;
title: string;
description: string;
- tags?: Tag[];
+ tags?: Array;
}
let {
@@ -137,7 +131,7 @@
w-fit rounded-full px-3
py-1 text-white transition-colors duration-300"
>
- {tag.text}
+ {tag}
{/each}
diff --git a/src/components/skills/Skill.astro b/src/components/skills/Skill.astro
index 89b911e..96bc434 100644
--- a/src/components/skills/Skill.astro
+++ b/src/components/skills/Skill.astro
@@ -1,18 +1,10 @@
---
import Card from "../global/Card.astro";
-interface Tag {
- text: string;
- bgColor: string;
- textColor?: string;
- hoverTextColor?: string;
- className?: string;
-}
-
interface Props {
title: string;
- tags?: Tag[];
- primaryColor: string;
+ tags?: Array;
+ primaryColor?: string;
className?: string;
}
@@ -35,7 +27,7 @@ const { title, tags, primaryColor, className = "" } = Astro.props;
- {tag.text}
+ {tag}
))
}
diff --git a/src/components/skills/SkillsComponent.astro b/src/components/skills/SkillsComponent.astro
index d8a589f..97834b2 100644
--- a/src/components/skills/SkillsComponent.astro
+++ b/src/components/skills/SkillsComponent.astro
@@ -13,51 +13,16 @@ import Skill from "./Skill.astro";
title="Frontend Development"
primaryColor="#19a7ce"
tags={[
- {
- text: "HTML",
- bgColor: "var(--color-html)",
- },
- {
- text: "CSS",
- bgColor: "var(--color-blue-700)",
- },
- {
- text: "Javascript",
- bgColor: "var(--color-yellow-400)",
- textColor: "black",
- },
- {
- text: "Typescript",
- bgColor: "var(--color-typescript)",
- },
- {
- text: "Svelte",
- bgColor: "var(--color-svelte)",
- },
- {
- text: "React",
- bgColor: "var(--color-react)",
- textColor: "black",
- },
- {
- text: "Vue",
- bgColor: "var(--color-green-500)",
- textColor: "black",
- },
- {
- text: "WordPress",
- bgColor: "var(--color-wordpress)",
- },
- {
- text: "Astro",
- bgColor: "white",
- textColor: "black",
- },
- {
- text: "TailwindCSS",
- bgColor: "var(--color-tailwind)",
- textColor: "black",
- },
+ "HTML",
+ "CSS",
+ "Javascript",
+ "Typescript",
+ "Svelte",
+ "React",
+ "Vue",
+ "WordPress",
+ "Astro",
+ "TailwindCSS",
]}
/>
@@ -66,38 +31,15 @@ import Skill from "./Skill.astro";
title="Backend Development"
primaryColor="#474F7A"
tags={[
- {
- text: "Python",
- bgColor: "var(--color-python)",
- },
- {
- text: "Typescript",
- bgColor: "var(--color-typescript)",
- },
- {
- text: "C#",
- bgColor: "var(--color-csharp)",
- },
- {
- text: "Kotlin",
- bgColor: "var(--color-kotlin)",
- },
- {
- text: "PHP",
- bgColor: "var(--color-php)",
- },
- {
- text: "PostgreSQL",
- bgColor: "var(--color-postgresql)",
- },
- {
- text: "MySQL",
- bgColor: "var(--color-mysql)",
- },
- {
- text: "MongoDB",
- bgColor: "var(--color-mongodb)",
- },
+ "Python",
+ "Typescript",
+ "C#",
+ "Kotlin",
+ "PHP",
+ "PostgreSQL",
+ "MySQL",
+ "MongoDB",
+ "Supabase",
]}
/>
@@ -106,39 +48,14 @@ import Skill from "./Skill.astro";
title="Data Science"
primaryColor="#a1eebd"
tags={[
- {
- text: "Python",
- bgColor: "var(--color-python)",
- },
- {
- text: "R",
- bgColor: "var(--color-cyan-500)",
- },
- {
- text: "OpenCV",
- bgColor: "var(--color-opencv)",
- },
- {
- text: "SAS",
- bgColor: "var(--color-blue-500)",
- },
- {
- text: "MySQL",
- bgColor: "var(--color-mysql)",
- },
- {
- text: "Pandas",
- bgColor: "var(--color-blue-800)",
- },
- {
- text: "Selenium",
- bgColor: "var(--color-green-700)",
- },
- {
- text: "BeautifulSoup4",
- bgColor: "white",
- textColor: "black",
- },
+ "Python",
+ "R",
+ "OpenCV",
+ "SAS",
+ "MySQL",
+ "Pandas",
+ "Selenium",
+ "BeautifulSoup4",
]}
/>
diff --git a/src/components/ui/NavigationBar.tsx b/src/components/ui/NavigationBar.tsx
index 0989e62..539117c 100644
--- a/src/components/ui/NavigationBar.tsx
+++ b/src/components/ui/NavigationBar.tsx
@@ -49,54 +49,9 @@ export const HoverNavigation = ({
className?: string;
}) => {
const [hoveredIndex, setHoveredIndex] = useState(null);
- const { scrollY } = useScroll();
- const [navVisible, setNavVisible] = useState(true);
- const [availableVisible, setAvailableVisible] = useState(false);
-
- const [onContactPage, setOnContactPage] = useState(false);
const [hamburgerOpen, setHamburgerOpen] = useState(false);
const { width } = useWindowDimensions();
- // if on contact page, do not do width 0%
- useEffect(() => {
- setOnContactPage(window.location.href.includes("/contact"));
- }, []);
-
- useEffect(() => {
- updateNavBarState(width);
- }, [width]);
-
- const updateNavBarState = (
- width: number,
- scrollPosition: number = 0,
- scrollUp: boolean = false,
- ) => {
- if (width && width < 1024) {
- setNavVisible(false);
- setAvailableVisible(true);
- } else if (scrollPosition < 50) {
- setNavVisible(true);
- setAvailableVisible(false);
- } else if (!onContactPage) {
- setNavVisible(scrollUp);
- setAvailableVisible(!scrollUp);
- } else {
- setNavVisible(true);
- setAvailableVisible(false);
- }
- };
-
- useMotionValueEvent(scrollY, "change", (current) => {
- // Check if current is not undefined and is a number
- if (typeof current === "number") {
- let direction = current! - scrollY.getPrevious()!;
- let scrollUp = direction <= 0;
- let scrollProgress = scrollY.get();
-
- updateNavBarState(width, scrollProgress, scrollUp);
- }
- });
-
return (
@@ -112,13 +67,7 @@ export const HoverNavigation = ({
-
+
+
+
+
+ {children}
+
+
+ );
+}
+
+export const MovingBorder = ({
+ children,
+ duration = 3000,
+ rx,
+ ry,
+ ...otherProps
+}: {
+ children: React.ReactNode;
+ duration?: number;
+ rx?: string;
+ ry?: string;
+ [key: string]: any;
+}) => {
+ // @ts-expect-error
+ const pathRef = useRef();
+ const progress = useMotionValue(0);
+
+ useAnimationFrame((time) => {
+ const length = pathRef.current?.getTotalLength();
+ if (length) {
+ const pxPerMillisecond = length / duration;
+ progress.set((time * pxPerMillisecond) % length);
+ }
+ });
+
+ const x = useTransform(
+ progress,
+ (val) => pathRef.current?.getPointAtLength(val).x,
+ );
+ const y = useTransform(
+ progress,
+ (val) => pathRef.current?.getPointAtLength(val).y,
+ );
+
+ const transform = useMotionTemplate`translateX(${x}px) translateY(${y}px) translateX(-50%) translateY(-50%)`;
+
+ return (
+ <>
+
+
+
+
+ {children}
+
+ >
+ );
+};
diff --git a/src/components/ui/tabs.tsx b/src/components/ui/tabs.tsx
new file mode 100644
index 0000000..27aa6ba
--- /dev/null
+++ b/src/components/ui/tabs.tsx
@@ -0,0 +1,66 @@
+"use client";
+
+import * as React from "react";
+import * as TabsPrimitive from "@radix-ui/react-tabs";
+
+import { cn } from "@/lib/utils";
+
+function Tabs({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ );
+}
+
+function TabsList({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ );
+}
+
+function TabsTrigger({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ );
+}
+
+function TabsContent({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ );
+}
+
+export { Tabs, TabsList, TabsTrigger, TabsContent };
diff --git a/src/pages/experience.astro b/src/pages/experience.astro
deleted file mode 100644
index 47fbf9d..0000000
--- a/src/pages/experience.astro
+++ /dev/null
@@ -1,18 +0,0 @@
----
-import ExperienceComponent from "../components/experience/ExperienceComponent.astro";
-import MoreExperience from "../components/experience/MoreExperience.astro";
-import Footer from "../components/global/FooterComponent.astro";
-import PageLayout from "@/layouts/PageLayout.astro";
----
-
-
-
-
-
-
-
-
diff --git a/src/pages/index.astro b/src/pages/index.astro
index e323c0d..2be62bc 100644
--- a/src/pages/index.astro
+++ b/src/pages/index.astro
@@ -2,11 +2,12 @@
import NetworkLine from "../components/global/NetworkLine.astro";
import Intro from "../components/home/Intro.astro";
import Projects from "../components/projects/ProjectsComponent.astro";
-import Experience from "../components/experience/ExperienceComponent.astro";
+import Experience from "../components/experience/ExperienceComponent.tsx";
import Skills from "../components/skills/SkillsComponent.astro";
import Contact from "../components/contact/ContactComponent.astro";
import Footer from "../components/global/FooterComponent.astro";
import PageLayout from "@/layouts/PageLayout.astro";
+import { Button } from "@/components/ui/moving-border";
---
-
-
-
+
+
+
+
-
-
+
-
+
@@ -36,6 +51,7 @@ import PageLayout from "@/layouts/PageLayout.astro";
+