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"; ---
-
-
- +
+ +
+
-
-
+
+

Projects

+
-
+
@@ -36,6 +51,7 @@ import PageLayout from "@/layouts/PageLayout.astro";