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}

-
-
-
- {slide.alt} -
-
- )} + {({ 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;