update in progress

This commit is contained in:
liyunze 2025-08-02 18:14:51 +10:00
parent e56069d934
commit 6084e5c31a
7 changed files with 191 additions and 247 deletions

View file

@ -1,13 +1,15 @@
--- ---
interface Props { type Props = {
href?: string;
primaryColor: string; primaryColor: string;
bgColor?: string; bgColor?: string;
scaleOnHover?: boolean; scaleOnHover?: boolean;
pixelHeight?: string; pixelHeight?: string;
className?: string; className?: string;
} };
const { const {
href,
primaryColor, primaryColor,
bgColor = "#282828", bgColor = "#282828",
scaleOnHover = false, scaleOnHover = false,
@ -16,11 +18,34 @@ const {
} = Astro.props; } = Astro.props;
--- ---
<div class="card z-10" class:list={[{ scale: scaleOnHover }, className]}> <>
<div class="card-content"> {
<slot /> href && (
</div> <a href={href}>
</div> <div
class="card z-10"
class:list={[{ scale: scaleOnHover }, className]}
>
<div class="card-content">
<slot />
</div>
</div>
</a>
)
}
{
!href && (
<div
class="card z-10"
class:list={[{ scale: scaleOnHover }, className]}
>
<div class="card-content">
<slot />
</div>
</div>
)
}
</>
<style define:vars={{ primaryColor, bgColor, pixelHeight }}> <style define:vars={{ primaryColor, bgColor, pixelHeight }}>
* { * {
@ -62,15 +87,10 @@ const {
opacity: 0; opacity: 0;
} }
.card:after { /* .card:hover:after {
top: 65%;
opacity: 0;
}
.card:hover:after {
top: 25%; top: 25%;
opacity: 1; opacity: 1;
} } */
.card.scale { .card.scale {
transition: transform 0.5s ease; transition: transform 0.5s ease;

View file

@ -0,0 +1,67 @@
<script lang="ts">
import { onMount } from "svelte";
import Socials from "../socials/Socials.svelte";
// Roles
const typingInterval: number = 50;
function addCharacter(str1: string, str2: string) {
// str1: incomplete string, add a character after this
// str2: complete string, add a character from this
let str1Length = str1.length;
let str2Length = str2.length;
if (str1Length < str2Length) {
return str1 + str2[str1Length];
} else {
return str1;
}
}
function sleep(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
// Greeting
let date = new Date();
let hour = date.getHours();
let greeting: string = "";
if (hour >= 0 && hour < 12) {
greeting = "morning";
} else if (hour >= 12 && hour < 18) {
greeting = "afternoon";
} else if (hour >= 18) {
greeting = "evening";
}
let greetingState: string = $state("");
let greetingPulse: HTMLElement;
async function animateGreeting(greeting: string) {
for (let i = 0; i < greeting.length; i++) {
greetingState = addCharacter(greetingState, greeting);
if (i === greeting.length - 1) {
greetingPulse.classList.remove("animate-pulse");
greetingPulse.classList.add("hidden");
}
await sleep(typingInterval);
}
}
// after window finish loading, call animateRoles()
onMount(async () => {
animateGreeting(greeting);
});
</script>
<span>
Good {greetingState}<span
bind:this={greetingPulse}
class="animate-pulse font-extralight">|</span
></span
>

View file

@ -0,0 +1,77 @@
---
import Card from "../global/Card.astro";
import Socials from "../socials/Socials.svelte";
import Greeting from "./Greeting.svelte";
---
<div class="w-[90%] md:w-[600px] lg:w-1/2 xl:w-1/2">
<Card bgColor="#252525" primaryColor="#BEADFA" className="animate-fadeIn">
<div id="intro" class="flex h-fit flex-col text-white">
<div class="w-full px-5 pt-10 pb-2 lg:px-10">
<div class="flex h-20 flex-row">
<div class="mr-1 flex w-20 items-center justify-center">
<img
src="/images/pfp_new.webp"
alt="Ryan"
width="80"
height="80"
class="max-w-full rounded-full bg-[#505050]"
/>
</div>
<div class="ml-2 flex flex-col items-start justify-center">
<div
id="name"
class="animate-gradient text-2xl font-bold"
>
RythonDev
</div>
<div class="w-full text-xl">Full Stack Developer</div>
</div>
</div>
<div id="uwu" class="hidden items-center justify-center">
<img
src="/images/RythonDev-UwU-compressed.webp"
alt="RythonDev"
width="400"
height="131.8"
/>
</div>
<div class="mt-5 mb-5 text-2xl font-bold">
<Greeting client:load />, <br class="sm:hidden" />I'm Ryan!
</div>
<p class="text-left">
Born and raised in Malaysia, I'm currently pursuing a
Bachelor's in Computer Science in Australia.
</p>
<br />
<p class="text-left">
My work has connected me with Twitch streamers and content
creators, and I'm driven by interests in web development,
computer vision, and data science.
</p>
<div class="mt-8 flex flex-row items-center justify-center">
<Socials />
</div>
</div>
</div>
</Card>
</div>
<style>
#name {
background: linear-gradient(
90deg,
#16ff00 0%,
#72ffff 45%,
#0096ff 100%
);
background-size: 300%;
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
</style>

View file

@ -1,183 +0,0 @@
<script lang="ts">
import { onMount } from "svelte";
import Socials from "../socials/Socials.svelte";
// Roles
let roles = $state(["Developer", "Streamer", "Content creator", "Student"]);
let roleState: string = $state("");
let role: string;
let counter: number = $state(0);
let roleEmpty: boolean = true;
const roleInterval: number = 50;
const roleUpdateDelay: number = 2000; // delay after updating
const roleRemoveDelay: number = 500; // delay after removing
// Intro animation
function removeLastCharacter(str: string) {
return str.slice(0, -1);
}
function addCharacter(str1: string, str2: string) {
// str1: incomplete string, add a character after this
// str2: complete string, add a character from this
let str1Length = str1.length;
let str2Length = str2.length;
if (str1Length < str2Length) {
return str1 + str2[str1Length];
} else {
return str1;
}
}
function sleep(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function animateRoles() {
role = roles[counter];
if (roleEmpty) {
for (let i = 0; i < role.length; i++) {
roleState = addCharacter(roleState, role);
await sleep(roleInterval);
}
await sleep(roleUpdateDelay);
roleEmpty = false;
animateRoles();
} else {
for (let i = 0; i < role.length; i++) {
roleState = removeLastCharacter(roleState);
await sleep(roleInterval);
}
await sleep(roleRemoveDelay);
if (counter < roles.length - 1) {
counter++;
} else {
counter = 0;
}
roleEmpty = true;
animateRoles();
}
}
// Greeting
let date = new Date();
let hour = date.getHours();
let greeting: string = "";
if (hour >= 0 && hour < 12) {
greeting = "morning";
} else if (hour >= 12 && hour < 18) {
greeting = "afternoon";
} else if (hour >= 18) {
greeting = "evening";
}
let greetingState: string = $state("");
let greetingPulse: HTMLElement;
async function animateGreeting(greeting: string) {
for (let i = 0; i < greeting.length; i++) {
greetingState = addCharacter(greetingState, greeting);
if (i === greeting.length - 1) {
greetingPulse.classList.remove("animate-pulse");
greetingPulse.classList.add("hidden");
}
await sleep(roleInterval);
}
}
// after window finish loading, call animateRoles()
onMount(async () => {
await sleep(800);
animateGreeting(greeting);
await animateRoles();
});
</script>
<div
id="intro"
class="flex
h-fit
flex-col text-white"
>
<div class="w-full px-5 pt-10 pb-2 lg:px-10">
<div class="flex h-20 flex-row">
<div class="mr-1 flex w-20 items-center justify-center">
<img
src="/images/pfp_new.webp"
alt="Ryan"
width="80"
height="80"
class="max-w-full rounded-full bg-[#505050]"
/>
</div>
<div class="ml-2 flex flex-col items-start justify-center">
<div id="name" class="animate-gradient text-2xl font-bold">
RythonDev
</div>
<div class="w-full text-xl">
{roleState}<span class="animate-pulse">|</span>
</div>
</div>
</div>
<div id="uwu" class="hidden items-center justify-center">
<img
src="/images/RythonDev-UwU-compressed.webp"
alt="RythonDev"
width="400"
height="131.8"
/>
</div>
<div class="mt-2 mb-5 text-2xl font-bold">
Good {greetingState}<span
bind:this={greetingPulse}
class="animate-pulse font-extralight">|</span
>, <br class="sm:hidden" />I'm Ryan!
</div>
<p class="text-left">
I was born and raised in Malaysia, currently studying my Bachelor's
in Computer Science in Australia! I speak fluent in Mandarin Chinese
and English.
<br /><br />
I'm passionate about developing open source projects that benefit others,
and I have extensive experience in leadership roles.
<br /><br />
I'm also
<b
>well-connected with various Twitch streamers and content
creators</b
>, thanks to prominent projects that have had a positive impact on
the streaming community. I'm strongly motivated in the fields of
<b> web development</b>, <b>computer vision</b> and
<b>data science</b>.
</p>
<div class="mt-5 flex flex-row items-center justify-center">
<Socials />
</div>
</div>
</div>
<style>
#name {
background: linear-gradient(
90deg,
#16ff00 0%,
#72ffff 45%,
#0096ff 100%
);
background-size: 300%;
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
</style>

View file

@ -69,12 +69,12 @@ import Skill from "./Skill.astro";
bgColor: "var(--color-python)", bgColor: "var(--color-python)",
}, },
{ {
text: "C#", text: "Typescript",
bgColor: "var(--color-csharp)", bgColor: "var(--color-typescript)",
}, },
{ {
text: "Java", text: "C#",
bgColor: "var(--color-java)", bgColor: "var(--color-csharp)",
}, },
{ {
text: "Kotlin", text: "Kotlin",
@ -84,14 +84,6 @@ import Skill from "./Skill.astro";
text: "PHP", text: "PHP",
bgColor: "var(--color-php)", bgColor: "var(--color-php)",
}, },
{
text: "Go",
bgColor: "var(--color-go)",
},
{
text: "Rust",
bgColor: "var(--color-rust)",
},
{ {
text: "PostgreSQL", text: "PostgreSQL",
bgColor: "var(--color-postgresql)", bgColor: "var(--color-postgresql)",

View file

@ -43,25 +43,3 @@
/> />
</div> </div>
</a> </a>
<a href="https://instagram.com/RythonDev" target="_blank">
<div
class="mr-3 flex h-7 w-7 items-center justify-center rounded-full bg-white transition-[filter,background-color] duration-150 hover:bg-[#1bbfa0] hover:invert"
>
<img
src="/images/socials/instagram.svg"
alt="twitch"
class="aspect-square h-4 w-4"
/>
</div>
</a>
<a href="https://ko-fi.com/rython" target="_blank">
<div
class="mr-3 flex h-7 w-7 items-center justify-center rounded-full bg-white transition-colors duration-150 hover:bg-[#FF5E5B]"
>
<img
src="/images/socials/kofi.webp"
alt="twitch"
class="aspect-square h-4 w-4 translate-x-[1px] scale-125"
/>
</div>
</a>

View file

@ -3,7 +3,7 @@ import NavBar from "../components/global/NavBar.astro";
import Layout from "../layouts/Layout.astro"; import Layout from "../layouts/Layout.astro";
import NetworkLine from "../components/global/NetworkLine.astro"; import NetworkLine from "../components/global/NetworkLine.astro";
import WhatIDo from "../components/what-i-do/WhatIDoComponent.astro"; import WhatIDo from "../components/what-i-do/WhatIDoComponent.astro";
import Intro from "../components/home/IntroComponent.svelte"; import Intro from "../components/home/Intro.astro";
import Projects from "../components/projects/ProjectsComponent.astro"; import Projects from "../components/projects/ProjectsComponent.astro";
import Experience from "../components/experience/ExperienceComponent.astro"; import Experience from "../components/experience/ExperienceComponent.astro";
import Skills from "../components/skills/SkillsComponent.astro"; import Skills from "../components/skills/SkillsComponent.astro";
@ -18,20 +18,16 @@ import Footer from "../components/global/FooterComponent.astro";
> >
<NavBar /> <NavBar />
<div id="home" class="flex items-center justify-center pt-20"> <div id="home" class="flex items-center justify-center pt-20">
<div class="w-[90%] max-w-[1080px] lg:w-1/2 xl:w-1/2"> <Intro />
<Card
bgColor="#252525"
primaryColor="#BEADFA"
className="animate-fadeIn"
>
<Intro client:load />
</Card>
</div>
</div> </div>
<NetworkLine height="70px" /> <NetworkLine height="70px" />
<div id="what-i-do"> <!-- <div id="what-i-do">
<div class="mx-auto mb-10 h-[1px] w-1/3 bg-[#404040]"></div>
<WhatIDo /> <WhatIDo />
</div> -->
<div id="education">
<div class="mx-auto mb-10 h-[1px] w-1/3 bg-[#404040]"></div>
<Experience />
</div> </div>
<div id="projects"> <div id="projects">
<div class="pt-20"> <div class="pt-20">
@ -42,10 +38,7 @@ import Footer from "../components/global/FooterComponent.astro";
<div id="skills"> <div id="skills">
<Skills /> <Skills />
</div> </div>
<div id="education" class="py-20"> <div id="contact" class="pt-20">
<Experience />
</div>
<div id="contact">
<Contact /> <Contact />
</div> </div>
<Footer /> <Footer />