completed up till skills section

This commit is contained in:
liyunze 2023-10-05 19:14:57 +08:00
parent b795ef4d4a
commit 804cbea614
25 changed files with 1234 additions and 206 deletions

4
.prettierrc Normal file
View file

@ -0,0 +1,4 @@
{
"plugins": ["prettier-plugin-svelte", "prettier-plugin-astro"],
"tabWidth": 4
}

View file

@ -1,6 +0,0 @@
{
"prettier.documentSelectors": ["**/*.astro"],
"[astro]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}

View file

@ -1,9 +1,13 @@
import { defineConfig } from 'astro/config'; import { defineConfig } from "astro/config";
import tailwind from "@astrojs/tailwind"; import tailwind from "@astrojs/tailwind";
import svelte from "@astrojs/svelte"; import svelte from "@astrojs/svelte";
// https://astro.build/config // https://astro.build/config
export default defineConfig({ export default defineConfig({
integrations: [tailwind(), svelte()] integrations: [tailwind(), svelte()],
server: {
port: 8008,
hostname: "RythonDev",
},
}); });

13
package-lock.json generated
View file

@ -16,7 +16,8 @@
}, },
"devDependencies": { "devDependencies": {
"prettier": "^3.0.3", "prettier": "^3.0.3",
"prettier-plugin-astro": "^0.12.0" "prettier-plugin-astro": "^0.12.0",
"prettier-plugin-svelte": "^3.0.3"
} }
}, },
"node_modules/@alloc/quick-lru": { "node_modules/@alloc/quick-lru": {
@ -4653,6 +4654,16 @@
"integrity": "sha512-o/ObKgtMzl8SlpIdzaxFnt7SATKPxu4oIP/1NL+HDJRzxfJcAkOTAb/ZKMRyULbz4q+1t2/DAebs2Z1QairkZw==", "integrity": "sha512-o/ObKgtMzl8SlpIdzaxFnt7SATKPxu4oIP/1NL+HDJRzxfJcAkOTAb/ZKMRyULbz4q+1t2/DAebs2Z1QairkZw==",
"dev": true "dev": true
}, },
"node_modules/prettier-plugin-svelte": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.0.3.tgz",
"integrity": "sha512-dLhieh4obJEK1hnZ6koxF+tMUrZbV5YGvRpf2+OADyanjya5j0z1Llo8iGwiHmFWZVG/hLEw/AJD5chXd9r3XA==",
"dev": true,
"peerDependencies": {
"prettier": "^3.0.0",
"svelte": "^3.2.0 || ^4.0.0-next.0"
}
},
"node_modules/prismjs": { "node_modules/prismjs": {
"version": "1.29.0", "version": "1.29.0",
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz",

View file

@ -18,6 +18,7 @@
}, },
"devDependencies": { "devDependencies": {
"prettier": "^3.0.3", "prettier": "^3.0.3",
"prettier-plugin-astro": "^0.12.0" "prettier-plugin-astro": "^0.12.0",
"prettier-plugin-svelte": "^3.0.3"
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 654 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 574 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

View file

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="31.665px" height="31.665px" viewBox="0 0 31.665 31.665" fill="#000" style="enable-background:new 0 0 31.665 31.665;"
xml:space="preserve">
<g>
<path d="M16.878,0.415c-0.854-0.565-1.968-0.552-2.809,0.034L1.485,9.214c-0.671,0.468-1.071,1.233-1.071,2.052v9.444
c0,0.84,0.421,1.623,1.122,2.086l12.79,8.455c0.836,0.553,1.922,0.553,2.758,0l13.044-8.618c0.7-0.463,1.122-1.246,1.122-2.086
v-9.279c0-0.839-0.421-1.622-1.121-2.085L16.878,0.415z M26.621,10.645l-4.821,3.237l-4.521-3.288L17.25,4.127L26.621,10.645z
M13.979,4.133v6.329l-4.633,3.24l-4.621-3.099L13.979,4.133z M3.458,13.722l2.991,2.004l-2.991,2.093V13.722z M14.058,27.215
l-9.331-6.258l4.661-3.258l4.67,3.133V27.215z M12.286,15.674l3.021-2.113l3.519,2.313l-3.119,2.095L12.286,15.674z M17.354,27.215
V20.83l4.463-2.991l4.805,3.159L17.354,27.215z M27.954,17.927l-3.168-2.082l3.168-2.125V17.927z"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 483.3 483.3" fill="#007BFF" style="enable-background:new 0 0 483.3 483.3;" xml:space="preserve">
<g>
<g>
<path d="M424.3,57.75H59.1c-32.6,0-59.1,26.5-59.1,59.1v249.6c0,32.6,26.5,59.1,59.1,59.1h365.1c32.6,0,59.1-26.5,59.1-59.1
v-249.5C483.4,84.35,456.9,57.75,424.3,57.75z M456.4,366.45c0,17.7-14.4,32.1-32.1,32.1H59.1c-17.7,0-32.1-14.4-32.1-32.1v-249.5
c0-17.7,14.4-32.1,32.1-32.1h365.1c17.7,0,32.1,14.4,32.1,32.1v249.5H456.4z"/>
<path d="M304.8,238.55l118.2-106c5.5-5,6-13.5,1-19.1c-5-5.5-13.5-6-19.1-1l-163,146.3l-31.8-28.4c-0.1-0.1-0.2-0.2-0.2-0.3
c-0.7-0.7-1.4-1.3-2.2-1.9L78.3,112.35c-5.6-5-14.1-4.5-19.1,1.1c-5,5.6-4.5,14.1,1.1,19.1l119.6,106.9L60.8,350.95
c-5.4,5.1-5.7,13.6-0.6,19.1c2.7,2.8,6.3,4.3,9.9,4.3c3.3,0,6.6-1.2,9.2-3.6l120.9-113.1l32.8,29.3c2.6,2.3,5.8,3.4,9,3.4
c3.2,0,6.5-1.2,9-3.5l33.7-30.2l120.2,114.2c2.6,2.5,6,3.7,9.3,3.7c3.6,0,7.1-1.4,9.8-4.2c5.1-5.4,4.9-14-0.5-19.1L304.8,238.55z"
/>
</g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>github</title>
<path d="M0 15.968q0-3.264 1.28-6.208 2.528-5.952 8.48-8.48 2.944-1.28 6.208-1.28t6.208 1.28q5.888 2.496 8.48 8.48 1.28 3.040 1.28 6.208t-1.28 6.208q-2.592 6.016-8.48 8.544-2.944 1.28-6.208 1.28t-6.208-1.28q-5.952-2.56-8.48-8.544-1.28-2.944-1.28-6.208zM2.496 15.968q0 4.512 2.688 8.064 2.656 3.488 6.944 4.96v-2.56q0-1.92 1.28-2.784-0.64-0.032-1.504-0.224-1.632-0.288-2.784-1.024-2.912-1.76-2.912-6.368 0-2.4 1.6-4.096-0.736-1.888 0.16-4.096h0.64q0.32 0 0.8 0.16 1.248 0.384 2.784 1.408 1.952-0.512 3.84-0.512t3.872 0.512q1.248-0.832 2.336-1.28 1.024-0.384 1.472-0.32l0.384 0.032q0.864 2.208 0.16 4.096 1.6 1.696 1.6 4.096 0 3.584-1.76 5.408-0.96 1.024-2.528 1.6-1.312 0.48-2.912 0.608 1.312 0.928 1.312 2.784v2.56q4.128-1.472 6.816-5.024 2.624-3.52 2.624-8 0-2.72-1.056-5.248-1.024-2.432-2.88-4.288-1.792-1.792-4.288-2.848-2.56-1.088-5.216-1.088-2.624 0-5.248 1.088-2.4 1.024-4.288 2.848-1.792 1.856-2.88 4.288-1.056 2.528-1.056 5.248z"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="430.117px" height="430.118px" viewBox="0 0 430.117 430.118" fill="#007BFF" style="enable-background:new 0 0 430.117 430.118;"
xml:space="preserve">
<g>
<path id="LinkedIn__x28_alt_x29_" d="M398.355,0H31.782C14.229,0,0.002,13.793,0.002,30.817v368.471
c0,17.025,14.232,30.83,31.78,30.83h366.573c17.549,0,31.76-13.814,31.76-30.83V30.817C430.115,13.798,415.904,0,398.355,0z
M130.4,360.038H65.413V165.845H130.4V360.038z M97.913,139.315h-0.437c-21.793,0-35.92-14.904-35.92-33.563
c0-19.035,14.542-33.535,36.767-33.535c22.227,0,35.899,14.496,36.331,33.535C134.654,124.415,120.555,139.315,97.913,139.315z
M364.659,360.038h-64.966V256.138c0-26.107-9.413-43.921-32.907-43.921c-17.973,0-28.642,12.018-33.327,23.621
c-1.736,4.144-2.166,9.94-2.166,15.728v108.468h-64.954c0,0,0.85-175.979,0-194.192h64.964v27.531
c8.624-13.229,24.035-32.1,58.534-32.1c42.76,0,74.822,27.739,74.822,87.414V360.038z M230.883,193.99
c0.111-0.182,0.266-0.401,0.42-0.614v0.614H230.883z"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 32 32">
<title>twitch</title>
<path d="M3.421 0.75l-1.988 5.305v21.217h7.29v3.978h3.98l3.975-3.98h5.967l7.955-7.953v-18.567h-27.177zM6.070 3.4h21.878v14.589l-4.642 4.642h-7.291l-3.975 3.975v-3.975h-5.97v-19.23zM13.366 16.663h2.65v-7.955h-2.65v7.955zM20.655 16.663h2.65v-7.955h-2.65v7.955z"></path>
</svg>

After

Width:  |  Height:  |  Size: 428 B

View file

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>youtube</title>
<path d="M23.2 6.937c1.428 0.144 3.285 0 4.285 1.144 1.143 1.143 1.287 2.999 1.287 4.428 0.142 1.714 0.142 4.144 0.142 5.713-0.142 1.573 0 3.428-0.716 4.859-0.712 1.569-1.999 2.143-3.57 2.284-1.716 0.142-12.286 0.142-15.713 0-1.572-0.142-3.429-0.142-4.572-1.428-1-1.144-1-2.857-1.143-4.285 0-1.715 0-4.144 0-5.857 0-1.572 0-3.428 0.714-4.857 0.715-1.428 2.143-1.714 3.714-1.856 1.714-0.144 12.141-0.286 15.571-0.144zM13.2 11.794v8.57l7.857-4.285-7.857-4.285z"></path>
</svg>

After

Width:  |  Height:  |  Size: 629 B

View file

@ -1,61 +1,62 @@
--- ---
interface Props { interface Props {
title: string; primaryColor: string;
body: string; bgColor: string;
href: string;
} }
const { href, title, body } = Astro.props; const { primaryColor, bgColor = "#282828" } = Astro.props;
--- ---
<li class="link-card"> <div class="card">
<a href={href}> <slot />
<h2> </div>
{title}
<span>&rarr;</span> <style define:vars={{ primaryColor, bgColor }}>
</h2> * {
<p> box-sizing: border-box;
{body}
</p>
</a>
</li>
<style>
.link-card {
list-style: none;
display: flex;
padding: 1px;
background-color: #23262d;
background-image: none;
background-size: 400%;
border-radius: 7px;
background-position: 100%;
transition: background-position 0.6s cubic-bezier(0.22, 1, 0.36, 1);
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1);
}
.link-card > a {
width: 100%;
text-decoration: none;
line-height: 1.4;
padding: calc(1.5rem - 1px);
border-radius: 8px;
color: white;
background-color: #23262d;
opacity: 0.8;
}
h2 {
margin: 0;
font-size: 1.25rem;
transition: color 0.6s cubic-bezier(0.22, 1, 0.36, 1);
} }
h1,
h2,
h3,
p { p {
margin-top: 0.5rem; margin: 0rem;
margin-bottom: 0;
} }
.link-card:is(:hover, :focus-within) {
background-position: 0; .card {
background-image: var(--accent-gradient); height: inherit;
position: relative;
background-color: var(--bgColor);
border: 1px solid rgb(255 255 255 / 5%);
border-radius: 1.5rem;
padding: 0.5rem;
} }
.link-card:is(:hover, :focus-within) h2 {
color: rgb(var(--accent-light)); .card:after {
content: "";
height: 70px;
width: 1px;
position: absolute;
left: -1px;
top: 65%;
transition: top, opacity;
transition-duration: 600ms;
transition-timing-function: ease;
background: linear-gradient(
transparent,
var(--primaryColor),
transparent
);
opacity: 0;
}
.card:after {
top: 65%;
opacity: 0;
}
.card:hover:after {
top: 25%;
opacity: 1;
} }
</style> </style>

View file

@ -0,0 +1,61 @@
---
import Card from "./Card.astro";
import Line from "./NetworkLine.astro";
---
<div id="Experience" class="h-fit py-10">
<h1 class="text-5xl text-center">Education</h1>
<div class="flex flex-col items-center pt-10">
<div class="w-[90%] md:w-[500px]">
<Card primaryColor="#fff">
<div class="card-content">
<div class="flex flex-col justify-left w-full mb-3">
<h2 class="font-bold text-xl">
Diploma in Computer Science
</h2><h3>Jan 2022 - Present</h3>
</div>
<hr class="w-full mb-3" />
<h3 class="mb-1 font-bold text-lg">Achievements</h3>
<ul class="list-disc list-inside">
<li>3-time Dean's List recipient</li>
<li>President of Computer Programming Club</li>
<li>Vice President of Diploma Union</li>
</ul>
</div>
</Card>
<Line height="100px" />
<Card primaryColor="#fff">
<div class="card-content">
<div class="flex flex-col justify-left w-full mb-3">
<h2 class="font-bold text-xl">Cambridge IGCSE</h2><h3>
Sep 2016 - June 2021
</h3>
</div>
<hr class="w-full mb-3" />
<h3 class="mb-1 font-bold text-lg">Achievements</h3>
<ul class="list-disc list-inside">
<li>IGCSE 5 A*s, 3 A's</li>
<li>President of Technology Society</li>
<li>Technology Manager of Prefects' Board</li>
</ul>
</div>
</Card>
</div>
</div>
</div>
<style>
.card-content {
display: flex;
flex-direction: column;
background-image: radial-gradient(
rgba(255, 255, 255, 0.1) 1px,
transparent 1px
);
background-position: 50% 50%;
background-size: 1.1rem 1.1rem;
padding: 2rem 2rem;
border-radius: 1.25rem;
overflow: hidden;
}
</style>

View file

@ -1,19 +1,195 @@
<script lang="ts"> <script lang="ts">
import { onMount } from "svelte";
// 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";
}
// Intro
let intro1: string = "I like to make cool stuff";
let intro2: string = "as a ";
let introState1: string = "";
let introState2: string = "";
let lineOneFinished: boolean = false;
async function animateIntro(interval: number) {
for (let i = 0; i < intro1.length; i++) {
introState1 += intro1[i];
await sleep(interval);
}
lineOneFinished = true;
for (let j = 0; j < intro2.length; j++) {
introState2 += intro2[j];
await sleep(interval);
}
}
// Roles
let roles: string[] = [
"developer",
"streamer",
"content creator",
"student",
];
let roleState: string = "";
let role: string;
let counter: number = 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();
}
}
// after window finish loading, call animateRoles()
onMount(async () => {
await sleep(800);
await animateIntro(50);
animateRoles();
});
</script> </script>
<div class="w-full h-[90vh] text-white flex justify-center items-center"> <div
<div class="w-4/5 flex flex-row"> id="intro"
<div class="text-4xl flex flex-col"> class="w-full h-[105vh]
<p> text-white
Nice to meet you, I am flex justify-center items-end"
<br> >
Ryan <div
<br> id="intro-content"
I like to make cool stuff class="
<br> flex flex-row justify-between items-center
as a programmer w-4/5 h-4/5
p-20 mt-24
border-[#404040] border-2 border-solid
rounded-3xl"
>
<div class="w-1/2">
<h1 class="text-4xl mt-10">Good {greeting}, I'm</h1>
<h2
id="name"
class="animate-gradient text-5xl text-center py-2 font-bold w-fit"
>
RythonDev
</h2>
<p class="text-2xl mt-5 leading-7">
{introState1}<span
class:animate-pulse={!lineOneFinished}
class:opacity-0={lineOneFinished}>|</span
>
<br />{introState2}
{roleState}<span
class="opacity-0"
class:animate-pulse={lineOneFinished}
class:opacity-1={lineOneFinished}>|</span
>
</p>
<div class="mt-10">
<p class="text-lg leading-6">
A computer science undergraduate student, passionate in
frontend web development and content creation.
</p> </p>
</div> </div>
<div class="mt-10"></div>
</div> </div>
</div> </div>
</div>
<style>
#intro {
background: rgba(30, 32, 34, 1);
background: linear-gradient(
180deg,
rgba(30, 32, 34, 1) 0%,
rgba(30, 32, 34, 1) 95%,
rgba(20, 22, 24, 0) 100%
);
}
#intro-content {
background: rgb(29, 32, 35);
background: linear-gradient(
90deg,
rgba(29, 32, 35, 1) 0%,
rgba(29, 32, 35, 1) 70%,
rgba(50, 53, 58, 1) 100%
);
}
#name {
background: linear-gradient(
90deg,
#ff7dac 0%,
#33d2ff 55%,
#9845e8 100%
);
background-size: 300%;
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
</style>

View file

@ -0,0 +1,40 @@
---
interface Props {
height: string;
}
const { height } = Astro.props;
---
<div id="line-container" class="flex justify-center items-center p-0 relative">
<div id="line" class="w-[1px] h-full"></div>
</div>
<style define:vars={{ height }}>
@keyframes gradientAnimation {
0% {
background-position: 0 -100%;
}
100% {
background-position: 0 50%;
}
}
#line-container {
height: var(--height);
}
#line {
background-image: linear-gradient(
to bottom,
#404040 5%,
#aaa 10%,
#404040 15%
);
background-size: 100% 200%;
animation: gradientAnimation 2s linear infinite;
margin: 0;
display: flex;
align-items: center;
justify-content: center;
}
</style>

View file

@ -0,0 +1,453 @@
<script lang="ts">
// import { onMount } from "svelte";
const streamers = [
{
streamer: "4l1c3_0",
task: "mental breakdance",
},
{
streamer: "Acrone",
task: "play Valorant with twin brother",
},
{
streamer: "Ama_xinita",
task: "estudiar leyes",
},
{
streamer: "andolivconc",
task: "estudar Direito",
},
{
streamer: "arcanexviii",
task: "babysit",
},
{
streamer: "AuspexOneGaming",
task: "teach computer science",
},
{
streamer: "BintonDev",
task: "rubber duck debugging",
},
{
streamer: "brisim_claimhte",
task: "rewrite history thesis",
},
{
streamer: "brunixwho",
task: "Ensinar ingl\u00eas",
},
{
streamer: "Bubxmicn",
task: "drive a truck",
},
{
streamer: "charliosaurus",
task: "release another song on YouTube",
},
{
streamer: "cheshirepope",
task: "write 1000 words",
},
{
streamer: "chocomi_tv",
task: "improve English",
},
{
streamer: "Clarishy",
task: "be sweaty",
},
{
streamer: "cloudydayzzz",
task: "interpret ASL",
},
{
streamer: "creativepepper",
task: "develop mobile app",
},
{
streamer: "DarthTorLin",
task: "watch Star Wars",
},
{
streamer: "DATJI_",
task: "IRL KBBQ stream",
},
{
streamer: "EarliestTea",
task: "chat about MBTI",
},
{
streamer: "Elly78456",
task: "sell YOUthversity merch",
},
{
streamer: "Emerald_Glowo",
task: "drawing stream",
},
{
streamer: "emzkx",
task: "study public health, psychology and exercise science",
},
{
streamer: "eri__berry",
task: "play Palia",
},
{
streamer: "HarryIsTrying",
task: "be a strategy consultant",
},
{
streamer: "Hawokai",
task: "be a shark",
},
{
streamer: "itsbrandonut",
task: "stream music then play valorant",
},
{
streamer: "j3dg",
task: "spin class",
},
{
streamer: "jerrrs",
task: "play Animal Crossing",
},
{
streamer: "lala_xitlali",
task: "design fashionable clothes",
},
{
streamer: "long1nteger",
task: "AI project",
},
{
streamer: "lyricalclove",
task: "teach English",
},
{
streamer: "mikewhatwhere",
task: "be a dietician",
},
{
streamer: "msmushh",
task: "vibe on stream",
},
{
streamer: "nachoburrit0",
task: "update spreadsheets",
},
{
streamer: "nick_kendall",
task: "Instagram post",
},
{
streamer: "nihn_jnesyo",
task: "Release new Lo-fi music",
},
{
streamer: "novellaHT",
task: "play Don't Starve Together",
},
{
streamer: "pcc_lanezzz",
task: "be a supermodel",
},
{
streamer: "PineappleEffect",
task: "edit video",
},
{
streamer: "pinsaregood",
task: "go on another hiatus",
},
{
streamer: "procrastilate",
task: "chaos",
},
{
streamer: "samkitkat",
task: "learn React",
},
{
streamer: "studypaws",
task: "be a vet",
},
{
streamer: "sunfflawer",
task: "be a sunflower",
},
{
streamer: "Supernaturalwriter",
task: "hit the gym",
},
{
streamer: "TheCake404",
task: "wear a demon costume",
},
{
streamer: "ThePainfulPhD",
task: "study about pain",
},
{
streamer: "theyolotato",
task: "be a potato",
},
{
streamer: "valecey",
task: "graduate from university",
},
{
streamer: "wafflesdot025",
task: "perform in another musical",
},
{
streamer: "wasmishtaken_",
task: "simp for levi ackerman",
},
{
streamer: "xeno_hiraeth",
task: "anki flashcards",
},
];
// let primaryDivHeight: string;
// onMount(() => {
// const animatedElement = document.querySelector(".primary");
// if (animatedElement) {
// primaryDivHeight = `${animatedElement.clientHeight}px`;
// }
// console.log(streamers.length);
// console.log(primaryDivHeight);
// });
</script>
<div id="projects" class="h-fit pt-20 pb-10 [perspective:1000px]">
<h1 class="text-5xl text-center">Projects</h1>
<div class="mt-10 w-full">
<div
class="flex flex-col md:flex-row justify-between h-fit w-full px-20"
>
<div
class="image-container w-full md:w-1/2 aspect-video [perspective:200px] relative md:ml-20"
>
<img
src="/images/projects/coworking-guide.webp"
alt="coworking guide"
class="absolute max-w-full
top-1/2 left-1/2
[transform:rotateY(5deg)_rotateX(0deg)_translateZ(-50px)_translateX(-50%)_translateY(-50%)] opacity-40
border-2 border-solid border-white rounded-xl"
width="600"
/>
<img
src="/images/projects/coworking-guide.webp"
alt="coworking guide"
width="600"
class="absolute max-w-full
top-1/2 left-1/2
[transform:rotateY(5deg)_rotateX(0deg)_translateZ(-50px)_translateX(-48%)_translateY(-52%)] opacity-1
border-2 border-solid border-white rounded-xl"
/>
<div
class="visit-div absolute w-[600px] bg-[rgba(0,0,0,0.5)] opacity-0
aspect-video
rounded-xl
[transform:translateX(-50%)_translateY(-50%)] top-1/2 left-1/2
border-2 border-solid border-white
max-w-full"
>
<a
href="https://coworking-guide.vercel.app/"
target="_blank"
class="absolute [transform:translateX(-50%)_translateY(-50%)] top-1/2 left-1/2
px-5 py-3 bg-blue-500 rounded-xl opacity-1
font-bold">Visit site</a
>
</div>
</div>
<div
class="w-full md:w-1/2 h-[340px] flex flex-col justify-center md:pr-20"
>
<h2 class="text-3xl font-bold mb-5">Coworking Guide</h2>
<p class="text-xl">
A guide to coworking streams for Twitch streamers, covers
wide range of topics from tips on how to get started with
setting up stream to how to grow your audience!
</p>
</div>
</div>
<div
class="flex flex-col-reverse md:flex-row justify-between h-fit w-full px-16"
>
<div
class="w-full md:w-1/2 h-[340px] flex flex-col justify-center md:pl-20"
>
<h2 class="text-3xl font-bold mb-5">Chat-Task-Tic Widget</h2>
<p class="text-xl">
A widget for Coworking and Study Twitch streamers, allows
the streamer and the chatters to add their tasks to the
widget, to be displayed on stream!
</p>
</div>
<div
class="image-container w-full md:w-1/2 aspect-video [perspective:200px] relative md:ml-20"
>
<!-- task bot -->
<div
class="task-widget absolute flex flex-col opacity-30
w-full h-[99%]
top-1/2 left-1/2 [transform:translateX(-59%)_translateY(-49%)_translateZ(-50px)_rotateY(-3deg)]"
>
<div
class="w-full bg-black border-solid border-2 border-white
rounded-lg
px-5 py-2
text-xl text-white
flex flex-row justify-between items-center
font-['Fredoka',_sans-serif]"
>
<span>Hover here!</span>
<span>0/52</span>
</div>
<div
class="scroll-parent relative h-full overflow-hidden font-['Fredoka',_sans-serif]"
>
<div
class="scroll-element primary px-1 absolute w-full"
>
{#each streamers as { streamer, task }}
<div
class="w-full px-5 py-1 bg-white text-black my-2 rounded-full
whitespace-nowrap overflow-hidden overflow-ellipsis"
>
O {streamer} : {task}
</div>
{/each}
</div>
<div
class="scroll-element secondary px-1 absolute w-full"
>
{#each streamers as { streamer, task }}
<div
class="w-full px-5 py-1 bg-white text-black my-2 rounded-full
whitespace-nowrap overflow-hidden overflow-ellipsis"
>
O {streamer} : {task}
</div>
{/each}
</div>
</div>
</div>
<div
class="task-widget absolute flex flex-col
w-full h-[99%]
top-1/2 left-1/2 [transform:translateX(-60%)_translateY(-50%)_translateZ(-50px)_rotateY(-3deg)]"
>
<div
class="w-full bg-black border-solid border-2 border-white
rounded-lg
px-5 py-2
text-xl text-white
flex flex-row justify-between items-center
font-['Fredoka',_sans-serif]"
>
<span>Hover here!</span>
<span>0/52</span>
</div>
<div
class="scroll-parent relative h-full overflow-hidden font-['Fredoka',_sans-serif]"
>
<div
class="scroll-element primary px-1 absolute w-full"
>
{#each streamers as { streamer, task }}
<div
class="w-full px-5 py-1 bg-white text-black my-2 rounded-full
whitespace-nowrap overflow-hidden overflow-ellipsis"
>
O {streamer} : {task}
</div>
{/each}
</div>
<div
class="scroll-element secondary px-1 absolute w-full"
>
{#each streamers as { streamer, task }}
<div
class="w-full px-5 py-1 bg-white text-black my-2 rounded-full
whitespace-nowrap overflow-hidden overflow-ellipsis"
>
O {streamer} : {task}
</div>
{/each}
</div>
</div>
</div>
<div
class="visit-div absolute w-full h-full bg-[rgba(0,0,0,0.5)] opacity-0
rounded-md
[transform:translateX(-50%)_translateY(-50%)] top-1/2 left-1/2
border-2 border-solid border-white
overflow-hidden"
>
<a
href="https://github.com/liyunze-coding/multi-task-widget-infinity"
target="_blank"
class="absolute [transform:translateX(-50%)_translateY(-50%)] top-1/2 left-1/2
px-5 py-3 bg-blue-500 rounded-xl opacity-1
font-bold">View repository</a
>
</div>
</div>
</div>
</div>
</div>
<style>
.image-container img,
.image-container .task-widget {
transition: transform 0.5s ease-in-out;
}
.image-container:hover > img,
.image-container:hover > .task-widget {
transform: rotateY(0deg) rotateX(0deg) translateZ(0px) translateX(-50%)
translateY(-50%);
}
.image-container:hover > .visit-div {
opacity: 100%;
transition: opacity 0.3s ease-in-out;
transition-delay: 0.3s;
}
.primary {
animation: primary 30s linear infinite;
}
.secondary {
animation: secondary 30s linear infinite;
}
@keyframes primary {
from {
transform: translateY(0);
}
to {
transform: translateY(-2175px);
}
}
@keyframes secondary {
from {
transform: translateY(2175px);
}
to {
transform: translateY(0);
}
}
</style>

View file

@ -0,0 +1,44 @@
---
import Card from "../components/Card.astro";
---
<div class="w-full h-[200vh]">
<h1 class="text-center text-5xl">Skills</h1>
<div class="flex flex-col items-center">
<div class="w-1/2 pt-10">
<Card primaryColor="#fff">
<div class="card-content">
<div class="flex flex-col justify-left w-full mb-3">
<h2 class="font-bold text-xl">
Diploma in Computer Science
</h2><h3>Jan 2022 - Present</h3>
</div>
<hr class="w-full mb-3" />
<h3 class="mb-1 font-bold text-lg">Achievements</h3>
<ul class="list-disc list-inside">
<li>3-time Dean's List recipient</li>
<li>President of Computer Programming Club</li>
<li>Vice President of Diploma Union</li>
</ul>
</div>
</Card>
</div>
</div>
</div>
<style>
.card-content {
display: flex;
flex-direction: column;
gap: 1rem;
background-image: radial-gradient(
rgba(255, 255, 255, 0.1) 1px,
transparent 1px
);
background-position: 50% 50%;
background-size: 1.1rem 1.1rem;
padding: 2rem 2rem;
border-radius: 1.25rem;
overflow: hidden;
}
</style>

View file

@ -0,0 +1,61 @@
---
import Card from "../components/Card.astro";
---
<div class="w-full h-fit flex justify-center items-center flex-col">
<div class="h-[1px] w-1/3 bg-[#404040] mb-5"></div>
<h1 class="text-center text-5xl mb-10">What I Do</h1>
<div
class="grid grid-cols-1 xl:grid-cols-3 place-content-center justify-center w-4/5 gap-12"
>
<Card primaryColor="#be68ed">
<div class="card-content">
<h2 class="font-bold text-xl text-center">Data Science</h2>
<hr class="w-full" />
<p class="text-center">
I possess knowledge of data science and machine learning,
particularly interested in Computer Vision.
</p>
</div>
</Card>
<Card primaryColor="#be68ed">
<div class="card-content">
<h2 class="font-bold text-xl text-center">Web Development</h2>
<hr class="w-full" />
<p class="text-center">
I like to code things for the web, whether it's to inform or
to entertain.
</p>
</div>
</Card>
<Card primaryColor="#be68ed">
<div class="card-content">
<h2 class="font-bold text-xl text-center">Content Creation</h2>
<hr class="w-full" />
<p class="text-center">
I am experienced in streaming on Twitch and marketing
myself, but I aim to improve my video editing skills.
</p>
</div>
</Card>
</div>
</div>
<style>
.card-content {
display: flex;
flex-direction: column;
gap: 1rem;
background-image: radial-gradient(
rgba(255, 255, 255, 0.1) 1px,
transparent 1px
);
background-position: 50% 50%;
background-size: 1.1rem 1.1rem;
padding: 2rem 2rem;
border-radius: 1.25rem;
overflow: hidden;
}
</style>

View file

@ -23,92 +23,91 @@ const { title } = Astro.props;
<style is:global> <style is:global>
/* Fredoka Fonts */ /* Fredoka Fonts */
@font-face { @font-face {
font-family: 'Fredoka'; font-family: "Fredoka";
src: url('fonts/Fredoka-Bold.ttf') format('truetype'); src: url("fonts/Fredoka-Bold.ttf") format("truetype");
font-weight: bold; font-weight: bold;
font-style: normal; font-style: normal;
} }
@font-face { @font-face {
font-family: 'Fredoka'; font-family: "Fredoka";
src: url('fonts/Fredoka-Light.ttf') format('truetype'); src: url("fonts/Fredoka-Light.ttf") format("truetype");
font-weight: lighter; font-weight: lighter;
font-style: normal; font-style: normal;
} }
@font-face { @font-face {
font-family: 'Fredoka'; font-family: "Fredoka";
src: url('fonts/Fredoka-Medium.ttf') format('truetype'); src: url("fonts/Fredoka-Medium.ttf") format("truetype");
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
@font-face { @font-face {
font-family: 'Fredoka'; font-family: "Fredoka";
src: url('fonts/Fredoka-Regular.ttf') format('truetype'); src: url("fonts/Fredoka-Regular.ttf") format("truetype");
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
/* Montserrat Fonts */ /* Montserrat Fonts */
@font-face { @font-face {
font-family: 'Montserrat'; font-family: "Montserrat";
src: url('fonts/Montserrat-Bold.ttf') format('truetype'); src: url("fonts/Montserrat-Bold.ttf") format("truetype");
font-weight: bold; font-weight: bold;
font-style: normal; font-style: normal;
} }
@font-face { @font-face {
font-family: 'Montserrat'; font-family: "Montserrat";
src: url('fonts/Montserrat-Light.ttf') format('truetype'); src: url("fonts/Montserrat-Light.ttf") format("truetype");
font-weight: lighter; font-weight: lighter;
font-style: normal; font-style: normal;
} }
@font-face { @font-face {
font-family: 'Montserrat'; font-family: "Montserrat";
src: url('fonts/Montserrat-Medium.ttf') format('truetype'); src: url("fonts/Montserrat-Medium.ttf") format("truetype");
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
@font-face { @font-face {
font-family: 'Montserrat'; font-family: "Montserrat";
src: url('fonts/Montserrat-Regular.ttf') format('truetype'); src: url("fonts/Montserrat-Regular.ttf") format("truetype");
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
@font-face { @font-face {
font-family: 'Montserrat'; font-family: "Montserrat";
src: url('fonts/Montserrat-SemiBold.ttf') format('truetype'); src: url("fonts/Montserrat-SemiBold.ttf") format("truetype");
font-weight: 600; /* You can adjust this value if needed */ font-weight: 600; /* You can adjust this value if needed */
font-style: normal; font-style: normal;
} }
/* Poppins Fonts */ /* Poppins Fonts */
@font-face { @font-face {
font-family: 'Poppins-Light'; font-family: "Poppins-Light";
src: url('fonts/Poppins-Light.ttf') format('truetype'); src: url("fonts/Poppins-Light.ttf") format("truetype");
font-weight: lighter; font-weight: lighter;
font-style: normal; font-style: normal;
} }
@font-face { @font-face {
font-family: 'Poppins-Medium'; font-family: "Poppins-Medium";
src: url('fonts/Poppins-Medium.ttf') format('truetype'); src: url("fonts/Poppins-Medium.ttf") format("truetype");
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
@font-face { @font-face {
font-family: 'Poppins-Regular'; font-family: "Poppins-Regular";
src: url('fonts/Poppins-Regular.ttf') format('truetype'); src: url("fonts/Poppins-Regular.ttf") format("truetype");
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
/* You can add more font-face rules for other fonts as needed */
* { * {
margin: 0; margin: 0;
padding: 0; padding: 0;
@ -117,7 +116,7 @@ const { title } = Astro.props;
body { body {
font-family: "Montserrat", sans-serif; font-family: "Montserrat", sans-serif;
background: #141414; background: #202020;
color: #fff; color: #fff;
} }
</style> </style>

View file

@ -1,10 +1,18 @@
--- ---
import Layout from '../layouts/Layout.astro'; import Layout from "../layouts/Layout.astro";
import Card from '../components/Card.astro'; import NetworkLine from "../components/NetworkLine.astro";
import Intro from '../components/Intro.svelte'; import WhatIDo from "../components/WhatIDo.astro";
import Intro from "../components/Intro.svelte";
import Projects from "../components/Projects.svelte";
import Education from "../components/Education.astro";
import Skills from "../components/Skills.astro";
--- ---
<Layout title="Ryan's Portfolio"> <Layout title="Ryan's Portfolio">
<Intro client:load /> <Intro client:load />
<NetworkLine height="100px" />
<WhatIDo />
<Projects client:idle />
<Education />
<Skills />
</Layout> </Layout>

View file

@ -1,8 +1,25 @@
/** @type {import('tailwindcss').Config} */ /** @type {import('tailwindcss').Config} */
module.exports = { module.exports = {
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], content: ["./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}"],
theme: { theme: {
extend: {}, extend: {
keyframes: {
gradient: {
"0%": {
"background-position": "0% 50%",
},
"50%": {
"background-position": "100% 50%",
},
"100%": {
"background-position": "0% 50%",
},
},
},
animation: {
gradient: "gradient 15s ease infinite",
},
},
}, },
plugins: [], plugins: [],
} };