diff --git a/package-lock.json b/package-lock.json index 5b25fc2..a09168b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "website", "version": "0.1.0", "dependencies": { + "framer-motion": "^11.2.10", "gray-matter": "^4.0.3", "next": "14.1.4", "next-themes": "^0.3.0", @@ -1038,12 +1039,13 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -2255,10 +2257,11 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -2348,6 +2351,31 @@ "url": "https://github.com/sponsors/rawify" } }, + "node_modules/framer-motion": { + "version": "11.2.10", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.2.10.tgz", + "integrity": "sha512-/gr3PLZUVFCc86a9MqCUboVrALscrdluzTb3yew+2/qKBU8CX6nzs918/SRBRCqaPbx0TZP10CB6yFgK2C5cYQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -3297,6 +3325,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -6066,6 +6095,7 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, diff --git a/package.json b/package.json index 3b73a90..1521f3c 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "lint": "next lint" }, "dependencies": { + "framer-motion": "^11.2.10", "gray-matter": "^4.0.3", "next": "14.1.4", "next-themes": "^0.3.0", diff --git a/src/app/components/caret.js b/src/app/components/caret.js index 8eee3d9..3976623 100644 --- a/src/app/components/caret.js +++ b/src/app/components/caret.js @@ -28,7 +28,7 @@ function Caret() { } return ( -
+
diff --git a/src/app/components/navbar.js b/src/app/components/navbar.js index a24e071..298f18d 100644 --- a/src/app/components/navbar.js +++ b/src/app/components/navbar.js @@ -4,119 +4,140 @@ import { IoMdMenu } from "react-icons/io"; import { usePathname } from "next/navigation"; import Link from "next/link"; import { useTheme } from "next-themes"; -import { useState } from "react"; +import { useEffect, useState } from "react"; +import { motion, AnimatePresence } from "framer-motion"; function Navbar({ curPage }) { const [menu, setMenu] = useState(false); + const [atTop, setAtTop] = useState(true); const { theme, setTheme } = useTheme(); const pathName = usePathname(); + + useEffect(() => { + window.addEventListener("scroll", function () { + if (this.window.scrollY == 0) { + setAtTop(true); + } else { + setAtTop(false); + } + }); + }, []); + return ( -
-
- -
-
- d +
+ +
+ +
+
+ d +
+
+ . +
+
+ liu +
-
.
-
- liu -
-
- -
- - home - -
- {"//"} -
- - projects -
- {"//"} +
+ + home + +
+ {"//"} +
+ + projects + +
+ {"//"} +
+ + blog + +
{ + setTheme(theme === "light" ? "dark" : "light"); + }} + > + {theme === "light" ? : } +
- - blog -
{ - setTheme(theme === "light" ? "dark" : "light"); + console.log(menu); + setMenu(!menu); }} > - {theme === "light" ? : } +
-
{ - console.log(menu); - setMenu(!menu); - }} - > - -
-
-
- - home - - - projects - - - blog - -
+
+ + + {menu && ( + + + home + + + projects + + + blog + + + )} + +
); } diff --git a/src/app/globals.css b/src/app/globals.css index 24831ab..65bc340 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -5,48 +5,75 @@ @layer base { @font-face { font-family: "Rubik"; - font-style: normal; + font-style: light; font-weight: 400; font-display: swap; src: url(../assets/fonts/Rubik.ttf) format("truetype"); } @font-face { font-family: "Gabarito"; - font-style: normal; - font-weight: 400; + font-style: light; + font-weight: 200; font-display: swap; src: url(../assets/fonts/Gabarito.ttf) format("truetype"); } @font-face { font-family: "Dosis"; - font-style: normal; - font-weight: 400; + font-style: light; + font-weight: 200; font-display: swap; src: url(../assets/fonts/Dosis.ttf) format("truetype"); } @font-face { font-family: "Iosevka"; - font-style: normal; - font-weight: 400; + font-style: light; + font-weight: 200; font-display: swap; src: url(../assets/fonts/Iosevka.ttf) format("truetype"); } + .bgDark { + background: rgb(13, 17, 23); + background: radial-gradient( + ellipse at 80% 50%, + rgba(13, 17, 23, 1) 0%, + rgba(33, 38, 45, 1) 62%, + rgba(73, 108, 140, 1) 100% + ); + z-index: -10; + } + + .bg { + background-image: linear-gradient(315deg, #89929b 0%, #ecf2f8 74%); + z-index: -10; + } + + /* For Webkit-based browsers (Chrome, Safari and Opera) */ + .scrollbar-hide::-webkit-scrollbar { + display: none; + } + + /* For IE, Edge and Firefox */ + .scrollbar-hide { + -ms-overflow-style: none; /* IE and Edge */ + scrollbar-width: none; /* Firefox */ + } + * { - @apply transition-colors duration-500; + @apply transition-colors duration-500 scrollbar-hide; } .content-container { - @apply mx-8 md:mx-80 my-16 flex flex-col; + @apply mx-8 md:mx-80 my-40 flex flex-col; } .section { @apply mx-2 my-4 flex flex-col; } .section-bg { - @apply dark:bg-b1 bg-b4 rounded p-8 mx-2 my-4 flex flex-col; + @apply dark:bg-b1/40 bg-b4/40 backdrop-blur-lg rounded p-8 mx-2 my-4 flex flex-col; } .section-outline { - @apply border-b4 dark:border-b1 border-2 rounded-lg p-8 mx-2 my-4 flex flex-col; + @apply border-b4/40 dark:border-b1/40 backdrop-blur-lg border-2 rounded-lg p-8 mx-2 my-4 flex flex-col; } h1 { diff --git a/src/app/layout.js b/src/app/layout.js index 80d6c64..5ba95dc 100644 --- a/src/app/layout.js +++ b/src/app/layout.js @@ -11,7 +11,7 @@ export const metadata = { export default function RootLayout({ children }) { return ( - + diff --git a/src/app/page.js b/src/app/page.js index 7765d4e..adc6d72 100644 --- a/src/app/page.js +++ b/src/app/page.js @@ -3,6 +3,7 @@ import { TypeAnimation } from "react-type-animation"; import { FaFilePdf, FaGithub, FaLinkedin } from "react-icons/fa"; import { IoMdMail } from "react-icons/io"; import Break from "./components/break"; +import { motion } from "framer-motion"; export default function Home() { const skills = [ @@ -25,15 +26,31 @@ export default function Home() { "Figma", "Linux", "Bash", + ]; + + const libraries = [ + "Matplotlib", "Pytorch", "NumPy", "Pandas", "Seaborn", "SciKit-Learn", + "OpenMP", + "OpenMPI", ]; return (
-
+ Computer Science and Data Science at UC Berkeley
-
+
@@ -69,47 +86,76 @@ export default function Home() {

-

Skill 

-

Set

+

Programming 

+

Languages

+
+
+ {skills && + skills.map((name, index) => { + return ( +
+ {name} +
+ ); + })}
-
- {skills && - skills.map((name, index) => { - return ( -
- {name} -
- ); - })} + +
+
+

Coding 

+

Libraries

+
+
+ {libraries && + libraries.map((name, index) => { + return ( +
+ {name} +
+ ); + })} +
diff --git a/src/app/projects/projects.json b/src/app/projects/projects.json index 6b3ef9d..d3d5ef3 100644 --- a/src/app/projects/projects.json +++ b/src/app/projects/projects.json @@ -3,10 +3,10 @@ "section": "Personal Projects", "projects": [ { - "name": "Personal Blog", - "description": "

I created a website to be my blog, where I share and post about anything computer-related that I find interesting.

To create the website, I used Next.js and TailwindCSS for the frontend and hosted it on Vercel. Each blog post is formatted from a Markdown file that is compiled by Next.js into static webpages during the build process, allowing me to easily add new posts by just adding new Markdown files. The website includes features such as LaTeX integration for math equations and code syntax highlighting, giving me the things necessary to post about all my favorite topics.

", + "name": "Weather App", + "description": "

I developed a dynamic website that enables users to easily check local weather conditions based on their location. The site is built with Next.js and styled using TailwindCSS, ensuring a seamless and responsive user experience. It's hosted on Vercel for optimal performance and reliability.

Leveraging the power of the OpenWeatherAPI, the website converts city names into precise latitude and longitude coordinates, providing detailed hourly and weekly weather forecasts. Key features of the website include a dark and light mode, responsive design, unit conversion, and search saving.

", "skills": ["Next.js", "TailwindCSS"], - "link": "https://github.com/DanL2015/blog" + "link": "https://free-weather.vercel.app/" }, { "name": "Rate My GSI", @@ -55,6 +55,12 @@ "skills": ["Python", "Pytorch"], "link": "https://inst.eecs.berkeley.edu/~cs188/sp24/projects/proj5" }, + { + "name": "Reinforcement Learning", + "description": "

During this project, I simulated a Pacman game trained with reinforcement learning. I implemented value iteration, Q Learning, Approximate Q Learning, and Deep Q Learning using the Pytorch library.

During this, I solidified my understanding of Pytorch and Reinforcement Learning algorithms, including how to optimize hyperparameters such as the learning rate, number of hidden layers, hidden layer size, and batch size.

", + "skills": ["Python", "Pytorch"], + "link": "https://inst.eecs.berkeley.edu/~cs188/sp24/projects/proj6/" + }, { "name": "Scheme Intepreter", "description": "

Scheme Interpreter is a project where I designed an interpreter for Scheme that translates lines of Scheme code into Python, and returns its output.

The project relies heavily on a deep understanding of Scheme and Python’s object-oriented programming. Through recursion, it parses the Scheme expressions to a custom Python object through lexical and syntactic analysis, then evaluates and outputs the resulting expression. The recursion also uses the tail recursion optimization to minimize memory usage. The final result can parse Scheme expressions like primitives, call expressions, and special forms to their resulting values.

",