diff --git a/components/navbar.tsx b/components/navbar.tsx index 4bb0fa4..89daa22 100644 --- a/components/navbar.tsx +++ b/components/navbar.tsx @@ -168,6 +168,14 @@ const SocialLinksContainer = styled.div` color: rgb(var(--white)); } } + + @media (min-width: 768px) { + display: none; + } + + @media (min-width: 820px) { + display: flex; + } ` const Topbar = styled.div` diff --git a/components/projects.tsx b/components/projects.tsx index 81c4274..d14750d 100644 --- a/components/projects.tsx +++ b/components/projects.tsx @@ -5,6 +5,7 @@ import { useState } from "react" import { CaretLeftFill, CaretRightFill, Git } from "react-bootstrap-icons" import projects from "@/data/projects" import Link from "next/link" +import Image from "next/image" const ProjectsContainer = styled.section` width: 100%; @@ -15,6 +16,11 @@ const ProjectsContainer = styled.section` align-items: center; justify-content: center; gap: 2rem; + + @media (max-width: 1200px) { + padding: 1rem; + gap: 1rem; + } ` const ProjectsContent = styled.div` @@ -27,23 +33,36 @@ const ProjectsContent = styled.div` h2 { font-size: 3rem; font-weight: 600; + + @media (max-width: 1200px) { + font-size: 2rem; + } } p { font-size: 1.2rem; font-weight: 400; - } -` -const CarouselContainer = styled.div` - width: 100%; - position: relative; + @media (max-width: 1200px) { + font-size: 1rem; + } + } ` const CarouselWrapper = styled.div` display: flex; transition: transform 0.5s ease-in-out; gap: 2rem; + + @media (max-width: 1200px) { + flex-direction: column; + align-items: center; + } +` + +const CarouselContainer = styled.div` + width: 100%; + position: relative; ` const ProjectCard = styled.div` @@ -61,52 +80,42 @@ const ProjectCard = styled.div` h3 { font-size: 2rem; font-weight: 600; + + @media (max-width: 1200px) { + font-size: 1.5rem; + } } p { font-size: 1.2rem; font-weight: 400; - } - a { - font-size: 1.2rem; - font-weight: 600; - color: rgb(var(--white)); - background-color: rgb(var(--blue)); - padding: 0.5rem 1rem; - border-radius: 0.25rem; - text-decoration: none; - transition: background-color 0.2s; - - &:hover { - background-color: rgb(var(--light-blue)); + @media (max-width: 1200px) { + font-size: 1rem; } } img { - width: 200px; + width: 100%; height: 200px; object-fit: cover; border-radius: 1rem; + + @media (max-width: 1200px) { + height: 150px; + } } &:not(.active) { opacity: 0.5; transform: scale(0.8); } -` -const StateIndicator = styled.div` - position: absolute; - top: -1rem; - right: -1rem; - font-size: 1.5rem; - text-align: center; - line-height: 3rem; - background-color: rgba(var(--white)); - border-radius: 50%; - width: 3rem; - height: 3rem; + @media (max-width: 1200px) { + width: 100%; + height: auto; + padding: 1rem; + } ` const NavigationButton = styled.button` @@ -124,6 +133,10 @@ const NavigationButton = styled.button` &:hover { color: rgb(var(--white)); } + + @media (max-width: 1200px) { + display: none; + } ` const PrevButton = styled(NavigationButton)` @@ -139,6 +152,10 @@ const CarouselIndicator = styled.div` justify-content: center; gap: 0.5rem; margin-top: 1rem; + + @media (max-width: 1200px) { + margin-top: 0.5rem; + } ` const IndicatorDot = styled.div` @@ -151,6 +168,11 @@ const IndicatorDot = styled.div` &.active { background-color: rgb(var(--white)); } + + @media (max-width: 1200px) { + width: 8px; + height: 8px; + } ` const TechStack = styled.div` @@ -159,14 +181,72 @@ const TechStack = styled.div` gap: 0.5rem; span { - font-size: 1rem; + font-size: 0.8rem; font-weight: 400; background-color: rgba(var(--white), 0.1); padding: 0.25rem 0.5rem; border-radius: 0.25rem; + + @media (max-width: 1200px) { + font-size: 0.7rem; + padding: 0.2rem 0.4rem; + } } ` +const Links = styled.div` + display: flex; + flex-direction: row; + justify-content: space-between; + gap: 1rem; + margin-top: auto; +` + +const ViewLink = styled(Link)` + font-size: 1.2rem; + font-weight: 600; + color: rgb(var(--white)); + background-color: rgba(var(--primary), 0.8); + padding: 0.5rem 1rem; + border-radius: 0.25rem; + text-decoration: none; + transition: background-color 0.2s; + + &:hover { + background-color: rgb(var(--primary)); + } + + @media (max-width: 1200px) { + font-size: 1rem; + padding: 0.4rem 0.8rem; + } +` + +const SourceLink = styled(Link)` + svg { + transition: color 0.3s; + color: rgba(var(--white), 0.8); + } + + &:hover svg { + color: rgb(var(--white)); + } + + @media (max-width: 1200px) { + svg { + width: 25px; + height: 25px; + } + } +` + +const StateIndicator = styled.div` + position: absolute; + top: 1rem; + right: 1rem; + font-size: 1.5rem; +` + const Projects = () => { const [currentIndex, setCurrentIndex] = useState(0) const projectCount = projects.length @@ -188,7 +268,7 @@ const Projects = () => { } return ( - +

📂 My Projects

Here are some of the projects I've worked on recently

@@ -206,12 +286,17 @@ const Projects = () => { } }} > - + {project.state === "wip" ? "🔄" : "✅"}

{project.title}

{project.image && ( - {project.title} + {project.title} )}

{project.description}

@@ -219,10 +304,24 @@ const Projects = () => { {tech} ))} - {project.href && View Project} - - - + + {project.href && ( + + View Project + + )} + + + + ))} diff --git a/components/skills.tsx b/components/skills.tsx index 5e59218..393857d 100644 --- a/components/skills.tsx +++ b/components/skills.tsx @@ -32,6 +32,7 @@ const Categories = styled.div` width: 100%; display: flex; flex-direction: column; + flex-wrap: wrap; align-items: center; justify-content: center; gap: 2rem; @@ -48,6 +49,7 @@ const SkillCategory = styled.div` flex-direction: column; align-items: center; gap: 2rem; + flex: 1; h3 { font-size: 1.75rem; diff --git a/data/links.ts b/data/links.ts index b2c76eb..d3e9ca9 100644 --- a/data/links.ts +++ b/data/links.ts @@ -20,6 +20,11 @@ const links: Link[] = [ href: "#skills", text: "Skills", }, + { + id: "projects", + href: "#projects", + text: "Projects", + }, { id: "contact", href: "#contact", diff --git a/data/projects.ts b/data/projects.ts index d3c0edd..10ec058 100644 --- a/data/projects.ts +++ b/data/projects.ts @@ -9,6 +9,24 @@ type Project = { } const projects: Project[] = [ + { + title: "Ephemr", + description: + "A simple social network, a place to share your thoughts with the world.", + image: "/ephemr.png", + techStack: [ + "Next.js", + "TypeScript", + "Styled Components", + "Socket.IO", + "Prisma", + "PostgreSQL", + "JWT", + ], + href: "https://ephemr.net", + source: "https://github.com/HangerThem/ephemr", + state: "wip", + }, { title: "HangerThem Portfolio", description: "This very website and my personal portfolio.", @@ -28,16 +46,6 @@ const projects: Project[] = [ source: "https://github.com/HangerThem/linkboard", state: "done", }, - { - title: "Ephemr", - description: - "A simple social network, a place to share your thoughts with the world.", - image: "/ephemr.png", - techStack: ["Next.js", "TypeScript", "Styled Components", "Socket.IO"], - href: "https://ephemr.net", - source: "https://github.com/HangerThem/ephemr", - state: "wip", - }, { title: "Evolution algorithm Flappy Bird", description: @@ -48,13 +56,7 @@ const projects: Project[] = [ source: "https://github.com/HangerThem/js-flappy-bird-ea", state: "done", }, - { - title: "Peer to Peer Chat", - description: "A simple peer-to-peer chat application.", - techStack: ["Python"], - source: "https://github.com/HangerThem/python-p2p-real-time-chat", - state: "wip", - }, + { title: "Simple 2D physics engine", description: "A simple 2D physics engine written in JavaScript.", @@ -64,6 +66,13 @@ const projects: Project[] = [ source: "https://hangerthem.github.io/js-2D-physic-engine/", state: "wip", }, + { + title: "Peer to Peer Chat", + description: "A simple peer-to-peer chat application.", + techStack: ["Python"], + source: "https://github.com/HangerThem/python-p2p-real-time-chat", + state: "wip", + }, ] export default projects diff --git a/package-lock.json b/package-lock.json index 4b76bcc..4a53dbb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -947,9 +947,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001584", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001584.tgz", - "integrity": "sha512-LOz7CCQ9M1G7OjJOF9/mzmqmj3jE/7VOmrfw6Mgs0E8cjOsbRXQJHsPBfmBOXDskXKrHLyyW3n7kpDW/4BsfpQ==", + "version": "1.0.30001651", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001651.tgz", + "integrity": "sha512-9Cf+Xv1jJNe1xPZLGuUXLNkE1BoDkqRqYyFJ9TDYSqhduqA4hu4oR9HluGoWYQC/aj8WHjsGVV+bwkh0+tegRg==", "funding": [ { "type": "opencollective", @@ -963,7 +963,8 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/canvas-confetti": { "version": "1.9.3",