diff --git a/index.html b/index.html
index aeb1553f..4fe55b3e 100644
--- a/index.html
+++ b/index.html
@@ -3,6 +3,11 @@
+
+
Josh Ashton
diff --git a/public/images/profile.jpg b/public/images/profile.jpg
new file mode 100644
index 00000000..91c37a8e
Binary files /dev/null and b/public/images/profile.jpg differ
diff --git a/src/About.jsx b/src/About.jsx
new file mode 100644
index 00000000..93943e52
--- /dev/null
+++ b/src/About.jsx
@@ -0,0 +1,5 @@
+import React from "react";
+
+export default function About() {
+ return TODO: About()
;
+}
diff --git a/src/App.jsx b/src/App.jsx
index be0441d7..8461640d 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -1,22 +1,50 @@
import React, { useRef, useState } from "react";
import VerticalSlider from "./components/VerticalSlider";
-import "./styles.css";
+import Primary from "./Primary";
+import Skills from "./Skills";
+import Projects from "./Projects";
+import Contact from "./Contact";
+import About from "./About";
+import ProjectCard from "./components/ProjectCard";
+import "./main.css";
+
+/**
+ * TODO: Read in data from a plain text file for easier editing in the future.
+ */
export default function App() {
- const data = [
- {
- title: "Test Header",
- description: "A description of some length. Lorem ipsum this shit.",
- color: "purple",
- image: "/images/landscape.jpg",
- alt: "A pretty background.",
- },
- {
- title: "Another one",
- description: "A description of some length. Lorem ipsum this shit.",
- color: "purple",
- image: "/images/landscape.jpg",
- alt: "A pretty background.",
- },
+ const cards = [, , ];
+
+ const skills = {
+ languages: ["Java", "JavaScript", "Go", "Dart", "Python", "C#"],
+ tools: [
+ "Git & GitHub",
+ "Docker & Kubernetes",
+ "Flutter",
+ "React",
+ "Linux",
+ "Microsoft Intune",
+ ],
+ other: [
+ "Written Communication",
+ "Conflict Resolution",
+ "Project Management",
+ "Event Planning",
+ "Electronics Repair",
+ "Soldering",
+ ],
+ };
+
+ const slides = [
+ ,
+ ,
+ ,
+ ,
];
- return ;
+ return ;
}
diff --git a/src/Contact.jsx b/src/Contact.jsx
new file mode 100644
index 00000000..e8cca20b
--- /dev/null
+++ b/src/Contact.jsx
@@ -0,0 +1,5 @@
+import React from "react";
+
+export default function Contact() {
+ return TODO: Contact()
;
+}
diff --git a/src/Primary.jsx b/src/Primary.jsx
new file mode 100644
index 00000000..8ec042e5
--- /dev/null
+++ b/src/Primary.jsx
@@ -0,0 +1,53 @@
+// TODO: Replace h4 callToAction with a button callToAction.
+import React, { useState } from "react";
+import SkillCard from "./components/SkillCard";
+
+export default function Primary({
+ primaryText,
+ secondaryText,
+ callToAction,
+ image,
+ skills,
+}) {
+ return (
+ <>
+
+
+
+
+ keyboard_double_arrow_down
+
+
+ >
+ );
+}
diff --git a/src/Projects.jsx b/src/Projects.jsx
new file mode 100644
index 00000000..741c0ecf
--- /dev/null
+++ b/src/Projects.jsx
@@ -0,0 +1,5 @@
+import React from "react";
+
+export default function Projects() {
+ return TODO: Projects()
;
+}
diff --git a/src/Skills.jsx b/src/Skills.jsx
new file mode 100644
index 00000000..98936875
--- /dev/null
+++ b/src/Skills.jsx
@@ -0,0 +1,8 @@
+import React from "react";
+
+export default function Skills({ skills }) {
+ const languages = skills.languages;
+ const tools = skills.tools;
+ const other = skills.other;
+ return <>>;
+}
diff --git a/src/components/AccordionContext.jsx b/src/components/AccordionContext.jsx
new file mode 100644
index 00000000..32d6fdc6
--- /dev/null
+++ b/src/components/AccordionContext.jsx
@@ -0,0 +1,19 @@
+import React, { createContext, useState } from "react";
+
+const AccordionContext = createContext();
+
+export const AccordionProvider = ({ children }) => {
+ const [expandedCardId, setExpandedCardId] = useState(null);
+
+ const handleAccordionClick = (cardId) => {
+ setExpandedCardId(cardId === expandedCardId ? null : cardId);
+ };
+
+ return (
+
+ {children}
+
+ );
+};
+
+export default AccordionContext;
diff --git a/src/components/Footer.jsx b/src/components/Footer.jsx
new file mode 100644
index 00000000..e69de29b
diff --git a/src/components/ProjectCard.jsx b/src/components/ProjectCard.jsx
new file mode 100644
index 00000000..e2e44d82
--- /dev/null
+++ b/src/components/ProjectCard.jsx
@@ -0,0 +1,5 @@
+import React from "react";
+
+export default function ProjectCard() {
+ return TODO: Need to implement ProjectCard
;
+}
diff --git a/src/components/SkillCard.jsx b/src/components/SkillCard.jsx
new file mode 100644
index 00000000..7c469bff
--- /dev/null
+++ b/src/components/SkillCard.jsx
@@ -0,0 +1,25 @@
+import React, { useState } from "react";
+
+export default function SkillCard({ header, symbol, list, initState }) {
+ const [isExpanded, setIsExpanded] = useState(initState); // Initial state
+
+ const toggleExpansion = () => {
+ setIsExpanded(!isExpanded);
+ };
+
+ return (
+
+
+ {symbol}
+
{header}
+
+ {isExpanded && (
+
+ {list.map((item) => (
+ - {item}
+ ))}
+
+ )}
+
+ );
+}
diff --git a/src/components/VerticalSlider.jsx b/src/components/VerticalSlider.jsx
index fd6b95e5..72edb32f 100644
--- a/src/components/VerticalSlider.jsx
+++ b/src/components/VerticalSlider.jsx
@@ -4,16 +4,16 @@ import { Mousewheel, Pagination } from "swiper/modules";
import "swiper/css";
import "swiper/css/pagination";
-import "../styles.css";
+import "../main.css";
-export default function VerticalSlider({ slideData }) {
+export default function VerticalSlider({ slides }) {
return (
<>
- {slideData.map((slide, index) => (
+ {slides.map((slide, index) => (
- {({ isActive }) => (
-
-
-
{slide.title}
-
{slide.description}
-
-
-
-

-
-
- )}
+ {({ isActive }) => {slide}
}
))}
diff --git a/src/main.css b/src/main.css
new file mode 100644
index 00000000..d76577d5
--- /dev/null
+++ b/src/main.css
@@ -0,0 +1,429 @@
+@import url("https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,100;0,300;0,400;0,700;0,900;1,100;1,300;1,400;1,700;1,900&display=swap");
+
+/*
+#EBD2FF
+#c69bca
+#9e75a8
+#4a245e
+*/
+
+:root {
+ --width: 480px;
+}
+
+*,
+*::before,
+*::after {
+ padding: 0;
+ margin: 0;
+ box-sizing: border-box;
+ font-family: "Lato", sans-serif;
+}
+
+html,
+body {
+ position: relative;
+ height: 100%;
+ background: #222;
+}
+
+body {
+ margin: 0;
+ height: 100vh;
+ background: linear-gradient(
+ 135deg,
+ #84509f 0%,
+ #5e3276 39%,
+ hsl(279deg 62% 19%) 61%,
+ hsl(279deg 94% 7%) 100%
+ );
+ background-size:
+ 300% 100%,
+ cover;
+ animation: background-fade 4s linear infinite;
+ animation-direction: alternate;
+ background-attachment: fixed;
+}
+
+.swiper {
+ width: 100%;
+ height: 100vh;
+ overflow: hidden;
+}
+
+.swiper-pagination-bullet {
+ width: 18px;
+ height: 18px;
+ background-color: #f9f2ff;
+ border-radius: 50%;
+ transition: all 0.6s ease-in-out;
+}
+
+.swiper-pagination-bullet-active {
+ height: 36px;
+ background-color: #ebd2ff;
+ border-radius: 14px;
+}
+
+#primary {
+ display: grid;
+ height: 100vh;
+ grid-template-columns: 100%;
+ grid-template-rows: 40% 50% 10%;
+ column-gap: 1vh;
+}
+
+#header {
+ width: 100%;
+ overflow: hidden;
+
+ display: grid;
+ grid-template-columns: 60% 35%;
+ grid-template-rows: 100%;
+ column-gap: 2vw;
+}
+
+#header-text {
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding-left: 120px;
+ text-align: center;
+ opacity: 0;
+}
+
+#header-text h1 {
+ font-size: clamp(4.25rem, 5.5vw, 10rem);
+ font-weight: 600;
+ letter-spacing: 2px;
+ width: max-content;
+ margin-bottom: 32px;
+ opacity: 0;
+ color: #ebd2ff;
+}
+
+#header-text h3,
+#header-text h4 {
+ color: #ebd2ff;
+ font-weight: 300;
+ line-height: 1.5;
+ opacity: 0;
+}
+
+#header-text h3 {
+ font-size: clamp(1.5rem, 3vw, 3rem);
+}
+#header-text h4 {
+ font-size: clamp(1rem, 1.5vw, 1.25rem);
+}
+
+.swiper-slide-active #header-text {
+ opacity: 1;
+}
+
+.swiper-slide-active #header-text h1,
+.swiper-slide-active #header-text h3,
+.swiper-slide-active #header-text h4 {
+ animation: moveDown 0.8s ease-in forwards;
+}
+
+.swiper-slide-active #header-text h1 {
+ animation-delay: 0.2s;
+}
+
+.swiper-slide-active #header-text h3 {
+ animation-delay: 0.8s;
+}
+
+.swiper-slide-active #header-text h4 {
+ animation-delay: 0.8s;
+}
+
+#header-image {
+ height: 40vh;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: var(--width);
+ aspect-ratio: 1/1;
+ margin: 0 auto;
+ border-radius: 50%;
+ overflow: hidden;
+}
+
+#header-image img {
+ display: block;
+ width: calc(var(--width) / 2);
+ filter: drop-shadow(5px 6px 5px rgba(36, 36, 42, 0.5));
+ user-select: none;
+ opacity: 0;
+ z-index: 1;
+ border-radius: 50%;
+}
+
+#header-image img {
+ animation: imgMoveDown 0.8s ease-in forwards 0.2s;
+}
+
+.material-icons {
+ font-variation-settings:
+ "FILL" 0,
+ "wght" 200,
+ "GRAD" 0,
+ "opsz" 24;
+ font-size: 5vw;
+ color: #ebd2ff;
+
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+}
+
+#skills-section {
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ text-align: center;
+}
+
+#skills-section h2 {
+ font-size: clamp(3.25rem, 4.5vw, 8rem);
+ color: #ebd2ff;
+ opacity: 0;
+ padding-bottom: 36px;
+}
+
+.cards {
+ display: grid;
+ grid-template-columns: 30% 30% 30%;
+ grid-template-rows: 100%;
+ column-gap: 2.25vw;
+ justify-content: center;
+}
+
+.card {
+ align-items: center;
+ justify-content: center;
+ text-align: center;
+ background-color: #ebd2ff;
+ border-radius: 20px;
+ width: 20vw;
+ box-shadow:
+ 0 13px 27px -5px hsla(240, 30.1%, 28%, 0.25),
+ 0 8px 16px -8px hsla(0, 0%, 0%, 0.3),
+ 0 -6px 16px -6px hsla(0, 0%, 0%, 0.03);
+}
+
+.card .skill-section-header {
+ display: grid;
+ grid-template-columns: 20% 60%;
+ grid-template-rows: 100%;
+ column-gap: 1vw;
+ align-items: center;
+ justify-content: center;
+ text-align: center;
+
+ padding: 2vw;
+ margin: 0;
+ background-color: #4a245e;
+ border-radius: 18px 18px 0 0;
+
+ width: 100%;
+}
+
+.card .skill-section-header .skill-symbol {
+ font-variation-settings:
+ "FILL" 0,
+ "wght" 200,
+ "GRAD" 0,
+ "opsz" 24;
+ font-size: 5vw;
+ height: 5vh;
+ text-align: left;
+}
+
+.card .skill-section-header h3 {
+ font-size: clamp(1rem, 2vw, 3rem);
+ color: #ebd2ff;
+}
+
+.card ul {
+ padding: 1vw;
+}
+
+.card ul li {
+ list-style: none;
+ font-size: clamp(1rem, 1.25vw, 1.5rem);
+ color: #4a245e;
+}
+
+.swiper-slide-active #skills-section .cards .card {
+ opacity: 0;
+}
+
+.swiper-slide-active #skills-section h2,
+.swiper-slide-active #skills-section .card {
+ animation: moveCardsDown 0.8s ease-in forwards;
+}
+
+.swiper-slide-active #skills-section .card {
+ animation-delay: 1.2s;
+}
+
+.down-indicator {
+ opacity: 0;
+ animation: moveDown 0.8s ease-in forwards;
+ animation-delay: 0.2s;
+}
+
+/**Animations**/
+@keyframes background-fade {
+ from {
+ background-position: right, center;
+ }
+}
+
+@keyframes moveDown {
+ 0% {
+ transform: translateY(-20px);
+ opacity: 0;
+ }
+ 100% {
+ transform: translateY(0);
+ opacity: 1;
+ }
+}
+
+@keyframes moveCardsDown {
+ 0% {
+ transform: translateY(-40px);
+ opacity: 0;
+ }
+ 100% {
+ transform: translateY(0);
+ opacity: 1;
+ }
+}
+
+@keyframes imgMoveDown {
+ 0% {
+ transform: translateY(calc(var(--width) / -5));
+ opacity: 0;
+ }
+ 100% {
+ transform: translateY(0);
+ opacity: 1;
+ }
+}
+
+/**Responsiveness**/
+@media (max-width: 1250px) {
+ #header-text {
+ padding-left: 90px;
+ }
+}
+
+@media (max-width: 1075px) {
+ :root {
+ --width: 400px;
+ }
+
+ .swiper-slide .slide-container {
+ column-gap: 20px;
+ }
+
+ #header-text {
+ padding-left: 60px;
+ }
+}
+
+@media (max-width: 990px) {
+ :root {
+ --width: 360px;
+ }
+
+ #header-text {
+ padding-left: 0px;
+ }
+}
+
+@media (max-width: 790px) {
+ #primary {
+ display: grid;
+ grid-template-rows: 50% 40% 10%;
+ grid-template-columns: 100%;
+ }
+
+ #header {
+ grid-template-columns: 60% 40%;
+ }
+
+ #header-text {
+ margin: 0;
+ }
+
+ #header-text h1 {
+ font-size: clamp(2.5rem, 2.75vw, 3rem);
+ }
+
+ #header-image {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: left;
+ }
+
+ #skills-section .card .skill-section-header {
+ border-radius: 18px 18px 18px 18px;
+ }
+
+ #skills-section h2 {
+ padding-bottom: 0;
+ }
+
+ .cards {
+ grid-template-columns: 100%;
+ grid-template-rows: 30% 30% 30%;
+ column-gap: 0;
+ padding: 30px;
+ }
+
+ .card {
+ width: 50vw;
+ margin: 1vw;
+ }
+
+ .card .skill-section-header h3 {
+ font-size: clamp(1.5rem, 2vw, 2.5rem);
+ }
+
+ #header-text h1 {
+ margin-bottom: 16px;
+ width: unset;
+ line-height: 1.1;
+ }
+
+ .swiper-pagination-bullet {
+ width: 14px;
+ height: 14px;
+ }
+
+ .swiper-pagination-bullet-active {
+ height: 28px;
+ }
+
+ .material-symbols-outlined {
+ font-size: 10vw;
+ }
+}
+
+@media (max-width: 485px) {
+ :root {
+ --width: 280px;
+ }
+}
diff --git a/src/styles.css b/src/styles.css
index f45bfd4b..a444ea9b 100644
--- a/src/styles.css
+++ b/src/styles.css
@@ -175,7 +175,7 @@ body {
}
}
-.swiper-paginatino-bullet {
+.swiper-pagination-bullet {
width: 18px;
height: 18px;
background-color: #7e7e7e;