├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
├── favicon.ico
└── index.html
└── src
├── App.js
├── about
├── About.js
├── AboutMenu.js
├── AboutMenuItem.js
├── AboutSubheading.js
└── subheadingsData.js
├── assets
├── astronaut-helmet.png
├── avatar-image.png
├── bg-universe.mp4
├── dead-eye.png
├── eagle-emblem.png
├── envelope.png
├── fallback-image.png
├── hawk-emblem.png
├── moebius-triangle.png
├── project-1.png
├── project-2.png
├── project-3.png
├── stack.png
├── triple-corn.png
└── upgrade.png
├── avatar
└── Avatar.js
├── background
└── Background.js
├── contact
├── Contact.js
└── ContactMenu.js
├── index.js
├── nav
└── Nav.js
├── playerStats
└── PlayerStats.js
├── projects
├── Projects.js
├── ProjectsMenu.js
└── projectsData.js
├── skills
├── Skills.js
├── SkillsMenu.js
└── skillsData.js
└── styles
├── aboutMenu.css
├── app.css
├── avatar.css
├── background.css
├── contact.css
├── nav.css
├── playerStats.css
├── projectsMenu.css
└── skillsMenu.css
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Getting Started with Create React App
2 |
3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
4 |
5 | ## Available Scripts
6 |
7 | In the project directory, you can run:
8 |
9 | ### `npm start`
10 |
11 | Runs the app in the development mode.\
12 | Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
13 |
14 | The page will reload when you make changes.\
15 | You may also see any lint errors in the console.
16 |
17 | ### `npm test`
18 |
19 | Launches the test runner in the interactive watch mode.\
20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
21 |
22 | ### `npm run build`
23 |
24 | Builds the app for production to the `build` folder.\
25 | It correctly bundles React in production mode and optimizes the build for the best performance.
26 |
27 | The build is minified and the filenames include the hashes.\
28 | Your app is ready to be deployed!
29 |
30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
31 |
32 | ### `npm run eject`
33 |
34 | **Note: this is a one-way operation. Once you `eject`, you can't go back!**
35 |
36 | If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
37 |
38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
39 |
40 | You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
41 |
42 | ## Learn More
43 |
44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
45 |
46 | To learn React, check out the [React documentation](https://reactjs.org/).
47 |
48 | ### Code Splitting
49 |
50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
51 |
52 | ### Analyzing the Bundle Size
53 |
54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
55 |
56 | ### Making a Progressive Web App
57 |
58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
59 |
60 | ### Advanced Configuration
61 |
62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
63 |
64 | ### Deployment
65 |
66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
67 |
68 | ### `npm run build` fails to minify
69 |
70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
71 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-portfolio-v2",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.16.5",
7 | "@testing-library/react": "^13.4.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "classnames": "^2.3.2",
10 | "dompurify": "^3.0.3",
11 | "emailjs-com": "^3.2.0",
12 | "react": "^18.2.0",
13 | "react-dom": "^18.2.0",
14 | "react-router-dom": "^6.11.2",
15 | "react-scripts": "5.0.1",
16 | "web-vitals": "^2.1.4"
17 | },
18 | "scripts": {
19 | "start": "react-scripts start",
20 | "build": "react-scripts build",
21 | "test": "react-scripts test",
22 | "eject": "react-scripts eject"
23 | },
24 | "eslintConfig": {
25 | "extends": [
26 | "react-app",
27 | "react-app/jest"
28 | ]
29 | },
30 | "browserslist": {
31 | "production": [
32 | ">0.2%",
33 | "not dead",
34 | "not op_mini all"
35 | ],
36 | "development": [
37 | "last 1 chrome version",
38 | "last 1 firefox version",
39 | "last 1 safari version"
40 | ]
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ade-mir/react-portfolio-v2/76915a07a21742c0ad69feb0b1342a55d388660b/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 | React App
13 |
14 |
15 | You need to enable JavaScript to run this app.
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
3 | import Nav from "./nav/Nav.js";
4 | import About from "./about/About";
5 | import Skills from "./skills/Skills";
6 | import Projects from "./projects/Projects";
7 | import Contact from "./contact/Contact";
8 | import "./styles/app.css";
9 | import Background from "./background/Background.js";
10 | import PlayerStats from "./playerStats/PlayerStats.js";
11 |
12 | const App = () => {
13 | return (
14 |
15 |
16 |
17 |
18 | } />
19 | } />
20 | } />
21 | } />
22 |
23 |
24 |
25 | );
26 | };
27 |
28 | export default App;
29 |
--------------------------------------------------------------------------------
/src/about/About.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import Avatar from "../avatar/Avatar.js";
3 | import AboutMenu from "./AboutMenu.js";
4 |
5 | export default class About extends Component {
6 | render() {
7 | return (
8 | <>
9 |
10 |
11 | >
12 | );
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/about/AboutMenu.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import AboutMenuItem from "./AboutMenuItem";
3 | import AboutSubheading from "./AboutSubheading";
4 | import subheadingsData from "./subheadingsData";
5 | import personalIcon from "../assets/moebius-triangle.png";
6 | import educationIcon from "../assets/upgrade.png";
7 | import careerIcon from "../assets/triple-corn.png";
8 |
9 | export default class AboutMenu extends Component {
10 | constructor(props) {
11 | super(props);
12 | this.state = {
13 | activeMenuItem: 1,
14 | activeSubheading: 1,
15 | };
16 | }
17 |
18 | handleMenuItemClick = (menuItem) => {
19 | this.setState({
20 | activeMenuItem: menuItem,
21 | activeSubheading: 1,
22 | });
23 | };
24 |
25 | handleSubheadingClick = (subheading) => {
26 | this.setState({
27 | activeSubheading: subheading,
28 | });
29 | };
30 |
31 | render() {
32 | const { activeMenuItem, activeSubheading } = this.state;
33 | const menuItems = ["PERSONAL", "EDUCATION", "CAREER"];
34 | const activeMenuTitle = menuItems[activeMenuItem - 1];
35 | const activeMenuIcon =
36 | activeMenuTitle === "PERSONAL"
37 | ? personalIcon
38 | : activeMenuTitle === "EDUCATION"
39 | ? educationIcon
40 | : careerIcon;
41 |
42 | const subheadings = subheadingsData[activeMenuItem];
43 |
44 | return (
45 | <>
46 |
47 | {menuItems.map((item, index) => (
48 |
this.handleMenuItemClick(index + 1)}
53 | />
54 | ))}
55 |
56 |
57 |
58 |
59 |
{activeMenuTitle}
60 |
61 | {subheadings.map((subheading, index) => (
62 |
this.handleSubheadingClick(index + 1)}
68 | menuItem={activeMenuItem}
69 | />
70 | ))}
71 |
72 | >
73 | );
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/about/AboutMenuItem.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import classNames from "classnames";
3 | import "../styles/aboutMenu.css";
4 |
5 | const AboutMenuItem = ({ title, active, onClick }) => {
6 | return (
7 |
8 |
{title}
9 |
10 | );
11 | };
12 |
13 | export default AboutMenuItem;
14 |
--------------------------------------------------------------------------------
/src/about/AboutSubheading.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import classNames from "classnames";
3 | import "../styles/aboutMenu.css";
4 |
5 | const AboutSubheading = ({ title, content, active, onClick, menuItem }) => {
6 | const subContainerClass = `sub-container-${menuItem}`;
7 |
8 | return (
9 |
12 |
{title}
13 |
{content}
14 |
15 | );
16 | };
17 |
18 | export default AboutSubheading;
19 |
--------------------------------------------------------------------------------
/src/about/subheadingsData.js:
--------------------------------------------------------------------------------
1 | const subheadingsData = {
2 | 1: [
3 | {
4 | title: "About Me",
5 | content: (
6 | <>
7 |
8 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
9 | eiusmod tempor incididunt ut labore et dolore magna aliqua.
10 |
11 | >
12 | ),
13 | },
14 | ],
15 | 2: [
16 | {
17 | title: "2016 Masters Degree",
18 | content: (
19 | <>
20 |
21 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
22 | eiusmod tempor incididunt ut labore et dolore magna aliqua.
23 |
24 | >
25 | ),
26 | },
27 | {
28 | title: "2014 Bachelors Degree",
29 | content: (
30 | <>
31 |
32 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
33 | eiusmod tempor incididunt ut labore et dolore magna aliqua.
34 |
35 | >
36 | ),
37 | },
38 | ],
39 | 3: [
40 | {
41 | title: "2022 Front End Developer",
42 | content: (
43 | <>
44 |
45 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
46 | eiusmod tempor incididunt ut labore et dolore magna aliqua.
47 |
48 | >
49 | ),
50 | },
51 | {
52 | title: "2020 UX Designer",
53 | content: (
54 | <>
55 |
56 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
57 | eiusmod tempor incididunt ut labore et dolore magna aliqua.
58 |
59 | >
60 | ),
61 | },
62 | {
63 | title: "2017 IT Consultant",
64 | content: (
65 | <>
66 |
67 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
68 | eiusmod tempor incididunt ut labore et dolore magna aliqua.
69 |
70 | >
71 | ),
72 | },
73 | ],
74 | };
75 |
76 | export default subheadingsData;
77 |
--------------------------------------------------------------------------------
/src/assets/astronaut-helmet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ade-mir/react-portfolio-v2/76915a07a21742c0ad69feb0b1342a55d388660b/src/assets/astronaut-helmet.png
--------------------------------------------------------------------------------
/src/assets/avatar-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ade-mir/react-portfolio-v2/76915a07a21742c0ad69feb0b1342a55d388660b/src/assets/avatar-image.png
--------------------------------------------------------------------------------
/src/assets/bg-universe.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ade-mir/react-portfolio-v2/76915a07a21742c0ad69feb0b1342a55d388660b/src/assets/bg-universe.mp4
--------------------------------------------------------------------------------
/src/assets/dead-eye.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ade-mir/react-portfolio-v2/76915a07a21742c0ad69feb0b1342a55d388660b/src/assets/dead-eye.png
--------------------------------------------------------------------------------
/src/assets/eagle-emblem.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ade-mir/react-portfolio-v2/76915a07a21742c0ad69feb0b1342a55d388660b/src/assets/eagle-emblem.png
--------------------------------------------------------------------------------
/src/assets/envelope.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ade-mir/react-portfolio-v2/76915a07a21742c0ad69feb0b1342a55d388660b/src/assets/envelope.png
--------------------------------------------------------------------------------
/src/assets/fallback-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ade-mir/react-portfolio-v2/76915a07a21742c0ad69feb0b1342a55d388660b/src/assets/fallback-image.png
--------------------------------------------------------------------------------
/src/assets/hawk-emblem.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ade-mir/react-portfolio-v2/76915a07a21742c0ad69feb0b1342a55d388660b/src/assets/hawk-emblem.png
--------------------------------------------------------------------------------
/src/assets/moebius-triangle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ade-mir/react-portfolio-v2/76915a07a21742c0ad69feb0b1342a55d388660b/src/assets/moebius-triangle.png
--------------------------------------------------------------------------------
/src/assets/project-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ade-mir/react-portfolio-v2/76915a07a21742c0ad69feb0b1342a55d388660b/src/assets/project-1.png
--------------------------------------------------------------------------------
/src/assets/project-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ade-mir/react-portfolio-v2/76915a07a21742c0ad69feb0b1342a55d388660b/src/assets/project-2.png
--------------------------------------------------------------------------------
/src/assets/project-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ade-mir/react-portfolio-v2/76915a07a21742c0ad69feb0b1342a55d388660b/src/assets/project-3.png
--------------------------------------------------------------------------------
/src/assets/stack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ade-mir/react-portfolio-v2/76915a07a21742c0ad69feb0b1342a55d388660b/src/assets/stack.png
--------------------------------------------------------------------------------
/src/assets/triple-corn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ade-mir/react-portfolio-v2/76915a07a21742c0ad69feb0b1342a55d388660b/src/assets/triple-corn.png
--------------------------------------------------------------------------------
/src/assets/upgrade.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ade-mir/react-portfolio-v2/76915a07a21742c0ad69feb0b1342a55d388660b/src/assets/upgrade.png
--------------------------------------------------------------------------------
/src/avatar/Avatar.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import PropTypes from "prop-types";
3 | import avatarImage from "../assets/avatar-image.png";
4 | import "../styles/avatar.css";
5 |
6 | const Avatar = ({ page }) => {
7 | const avatarClass = `avatar ${page}`;
8 | const spanClass = `shadow-overlay-${page}`;
9 |
10 | return (
11 | <>
12 |
13 |
14 | >
15 | );
16 | };
17 |
18 | Avatar.propTypes = {
19 | page: PropTypes.string.isRequired,
20 | };
21 |
22 | export default Avatar;
23 |
--------------------------------------------------------------------------------
/src/background/Background.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import "../styles/background.css";
3 | import video from "../assets/bg-universe.mp4";
4 | import fallbackImage from "../assets/fallback-image.png";
5 |
6 | const Background = () => {
7 | return (
8 | <>
9 |
10 |
19 |
20 |
21 | >
22 | );
23 | };
24 |
25 | export default Background;
26 |
--------------------------------------------------------------------------------
/src/contact/Contact.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ContactMenu from "./ContactMenu";
3 | import "../styles/contact.css";
4 |
5 | const Contact = () => {
6 | return (
7 | <>
8 |
9 | >
10 | );
11 | };
12 |
13 | export default Contact;
14 |
--------------------------------------------------------------------------------
/src/contact/ContactMenu.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import emailjs from "emailjs-com";
3 | import DOMPurify from "dompurify";
4 |
5 | export default function ContactMenu() {
6 | const initialState = {
7 | name: "",
8 | email: "",
9 | message: "",
10 | };
11 |
12 | const [formData, setFormData] = useState(initialState);
13 | const [errors, setErrors] = useState({});
14 | const [isLoading, setIsLoading] = useState(false);
15 | const [isSent, setIsSent] = useState(false);
16 |
17 | const handleChange = (e) => {
18 | const { name, value } = e.target;
19 | setFormData((prevFormData) => ({
20 | ...prevFormData,
21 | [name]: value,
22 | }));
23 | };
24 |
25 | const handleSubmit = (e) => {
26 | e.preventDefault();
27 | const validateErrors = validateForm();
28 | if (Object.keys(validateErrors).length > 0) {
29 | setErrors(validateErrors);
30 | return;
31 | }
32 |
33 | setIsLoading(true);
34 |
35 | const { name, email, message } = formData;
36 | const sanitizedData = {
37 | name: "Name: " + DOMPurify.sanitize(name),
38 | email: "Email: " + DOMPurify.sanitize(email),
39 | message: "Message: " + DOMPurify.sanitize(message),
40 | };
41 |
42 | const serviceID = process.env.REACT_APP_EMAILJS_SERVICE_ID;
43 | const templateID = process.env.REACT_APP_EMAILJS_TEMPLATE_ID;
44 | const userID = process.env.REACT_APP_EMAILJS_USER_ID;
45 |
46 | emailjs
47 | .send(serviceID, templateID, sanitizedData, userID)
48 | .then((response) => {
49 | console.log("Email is sent successfully!", response.text);
50 | setFormData(initialState);
51 | setErrors({});
52 | setIsSent(true);
53 | })
54 | .catch((error) => {
55 | console.error("Email sending failed", error);
56 | })
57 | .finally(() => {
58 | setIsLoading(false);
59 | });
60 | };
61 |
62 | const validateForm = () => {
63 | const { name, email, message } = formData;
64 | const errors = {};
65 |
66 | if (!name.trim()) {
67 | errors.name = "Name is required";
68 | }
69 |
70 | if (!email.trim()) {
71 | errors.email = "Email is required";
72 | } else if (!isValidEmail(email)) {
73 | errors.email = "Invalid email format";
74 | }
75 |
76 | if (!message.trim()) {
77 | errors.message = "Message is required";
78 | }
79 |
80 | return errors;
81 | };
82 |
83 | const isValidEmail = (value) => {
84 | const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
85 | return emailRegex.test(value);
86 | };
87 |
88 | return (
89 |
90 | {!isSent && (
91 |
143 | )}
144 | {isSent && (
145 |
146 |
SUCCESS!
147 |
Your message has been successfully sent!
148 |
You can safely leave this page.
149 |
150 | )}
151 |
152 | );
153 | }
154 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom/client";
3 | import App from "./App";
4 |
5 | const root = ReactDOM.createRoot(document.getElementById("root"));
6 | root.render( );
7 |
--------------------------------------------------------------------------------
/src/nav/Nav.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import { Link, useLocation } from "react-router-dom";
3 | import astronautHelmet from "../assets/astronaut-helmet.png";
4 | import deadEye from "../assets/dead-eye.png";
5 | import stack from "../assets/stack.png";
6 | import envelope from "../assets/envelope.png";
7 | import "../styles/nav.css";
8 |
9 | export default function Nav() {
10 | const location = useLocation();
11 |
12 | const getNavPositionClass = () => {
13 | switch (location.pathname) {
14 | case "/":
15 | return "nav-about";
16 | case "/skills":
17 | return "nav-skills";
18 | case "/projects":
19 | return "nav-projects";
20 | case "/contact":
21 | return "nav-contact";
22 | default:
23 | return "";
24 | }
25 | };
26 |
27 | const getPageTitle = () => {
28 | switch (location.pathname) {
29 | case "/":
30 | return "ABOUT";
31 | case "/skills":
32 | return "SKILLS";
33 | case "/projects":
34 | return "PROJECTS";
35 | case "/contact":
36 | return "CONTACT";
37 | default:
38 | return "";
39 | }
40 | };
41 |
42 | const navPositionClass = getNavPositionClass();
43 | const pageTitle = getPageTitle();
44 |
45 | const isCurrentPage = (navClass) => {
46 | return navClass === navPositionClass;
47 | };
48 |
49 | const renderNavLink = (to, imgSrc, altText, navClass) => {
50 | const isCurrent = isCurrentPage(navClass);
51 | const linkClass = isCurrent ? "nav-link current" : "nav-link";
52 |
53 | return (
54 |
55 |
56 | {isCurrent && {pageTitle} }
57 |
58 | );
59 | };
60 |
61 | return (
62 |
63 | {renderNavLink(
64 | "/",
65 | astronautHelmet,
66 | "astronaut helmet icon",
67 | "nav-about"
68 | )}
69 | {renderNavLink("/skills", deadEye, "deadEye icon", "nav-skills")}
70 | {renderNavLink("/projects", stack, "stack icon", "nav-projects")}
71 | {renderNavLink("contact", envelope, "envelope icon", "nav-contact")}
72 |
73 | );
74 | }
75 |
--------------------------------------------------------------------------------
/src/playerStats/PlayerStats.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import "../styles/playerStats.css";
3 |
4 | const PlayerStats = () => {
5 | return (
6 |
7 |
JOHN DOE LEVEL 31
8 |
9 |
10 |
11 |
12 |
Fullstack Developer
13 |
14 | );
15 | };
16 |
17 | export default PlayerStats;
18 |
--------------------------------------------------------------------------------
/src/projects/Projects.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import ProjectsMenu from "./ProjectsMenu";
3 |
4 | export default class Projects extends Component {
5 | render() {
6 | return (
7 | <>
8 |
9 | >
10 | );
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/projects/ProjectsMenu.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import classNames from "classnames";
3 | import projects from "./projectsData";
4 | import "../styles/projectsMenu.css";
5 |
6 | export default class ProjectsMenu extends Component {
7 | constructor(props) {
8 | super(props);
9 | this.state = {
10 | activeProject: 1,
11 | };
12 | }
13 |
14 | handleProjectClick = (project) => {
15 | this.setState({
16 | activeProject: project,
17 | });
18 | };
19 |
20 | renderContent = (projects) => {
21 | return projects.map((project, index) => (
22 |
23 |
{project.title}
24 |
25 |
{project.description}
26 |
34 |
35 | ));
36 | };
37 |
38 | render() {
39 | const { activeProject } = this.state;
40 | const projectItems = ["PROJECT ONE", "PROJECT TWO", "PROJECT THREE"];
41 |
42 | return (
43 |
44 |
45 | {projectItems.map((item, index) => (
46 |
this.handleProjectClick(index + 1)}
52 | >
53 |
{item}
54 |
55 | ))}
56 |
57 |
58 | {this.renderContent([projects[activeProject]])}
59 |
60 |
61 | );
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/projects/projectsData.js:
--------------------------------------------------------------------------------
1 | import projectOne from "../assets/project-1.png";
2 | import projectTwo from "../assets/project-2.png";
3 | import projectThree from "../assets/project-3.png";
4 |
5 | const projects = {
6 | 1: {
7 | title: "SoMe Platform",
8 | image: projectOne,
9 | description: (
10 | <>
11 |
12 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
13 | eiusmod tempor incididunt ut labore et dolore magna aliqua.
14 |
15 | >
16 | ),
17 | github: "https://github.com",
18 | demo: "https://netlify.com",
19 | },
20 | 2: {
21 | title: "Productivity App",
22 | image: projectTwo,
23 | description: (
24 | <>
25 |
26 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
27 | eiusmod tempor incididunt ut labore et dolore magna aliqua.
28 |
29 | >
30 | ),
31 | github: "https://github.com",
32 | demo: "https://netlify.com",
33 | },
34 | 3: {
35 | title: "Food Delivery App",
36 | image: projectThree,
37 | description: (
38 | <>
39 |
40 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
41 | eiusmod tempor incididunt ut labore et dolore magna aliqua.
42 |
43 | >
44 | ),
45 | github: "https://github.com",
46 | demo: "https://netlify.com",
47 | },
48 | };
49 |
50 | export default projects;
51 |
--------------------------------------------------------------------------------
/src/skills/Skills.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import Avatar from "../avatar/Avatar.js";
3 | import SkillsMenu from "./SkillsMenu.js";
4 |
5 | export default class About extends Component {
6 | render() {
7 | return (
8 | <>
9 |
10 |
11 | >
12 | );
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/skills/SkillsMenu.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import classNames from "classnames";
3 | import "../styles/skillsMenu.css";
4 | import skills from "./skillsData";
5 | import frontendIcon from "../assets/eagle-emblem.png";
6 | import backendIcon from "../assets/hawk-emblem.png";
7 |
8 | export default class SkillsMenu extends Component {
9 | constructor(props) {
10 | super(props);
11 | this.state = {
12 | activeMenuItem: 1,
13 | };
14 | }
15 |
16 | handleMenuItemClick = (menuItem) => {
17 | this.setState({
18 | activeMenuItem: menuItem,
19 | });
20 | };
21 |
22 | renderContent = (skills) => {
23 | return skills.map((skill, index) => (
24 |
28 |
{skill.title}
29 |
30 | {[...Array(6)].map((_, i) => (
31 |
37 | ))}
38 |
39 |
40 | ));
41 | };
42 |
43 | render() {
44 | const { activeMenuItem } = this.state;
45 | const menuItems = ["FRONT-END", "BACK-END"];
46 |
47 | const currentIcon = activeMenuItem === 1 ? frontendIcon : backendIcon;
48 |
49 | return (
50 |
51 | {menuItems.map((item, index) => (
52 |
this.handleMenuItemClick(index + 1)}
58 | >
59 |
{item}
60 |
61 | ))}
62 |
63 |
64 | {this.renderContent(skills[activeMenuItem])}
65 |
66 |
67 | );
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/skills/skillsData.js:
--------------------------------------------------------------------------------
1 | const skills = {
2 | 1: [
3 | {
4 | title: "HTML",
5 | level: 6,
6 | },
7 | {
8 | title: "CSS",
9 | level: 5,
10 | },
11 | {
12 | title: "SASS",
13 | level: 2,
14 | },
15 | {
16 | title: "JavaScript",
17 | level: 5,
18 | },
19 | {
20 | title: "TypeScript",
21 | level: 4,
22 | },
23 | {
24 | title: "Tailwind CSS",
25 | level: 1,
26 | },
27 | {
28 | title: "React JS",
29 | level: 3,
30 | },
31 | {
32 | title: "Figma",
33 | level: 4,
34 | },
35 | ],
36 | 2: [
37 | {
38 | title: "PostgreSQL",
39 | level: 5,
40 | },
41 | {
42 | title: "Node.js",
43 | level: 4,
44 | },
45 | {
46 | title: "MongoDB",
47 | level: 2,
48 | },
49 | {
50 | title: "Git",
51 | level: 4,
52 | },
53 | {
54 | title: "PHP",
55 | level: 1,
56 | },
57 | {
58 | title: "SQL",
59 | level: 3,
60 | },
61 | {
62 | title: "Express.js",
63 | level: 3,
64 | },
65 | ],
66 | };
67 |
68 | export default skills;
69 |
--------------------------------------------------------------------------------
/src/styles/aboutMenu.css:
--------------------------------------------------------------------------------
1 | .menu {
2 | width: 19rem;
3 | position: fixed;
4 | display: flex;
5 | flex-direction: column;
6 | top: 60%;
7 | transform: translateY(-60%);
8 | left: 10vw;
9 | }
10 |
11 | .item {
12 | height: 3.7rem;
13 | display: flex;
14 | justify-content: flex-end;
15 | align-items: center;
16 | cursor: pointer;
17 | }
18 |
19 | .title {
20 | font-size: 1rem;
21 | padding-right: 2.5rem;
22 | }
23 |
24 | .item.active .title {
25 | font-size: 1.5rem;
26 | }
27 |
28 | .sub-container {
29 | width: 18.5rem;
30 | position: fixed;
31 | display: flex;
32 | flex-direction: column;
33 | top: 32%;
34 | right: 10vw;
35 | cursor: pointer;
36 | }
37 |
38 | .active-subheading {
39 | cursor: default;
40 | }
41 |
42 | .item.active:nth-child(1) {
43 | background: linear-gradient(90deg, var(--transparent), var(--purple) 70%);
44 | border-radius: var(--radius-right);
45 | }
46 | .item.active:nth-child(2) {
47 | background: linear-gradient(90deg, var(--transparent), var(--blue) 70%);
48 | border-radius: var(--radius-right);
49 | }
50 | .item.active:nth-child(3) {
51 | background: linear-gradient(90deg, var(--transparent), var(--cyan) 70%);
52 | border-radius: var(--radius-right);
53 | }
54 |
55 | .sub-container-1.active-subheading h3,
56 | .sub-container-2.active-subheading h3,
57 | .sub-container-3.active-subheading h3 {
58 | border-radius: var(--radius-left);
59 | }
60 |
61 | .sub-container-1.active-subheading h3 {
62 | background: linear-gradient(90deg, var(--purple), var(--transparent) 100%);
63 | }
64 | .sub-container-2.active-subheading h3 {
65 | background: linear-gradient(90deg, var(--blue), var(--transparent) 100%);
66 | }
67 | .sub-container-3.active-subheading h3 {
68 | background: linear-gradient(90deg, var(--cyan), var(--transparent) 100%);
69 | }
70 |
71 | .item.active {
72 | position: relative;
73 | cursor: default;
74 | }
75 |
76 | .p-container {
77 | display: none;
78 | }
79 |
80 | .active-subheading .p-container {
81 | display: block;
82 | font-size: 1rem;
83 | }
84 |
85 | .icon-title-container {
86 | display: flex;
87 | gap: 1.2rem;
88 | margin-bottom: 0.5rem;
89 | cursor: default;
90 | }
91 |
92 | .icon {
93 | width: 3rem;
94 | height: 3rem;
95 | }
96 |
97 | .sub-container-1 h3,
98 | .sub-container-2 h3,
99 | .sub-container-3 h3 {
100 | position: relative;
101 | margin: 0.2rem 0;
102 | padding: 0.5rem 0 0.5rem 1rem;
103 | }
104 |
105 | @media (max-width: 700px) {
106 | .sub-container {
107 | right: 1rem;
108 | }
109 | .item.active .title {
110 | font-size: 1rem;
111 | }
112 | .item {
113 | height: 2rem;
114 | }
115 | }
116 | @media (max-width: 700px) {
117 | .sub-container {
118 | width: 15rem;
119 | top: 50%;
120 | left: 50%;
121 | transform: translateX(-50%);
122 | }
123 | .title {
124 | font-size: 0.8rem;
125 | padding-right: 2.5rem;
126 | }
127 | .active-subheading .p-container {
128 | font-size: 0.8rem;
129 | }
130 | .icon-title-container,
131 | .icon {
132 | display: none;
133 | }
134 | h1 {
135 | font-size: 0.8rem;
136 | }
137 | h2,
138 | h3,
139 | p {
140 | font-size: 0.8rem;
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/src/styles/app.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Russo+One&display=swap");
2 |
3 | body {
4 | font-family: "Russo One", sans-serif;
5 | color: white;
6 | -webkit-tap-highlight-color: transparent;
7 | }
8 |
9 | :root {
10 | --purple: #540351;
11 | --blue: #3627b1;
12 | --cyan: #25afce;
13 | --transparent: #00000000;
14 | --radius-left: 3rem 0 0 3rem;
15 | --radius-right: 0 3rem 3rem 0;
16 | }
17 |
18 | button:hover,
19 | .class-sub-container a:hover,
20 | .project-item:hover,
21 | .skill-item:hover,
22 | .item:not(.active):hover,
23 | .sub-container-2:not(.active-subheading):hover,
24 | .sub-container-3:not(.active-subheading):hover {
25 | background-image: linear-gradient(90deg, #ffffff00, #ffffff42 50%, #ffffff00);
26 | }
27 |
--------------------------------------------------------------------------------
/src/styles/avatar.css:
--------------------------------------------------------------------------------
1 | .avatar {
2 | position: fixed;
3 | overflow: hidden;
4 | z-index: -2;
5 | }
6 |
7 | .avatar.about {
8 | height: 89vh;
9 | bottom: -8vh;
10 | left: 50%;
11 | transform: translateX(-50%);
12 | }
13 |
14 | .avatar.skills {
15 | height: 190vh;
16 | bottom: -110vh;
17 | left: -1.5rem;
18 | transform: translateX(0%) scaleX(-1);
19 | }
20 |
21 | .shadow-overlay-skills {
22 | height: 100vh;
23 | width: 100vh;
24 | display: block;
25 | position: fixed;
26 | background: linear-gradient(
27 | 90deg,
28 | rgba(0, 0, 0, 0.25),
29 | rgba(255, 255, 255, 0)
30 | );
31 | z-index: -1;
32 | }
33 |
34 | @media (max-width: 1100px) {
35 | .avatar.skills {
36 | z-index: -5;
37 | height: 95vh;
38 | bottom: -15vh;
39 | }
40 | }
41 |
42 | @media (max-width: 700px) {
43 | .avatar.about {
44 | z-index: -5;
45 | height: 95vh;
46 | bottom: -15vh;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/styles/background.css:
--------------------------------------------------------------------------------
1 | #bg {
2 | object-fit: cover;
3 | width: 100vw;
4 | height: 100vh;
5 | position: fixed;
6 | top: 0;
7 | left: 0;
8 | z-index: -5;
9 | }
10 |
11 | .shadow-overlay {
12 | position: fixed;
13 | top: 0;
14 | left: 0;
15 | z-index: -4;
16 | width: 100vw;
17 | height: 100vh;
18 | background-color: rgba(0, 0, 0, 0.4);
19 | }
20 |
21 | @media (max-width: 700px) {
22 | .shadow-overlay {
23 | background-color: rgba(0, 0, 0, 0.7);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/styles/contact.css:
--------------------------------------------------------------------------------
1 | .contact-menu {
2 | position: absolute;
3 | top: 57%;
4 | left: 50%;
5 | transform: translate(-50%, -50%);
6 | }
7 |
8 | form {
9 | display: flex;
10 | flex-direction: column;
11 | gap: 2rem;
12 | width: 18.5rem;
13 | }
14 |
15 | .form-group {
16 | width: 100%;
17 | }
18 |
19 | input,
20 | #message {
21 | width: 100%;
22 | background-color: #00000040;
23 | border-radius: 0.3rem;
24 | border: 0.07rem solid rgba(255, 255, 255, 0.4);
25 | outline: none;
26 | color: white;
27 | padding: 0.5rem;
28 | font-weight: bold;
29 | font-size: 1rem;
30 | font-family: "Russo One", sans-serif;
31 | }
32 |
33 | input {
34 | height: 1.9rem;
35 | }
36 |
37 | ::placeholder {
38 | color: white;
39 | font-weight: 400;
40 | }
41 |
42 | #message {
43 | height: 6.2rem;
44 | resize: none;
45 | }
46 |
47 | button {
48 | color: white;
49 | font-size: 1rem;
50 | font-weight: 600;
51 | width: 102%;
52 | padding: 0.5rem 0;
53 | background-color: transparent;
54 | border: none;
55 | font-family: "Russo One", sans-serif;
56 | cursor: pointer;
57 | }
58 |
59 | .success-message {
60 | text-align: center;
61 | display: flex;
62 | flex-direction: column;
63 | justify-content: center;
64 | background-color: #00000030;
65 | width: 100%;
66 | height: 12.5rem;
67 | border-radius: 0.3rem;
68 | border: 0.07rem solid rgba(255, 255, 255, 0.7);
69 | }
70 |
71 | .success-message p {
72 | margin: 0.5rem;
73 | padding: 0 3.7rem;
74 | }
75 |
76 | .error-message {
77 | padding: 0.3rem;
78 | color: white;
79 | background-color: rgb(255, 59, 59);
80 | border-radius: 0.2rem;
81 | }
82 |
83 | label {
84 | display: none;
85 | }
86 |
87 | @media (max-width: 1100px) {
88 | .contact-menu {
89 | top: 50%;
90 | }
91 | }
92 | @media (max-width: 700px) {
93 | .contact-menu {
94 | width: 70%;
95 | }
96 | form {
97 | width: 100%;
98 | }
99 | input,
100 | #message {
101 | width: 92%;
102 | }
103 | .success-message p {
104 | padding: 0 0.5rem;
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/src/styles/nav.css:
--------------------------------------------------------------------------------
1 | .nav {
2 | position: fixed;
3 | display: flex;
4 | align-items: flex-start;
5 | top: 3rem;
6 | gap: 1.5625rem;
7 | left: 50%;
8 | }
9 |
10 | .nav-about {
11 | transform: translateX(-1.56rem);
12 | }
13 | .nav-skills {
14 | transform: translateX(-6.25rem);
15 | }
16 | .nav-projects {
17 | transform: translateX(-10.94rem);
18 | }
19 | .nav-contact {
20 | transform: translateX(-15.62rem);
21 | }
22 |
23 | a {
24 | width: 3.125rem;
25 | display: flex;
26 | flex-direction: column;
27 | justify-content: center;
28 | align-items: center;
29 | gap: 0.625rem;
30 | }
31 |
32 | .page-title {
33 | font-size: 0.875rem;
34 | color: white;
35 | cursor: default;
36 | }
37 |
38 | .nav-link {
39 | opacity: 0.7;
40 | }
41 |
42 | .nav-link:hover {
43 | opacity: 1;
44 | }
45 |
46 | .nav-link.current {
47 | opacity: 1;
48 | }
49 |
50 | @media (max-width: 1100px) {
51 | .nav-about,
52 | .nav-skills,
53 | .nav-projects,
54 | .nav-contact {
55 | transform: translateX(0);
56 | }
57 | .nav {
58 | top: calc(100vh - 8rem);
59 | transform: translateX(-50%);
60 | }
61 | .nav-link {
62 | width: 2rem;
63 | }
64 | .nav-link img {
65 | width: 2rem;
66 | }
67 | .page-title {
68 | display: none;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/styles/playerStats.css:
--------------------------------------------------------------------------------
1 | #playerStats {
2 | width: 15rem;
3 | height: 4rem;
4 | position: fixed;
5 | display: flex;
6 | flex-direction: column;
7 | justify-content: space-between;
8 | top: 3rem;
9 | left: 3rem;
10 | }
11 |
12 | h1 {
13 | margin: 0;
14 | font-size: 1.5rem;
15 | }
16 |
17 | h2 {
18 | margin: 0;
19 | font-size: 1rem;
20 | }
21 |
22 | #playerStats__lines {
23 | display: flex;
24 | align-items: center;
25 | }
26 |
27 | #playerStats__lines__thick {
28 | display: block;
29 | background-color: white;
30 | height: 0.2rem;
31 | width: 8.75rem;
32 | }
33 |
34 | #playerStats__lines__thin {
35 | display: block;
36 | background-color: lightgray;
37 | height: 0.1rem;
38 | width: 6.2rem;
39 | }
40 |
41 | @media (max-width: 1100px) {
42 | #playerStats {
43 | left: 50%;
44 | transform: translateX(-50%);
45 | width: 8rem;
46 | height: 2.5rem;
47 | top: 2rem;
48 | }
49 | h1 {
50 | font-size: 0.8rem;
51 | }
52 | h2,
53 | h3,
54 | p {
55 | font-size: 0.7rem;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/styles/projectsMenu.css:
--------------------------------------------------------------------------------
1 | .project-menu {
2 | width: 45rem;
3 | position: fixed;
4 | display: flex;
5 | top: 25%;
6 | left: 50%;
7 | transform: translateX(-50%);
8 | }
9 |
10 | .project-items-container {
11 | flex-direction: column;
12 | display: flex;
13 | position: relative;
14 | width: 40%;
15 | margin-top: 12rem;
16 | align-items: flex-end;
17 | }
18 |
19 | .project-item {
20 | height: 3.75rem;
21 | width: 90%;
22 | display: flex;
23 | position: relative;
24 | justify-content: flex-end;
25 | align-items: center;
26 | cursor: pointer;
27 | }
28 |
29 | .project-item.activeProject .title {
30 | font-size: 1.5rem;
31 | }
32 |
33 | .activeProject {
34 | border-radius: var(--radius-left);
35 | cursor: default;
36 | }
37 |
38 | .project-item.activeProject:nth-child(1) {
39 | background: linear-gradient(270deg, #ffffff00, var(--purple) 70%);
40 | }
41 | .project-item.activeProject:nth-child(2) {
42 | background: linear-gradient(270deg, #ffffff00, var(--blue) 70%);
43 | }
44 | .project-item.activeProject:nth-child(3) {
45 | background: linear-gradient(270deg, #ffffff00, var(--cyan) 70%);
46 | }
47 |
48 | .project-sub-container {
49 | width: 60%;
50 | margin-top: 2rem;
51 | display: flex;
52 | flex-direction: column;
53 | gap: 0.375rem;
54 | }
55 | .project-sub-container h3 {
56 | position: relative;
57 | margin: 0;
58 | }
59 | .project-sub-container img {
60 | width: 100%;
61 | object-fit: cover;
62 | border-radius: 0.5rem 3rem 0.5rem 0.5rem;
63 | opacity: 0.9;
64 | }
65 | .project-sub-container p {
66 | font-size: 0.875rem;
67 | }
68 |
69 | .link-container a {
70 | color: white;
71 | text-decoration: none;
72 | margin-top: 1rem;
73 | width: 50%;
74 | height: 2.75rem;
75 | text-align: center;
76 | }
77 |
78 | .link-container {
79 | display: flex;
80 | justify-content: space-around;
81 | }
82 |
83 | @media (max-width: 1100px) {
84 | .project-menu {
85 | width: 28rem;
86 | top: 20%;
87 | transform: translateX(-50%);
88 | }
89 | .project-item {
90 | height: 2rem;
91 | width: 100%;
92 | }
93 | .project-item.activeProject .title {
94 | font-size: 1rem;
95 | }
96 | .title {
97 | font-size: 0.8rem;
98 | }
99 | }
100 | @media (max-width: 700px) {
101 | .project-menu {
102 | width: 28rem;
103 | flex-direction: column;
104 | align-items: center;
105 | }
106 | .project-menu p {
107 | font-size: 0.7rem;
108 | }
109 | .project-sub-container {
110 | margin-top: 1rem;
111 | width: 12rem;
112 | }
113 | .project-sub-container img {
114 | width: 12rem;
115 | }
116 | .link-container a {
117 | margin-top: 0.5rem;
118 | width: 50%;
119 | height: 2rem;
120 | }
121 | .project-items-container {
122 | margin-top: 0;
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/src/styles/skillsMenu.css:
--------------------------------------------------------------------------------
1 | .skill-menu {
2 | width: 31.2rem;
3 | position: fixed;
4 | display: flex;
5 | flex-direction: column;
6 | top: 30%;
7 | right: 15vw;
8 | align-items: flex-end;
9 | }
10 |
11 | .skill-item {
12 | height: 3.7rem;
13 | width: 50%;
14 | display: flex;
15 | position: relative;
16 | justify-content: flex-end;
17 | align-items: center;
18 | cursor: pointer;
19 | }
20 |
21 | .skill-title {
22 | font-size: 1rem;
23 | padding-right: 4.5rem;
24 | }
25 |
26 | .skill-item.activeSkill .skill-title {
27 | font-size: 1.5rem;
28 | }
29 |
30 | .activeSkill {
31 | border-radius: var(--radius-left);
32 | cursor: default;
33 | }
34 |
35 | .skill-item.activeSkill:nth-child(1) {
36 | background: linear-gradient(270deg, #ffffff00, var(--purple) 70%);
37 | }
38 | .skill-item.activeSkill:nth-child(2) {
39 | background: linear-gradient(270deg, #ffffff00, var(--blue) 70%);
40 | }
41 |
42 | .skill-icon {
43 | width: 5rem;
44 | height: 5rem;
45 | position: absolute;
46 | top: 1.8rem;
47 | left: 8rem;
48 | }
49 |
50 | .skill-sub-container-1 h3,
51 | .skill-sub-container-2 h3 {
52 | position: relative;
53 | margin: 0;
54 | }
55 |
56 | .menu {
57 | width: 19rem;
58 | position: fixed;
59 | display: flex;
60 | flex-direction: column;
61 | top: 50%;
62 | transform: translateY(-25%);
63 | right: 15vw;
64 | }
65 |
66 | .skill-sub-container-1,
67 | .skill-sub-container-2 {
68 | display: flex;
69 | justify-content: right;
70 | gap: 2rem;
71 | }
72 |
73 | .level-container {
74 | display: flex;
75 | gap: 0.3rem;
76 | }
77 |
78 | .level-point {
79 | width: 3rem;
80 | height: 2rem;
81 | border-radius: 0.2rem;
82 | }
83 |
84 | .filled {
85 | background: linear-gradient(180deg, #236473, #25afce, #7ce7ff);
86 | }
87 | .unfilled {
88 | background: linear-gradient(180deg, #1c8298, #074654, #074654);
89 | }
90 |
91 | .skill-sub-container {
92 | margin-top: 2rem;
93 | display: flex;
94 | flex-direction: column;
95 | gap: 0.4rem;
96 | }
97 |
98 | @media (max-width: 1100px) {
99 | .skill-item.activeSkill .skill-title {
100 | font-size: 1rem;
101 | }
102 | .skill-icon {
103 | display: none;
104 | }
105 | .level-point {
106 | width: 1.2rem;
107 | height: 1rem;
108 | border-radius: 0.1rem;
109 | }
110 | .level-container {
111 | gap: 0.15rem;
112 | }
113 | .skill-sub-container-1,
114 | .skill-sub-container-2 {
115 | gap: 0.5rem;
116 | }
117 | .skill-sub-container {
118 | margin-top: 2rem;
119 | gap: 0.2rem;
120 | }
121 | h1 {
122 | font-size: 0.8rem;
123 | }
124 | h2,
125 | h3,
126 | p {
127 | font-size: 0.7rem;
128 | }
129 | .skill-menu {
130 | flex-direction: column;
131 | left: 50%;
132 | transform: translateX(-50%);
133 | align-items: center;
134 | top: 30%;
135 | }
136 | .skill-item {
137 | height: 2rem;
138 | width: 12em;
139 | }
140 | }
141 | @media (max-width: 700px) {
142 | .menu {
143 | width: 10rem;
144 | top: 30%;
145 | left: 50%;
146 | transform: translateY(-50%);
147 | }
148 | }
149 |
--------------------------------------------------------------------------------