Merge pull request #1 from liyunze-coding/project-component
Project and Skills component
16
package-lock.json
generated
|
|
@ -11,7 +11,7 @@
|
||||||
"@astrojs/mdx": "^4.3.0",
|
"@astrojs/mdx": "^4.3.0",
|
||||||
"@astrojs/svelte": "^7.1.0",
|
"@astrojs/svelte": "^7.1.0",
|
||||||
"@tailwindcss/vite": "^4.1.8",
|
"@tailwindcss/vite": "^4.1.8",
|
||||||
"astro": "^5.9.1",
|
"astro": "^5.10.0",
|
||||||
"caniuse-lite": "^1.0.30001698",
|
"caniuse-lite": "^1.0.30001698",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"moment-timezone": "^0.6.0",
|
"moment-timezone": "^0.6.0",
|
||||||
|
|
@ -38,9 +38,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@astrojs/compiler": {
|
"node_modules/@astrojs/compiler": {
|
||||||
"version": "2.12.1",
|
"version": "2.12.2",
|
||||||
"resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-2.12.1.tgz",
|
"resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-2.12.2.tgz",
|
||||||
"integrity": "sha512-WDSyVIiz7sNcJcCJxJFITu6XjfGhJ50Z0auyaWsrM+xb07IlhBLFtQuDkNy0caVHWNcKTM2LISAaHhgkRqGAVg==",
|
"integrity": "sha512-w2zfvhjNCkNMmMMOn5b0J8+OmUaBL1o40ipMvqcG6NRpdC+lKxmTi48DT8Xw0SzJ3AfmeFLB45zXZXtmbsjcgw==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@astrojs/internal-helpers": {
|
"node_modules/@astrojs/internal-helpers": {
|
||||||
|
|
@ -1587,12 +1587,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/astro": {
|
"node_modules/astro": {
|
||||||
"version": "5.9.1",
|
"version": "5.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/astro/-/astro-5.9.1.tgz",
|
"resolved": "https://registry.npmjs.org/astro/-/astro-5.10.0.tgz",
|
||||||
"integrity": "sha512-wxoJcTbuDZNFSv6EaL0PAlrp0Wx6VnOAULCXvy0scsV70oWMeUkdxuBxfO54JxO5Qgyvwj9h99y6E0elqOpGtA==",
|
"integrity": "sha512-g/t54kVzQnFVijs+GbbbX/NBAFTl/3yNAEA/AQYq4FumLLVv7n4BIF+jKhcPGn9iFGyT1Cjvr7KB/qYyNvHEIg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/compiler": "^2.12.1",
|
"@astrojs/compiler": "^2.12.2",
|
||||||
"@astrojs/internal-helpers": "0.6.1",
|
"@astrojs/internal-helpers": "0.6.1",
|
||||||
"@astrojs/markdown-remark": "6.3.2",
|
"@astrojs/markdown-remark": "6.3.2",
|
||||||
"@astrojs/telemetry": "3.3.0",
|
"@astrojs/telemetry": "3.3.0",
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
"@astrojs/mdx": "^4.3.0",
|
"@astrojs/mdx": "^4.3.0",
|
||||||
"@astrojs/svelte": "^7.1.0",
|
"@astrojs/svelte": "^7.1.0",
|
||||||
"@tailwindcss/vite": "^4.1.8",
|
"@tailwindcss/vite": "^4.1.8",
|
||||||
"astro": "^5.9.1",
|
"astro": "^5.10.0",
|
||||||
"caniuse-lite": "^1.0.30001698",
|
"caniuse-lite": "^1.0.30001698",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"moment-timezone": "^0.6.0",
|
"moment-timezone": "^0.6.0",
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Socials from "../elements/Socials.svelte";
|
import Socials from "../socials/Socials.svelte";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="relative flex h-fit w-full flex-col items-center justify-center">
|
<div class="relative flex h-fit w-full flex-col items-center justify-center">
|
||||||
<div class="flex flex-col items-center justify-center">
|
<div class="flex flex-col items-center justify-center">
|
||||||
<div
|
<div
|
||||||
id="title"
|
id="title"
|
||||||
class="mb-3 animate-gradient text-center text-3xl font-bold"
|
class="animate-gradient mb-3 text-center text-3xl font-bold"
|
||||||
>
|
>
|
||||||
Get in Touch with me!
|
Get in Touch with me!
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
import Card from "../elements/Card.astro";
|
import Card from "../global/Card.astro";
|
||||||
import Line from "../elements/NetworkLine.astro";
|
import Line from "../global/NetworkLine.astro";
|
||||||
---
|
---
|
||||||
|
|
||||||
<div id="Experience" class="h-fit">
|
<div id="Experience" class="h-fit">
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
import Card from "../elements/Card.astro";
|
import Card from "../global/Card.astro";
|
||||||
import Line from "../elements/NetworkLine.astro";
|
import Line from "../global/NetworkLine.astro";
|
||||||
---
|
---
|
||||||
|
|
||||||
<div id="Experience" class="h-fit">
|
<div id="Experience" class="h-fit">
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
import Socials from "../elements/Socials.svelte";
|
import Socials from "../socials/Socials.svelte";
|
||||||
|
|
||||||
// Roles
|
// Roles
|
||||||
let roles = $state(["Developer", "Streamer", "Content creator", "Student"]);
|
let roles = $state(["Developer", "Streamer", "Content creator", "Student"]);
|
||||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 230 KiB After Width: | Height: | Size: 230 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
65
src/components/projects/MoreProjects.svelte
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import VideoProject from "./VideoProject.svelte";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="flex h-fit flex-col items-center pt-20 [perspective:1000px]">
|
||||||
|
<div class="w-full max-w-[1440px]">
|
||||||
|
<VideoProject
|
||||||
|
image_src="/images/projects/chess-opencv.webp"
|
||||||
|
image_alt="computer vision chess bot"
|
||||||
|
position="left"
|
||||||
|
video_src="/videos/chess_opencv_demo.webm"
|
||||||
|
title="Computer Vision Chess Bot"
|
||||||
|
description={`
|
||||||
|
A script that plays against opponents on lichess. Uses
|
||||||
|
OpenCV to detect the board and pieces, and the Stockfish
|
||||||
|
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",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
></VideoProject>
|
||||||
|
<VideoProject
|
||||||
|
image_src="/images/projects/aim-lab.webp"
|
||||||
|
image_alt="Computer Vision AimLab Bot"
|
||||||
|
position="right"
|
||||||
|
video_src="/videos/aim_lab_demo.webm"
|
||||||
|
title="Computer Vision AimLab Bot"
|
||||||
|
description={`
|
||||||
|
A script that plays AimLab, a game that helps improve your aim in FPS games. Uses OpenCV to detect the targets and win32API to move the mouse and click.
|
||||||
|
`}
|
||||||
|
tags={[
|
||||||
|
{
|
||||||
|
text: "Python",
|
||||||
|
textColor: "white",
|
||||||
|
bgColor: "var(--color-python)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "OpenCV",
|
||||||
|
textColor: "white",
|
||||||
|
bgColor: "var(--color-opencv)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "win32API",
|
||||||
|
textColor: "white",
|
||||||
|
bgColor: "var(--color-win32api)",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
></VideoProject>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
144
src/components/projects/Project.astro
Normal file
|
|
@ -0,0 +1,144 @@
|
||||||
|
---
|
||||||
|
import { Image } from "astro:assets";
|
||||||
|
|
||||||
|
interface Tag {
|
||||||
|
text: string;
|
||||||
|
textColor: string;
|
||||||
|
bgColor: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
position?: "left" | "right";
|
||||||
|
image?: ImageMetadata;
|
||||||
|
alt?: string;
|
||||||
|
href: string;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
label?: string;
|
||||||
|
tags?: Tag[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
image,
|
||||||
|
alt,
|
||||||
|
href,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
label = "View Repository",
|
||||||
|
tags = [],
|
||||||
|
position = "left",
|
||||||
|
} = Astro.props;
|
||||||
|
|
||||||
|
const leftProject = position == "left";
|
||||||
|
---
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="flex h-fit w-full flex-col justify-center px-10 lg:px-20"
|
||||||
|
class:list={leftProject ? "lg:flex-row" : "lg:flex-row-reverse"}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="image-container relative mb-5 flex aspect-video w-full [perspective:200px] lg:mr-5 lg:mb-0 lg:ml-auto lg:w-1/2"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
{
|
||||||
|
image && alt &&
|
||||||
|
(
|
||||||
|
<Image
|
||||||
|
src={image}
|
||||||
|
alt={alt}
|
||||||
|
class={`absolute max-w-full
|
||||||
|
aspect-video
|
||||||
|
opacity-40
|
||||||
|
border-2 border-solid border-white rounded-xl`}
|
||||||
|
class:list={leftProject
|
||||||
|
? "[transform:translateX(50px)_translateY(5px)_rotateY(5deg)_rotateX(0deg)_translateZ(-50px)]"
|
||||||
|
: "[transform:translateX(10px)_translateY(5px)_translateZ(-50px)_rotateY(-3deg)]"}
|
||||||
|
width="700"
|
||||||
|
/>
|
||||||
|
<Image
|
||||||
|
src={image}
|
||||||
|
alt={alt}
|
||||||
|
width="700"
|
||||||
|
class={`absolute max-w-full
|
||||||
|
aspect-video
|
||||||
|
opacity-100
|
||||||
|
border-2 border-solid border-white rounded-xl`}
|
||||||
|
class:list={leftProject
|
||||||
|
? "[transform:rotateY(5deg)_rotateX(0deg)_translateX(60px)_translateZ(-50px)]"
|
||||||
|
: "[transform:translateZ(-50px)_rotateY(-3deg)]"}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="visit-div absolute top-1/2 left-1/2 aspect-video w-[700px] max-w-full [transform:translateX(-50%)_translateY(-50%)] rounded-xl border-2 border-solid border-white bg-[rgba(0,0,0,0.5)] opacity-0"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href={href}
|
||||||
|
target="_blank"
|
||||||
|
class="absolute top-1/2 left-1/2 hidden [transform:translateX(-50%)_translateY(-50%)] rounded-xl bg-blue-600 px-5 py-3 font-bold opacity-100 transition-colors duration-300 hover:bg-white hover:text-blue-500 lg:block"
|
||||||
|
>{label}</a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mb-10 flex items-center justify-center lg:hidden">
|
||||||
|
<a
|
||||||
|
href={href}
|
||||||
|
target="_blank"
|
||||||
|
class="rounded-xl bg-blue-600 px-5 py-3 font-bold opacity-100 transition-colors duration-300 hover:bg-white hover:text-blue-500"
|
||||||
|
>{label}</a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="flex h-fit w-full flex-col items-center justify-center lg:h-[340px] lg:w-1/2 lg:px-10"
|
||||||
|
class:list={leftProject ? "lg:items-start" : "lg:items-end"}
|
||||||
|
>
|
||||||
|
<h2
|
||||||
|
class="mb-5 text-center text-3xl font-bold"
|
||||||
|
class:list={leftProject ? "lg:text-left" : "lg:text-right"}
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</h2>
|
||||||
|
<p
|
||||||
|
class="max-w-lg text-center text-xl text-balance lg:max-w-none"
|
||||||
|
class:list={leftProject ? "lg:text-left" : "lg:text-right"}
|
||||||
|
>
|
||||||
|
{description}
|
||||||
|
</p>
|
||||||
|
<div
|
||||||
|
class="mt-5 flex w-full flex-row flex-wrap justify-center"
|
||||||
|
class:list={leftProject ? "lg:justify-start" : "lg:justify-end"}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
tags.map((tag) => (
|
||||||
|
<div
|
||||||
|
class="my-1 mr-1 w-fit rounded-full px-3 py-1 transition-colors duration-300"
|
||||||
|
style={`
|
||||||
|
background-color: ${tag.bgColor || "black"};
|
||||||
|
color: ${tag.textColor || "white"};
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
{tag.text}
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.image-container img {
|
||||||
|
transition: transform 0.5s ease-in-out;
|
||||||
|
}
|
||||||
|
@media (min-width: 1025px) {
|
||||||
|
.image-container:hover > img {
|
||||||
|
transform: rotateY(0deg) rotateX(0deg) translateZ(0px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-container:hover > .visit-div {
|
||||||
|
opacity: 100%;
|
||||||
|
transition: opacity 0.3s ease-in-out;
|
||||||
|
transition-delay: 0.3s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
156
src/components/projects/ProjectsComponent.astro
Normal file
|
|
@ -0,0 +1,156 @@
|
||||||
|
---
|
||||||
|
import TaskWidget from "./TaskWidget.svelte";
|
||||||
|
import CoworkingGuide from "../images/projects/coworking-guide.webp";
|
||||||
|
import Wnrs from "../images/projects/wnrs.webp";
|
||||||
|
import TwitchPlays from "../images/projects/twitchplays.webp";
|
||||||
|
import Project from "./Project.astro";
|
||||||
|
---
|
||||||
|
|
||||||
|
<div
|
||||||
|
id="projects"
|
||||||
|
class="flex h-fit flex-col items-center [perspective:1000px]"
|
||||||
|
>
|
||||||
|
<div class="w-full max-w-[1440px]">
|
||||||
|
<Project
|
||||||
|
position="left"
|
||||||
|
image={CoworkingGuide}
|
||||||
|
alt="coworking guide"
|
||||||
|
href="https://coworking-guide.vercel.app/"
|
||||||
|
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",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<Project
|
||||||
|
position="right"
|
||||||
|
href="https://github.com/liyunze-coding/chat-task-tic-overlay-infinity"
|
||||||
|
title="Chat-task-tic widget"
|
||||||
|
label="View Repository"
|
||||||
|
description={`
|
||||||
|
Used by 100+ Twitch streamers, allow viewers and streamers
|
||||||
|
to add their own tasks to the widget for accountability!
|
||||||
|
Easy to setup and the customization possibilities are
|
||||||
|
endless!`}
|
||||||
|
tags={[
|
||||||
|
{
|
||||||
|
text: "HTML",
|
||||||
|
bgColor: "var(--color-html)",
|
||||||
|
textColor: "white",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "CSS",
|
||||||
|
bgColor: "var(--color-blue-600)",
|
||||||
|
textColor: "white",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "Javascript",
|
||||||
|
bgColor: "var(--color-yellow-500)",
|
||||||
|
textColor: "black",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<TaskWidget
|
||||||
|
classList={`
|
||||||
|
widget
|
||||||
|
[perspective:200px] absolute [transform:translateX(-10px)_translateY(5px)_translateZ(-40px)_rotateY(-3deg)]
|
||||||
|
w-full h-full
|
||||||
|
opacity-10
|
||||||
|
`}
|
||||||
|
client:visible
|
||||||
|
/>
|
||||||
|
<TaskWidget
|
||||||
|
classList={`
|
||||||
|
widget
|
||||||
|
[perspective:200px] absolute
|
||||||
|
[transform:translateX(-20px)_translateZ(-40px)_rotateY(-3deg)]
|
||||||
|
w-full h-full
|
||||||
|
hover:[transform:translateX(0)_translateY(0)_translateZ(0)_rotateY(0)]`}
|
||||||
|
client:visible
|
||||||
|
/>
|
||||||
|
</Project>
|
||||||
|
|
||||||
|
<Project
|
||||||
|
position="left"
|
||||||
|
image={Wnrs}
|
||||||
|
alt="We're not really strangers"
|
||||||
|
href="https://liyunze-coding.github.io/wnrs/"
|
||||||
|
label="Visit Site"
|
||||||
|
title="We're not really strangers"
|
||||||
|
description="Otherwise abbreviated as 'WNRS', this is a digitaladaptation of the popular card game designed to foster meaningful connections through engaging questions and prompts."
|
||||||
|
tags={[
|
||||||
|
{
|
||||||
|
text: "React",
|
||||||
|
bgColor: "var(--color-react)",
|
||||||
|
textColor: "black",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "TypeScript",
|
||||||
|
bgColor: "var(--color-typescript)",
|
||||||
|
textColor: "white",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<Project
|
||||||
|
position="right"
|
||||||
|
image={TwitchPlays}
|
||||||
|
alt="Twitch Plays X"
|
||||||
|
href="https://github.com/liyunze-coding/TwitchPlaysX"
|
||||||
|
title="Twitch Plays X"
|
||||||
|
description={`Allow Twitch chatters to play games such as Pokemon!
|
||||||
|
Chatters can enter messages such as "up up down down left
|
||||||
|
right B A" and the Python program will trigger the
|
||||||
|
corresponding keypresses.`}
|
||||||
|
tags={[
|
||||||
|
{
|
||||||
|
text: "win32API",
|
||||||
|
bgColor: "var(--color-win32api)",
|
||||||
|
textColor: "white",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "Python",
|
||||||
|
bgColor: "var(--color-python)",
|
||||||
|
textColor: "white",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style is:global>
|
||||||
|
.image-container img,
|
||||||
|
.image-container .widget,
|
||||||
|
.image-container video {
|
||||||
|
transition: transform 0.5s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1025px) {
|
||||||
|
.image-container:hover > img,
|
||||||
|
.image-container:hover .widget,
|
||||||
|
.image-container:hover video {
|
||||||
|
transform: rotateY(0deg) rotateX(0deg) translateZ(0px) translateX(0)
|
||||||
|
translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-container:hover > .visit-div {
|
||||||
|
opacity: 100%;
|
||||||
|
transition: opacity 0.3s ease-in-out;
|
||||||
|
transition-delay: 0.3s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -113,17 +113,17 @@
|
||||||
task: "anki flashcards",
|
task: "anki flashcards",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
classList: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
let { classList }: Props = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div class={`${classList} aspect-video`}>
|
||||||
class="image-container relative mr-0 mb-3 ml-0 aspect-video [perspective:200px] md:mr-5 lg:mr-0 lg:mb-0 lg:ml-1 lg:w-1/2"
|
|
||||||
>
|
|
||||||
<!-- task bot -->
|
<!-- task bot -->
|
||||||
<div
|
<div class="task-widget absolute flex h-[99%] w-full flex-col">
|
||||||
class="task-widget absolute top-1/2 left-1/2 flex
|
|
||||||
h-[99%] w-full
|
|
||||||
[transform:translateX(-50%)_translateY(-49%)_translateZ(-50px)_rotateY(-3deg)] flex-col opacity-30"
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
class="flex w-full flex-row items-center justify-between
|
class="flex w-full flex-row items-center justify-between
|
||||||
rounded-lg
|
rounded-lg
|
||||||
|
|
@ -160,84 +160,9 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
class="task-widget absolute top-1/2 left-1/2
|
|
||||||
flex h-[99%]
|
|
||||||
w-full [transform:translateX(-51%)_translateY(-50%)_translateZ(-50px)_rotateY(-3deg)] flex-col"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="flex w-full flex-row items-center justify-between
|
|
||||||
rounded-lg
|
|
||||||
border-2 border-solid
|
|
||||||
border-white bg-black
|
|
||||||
px-5 py-2 font-['Fredoka',_sans-serif] text-xl
|
|
||||||
text-white"
|
|
||||||
>
|
|
||||||
<span>Hover here!</span>
|
|
||||||
<span>0/100+</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="scroll-parent relative h-full overflow-hidden font-['Fredoka',_sans-serif]"
|
|
||||||
>
|
|
||||||
<div class="scroll-element primary absolute w-full px-1">
|
|
||||||
{#each streamers as { streamer, task }}
|
|
||||||
<div
|
|
||||||
class="my-2 w-full overflow-hidden rounded-md bg-[#404040] px-5 py-1
|
|
||||||
overflow-ellipsis whitespace-nowrap text-white"
|
|
||||||
>
|
|
||||||
O {streamer} : {task}
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
<div class="scroll-element secondary absolute w-full px-1">
|
|
||||||
{#each streamers as { streamer, task }}
|
|
||||||
<div
|
|
||||||
class="my-2 w-full overflow-hidden rounded-md bg-[#404040] px-5 py-1
|
|
||||||
overflow-ellipsis whitespace-nowrap text-white"
|
|
||||||
>
|
|
||||||
O {streamer} : {task}
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="visit-div absolute top-1/2 left-1/2 h-full w-full
|
|
||||||
[transform:translateX(-50%)_translateY(-50%)]
|
|
||||||
overflow-hidden rounded-md border-2
|
|
||||||
border-solid border-white bg-[rgba(0,0,0,0.5)]
|
|
||||||
opacity-0"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
href="https://github.com/liyunze-coding/chat-task-tic-overlay-infinity"
|
|
||||||
target="_blank"
|
|
||||||
class="absolute top-1/2 left-1/2 hidden
|
|
||||||
[transform:translateX(-50%)_translateY(-50%)] rounded-xl bg-blue-500 px-5 py-3
|
|
||||||
font-bold
|
|
||||||
opacity-100 transition-colors
|
|
||||||
duration-300 hover:bg-white
|
|
||||||
hover:text-blue-500 lg:block">View repository</a
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.image-container .task-widget {
|
|
||||||
transition: transform 0.5s ease-in-out;
|
|
||||||
}
|
|
||||||
@media (min-width: 1025px) {
|
|
||||||
.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 {
|
.primary {
|
||||||
animation: primary 20s linear infinite;
|
animation: primary 20s linear infinite;
|
||||||
}
|
}
|
||||||
149
src/components/projects/VideoProject.svelte
Normal file
|
|
@ -0,0 +1,149 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
|
||||||
|
interface Tag {
|
||||||
|
text: string;
|
||||||
|
textColor: string;
|
||||||
|
bgColor: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
position?: "left" | "right";
|
||||||
|
image_src: string;
|
||||||
|
image_alt: string;
|
||||||
|
video_src: string;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
tags?: Tag[];
|
||||||
|
}
|
||||||
|
|
||||||
|
let {
|
||||||
|
position = "left",
|
||||||
|
image_src,
|
||||||
|
image_alt,
|
||||||
|
video_src,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
tags = [],
|
||||||
|
}: Props = $props();
|
||||||
|
|
||||||
|
const positionLeft = position == "left";
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
const videos = document.querySelectorAll<HTMLVideoElement>(".playable");
|
||||||
|
|
||||||
|
let userInteracted = false;
|
||||||
|
|
||||||
|
const handleUserInteraction = () => {
|
||||||
|
userInteracted = true;
|
||||||
|
document.removeEventListener("click", handleUserInteraction);
|
||||||
|
document.removeEventListener("keydown", handleUserInteraction);
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener("click", handleUserInteraction);
|
||||||
|
document.addEventListener("keydown", handleUserInteraction);
|
||||||
|
|
||||||
|
videos.forEach((video) => {
|
||||||
|
// Ensure the video element supports play and pause methods
|
||||||
|
if (
|
||||||
|
typeof video.play === "function" &&
|
||||||
|
typeof video.pause === "function"
|
||||||
|
) {
|
||||||
|
video.addEventListener("mouseenter", () => {
|
||||||
|
if (userInteracted) {
|
||||||
|
video.volume = 0.2;
|
||||||
|
video.muted = false;
|
||||||
|
video.play();
|
||||||
|
} else {
|
||||||
|
video.volume = 0;
|
||||||
|
video.muted = true;
|
||||||
|
video.play();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
video.addEventListener("mouseleave", () => {
|
||||||
|
video.pause();
|
||||||
|
video.currentTime = 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check if the screen width is less than or equal to 768px (mobile screen size)
|
||||||
|
if (window.innerWidth <= 768) {
|
||||||
|
video.muted = true;
|
||||||
|
video.autoplay = true;
|
||||||
|
video.loop = true;
|
||||||
|
video.play();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="flex h-fit w-full flex-col justify-center px-10 lg:flex-row lg:px-20"
|
||||||
|
class:lg:flex-row={positionLeft}
|
||||||
|
class:lg:flex-row-reverse={!positionLeft}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="image-container relative mb-5 flex aspect-video w-full [perspective:200px] lg:mr-5 lg:mb-0 lg:ml-auto lg:w-1/2"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={image_src}
|
||||||
|
alt={image_alt}
|
||||||
|
class="absolute max-w-full
|
||||||
|
rounded-xl
|
||||||
|
border-2 border-solid border-white opacity-40
|
||||||
|
{positionLeft
|
||||||
|
? '[transform:rotateY(5deg)_translateX(50px)_translateY(5px)_translateZ(-50px)]'
|
||||||
|
: '[transform:rotateY(-5deg)_translateX(-20px)_translateY(5px)_translateZ(-50px)]'}"
|
||||||
|
width="700"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- svelte-ignore a11y_media_has_caption -->
|
||||||
|
<video
|
||||||
|
width="700"
|
||||||
|
class="playable absolute max-w-full
|
||||||
|
rounded-xl border-2 border-solid border-white
|
||||||
|
opacity-100
|
||||||
|
{positionLeft
|
||||||
|
? '[transform:rotateY(5deg)_translateX(60px)_translateZ(-50px)]'
|
||||||
|
: '[transform:rotateY(-5deg)_translateX(-30px)_translateZ(-50px)]'}"
|
||||||
|
>
|
||||||
|
<source src={video_src} type="video/webm" />
|
||||||
|
</video>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="flex h-fit w-full flex-col items-center justify-center lg:h-[340px] lg:w-1/2 lg:px-10
|
||||||
|
{positionLeft ? 'lg:items-start' : 'lg:items-end'}"
|
||||||
|
>
|
||||||
|
<h2
|
||||||
|
class="mb-5 text-center text-3xl font-bold
|
||||||
|
{positionLeft ? 'lg:text-left' : 'lg:text-right'}"
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</h2>
|
||||||
|
<p
|
||||||
|
class="max-w-lg text-center text-xl text-balance lg:max-w-none
|
||||||
|
{positionLeft ? 'lg:text-left' : 'lg:text-right'}"
|
||||||
|
>
|
||||||
|
{description}
|
||||||
|
</p>
|
||||||
|
<div
|
||||||
|
class="mt-5 flex w-full flex-row flex-wrap justify-center
|
||||||
|
{positionLeft ? 'lg:justify-start' : 'lg:justify-end'}"
|
||||||
|
>
|
||||||
|
{#each tags as tag}
|
||||||
|
<div
|
||||||
|
class="my-1 mr-1 w-fit
|
||||||
|
rounded-full px-3 py-1
|
||||||
|
transition-colors duration-300"
|
||||||
|
style={`
|
||||||
|
background-color: ${tag.bgColor || "black"};
|
||||||
|
color: ${tag.textColor || "white"};
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
{tag.text}
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -1,206 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
import { onMount } from "svelte";
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
const videos = document.querySelectorAll<HTMLVideoElement>(".playable");
|
|
||||||
|
|
||||||
let userInteracted = false;
|
|
||||||
|
|
||||||
const handleUserInteraction = () => {
|
|
||||||
userInteracted = true;
|
|
||||||
document.removeEventListener("click", handleUserInteraction);
|
|
||||||
document.removeEventListener("keydown", handleUserInteraction);
|
|
||||||
};
|
|
||||||
|
|
||||||
document.addEventListener("click", handleUserInteraction);
|
|
||||||
document.addEventListener("keydown", handleUserInteraction);
|
|
||||||
|
|
||||||
videos.forEach((video) => {
|
|
||||||
// Ensure the video element supports play and pause methods
|
|
||||||
if (
|
|
||||||
typeof video.play === "function" &&
|
|
||||||
typeof video.pause === "function"
|
|
||||||
) {
|
|
||||||
video.addEventListener("mouseenter", () => {
|
|
||||||
if (userInteracted) {
|
|
||||||
video.volume = 0.2;
|
|
||||||
video.muted = false;
|
|
||||||
video.play();
|
|
||||||
} else {
|
|
||||||
video.volume = 0;
|
|
||||||
video.muted = true;
|
|
||||||
video.play();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
video.addEventListener("mouseleave", () => {
|
|
||||||
video.pause();
|
|
||||||
video.currentTime = 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Check if the screen width is less than or equal to 768px (mobile screen size)
|
|
||||||
if (window.innerWidth <= 768) {
|
|
||||||
video.muted = true;
|
|
||||||
video.autoplay = true;
|
|
||||||
video.loop = true;
|
|
||||||
video.play();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="flex h-fit flex-col items-center pt-20 [perspective:1000px]">
|
|
||||||
<div class="w-full max-w-[1440px]">
|
|
||||||
<div
|
|
||||||
class="flex h-fit w-full flex-col justify-center px-10 lg:flex-row lg:px-20"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="image-container relative mb-5 flex aspect-video w-full [perspective:200px] lg:mr-5 lg:mb-0 lg:ml-auto lg:w-1/2"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
src="/images/projects/chess-opencv.webp"
|
|
||||||
alt="computer vision chess bot"
|
|
||||||
class="absolute top-1/2
|
|
||||||
left-1/2 max-w-full
|
|
||||||
[transform:rotateY(5deg)_rotateX(0deg)_translateZ(-50px)_translateX(-45%)_translateY(-50%)] rounded-xl
|
|
||||||
border-2 border-solid border-white opacity-40"
|
|
||||||
width="700"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- svelte-ignore a11y-media-has-caption -->
|
|
||||||
<video
|
|
||||||
width="700"
|
|
||||||
class="playable absolute top-1/2
|
|
||||||
left-1/2 max-w-full
|
|
||||||
[transform:rotateY(5deg)_rotateX(0deg)_translateZ(-50px)_translateX(-43%)_translateY(-52%)] rounded-xl
|
|
||||||
border-2 border-solid border-white opacity-100"
|
|
||||||
>
|
|
||||||
<source
|
|
||||||
src="/videos/chess_opencv_demo.webm"
|
|
||||||
type="video/webm"
|
|
||||||
/>
|
|
||||||
</video>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="flex h-fit w-full flex-col items-center justify-center lg:h-[340px] lg:w-1/2 lg:items-start lg:px-10"
|
|
||||||
>
|
|
||||||
<h2 class="mb-5 text-center text-3xl font-bold lg:text-left">
|
|
||||||
Computer Vision Chess bot
|
|
||||||
</h2>
|
|
||||||
<p
|
|
||||||
class="max-w-lg text-center text-xl text-balance lg:max-w-none lg:text-left"
|
|
||||||
>
|
|
||||||
A script that plays against opponents on lichess. Uses
|
|
||||||
OpenCV to detect the board and pieces, and the Stockfish
|
|
||||||
chess engine to determine the best moves. Then uses
|
|
||||||
PyAutoGUI to play the moves on the browser.
|
|
||||||
</p>
|
|
||||||
<div
|
|
||||||
class="mt-5 flex w-full flex-row flex-wrap justify-center lg:justify-start"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="my-1 mr-1 w-fit
|
|
||||||
rounded-full bg-[#3776AB] px-3 py-1 text-white
|
|
||||||
transition-colors duration-300"
|
|
||||||
>
|
|
||||||
Python
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="my-1 mr-1 w-fit
|
|
||||||
rounded-full bg-[#3178C6] px-3 py-1 text-white
|
|
||||||
transition-colors duration-300"
|
|
||||||
>
|
|
||||||
OpenCV
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="my-1 mr-1 w-fit
|
|
||||||
rounded-full bg-black px-3 py-1 text-white
|
|
||||||
transition-colors duration-300"
|
|
||||||
>
|
|
||||||
PyAutoGUI
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="mt-10 flex h-fit w-full flex-col-reverse justify-center px-10 lg:flex-row lg:px-16"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="flex h-fit w-full flex-col items-center justify-center lg:h-[340px] lg:w-1/2 lg:items-end lg:px-10"
|
|
||||||
>
|
|
||||||
<h2 class="mb-5 text-center text-3xl font-bold lg:text-right">
|
|
||||||
Computer Vision AimLab Bot
|
|
||||||
</h2>
|
|
||||||
<p
|
|
||||||
class="max-w-lg text-center text-xl text-balance lg:max-w-none lg:text-right"
|
|
||||||
>
|
|
||||||
A script that plays AimLab, a game that helps improve your
|
|
||||||
aim in FPS games. Uses OpenCV to detect the targets and
|
|
||||||
win32API to move the mouse and click.
|
|
||||||
</p>
|
|
||||||
<div
|
|
||||||
class="mt-5 mb-10 flex w-full flex-row flex-wrap justify-center lg:mb-0 lg:justify-end"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="my-1 mr-1 w-fit
|
|
||||||
rounded-full bg-[#3776AB] px-3 py-1 text-white
|
|
||||||
transition-colors duration-300"
|
|
||||||
>
|
|
||||||
Python
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="my-1 mr-1 w-fit
|
|
||||||
rounded-full bg-[#3178C6] px-3 py-1 text-white
|
|
||||||
transition-colors duration-300"
|
|
||||||
>
|
|
||||||
OpenCV
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="my-1 mr-1 w-fit
|
|
||||||
rounded-full bg-[#0078D4] px-3 py-1 text-white
|
|
||||||
transition-colors duration-300"
|
|
||||||
>
|
|
||||||
win32API
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="image-container relative mb-5 flex aspect-video w-full [perspective:200px] lg:mr-5 lg:mb-0 lg:ml-auto lg:w-1/2"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
src="/images/projects/aim-lab.webp"
|
|
||||||
alt="aim lab"
|
|
||||||
class="absolute top-1/2
|
|
||||||
left-1/2 max-w-full [transform:translateX(-48%)_translateY(-48%)_translateZ(-50px)_rotateY(-3deg)] rounded-xl
|
|
||||||
border-2 border-solid border-white opacity-40"
|
|
||||||
width="700"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- svelte-ignore a11y-media-has-caption -->
|
|
||||||
<video
|
|
||||||
width="700"
|
|
||||||
class="playable absolute top-1/2
|
|
||||||
left-1/2 max-w-full
|
|
||||||
[transform:translateX(-50%)_translateY(-50%)_translateZ(-50px)_rotateY(-3deg)] rounded-xl
|
|
||||||
border-2 border-solid border-white opacity-100"
|
|
||||||
><source src="/videos/aim_lab_demo.webm" /></video
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.image-container img,
|
|
||||||
.image-container video {
|
|
||||||
transition: transform 0.5s ease-in-out;
|
|
||||||
}
|
|
||||||
@media (min-width: 1025px) {
|
|
||||||
.image-container:hover > img,
|
|
||||||
.image-container:hover > video {
|
|
||||||
transform: rotateY(0deg) rotateX(0deg) translateZ(0px)
|
|
||||||
translateX(-50%) translateY(-50%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,103 +0,0 @@
|
||||||
---
|
|
||||||
import Card from "../elements/Card.astro";
|
|
||||||
import Line from "../elements/NetworkLine.astro";
|
|
||||||
---
|
|
||||||
|
|
||||||
<div id="Experience" class="h-fit">
|
|
||||||
<div class="flex flex-col items-center">
|
|
||||||
<div class="w-[90%] md:w-[600px]">
|
|
||||||
<Line height="50px" />
|
|
||||||
<div class="mx-auto w-[90%] md:w-[600px]">
|
|
||||||
<Card primaryColor="#9D76C1">
|
|
||||||
<div class="px-8 py-8">
|
|
||||||
<div class="justify-left flex w-full flex-col">
|
|
||||||
<h2 class="text-2xl font-bold">Content Creation</h2>
|
|
||||||
</div>
|
|
||||||
<hr class="my-3 w-full" />
|
|
||||||
<p class="text-left">
|
|
||||||
Since I was little, I loved watching YouTube videos
|
|
||||||
and the idea of bringing joy and laughter to a wider
|
|
||||||
audience. Thus, I began my journey in content
|
|
||||||
creation through YouTube videos and Twitch
|
|
||||||
streaming. I typically do coworking & study streams
|
|
||||||
to keep myself accountable and encourage
|
|
||||||
productivity amongst viewers. I also do software and
|
|
||||||
game development streams where I showcase my
|
|
||||||
workflow.
|
|
||||||
</p>
|
|
||||||
<div
|
|
||||||
class="flex w-full flex-row flex-wrap justify-start"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="my-1 mr-1 w-fit cursor-default rounded-full bg-[#141414] px-3 py-1 text-white transition-colors duration-300 hover:bg-[#141414] hover:text-white md:bg-gray-500"
|
|
||||||
>
|
|
||||||
OBS
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="my-1 mr-1 w-fit cursor-default rounded-full bg-gray-50 px-3 py-1 text-black transition-colors duration-300 hover:bg-gray-50 hover:text-black md:bg-gray-500 md:text-white"
|
|
||||||
>
|
|
||||||
DaVinci Resolve
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="my-1 mr-1 w-fit cursor-default rounded-full bg-purple-500 px-3 py-1 text-white transition-colors duration-300 hover:bg-purple-500 md:bg-gray-500"
|
|
||||||
>
|
|
||||||
Twitch
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="my-1 mr-1 w-fit cursor-default rounded-full bg-[#ff0000] px-3 py-1 text-white transition-colors duration-300 hover:bg-[#ff0000] hover:text-white md:bg-gray-500"
|
|
||||||
>
|
|
||||||
YouTube
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
<Line height="50px" />
|
|
||||||
<div class="mx-auto w-[90%] md:w-[600px]">
|
|
||||||
<Card primaryColor="#9D76C1">
|
|
||||||
<div class="px-8 py-8">
|
|
||||||
<div class="justify-left flex w-full flex-col">
|
|
||||||
<h2 class="text-2xl font-bold">
|
|
||||||
Mobile Development
|
|
||||||
</h2>
|
|
||||||
</div>
|
|
||||||
<hr class="my-3 w-full" />
|
|
||||||
<p class="text-left">
|
|
||||||
In my Mobile App Development unit in University, I
|
|
||||||
am tasked to develop Android apps using Android
|
|
||||||
Studio. The final app project I had developed was a
|
|
||||||
LLM-powered quiz app with features such as choosing
|
|
||||||
your own topics, viewing your question attempt
|
|
||||||
history afterwards, and upgrading your tier with
|
|
||||||
Google Pay.
|
|
||||||
</p>
|
|
||||||
<p class="text-left">
|
|
||||||
The marking tutor was impressed with my work, and
|
|
||||||
offered me to join a research lab because I had good
|
|
||||||
potential.
|
|
||||||
</p>
|
|
||||||
<div
|
|
||||||
class="mt-5 flex w-full flex-row flex-wrap justify-start"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="my-1 mr-1 w-fit cursor-default rounded-full bg-[#106539] px-3 py-1 text-white transition-colors duration-300 hover:bg-[#106539] hover:text-white md:bg-gray-500"
|
|
||||||
>
|
|
||||||
Android
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="my-1 mr-1 w-fit cursor-default rounded-full bg-[#ED8B00] px-3 py-1 text-white transition-colors duration-300 hover:bg-[#ED8B00] md:bg-gray-500"
|
|
||||||
>
|
|
||||||
Java
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="my-1 mr-1 w-fit cursor-default rounded-full bg-[#7F52FF] px-3 py-1 text-white transition-colors duration-300 hover:bg-[#7F52FF] md:bg-gray-500"
|
|
||||||
>
|
|
||||||
Kotlin
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,306 +0,0 @@
|
||||||
---
|
|
||||||
import TaskWidget from "./TaskWidget.svelte";
|
|
||||||
import { Image } from "astro:assets";
|
|
||||||
import CoworkingGuide from "./images/projects/coworking-guide.webp";
|
|
||||||
import Wnrs from "./images/projects/wnrs.webp";
|
|
||||||
import TwitchPlays from "./images/projects/twitchplays.webp";
|
|
||||||
---
|
|
||||||
|
|
||||||
<div
|
|
||||||
id="projects"
|
|
||||||
class="flex h-fit flex-col items-center [perspective:1000px]"
|
|
||||||
>
|
|
||||||
<div class="w-full max-w-[1440px]">
|
|
||||||
<div
|
|
||||||
class="flex h-fit w-full flex-col justify-center px-10 lg:flex-row lg:px-20"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="image-container relative mb-5 flex aspect-video w-full [perspective:200px] lg:mr-5 lg:mb-0 lg:ml-auto lg:w-1/2"
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
src={CoworkingGuide}
|
|
||||||
alt="coworking guide"
|
|
||||||
class=`absolute max-w-full
|
|
||||||
top-1/2 left-1/2
|
|
||||||
[transform:rotateY(5deg)_rotateX(0deg)_translateZ(-50px)_translateX(-45%)_translateY(-50%)] opacity-40
|
|
||||||
border-2 border-solid border-white rounded-xl`
|
|
||||||
width="700"
|
|
||||||
/>
|
|
||||||
<Image
|
|
||||||
src={CoworkingGuide}
|
|
||||||
alt="coworking guide"
|
|
||||||
width="700"
|
|
||||||
class=`absolute max-w-full
|
|
||||||
top-1/2 left-1/2
|
|
||||||
[transform:rotateY(5deg)_rotateX(0deg)_translateZ(-50px)_translateX(-43%)_translateY(-52%)] opacity-100
|
|
||||||
border-2 border-solid border-white rounded-xl`
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
class="visit-div absolute top-1/2 left-1/2 aspect-video w-[700px] max-w-full [transform:translateX(-50%)_translateY(-50%)] rounded-xl border-2 border-solid border-white bg-[rgba(0,0,0,0.5)] opacity-0"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
href="https://coworking-guide.vercel.app/"
|
|
||||||
target="_blank"
|
|
||||||
class="absolute top-1/2 left-1/2 hidden [transform:translateX(-50%)_translateY(-50%)] rounded-xl bg-blue-600 px-5 py-3 font-bold opacity-100 transition-colors duration-300 hover:bg-white hover:text-blue-500 lg:block"
|
|
||||||
>Visit site</a
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="mb-10 flex items-center justify-center lg:hidden">
|
|
||||||
<a
|
|
||||||
href="https://coworking-guide.vercel.app/"
|
|
||||||
target="_blank"
|
|
||||||
class="rounded-xl bg-blue-600 px-5 py-3 font-bold opacity-100 transition-colors duration-300 hover:bg-white hover:text-blue-500"
|
|
||||||
>View repository</a
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="flex h-fit w-full flex-col items-center justify-center lg:h-[340px] lg:w-1/2 lg:items-start lg:px-10"
|
|
||||||
>
|
|
||||||
<h2 class="mb-5 text-center text-3xl font-bold lg:text-left">
|
|
||||||
Coworking Guide
|
|
||||||
</h2>
|
|
||||||
<p
|
|
||||||
class="max-w-lg text-center text-xl text-balance lg:max-w-none lg:text-left"
|
|
||||||
>
|
|
||||||
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!
|
|
||||||
</p>
|
|
||||||
<div
|
|
||||||
class="mt-5 flex w-full flex-row flex-wrap justify-center lg:justify-start"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="my-1 mr-1 w-fit rounded-full bg-white px-3 py-1 text-black transition-colors duration-300"
|
|
||||||
>
|
|
||||||
Astro
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="my-1 mr-1 w-fit rounded-full bg-[#3178C6] px-3 py-1 text-white transition-colors duration-300"
|
|
||||||
>
|
|
||||||
TypeScript
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="my-1 mr-1 w-fit rounded-full bg-black px-3 py-1 text-white transition-colors duration-300"
|
|
||||||
>
|
|
||||||
Markdown
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="mt-10 flex h-fit w-full flex-col-reverse justify-center px-10 lg:flex-row lg:px-16"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="flex h-fit w-full flex-col items-center justify-center lg:h-[340px] lg:w-1/2 lg:items-end lg:px-10"
|
|
||||||
>
|
|
||||||
<h2 class="mb-5 text-center text-3xl font-bold lg:text-right">
|
|
||||||
Chat-Task-Tic Widget
|
|
||||||
</h2>
|
|
||||||
<p
|
|
||||||
class="max-w-lg text-center text-xl text-balance lg:max-w-none lg:text-right"
|
|
||||||
>
|
|
||||||
Used by 100+ Twitch streamers, allow viewers and streamers
|
|
||||||
to add their own tasks to the widget for accountability!
|
|
||||||
Easy to setup and the customization possibilities are
|
|
||||||
endless!
|
|
||||||
</p>
|
|
||||||
<div
|
|
||||||
class="mt-5 flex w-full flex-row flex-wrap justify-center lg:justify-end"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="bg-html my-1 mr-1 w-fit rounded-full px-3 py-1 text-white transition-colors duration-300"
|
|
||||||
>
|
|
||||||
HTML
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="my-1 mr-1 w-fit rounded-full bg-blue-700 px-3 py-1 text-white transition-colors duration-300"
|
|
||||||
>
|
|
||||||
CSS
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="my-1 mr-1 w-fit rounded-full bg-yellow-400 px-3 py-1 text-black transition-colors duration-300"
|
|
||||||
>
|
|
||||||
Javascript
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="mb-10 flex items-center justify-center lg:hidden">
|
|
||||||
<a
|
|
||||||
href="https://github.com/liyunze-coding/chat-task-tic-overlay-infinity"
|
|
||||||
target="_blank"
|
|
||||||
class="rounded-xl bg-blue-600 px-5 py-3 font-bold opacity-100 transition-colors duration-300 hover:bg-white hover:text-blue-600"
|
|
||||||
>View repository</a
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<TaskWidget client:visible />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="mt-5 flex h-fit w-full flex-col justify-center px-10 lg:mt-0 lg:flex-row lg:px-20"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="image-container relative mb-5 flex aspect-video w-full [perspective:200px] lg:mr-5 lg:mb-0 lg:ml-auto lg:w-1/2"
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
src={Wnrs}
|
|
||||||
alt="Hex Guess"
|
|
||||||
class=`absolute max-w-full
|
|
||||||
top-1/2 left-1/2
|
|
||||||
[transform:rotateY(5deg)_rotateX(0deg)_translateZ(-50px)_translateX(-45%)_translateY(-50%)] opacity-40
|
|
||||||
border-2 border-solid border-white rounded-xl
|
|
||||||
aspect-video`
|
|
||||||
width="700"
|
|
||||||
/>
|
|
||||||
<Image
|
|
||||||
src={Wnrs}
|
|
||||||
alt="Hex Guess"
|
|
||||||
width="700"
|
|
||||||
class=`absolute max-w-full
|
|
||||||
top-1/2 left-1/2
|
|
||||||
[transform:rotateY(5deg)_rotateX(0deg)_translateZ(-50px)_translateX(-43%)_translateY(-52%)] opacity-100
|
|
||||||
border-2 border-solid border-white rounded-xl
|
|
||||||
aspect-video`
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
class="visit-div absolute top-1/2 left-1/2 aspect-video w-[700px] max-w-full [transform:translateX(-50%)_translateY(-50%)] rounded-xl border-2 border-solid border-white bg-[rgba(0,0,0,0.5)] opacity-0"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
href="https://liyunze-coding.github.io/wnrs/"
|
|
||||||
target="_blank"
|
|
||||||
class="absolute top-1/2 left-1/2 hidden [transform:translateX(-50%)_translateY(-50%)] rounded-xl bg-blue-600 px-5 py-3 font-bold opacity-100 transition-colors duration-300 hover:bg-white hover:text-blue-500 lg:block"
|
|
||||||
>Visit site</a
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="mb-10 flex items-center justify-center lg:hidden">
|
|
||||||
<a
|
|
||||||
href="https://hex-guess.vercel.app/"
|
|
||||||
target="_blank"
|
|
||||||
class="rounded-xl bg-blue-600 px-5 py-3 font-bold opacity-100 transition-colors duration-300 hover:bg-white hover:text-blue-500"
|
|
||||||
>View repository</a
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="flex h-fit w-full flex-col items-center justify-center lg:h-[340px] lg:w-1/2 lg:items-start lg:px-10"
|
|
||||||
>
|
|
||||||
<h2 class="mb-5 text-center text-3xl font-bold">
|
|
||||||
We're Not Really Strangers
|
|
||||||
</h2>
|
|
||||||
<p
|
|
||||||
class="max-w-lg text-center text-xl text-balance lg:max-w-none lg:text-left"
|
|
||||||
>
|
|
||||||
Otherwise abbreviated as "WNRS", this is a digital
|
|
||||||
adaptation of the popular card game designed to foster
|
|
||||||
meaningful connections through engaging questions and
|
|
||||||
prompts.
|
|
||||||
</p>
|
|
||||||
<div
|
|
||||||
class="mt-5 flex w-full flex-row flex-wrap justify-center lg:justify-start"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="bg-react my-1 mr-1 w-fit rounded-full px-3 py-1 text-black transition-colors duration-300"
|
|
||||||
>
|
|
||||||
React
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-typescript my-1 mr-1 w-fit rounded-full px-3 py-1 text-white transition-colors duration-300"
|
|
||||||
>
|
|
||||||
Typescript
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="mt-10 flex h-fit w-full flex-col-reverse justify-center px-10 lg:flex-row lg:px-16"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="flex h-fit w-full flex-col items-center justify-center lg:h-[340px] lg:w-1/2 lg:items-end lg:px-10"
|
|
||||||
>
|
|
||||||
<h2 class="mb-5 text-center text-3xl font-bold lg:text-right">
|
|
||||||
Twitch Plays X
|
|
||||||
</h2>
|
|
||||||
<p
|
|
||||||
class="max-w-lg text-center text-xl text-balance lg:max-w-none lg:text-right"
|
|
||||||
>
|
|
||||||
Allow Twitch chatters to play games such as Pokemon!
|
|
||||||
Chatters can enter messages such as "up up down down left
|
|
||||||
right B A" and the Python program will trigger the
|
|
||||||
corresponding keypresses.
|
|
||||||
</p>
|
|
||||||
<div
|
|
||||||
class="mt-5 flex w-full flex-row flex-wrap justify-center lg:justify-end"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="bg-python my-1 mr-1 w-fit rounded-full px-3 py-1 text-white transition-colors duration-300"
|
|
||||||
>
|
|
||||||
Python
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-win32api my-1 mr-1 w-fit rounded-full px-3 py-1 text-white transition-colors duration-300"
|
|
||||||
>
|
|
||||||
win32API
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="mb-10 flex items-center justify-center lg:hidden">
|
|
||||||
<a
|
|
||||||
href="https://github.com/liyunze-coding/TwitchPlaysX"
|
|
||||||
target="_blank"
|
|
||||||
class="rounded-xl bg-blue-600 px-5 py-3 font-bold opacity-100 transition-colors duration-300 hover:bg-white hover:text-blue-500"
|
|
||||||
>View repository</a
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="image-container relative mb-5 flex aspect-video w-full [perspective:200px] lg:mr-5 lg:mb-0 lg:ml-auto lg:w-1/2"
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
src={TwitchPlays}
|
|
||||||
alt="Twitch Plays X"
|
|
||||||
class=`absolute max-w-full
|
|
||||||
top-1/2 left-1/2 [transform:translateX(-48%)_translateY(-48%)_translateZ(-50px)_rotateY(-3deg)] opacity-40
|
|
||||||
border-2 border-solid border-white rounded-xl`
|
|
||||||
`
|
|
||||||
width="700"
|
|
||||||
/>
|
|
||||||
<Image
|
|
||||||
src={TwitchPlays}
|
|
||||||
alt="Twitch Plays X"
|
|
||||||
width="700"
|
|
||||||
class=`absolute max-w-full
|
|
||||||
top-1/2 left-1/2
|
|
||||||
[transform:translateX(-50%)_translateY(-50%)_translateZ(-50px)_rotateY(-3deg)] opacity-100
|
|
||||||
border-2 border-solid border-white rounded-xl`
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
class="visit-div absolute top-1/2 left-1/2 aspect-video w-[700px] max-w-full [transform:translateX(-50%)_translateY(-50%)] rounded-xl border-2 border-solid border-white bg-[rgba(0,0,0,0.5)] opacity-0"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
href="https://github.com/liyunze-coding/TwitchPlaysX"
|
|
||||||
target="_blank"
|
|
||||||
class="absolute top-1/2 left-1/2 hidden [transform:translateX(-50%)_translateY(-50%)] rounded-xl bg-blue-600 px-5 py-3 font-bold opacity-100 transition-colors duration-300 hover:bg-white hover:text-blue-500 lg:block"
|
|
||||||
>View repository</a
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.image-container img {
|
|
||||||
transition: transform 0.5s ease-in-out;
|
|
||||||
}
|
|
||||||
@media (min-width: 1025px) {
|
|
||||||
.image-container:hover > img {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,217 +0,0 @@
|
||||||
---
|
|
||||||
import Card from "../elements/Card.astro";
|
|
||||||
import Line from "../elements/NetworkLine.astro";
|
|
||||||
---
|
|
||||||
|
|
||||||
<div class="h-fit w-full pt-20">
|
|
||||||
<h1 class="text-center text-5xl">Skills</h1>
|
|
||||||
<div class="flex flex-col items-center">
|
|
||||||
<div class="w-[90%] pt-10 md:w-[600px]">
|
|
||||||
<Card primaryColor="#19a7ce">
|
|
||||||
<div class="px-8 py-8">
|
|
||||||
<div class="justify-left flex w-full flex-col">
|
|
||||||
<h2 class="text-2xl font-bold">Frontend Development</h2>
|
|
||||||
</div>
|
|
||||||
<hr class="my-3 w-full" />
|
|
||||||
<p class="text-left">
|
|
||||||
I started my web development journey by building
|
|
||||||
websites and widgets using vanilla HTML, CSS, Javascript
|
|
||||||
and Express. As I learnt more about the fundamentals of
|
|
||||||
web development, I delved into frontend frameworks such
|
|
||||||
as Svelte, React and Astro.
|
|
||||||
</p>
|
|
||||||
<div
|
|
||||||
class="mt-4 flex w-full flex-row flex-wrap justify-start"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="bg-html hover:bg-html my-1 mr-1 w-fit cursor-default rounded-full px-3 py-1 text-white transition-colors duration-300 md:bg-gray-500"
|
|
||||||
>
|
|
||||||
HTML
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="my-1 mr-1 w-fit cursor-default rounded-full bg-blue-700 px-3 py-1 text-white transition-colors duration-300 hover:bg-blue-700 md:bg-gray-500"
|
|
||||||
>
|
|
||||||
CSS
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="my-1 mr-1 w-fit cursor-default rounded-full bg-yellow-400 px-3 py-1 text-black transition-colors duration-300 hover:bg-yellow-400 md:bg-gray-500 md:text-white md:hover:text-black"
|
|
||||||
>
|
|
||||||
Javascript
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-typescript hover:bg-typescript my-1 mr-1 w-fit cursor-default rounded-full px-3 py-1 text-white transition-colors duration-300 md:bg-gray-500 md:text-white md:hover:text-white"
|
|
||||||
>
|
|
||||||
TypeScript
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="hover:bg-svelte bg-svelte my-1 mr-1 w-fit cursor-default rounded-full px-3 py-1 text-white transition-colors duration-300 md:bg-gray-500"
|
|
||||||
>
|
|
||||||
Svelte
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-react hover:bg-react my-1 mr-1 w-fit cursor-default rounded-full px-3 py-1 text-black transition-colors duration-300 md:bg-gray-500 md:text-white md:hover:text-black"
|
|
||||||
>
|
|
||||||
React
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="my-1 mr-1 w-fit cursor-default rounded-full bg-green-500 px-3 py-1 text-black transition-colors duration-300 hover:bg-green-500 md:bg-gray-500 md:text-white md:hover:text-black"
|
|
||||||
>
|
|
||||||
Vue
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-wordpress hover:bg-wordpress my-1 mr-1 w-fit cursor-default rounded-full px-3 py-1 text-white transition-colors duration-300 md:bg-gray-500"
|
|
||||||
>
|
|
||||||
WordPress
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="my-1 mr-1 w-fit cursor-default rounded-full bg-white px-3 py-1 text-black transition-colors duration-300 hover:bg-white md:bg-gray-500 md:text-white md:hover:text-black"
|
|
||||||
>
|
|
||||||
Astro
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-htmx hover:bg-htmx my-1 mr-1 w-fit cursor-default rounded-full px-3 py-1 text-white transition-colors duration-300 hover:text-white md:bg-gray-500"
|
|
||||||
>
|
|
||||||
HTMX
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-tailwind hover:bg-tailwind my-1 mr-1 w-fit cursor-default rounded-full px-3 py-1 text-black transition-colors duration-300 md:bg-gray-500 md:text-white md:hover:text-black"
|
|
||||||
>
|
|
||||||
TailwindCSS
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Card>
|
|
||||||
<Line height="50px" />
|
|
||||||
<Card primaryColor="#474F7A">
|
|
||||||
<div class="px-8 py-8">
|
|
||||||
<div class="justify-left flex w-full flex-col">
|
|
||||||
<h2 class="text-2xl font-bold">Backend Development</h2>
|
|
||||||
</div>
|
|
||||||
<hr class="my-3 w-full" />
|
|
||||||
<p class="text-left">
|
|
||||||
With experience in various programming languages, I
|
|
||||||
learnt to setup databases, implement routing and
|
|
||||||
organized my code to ensure maintainability and
|
|
||||||
scalability.
|
|
||||||
</p>
|
|
||||||
<div
|
|
||||||
class="mt-4 flex w-full flex-row flex-wrap justify-start"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="bg-python hover:bg-python my-1 mr-1 w-fit cursor-default rounded-full px-3 py-1 text-white transition-colors duration-300 md:bg-gray-500"
|
|
||||||
>
|
|
||||||
Python
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-csharp hover:bg-csharp my-1 mr-1 w-fit cursor-default rounded-full px-3 py-1 text-white transition-colors duration-300 md:bg-gray-500"
|
|
||||||
>
|
|
||||||
C#
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-java hover:bg-java my-1 mr-1 w-fit cursor-default rounded-full px-3 py-1 text-white transition-colors duration-300 md:bg-gray-500"
|
|
||||||
>
|
|
||||||
Java
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-kotlin hover:bg-kotlin my-1 mr-1 w-fit cursor-default rounded-full px-3 py-1 text-white transition-colors duration-300 md:bg-gray-500"
|
|
||||||
>
|
|
||||||
Kotlin
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-php hover:bg-php my-1 mr-1 w-fit cursor-default rounded-full px-3 py-1 text-white transition-colors duration-300 md:bg-gray-500"
|
|
||||||
>
|
|
||||||
PHP
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-go hover:bg-go my-1 mr-1 w-fit cursor-default rounded-full px-3 py-1 text-white transition-colors duration-30 md:bg-gray-500"
|
|
||||||
>
|
|
||||||
Go
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-rust hover:bg-rust my-1 mr-1 w-fit cursor-default rounded-full px-3 py-1 text-white transition-colors duration-300 md:bg-gray-500"
|
|
||||||
>
|
|
||||||
Rust
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-postgresql hover:bg-postgresql my-1 mr-1 w-fit cursor-default rounded-full px-3 py-1 text-white transition-colors duration-300 md:bg-gray-500"
|
|
||||||
>
|
|
||||||
PostgreSQL
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-mysql hover:bg-mysql my-1 mr-1 w-fit cursor-default rounded-full px-3 py-1 text-white transition-colors duration-300 md:bg-gray-500"
|
|
||||||
>
|
|
||||||
MySQL
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-mongodb hover:bg-mongodb my-1 mr-1 w-fit cursor-default rounded-full px-3 py-1 text-white transition-colors duration-300 md:bg-gray-500"
|
|
||||||
>
|
|
||||||
MongoDB
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Card>
|
|
||||||
<Line height="50px" />
|
|
||||||
<Card primaryColor="#a1eebd">
|
|
||||||
<div class="px-8 py-8">
|
|
||||||
<div class="justify-left flex w-full flex-col">
|
|
||||||
<h2 class="text-2xl font-bold">Data Science</h2>
|
|
||||||
</div>
|
|
||||||
<hr class="my-3 w-full" />
|
|
||||||
<p class="text-left">
|
|
||||||
My first exposure to data science was through learning
|
|
||||||
Computer Vision. I learn how to use OpenCV in Python to
|
|
||||||
open a webcam and detect faces. Later on, I took a
|
|
||||||
Diploma course that is focused in data science, where I
|
|
||||||
learnt how to do the fundamentals of data science such
|
|
||||||
as extracting, transforming and loading data, as well as
|
|
||||||
data visualisation.
|
|
||||||
</p>
|
|
||||||
<div
|
|
||||||
class="mt-4 flex w-full flex-row flex-wrap justify-start"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="bg-python hover:bg-python my-1 mr-1 w-fit cursor-default rounded-full px-3 py-1 text-white transition-colors duration-300 md:bg-gray-500"
|
|
||||||
>
|
|
||||||
Python
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="my-1 mr-1 w-fit cursor-default rounded-full bg-cyan-500 px-3 py-1 text-white transition-colors duration-300 hover:bg-cyan-500 md:bg-gray-500"
|
|
||||||
>
|
|
||||||
R
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-opencv hover:bg-opencv my-1 mr-1 w-fit cursor-default rounded-full px-3 py-1 text-white transition-colors duration-300 md:bg-gray-500"
|
|
||||||
>
|
|
||||||
OpenCV
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="my-1 mr-1 w-fit cursor-default rounded-full bg-blue-500 px-3 py-1 text-black transition-colors duration-300 hover:bg-blue-500 md:bg-gray-500 md:text-white md:hover:text-black"
|
|
||||||
>
|
|
||||||
SAS
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="bg-mysql hover:bg-mysql my-1 mr-1 w-fit cursor-default rounded-full px-3 py-1 text-white transition-colors duration-300 md:bg-gray-500"
|
|
||||||
>
|
|
||||||
MySQL
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="my-1 mr-1 w-fit cursor-default rounded-full bg-blue-800 px-3 py-1 text-white transition-colors duration-300 hover:bg-blue-800 md:bg-gray-500"
|
|
||||||
>
|
|
||||||
Pandas
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="my-1 mr-1 w-fit cursor-default rounded-full bg-green-700 px-3 py-1 text-white transition-colors duration-300 hover:bg-green-700 md:bg-gray-500"
|
|
||||||
>
|
|
||||||
Selenium
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="my-1 mr-1 w-fit cursor-default rounded-full bg-gray-200 px-3 py-1 text-black transition-colors duration-300 hover:bg-gray-200 md:bg-gray-500 md:text-white md:hover:text-black"
|
|
||||||
>
|
|
||||||
BeautifulSoup4
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
72
src/components/skills/MoreSkills.astro
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
---
|
||||||
|
import Card from "../global/Card.astro";
|
||||||
|
import Line from "../global/NetworkLine.astro";
|
||||||
|
import Skill from "./Skill.astro";
|
||||||
|
---
|
||||||
|
|
||||||
|
<div id="Experience" class="h-fit">
|
||||||
|
<div class="flex flex-col items-center">
|
||||||
|
<div class="w-[90%] md:w-[600px]">
|
||||||
|
<Line height="50px" />
|
||||||
|
<Skill
|
||||||
|
title="Content Creation"
|
||||||
|
primaryColor="#9D76C1"
|
||||||
|
tags={[
|
||||||
|
{ text: "OBS", bgColor: "#141414" },
|
||||||
|
{
|
||||||
|
text: "DaVinci Resolve",
|
||||||
|
bgColor: "white",
|
||||||
|
hoverTextColor: "black",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "Twitch",
|
||||||
|
bgColor: "var(--color-purple-500)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "YouTube",
|
||||||
|
bgColor: "red",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
Since I was little, I loved watching YouTube videos and the idea
|
||||||
|
of bringing joy and laughter to a wider audience. Thus, I began
|
||||||
|
my journey in content creation through YouTube videos and Twitch
|
||||||
|
streaming. I typically do coworking & study streams to keep
|
||||||
|
myself accountable and encourage productivity amongst viewers. I
|
||||||
|
also do software and game development streams where I showcase
|
||||||
|
my workflow.
|
||||||
|
</Skill>
|
||||||
|
<Line height="50px" />
|
||||||
|
<Skill
|
||||||
|
primaryColor="#9D76C1"
|
||||||
|
title="Mobile Development"
|
||||||
|
tags={[
|
||||||
|
{
|
||||||
|
text: "Android",
|
||||||
|
bgColor: "#106539",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "Java",
|
||||||
|
bgColor: "var(--color-java)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "Kotlin",
|
||||||
|
bgColor: "var(--color-kotlin)",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
><p class="text-left">
|
||||||
|
In my Mobile App Development unit in University, I am tasked
|
||||||
|
to develop Android apps using Android Studio. The final app
|
||||||
|
project I had developed was a LLM-powered quiz app with
|
||||||
|
features such as choosing your own topics, viewing your
|
||||||
|
question attempt history afterwards, and upgrading your tier
|
||||||
|
with Google Pay.
|
||||||
|
</p>
|
||||||
|
<p class="text-left">
|
||||||
|
The marking tutor was impressed with my work, and offered me
|
||||||
|
to join a research lab because I had good potential.
|
||||||
|
</p>
|
||||||
|
</Skill>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
63
src/components/skills/Skill.astro
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
---
|
||||||
|
import Card from "../global/Card.astro";
|
||||||
|
|
||||||
|
interface Tag {
|
||||||
|
text: string;
|
||||||
|
bgColor: string;
|
||||||
|
textColor?: string;
|
||||||
|
hoverTextColor?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
title: string;
|
||||||
|
tags?: Tag[];
|
||||||
|
primaryColor: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { title, tags, primaryColor } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<div class="mx-auto w-[90%] md:w-[600px]">
|
||||||
|
<Card primaryColor={primaryColor}>
|
||||||
|
<div class="px-8 py-8">
|
||||||
|
<div class="flex w-full flex-col">
|
||||||
|
<h2 class="text-2xl font-bold">{title}</h2>
|
||||||
|
</div>
|
||||||
|
<hr class="my-3 w-full" />
|
||||||
|
<p class="text-left">
|
||||||
|
<slot />
|
||||||
|
</p>
|
||||||
|
<div class="mt-5 flex w-full flex-row flex-wrap justify-start">
|
||||||
|
{
|
||||||
|
tags?.map((tag, index) => (
|
||||||
|
<div
|
||||||
|
class={`tag-${index} my-1 mr-1 w-fit cursor-default rounded-full px-3 py-1 transition-colors duration-300`}
|
||||||
|
style={`--tag-bg: ${tag.bgColor || "#000"}; --tag-text: ${tag.textColor || "#ffffff"};
|
||||||
|
--tag-hover-text: ${tag.hoverTextColor || "#ffffff"}`}
|
||||||
|
>
|
||||||
|
{tag.text}
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
[class*="tag-"] {
|
||||||
|
background-color: var(--tag-bg);
|
||||||
|
color: var(--tag-text);
|
||||||
|
|
||||||
|
@media (width >= 48rem /* 768px */) {
|
||||||
|
background-color: var(--color-gray-500);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
@media (hover: hover) {
|
||||||
|
background-color: var(--tag-bg);
|
||||||
|
color: var(--tag-hover-text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
172
src/components/skills/SkillsComponent.astro
Normal file
|
|
@ -0,0 +1,172 @@
|
||||||
|
---
|
||||||
|
import Card from "../global/Card.astro";
|
||||||
|
import Line from "../global/NetworkLine.astro";
|
||||||
|
import Skill from "./Skill.astro";
|
||||||
|
---
|
||||||
|
|
||||||
|
<div class="h-fit w-full pt-20">
|
||||||
|
<h1 class="text-center text-5xl">Skills</h1>
|
||||||
|
<div class="flex flex-col items-center">
|
||||||
|
<div class="w-[90%] pt-10 md:w-[600px]">
|
||||||
|
<Skill
|
||||||
|
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)",
|
||||||
|
hoverTextColor: "black",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "Typescript",
|
||||||
|
bgColor: "var(--color-typescript)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "Svelte",
|
||||||
|
bgColor: "var(--color-svelte)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "React",
|
||||||
|
bgColor: "var(--color-react)",
|
||||||
|
hoverTextColor: "black",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "Vue",
|
||||||
|
bgColor: "var(--color-green-500)",
|
||||||
|
hoverTextColor: "black",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "WordPress",
|
||||||
|
bgColor: "var(--color-wordpress)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "Astro",
|
||||||
|
bgColor: "white",
|
||||||
|
hoverTextColor: "black",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "HTMX",
|
||||||
|
bgColor: "var(--color-htmx)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "TailwindCSS",
|
||||||
|
bgColor: "var(--color-tailwind)",
|
||||||
|
hoverTextColor: "black",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
I started my web development journey by building websites and
|
||||||
|
widgets using vanilla HTML, CSS, Javascript and Express. As I
|
||||||
|
learnt more about the fundamentals of web development, I delved
|
||||||
|
into frontend frameworks such as Svelte, React and Astro.
|
||||||
|
</Skill>
|
||||||
|
|
||||||
|
<Line height="50px" />
|
||||||
|
<Skill
|
||||||
|
title="Backend Development"
|
||||||
|
primaryColor="#474F7A"
|
||||||
|
tags={[
|
||||||
|
{
|
||||||
|
text: "Python",
|
||||||
|
bgColor: "var(--color-python)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "C#",
|
||||||
|
bgColor: "var(--color-csharp)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "Java",
|
||||||
|
bgColor: "var(--color-java)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "Kotlin",
|
||||||
|
bgColor: "var(--color-kotlin)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "PHP",
|
||||||
|
bgColor: "var(--color-php)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "Go",
|
||||||
|
bgColor: "var(--color-go)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "Rust",
|
||||||
|
bgColor: "var(--color-rust)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "PostgreSQL",
|
||||||
|
bgColor: "var(--color-postgresql)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "MySQL",
|
||||||
|
bgColor: "var(--color-mysql)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "MongoDB",
|
||||||
|
bgColor: "var(--color-mongodb)",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
With experience in various programming languages, I learnt to
|
||||||
|
setup databases, implement routing and organized my code to
|
||||||
|
ensure maintainability and scalability.
|
||||||
|
</Skill>
|
||||||
|
<Line height="50px" />
|
||||||
|
<Skill
|
||||||
|
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",
|
||||||
|
hoverTextColor: "black",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
My first exposure to data science was through learning Computer
|
||||||
|
Vision. I learn how to use OpenCV in Python to open a webcam and
|
||||||
|
detect faces. Later on, I took a Diploma course that is focused
|
||||||
|
in data science, where I learnt how to do the fundamentals of
|
||||||
|
data science such as extracting, transforming and loading data,
|
||||||
|
as well as data visualisation.
|
||||||
|
</Skill>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
---
|
---
|
||||||
import Card from "../elements/Card.astro";
|
import Card from "../global/Card.astro";
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="flex w-full flex-col items-center justify-center">
|
<div class="flex w-full flex-col items-center justify-center">
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
import { getCollection } from "astro:content";
|
import { getCollection } from "astro:content";
|
||||||
import BackToBlogs from "../../components/sections/BackToBlogs.astro";
|
import BackToBlogs from "../../components/blog/BackToBlogs.astro";
|
||||||
import Layout from "../../layouts/Layout.astro";
|
import Layout from "../../layouts/Layout.astro";
|
||||||
import Footer from "../../components/sections/FooterComponent.astro";
|
import Footer from "../../components/global/FooterComponent.astro";
|
||||||
|
|
||||||
export async function getStaticPaths() {
|
export async function getStaticPaths() {
|
||||||
const blogEntries = await getCollection("blog");
|
const blogEntries = await getCollection("blog");
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
---
|
---
|
||||||
import NavBar from "../../components/sections/NavBar.astro";
|
|
||||||
import Layout from "../../layouts/Layout.astro";
|
import Layout from "../../layouts/Layout.astro";
|
||||||
import Card from "../../components/elements/Card.astro";
|
import Card from "../../components/global/Card.astro";
|
||||||
import Footer from "../../components/sections/FooterComponent.astro";
|
import Footer from "../../components/global/FooterComponent.astro";
|
||||||
import { getCollection } from "astro:content";
|
import { getCollection } from "astro:content";
|
||||||
|
|
||||||
const blogPosts = await getCollection("blog");
|
const blogPosts = await getCollection("blog");
|
||||||
|
|
@ -45,7 +44,7 @@ const blogPosts = await getCollection("blog");
|
||||||
fill="none"
|
fill="none"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
stroke-width="1.5"
|
stroke-width="1.5"
|
||||||
class="absolute right-3 top-3 size-6 stroke-white transition-all duration-150 group-hover:right-2 group-hover:top-2 group-hover:stroke-green-400"
|
class="absolute top-3 right-3 size-6 stroke-white transition-all duration-150 group-hover:top-2 group-hover:right-2 group-hover:stroke-green-400"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
---
|
---
|
||||||
import NavBar from "../components/sections/NavBar.astro";
|
import NavBar from "../components/global/NavBar.astro";
|
||||||
import Layout from "../layouts/Layout.astro";
|
import Layout from "../layouts/Layout.astro";
|
||||||
import ContactComponent from "../components/sections/ContactComponent.svelte";
|
import ContactComponent from "../components/contact/ContactComponent.svelte";
|
||||||
import Card from "../components/elements/Card.astro";
|
import Card from "../components/global/Card.astro";
|
||||||
import Footer from "../components/sections/FooterComponent.astro";
|
import Footer from "../components/global/FooterComponent.astro";
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout
|
<Layout
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
---
|
---
|
||||||
import NavBar from "../components/sections/NavBar.astro";
|
import NavBar from "../components/global/NavBar.astro";
|
||||||
import Layout from "../layouts/Layout.astro";
|
import Layout from "../layouts/Layout.astro";
|
||||||
import EducationComponent from "../components/sections/ExperienceComponent.astro";
|
import EducationComponent from "../components/experience/ExperienceComponent.astro";
|
||||||
import MoreExperience from "../components/sections/MoreExperience.astro";
|
import MoreExperience from "../components/experience/MoreExperience.astro";
|
||||||
import Footer from "../components/sections/FooterComponent.astro";
|
import Footer from "../components/global/FooterComponent.astro";
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout
|
<Layout
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
import Layout from "../layouts/Layout.astro";
|
import Layout from "../layouts/Layout.astro";
|
||||||
import Card from "../components/elements/Card.astro";
|
import Card from "../components/global/Card.astro";
|
||||||
import Footer from "../components/sections/FooterComponent.astro";
|
import Footer from "../components/global/FooterComponent.astro";
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout title="Socials" description="Check out Ryan's socials">
|
<Layout title="Socials" description="Check out Ryan's socials">
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
---
|
---
|
||||||
import NavBar from "../components/sections/NavBar.astro";
|
import NavBar from "../components/global/NavBar.astro";
|
||||||
import Layout from "../layouts/Layout.astro";
|
import Layout from "../layouts/Layout.astro";
|
||||||
import NetworkLine from "../components/elements/NetworkLine.astro";
|
import NetworkLine from "../components/global/NetworkLine.astro";
|
||||||
import WhatIDo from "../components/sections/WhatIDoComponent.astro";
|
import WhatIDo from "../components/what-i-do/WhatIDoComponent.astro";
|
||||||
import Intro from "../components/sections/IntroComponent.svelte";
|
import Intro from "../components/home/IntroComponent.svelte";
|
||||||
import Projects from "../components/sections/ProjectsComponent.astro";
|
import Projects from "../components/projects/ProjectsComponent.astro";
|
||||||
import Experience from "../components/sections/ExperienceComponent.astro";
|
import Experience from "../components/experience/ExperienceComponent.astro";
|
||||||
import Skills from "../components/sections/SkillsComponent.astro";
|
import Skills from "../components/skills/SkillsComponent.astro";
|
||||||
import Contact from "../components/sections/ContactComponent.svelte";
|
import Contact from "../components/contact/ContactComponent.svelte";
|
||||||
import Card from "../components/elements/Card.astro";
|
import Card from "../components/global/Card.astro";
|
||||||
import Footer from "../components/sections/FooterComponent.astro";
|
import Footer from "../components/global/FooterComponent.astro";
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout
|
<Layout
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
---
|
---
|
||||||
import NavBar from "../components/sections/NavBar.astro";
|
import NavBar from "../components/global/NavBar.astro";
|
||||||
import Layout from "../layouts/Layout.astro";
|
import Layout from "../layouts/Layout.astro";
|
||||||
import ProjectsComponent from "../components/sections/ProjectsComponent.astro";
|
import ProjectsComponent from "../components/projects/ProjectsComponent.astro";
|
||||||
import MoreProjects from "../components/sections/MoreProjects.svelte";
|
import MoreProjects from "../components/projects/MoreProjects.svelte";
|
||||||
import Footer from "../components/sections/FooterComponent.astro";
|
import Footer from "../components/global/FooterComponent.astro";
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout title="Projects" description="View what projects RythonDev has made">
|
<Layout title="Projects" description="View what projects RythonDev has made">
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
---
|
---
|
||||||
import NavBar from "../components/sections/NavBar.astro";
|
import NavBar from "../components/global/NavBar.astro";
|
||||||
import Layout from "../layouts/Layout.astro";
|
import Layout from "../layouts/Layout.astro";
|
||||||
import SkillsComponent from "../components/sections/SkillsComponent.astro";
|
import SkillsComponent from "../components/skills/SkillsComponent.astro";
|
||||||
import MoreSkills from "../components/sections/MoreSkills.astro";
|
import MoreSkills from "../components/skills/MoreSkills.astro";
|
||||||
import Footer from "../components/sections/FooterComponent.astro";
|
import Footer from "../components/global/FooterComponent.astro";
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout
|
<Layout
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
import Layout from "../layouts/Layout.astro";
|
import Layout from "../layouts/Layout.astro";
|
||||||
import StreamScheduleComponent from "../components/sections/StreamSchedule.svelte";
|
import StreamScheduleComponent from "../components/socials/StreamSchedule.svelte";
|
||||||
import Footer from "../components/sections/FooterComponent.astro";
|
import Footer from "../components/global/FooterComponent.astro";
|
||||||
import { Image } from "astro:assets";
|
import { Image } from "astro:assets";
|
||||||
import profile from "./_images/profile.webp";
|
import profile from "./_images/profile.webp";
|
||||||
import WebsiteIcon from "./_images/website-icon.svg";
|
import WebsiteIcon from "./_images/website-icon.svg";
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
---
|
---
|
||||||
import NavBar from "../components/sections/NavBar.astro";
|
import NavBar from "../components/global/NavBar.astro";
|
||||||
import Layout from "../layouts/Layout.astro";
|
import Layout from "../layouts/Layout.astro";
|
||||||
import WhatIDoComponent from "../components/sections/WhatIDoComponent.astro";
|
import WhatIDoComponent from "../components/what-i-do/WhatIDoComponent.astro";
|
||||||
import Card from "../components/elements/Card.astro";
|
import Card from "../components/global/Card.astro";
|
||||||
import Line from "../components/elements/NetworkLine.astro";
|
import Line from "../components/global/NetworkLine.astro";
|
||||||
import Footer from "../components/sections/FooterComponent.astro";
|
import Footer from "../components/global/FooterComponent.astro";
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout
|
<Layout
|
||||||
|
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
/** @type {import('tailwindcss').Config} */
|
|
||||||
module.exports = {
|
|
||||||
content: ["./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}"],
|
|
||||||
theme: {
|
|
||||||
extend: {
|
|
||||||
keyframes: {
|
|
||||||
gradient: {
|
|
||||||
"0%": {
|
|
||||||
"background-position": "0% 50%",
|
|
||||||
},
|
|
||||||
"50%": {
|
|
||||||
"background-position": "100% 50%",
|
|
||||||
},
|
|
||||||
"100%": {
|
|
||||||
"background-position": "0% 50%",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
fadeIn: {
|
|
||||||
"0%": { opacity: 0 },
|
|
||||||
"100%": { opacity: 1 },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
animation: {
|
|
||||||
gradient: "gradient 15s ease infinite",
|
|
||||||
fadeIn: "fadeIn 1s ease",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: [],
|
|
||||||
};
|
|
||||||