updated site including discord

This commit is contained in:
liyunze 2025-11-01 01:32:44 +11:00
parent a7f3531b9c
commit 389b1388be
8 changed files with 221 additions and 270 deletions

View file

@ -10,19 +10,16 @@ import Line from "../global/NetworkLine.astro";
<Card primaryColor="#F6DFD8" className="animate-fadeIn">
<div class="px-4 py-4 md:px-8 md:py-8">
<div class="mb-3 flex w-full flex-col justify-start gap-1">
<h2 class="text-xl font-bold">
Full Stack Developer (Contract)
</h2>
<h2 class="text-xl font-bold">Full Stack Developer</h2>
<h3 class="font-bold">@ Hyson Horizon</h3>
<h3>Dec 2024 - Present</h3>
</div>
<hr class="mb-3 w-full" />
<p class="mb-3">
Led implementation of frontend development of websites.
Efficiently translated designs into code, while ensuring
maintainability, accessibility and performance. Actively
researching and developing for LLM integration into
product.
Led implementation of frontend development, while also
developing and intergating a CMS on the backend for
website development. Actively contributing to LLM
product research and development.
</p>
<h3 class="mb-1 text-lg font-bold">Relevant skills:</h3>
<div
@ -31,9 +28,10 @@ import Line from "../global/NetworkLine.astro";
<ul class="list-inside list-disc">
<li>NextJS</li>
<li>React</li>
<li>Astro</li>
<li>Payload CMS</li>
</ul>
<ul class="list-inside list-disc">
<li>Astro</li>
<li>Typescript</li>
<li>TailwindCSS</li>
</ul>
@ -94,12 +92,13 @@ import Line from "../global/NetworkLine.astro";
>
<ul class="list-inside list-disc">
<li>WordPress & PHP</li>
<li>Typescript</li>
<li>TailwindCSS</li>
<li>NextJS</li>
<li>React</li>
</ul>
<ul class="list-inside list-disc">
<li>Adobe XD</li>
<li>NextJS & React</li>
<li>Typescript</li>
<li>TailwindCSS</li>
</ul>
</div>
</div>

View file

@ -1,7 +1,8 @@
---
type Props = {
href?: string;
primaryColor: string;
primaryColor?: string;
shadowColor?: string;
bgColor?: string;
scaleOnHover?: boolean;
pixelHeight?: string;
@ -11,6 +12,7 @@ type Props = {
const {
href,
primaryColor,
shadowColor = "rgb(12,12,12)",
bgColor = "var(--color-secondary)",
scaleOnHover = false,
pixelHeight = "70px",
@ -36,7 +38,7 @@ const {
{
!href && (
<div
class="card z-10 mb-0"
class="card z-10 mb-0 rounded-xl shadow-xl"
class:list={[{ scale: scaleOnHover }, className]}
>
<div class="card-content">
@ -47,7 +49,7 @@ const {
}
</>
<style define:vars={{ primaryColor, bgColor, pixelHeight }}>
<style define:vars={{ bgColor, pixelHeight, shadowColor }}>
* {
box-sizing: border-box;
}
@ -60,50 +62,15 @@ const {
}
.card {
height: inherit;
position: relative;
background-color: var(--bgColor);
border: 1px solid rgb(255 255 255 / 10%);
border-radius: 1.5rem;
background: #1c1c1c;
background: linear-gradient(
135deg,
rgba(18, 18, 18, 1) 0%,
rgba(30, 30, 30, 1) 33%,
rgba(25, 25, 25, 1) 66%,
rgba(19, 19, 19, 1) 100%
);
--tw-shadow-color: var(--shadowColor);
padding: 0.5rem;
}
.card:after {
content: "";
height: var(--pixelHeight);
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:hover:after {
top: 25%;
opacity: 1;
} */
.card.scale {
transition: transform 0.5s ease;
}
.card.scale:hover {
transform: scale(1.05);
}
.card-content {
display: flex;
flex-direction: column;
gap: 1rem;
background-position: 50% 50%;
background-size: 1.1rem 1.1rem;
}
</style>

View file

@ -7,7 +7,7 @@ import { Image } from "astro:assets";
---
<div class="w-[90%] md:w-[600px] lg:w-1/2">
<Card primaryColor="#BEADFA" className="animate-fadeIn">
<Card shadowColor="rgb(4, 57, 57)" className="animate-fadeIn">
<div id="intro" class="flex h-fit flex-col text-white">
<div class="w-full px-5 pt-10 pb-2 lg:px-10">
<div class="flex h-20 flex-row">

View file

@ -115,11 +115,7 @@ const leftProject = position == "left";
{
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"};
`}
class="my-1 mr-1 w-fit rounded-full px-3 py-1 transition-colors duration-300 text-white bg-secondary"
>
{tag.text}
</div>

View file

@ -1,176 +1,172 @@
<script lang="ts">
import { onMount } from "svelte";
import { onMount } from "svelte";
interface Tag {
text: string;
textColor: string;
bgColor: string;
}
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[];
}
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();
let {
position = "left",
image_src,
image_alt,
video_src,
title,
description,
tags = [],
}: Props = $props();
const positionLeft = position == "left";
const positionLeft = position == "left";
onMount(() => {
const videos = document.querySelectorAll<HTMLVideoElement>(".playable");
onMount(() => {
const videos = document.querySelectorAll<HTMLVideoElement>(".playable");
let userInteracted = false;
let userInteracted = false;
const handleUserInteraction = () => {
userInteracted = true;
document.removeEventListener("click", handleUserInteraction);
document.removeEventListener("keydown", handleUserInteraction);
};
const handleUserInteraction = () => {
userInteracted = true;
document.removeEventListener("click", handleUserInteraction);
document.removeEventListener("keydown", handleUserInteraction);
};
document.addEventListener("click", handleUserInteraction);
document.addEventListener("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();
}
});
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;
});
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();
}
}
});
});
// 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="mb-10 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}
class="mb-10 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="background-img absolute
<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="background-img absolute
top-1/2
left-1/2 max-w-full rounded-xl border-2
border-solid border-white
opacity-40
{positionLeft ? 'left' : 'right'}"
width="700"
/>
width="700"
/>
<!-- svelte-ignore a11y_media_has_caption -->
<video
width="700"
class="playable frontfacing-vid absolute
<!-- svelte-ignore a11y_media_has_caption -->
<video
width="700"
class="playable frontfacing-vid absolute
top-1/2 left-1/2 max-w-full rounded-xl
border-2
border-solid border-white
opacity-100
{positionLeft ? 'left' : 'right'}"
>
<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
>
<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
>
<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
>
{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
>
{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>
>
{#each tags as tag}
<div
class="bg-secondary my-1 mr-1
w-fit rounded-full px-3
py-1 text-white transition-colors duration-300"
>
{tag.text}
</div>
{/each}
</div>
</div>
</div>
<style>
.background-img.left {
transform: translateX(calc(-50% + 25px)) translateY(calc(-50% + 5px))
translateZ(-50px) rotateY(5deg);
}
.background-img.left {
transform: translateX(calc(-50% + 25px)) translateY(calc(-50% + 5px))
translateZ(-50px) rotateY(5deg);
}
.background-img.right {
transform: translateX(calc(-50%)) translateY(calc(-50% + 5px))
translateZ(-50px) rotateY(-3deg);
}
.background-img.right {
transform: translateX(calc(-50%)) translateY(calc(-50% + 5px))
translateZ(-50px) rotateY(-3deg);
}
.frontfacing-vid.left {
transform: translateX(calc(-50% + 35px)) translateY(calc(-50%))
translateZ(-50px) rotateY(5deg);
}
.frontfacing-vid.left {
transform: translateX(calc(-50% + 35px)) translateY(calc(-50%))
translateZ(-50px) rotateY(5deg);
}
.frontfacing-vid.right {
transform: translateX(calc(-50% - 10px)) translateY(-50%)
translateZ(-50px) rotateY(-3deg);
}
.frontfacing-vid.right {
transform: translateX(calc(-50% - 10px)) translateY(-50%)
translateZ(-50px) rotateY(-3deg);
}
.image-container:hover .frontfacing-vid,
.image-container:hover .background-img {
transform: translate(-50%, -50%);
}
.image-container:hover .frontfacing-vid,
.image-container:hover .background-img {
transform: translate(-50%, -50%);
}
</style>

View file

@ -33,9 +33,7 @@ const { title, tags, primaryColor, className = "" } = Astro.props;
{
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"}`}
class={`tag-${index} my-1 mr-1 w-fit cursor-default rounded-full bg-[#303030] px-3 py-1 text-white transition-colors duration-300`}
>
{tag.text}
</div>
@ -45,10 +43,3 @@ const { title, tags, primaryColor, className = "" } = Astro.props;
</div>
</Card>
</div>
<style>
[class*="tag-"] {
background-color: var(--tag-bg);
color: var(--tag-text);
}
</style>

View file

@ -9,5 +9,5 @@ import InfoLayout from "../layouts/InfoLayout.astro";
/>
<script is:inline>
window.location.href = "https://discord.gg/UnHyHkhbga";
window.location.href = "https://discord.gg/F5efU63Prz";
</script>

View file

@ -1,74 +1,76 @@
@import "tailwindcss";
@theme {
--color-html: #b11700;
--color-typescript: #3178c6;
--color-svelte: #b11700;
--color-react: #00d8ff;
--color-wordpress: #21759b;
--color-htmx: #3366cc;
--color-tailwind: #07b6d4;
--color-python: #3776ab;
--color-csharp: #672079;
--color-java: #ed8b00;
--color-kotlin: #7f52ff;
--color-php: #3d5694;
--color-go: #006080;
--color-rust: #b11700;
--color-postgresql: #4479a1;
--color-mysql: #1d6998;
--color-mongodb: #09934e;
--color-opencv: #10652f;
--color-win32api: #0078d4;
--color-primary: #fafafa;
--color-secondary: #1d1c20;
--color-html: #b11700;
--color-typescript: #3178c6;
--color-svelte: #b11700;
--color-react: #00d8ff;
--color-wordpress: #21759b;
--color-htmx: #3366cc;
--color-tailwind: #07b6d4;
--color-python: #3776ab;
--color-csharp: #672079;
--color-java: #ed8b00;
--color-kotlin: #7f52ff;
--color-php: #3d5694;
--color-go: #006080;
--color-rust: #b11700;
--color-postgresql: #4479a1;
--color-mysql: #1d6998;
--color-mongodb: #09934e;
--color-opencv: #10652f;
--color-win32api: #0078d4;
--color-primary: #fafafa;
--color-secondary: #1d1c20;
--animate-fadeIn: fadeIn 0.5s ease-in-out;
--animate-fadeUp: fadeUp 0.5s ease-in-out;
--animate-glow: glow 2s ease infinite;
--animate-fadeIn: fadeIn 0.5s ease-in-out;
--animate-fadeUp: fadeUp 0.5s ease-in-out;
--animate-glow: glow 2s ease infinite;
@keyframes fadeIn {
0% {
opacity: 0;
}
/* --gradient-primary: */
100% {
opacity: 100%;
}
}
@keyframes fadeIn {
0% {
opacity: 0;
}
@keyframes fadeUp {
0% {
opacity: 0;
translate: 0px 10px;
}
100% {
opacity: 100%;
}
}
50% {
opacity: 100%;
translate: 0px 0px;
}
}
@keyframes fadeUp {
0% {
opacity: 0;
translate: 0px 10px;
}
@keyframes glow {
0% {
scale: 1;
opacity: 100%;
}
100% {
scale: 4;
opacity: 5%;
}
}
50% {
opacity: 100%;
translate: 0px 0px;
}
}
@keyframes glow {
0% {
scale: 1;
opacity: 100%;
}
100% {
scale: 4;
opacity: 5%;
}
}
}
.view-fadeUp {
translate: 0px 30px;
opacity: 0;
translate: 0px 30px;
opacity: 0;
transition: all 0.5s ease;
transition: all 0.5s ease;
}
.view-appear {
translate: 0px 0px;
opacity: 100%;
translate: 0px 0px;
opacity: 100%;
}