diff --git a/README.md b/README.md
index 200f4282..169f2588 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,5 @@
# Portfolio
+
+Deployed Site:
+
+Figma link: https://www.figma.com/design/hFjGb9pVuXS6SbxUAGdCkL/--Bianka---Figma-designs-for-students--Copy-?node-id=3084-966&p=f&t=rOSwChuyln6MbyrC-0
diff --git a/index.html b/index.html
index 6676fb2d..55ce178a 100644
--- a/index.html
+++ b/index.html
@@ -1,11 +1,48 @@
-
+
-
- Portfolio
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Dev Portfolio - BLR
+
diff --git a/package.json b/package.json
index 48911600..5d5847ea 100644
--- a/package.json
+++ b/package.json
@@ -11,13 +11,16 @@
},
"dependencies": {
"react": "^19.0.0",
- "react-dom": "^19.0.0"
+ "react-dom": "^19.0.0",
+ "react-icons": "^5.5.0",
+ "styled-components": "^6.1.17"
},
"devDependencies": {
"@eslint/js": "^9.21.0",
"@types/react": "^19.0.10",
"@types/react-dom": "^19.0.4",
- "@vitejs/plugin-react": "^4.3.4",
+ "@vitejs/plugin-react": "^4.4.0",
+ "babel-plugin-styled-components": "^2.1.4",
"eslint": "^9.21.0",
"eslint-plugin-react-hooks": "^5.1.0",
"eslint-plugin-react-refresh": "^0.4.19",
diff --git a/public/images/a11y-app.png b/public/images/a11y-app.png
new file mode 100644
index 00000000..3c20c34c
Binary files /dev/null and b/public/images/a11y-app.png differ
diff --git a/public/images/abstract-unsplash.jpg b/public/images/abstract-unsplash.jpg
new file mode 100644
index 00000000..48d5eb5a
Binary files /dev/null and b/public/images/abstract-unsplash.jpg differ
diff --git a/public/images/articlesPlaceholder-unsplash.jpg b/public/images/articlesPlaceholder-unsplash.jpg
new file mode 100644
index 00000000..5c8a4bd0
Binary files /dev/null and b/public/images/articlesPlaceholder-unsplash.jpg differ
diff --git a/public/images/logoBlack.png b/public/images/logoBlack.png
new file mode 100644
index 00000000..c87350b8
Binary files /dev/null and b/public/images/logoBlack.png differ
diff --git a/public/images/logoTransparent.png b/public/images/logoTransparent.png
new file mode 100644
index 00000000..c1a77102
Binary files /dev/null and b/public/images/logoTransparent.png differ
diff --git a/public/images/only.logo.onWhite.svg b/public/images/only.logo.onWhite.svg
new file mode 100644
index 00000000..c6b330c9
--- /dev/null
+++ b/public/images/only.logo.onWhite.svg
@@ -0,0 +1 @@
+Yes
\ No newline at end of file
diff --git a/public/images/preview.dev.site.png b/public/images/preview.dev.site.png
new file mode 100644
index 00000000..46c0040e
Binary files /dev/null and b/public/images/preview.dev.site.png differ
diff --git a/public/images/recipe-library-app.png b/public/images/recipe-library-app.png
new file mode 100644
index 00000000..9c6590d5
Binary files /dev/null and b/public/images/recipe-library-app.png differ
diff --git a/public/images/stockholm-buzz-app.png b/public/images/stockholm-buzz-app.png
new file mode 100644
index 00000000..62af396c
Binary files /dev/null and b/public/images/stockholm-buzz-app.png differ
diff --git a/public/images/weather-app.png b/public/images/weather-app.png
new file mode 100644
index 00000000..24c289c0
Binary files /dev/null and b/public/images/weather-app.png differ
diff --git a/public/vite.svg b/public/vite.svg
deleted file mode 100644
index e7b8dfb1..00000000
--- a/public/vite.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/src/App.jsx b/src/App.jsx
index a161d8d3..cd5e154a 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -1,8 +1,31 @@
-export const App = () => {
+import projects from "./data/projects.json"
+import skills from "./data/skills.json"
+import articles from "./data/articles.json"
+import FeaturedProjects from "./sections/FeaturedProjects"
+import Footer from "./sections/Footer"
+import Header from "./sections/Header"
+import Skills from "./sections/Skills"
+import Tech from "./sections/Tech"
+import Reflections from "./sections/Reflections"
+import { GlobalStyle } from "./styles/GlobalStyle"
+import { ThemeProvider } from "styled-components"
+import { theme } from "./styles/theme"
+
+const App = () => {
return (
- <>
- Portfolio
- Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptatem, laborum! Maxime animi nostrum facilis distinctio neque labore consectetur beatae eum ipsum excepturi voluptatum, dicta repellendus incidunt fugiat, consequatur rem aperiam.
- >
+
+
+
+
+
+
+
+
+
)
}
+
+export default App
\ No newline at end of file
diff --git a/src/assets/BiankaRomero.jpg b/src/assets/BiankaRomero.jpg
new file mode 100644
index 00000000..5e35cc93
Binary files /dev/null and b/src/assets/BiankaRomero.jpg differ
diff --git a/src/assets/camera-BG.jpg b/src/assets/camera-BG.jpg
new file mode 100644
index 00000000..26d7fce2
Binary files /dev/null and b/src/assets/camera-BG.jpg differ
diff --git a/src/assets/laptop-BG.jpg b/src/assets/laptop-BG.jpg
new file mode 100644
index 00000000..65a2cd61
Binary files /dev/null and b/src/assets/laptop-BG.jpg differ
diff --git a/src/components/Card.jsx b/src/components/Card.jsx
new file mode 100644
index 00000000..288514e3
--- /dev/null
+++ b/src/components/Card.jsx
@@ -0,0 +1,50 @@
+import styled from "styled-components"
+import { media } from "../styles/media"
+
+const Tag = styled.li`
+ display: block;
+
+ @media ${media.desktop} {
+ align-self: left;
+ }
+`
+const TagsContainer = styled.ul`
+
+`
+const CardTitle = styled.h2`
+ padding-top: 16px;
+`
+const CardText = styled.p`
+ font-size: 16px;
+ padding-top: 16px;
+
+ @media ${media.desktop} {
+ font-size: 18px;
+ }
+`
+
+const Card = ({ title, text, tags, TitleComponent = CardTitle }) => {
+ const cardContent = (
+ <>
+ {tags && (
+
+ {tags.map((tag, index) => (
+ {tag}
+ ))}
+
+ )}
+ {text && (
+ {text}
+ )}
+ >
+ )
+
+ return (
+
+ {title}
+ {cardContent}
+
+ )
+}
+
+export default Card
\ No newline at end of file
diff --git a/src/components/Contact.jsx b/src/components/Contact.jsx
new file mode 100644
index 00000000..9a0aa59b
--- /dev/null
+++ b/src/components/Contact.jsx
@@ -0,0 +1,70 @@
+import styled from "styled-components"
+import { media } from "../styles/media"
+import { IoCallOutline, IoChatbubbleEllipsesOutline, IoMailOutline } from "react-icons/io5";
+
+const ContactContainer = styled.div`
+ display: block;
+ padding: 64px 0;
+
+ @media ${media.tablet} {
+ font-size: 24px;
+ }
+
+ @media ${media.desktop} {
+ font-size: 30px;
+ }
+
+ a {
+ color: inherit;
+ display: block;
+ margin-top: 8px;
+ }
+`
+
+const ContactItem = styled.a`
+ display: flex;
+ align-items: center;
+ gap: 16px;
+ cursor: pointer;
+ transition: color 0.2s ease;
+
+ &:hover {
+ transform: scale(1.1);
+ color: #0077ff;
+ }
+
+ svg {
+ flex-shrink: 0;
+ font-size: 1em;
+ vertical-align: middle;
+ }
+`
+
+const ContactName = styled.h3`
+ margin-bottom: 12px;
+`
+
+const Contact = ({ name, phone, email }) => {
+ // Clean phone number for tel and sms links (remove spaces, parentheses, dashes)
+ const cleanPhone = phone.replace(/[^+\d]/g, "");
+
+ return (
+
+ {name}
+
+
+ {phone}
+
+
+
+ Send SMS
+
+
+
+ {email}
+
+
+ )
+}
+
+export default Contact
\ No newline at end of file
diff --git a/src/components/HeroImages.jsx b/src/components/HeroImages.jsx
new file mode 100644
index 00000000..19569be1
--- /dev/null
+++ b/src/components/HeroImages.jsx
@@ -0,0 +1,90 @@
+import laptopBG from "../assets/laptop-BG.jpg"
+import cameraBG from "../assets/camera-BG.jpg"
+import BiankaRomero from "../assets/BiankaRomero.jpg"
+import styled, { keyframes } from "styled-components"
+
+
+const HeroContainer = styled.div`
+ max-width: 100vw;
+ width: 100%;
+ height: auto;
+ display: flex;
+ justify-content: center;
+ padding: 16px;
+ margin: 0 auto;
+
+`
+const HeroImg = styled.img`
+ width: 30%;
+ height: auto;
+ max-width: 100%;
+ object-fit: cover;
+ border-radius: 12px;
+ box-shadow: 0 4px 8px rgba(0,0,0,0.2);
+`
+
+const fadeUpCenter = keyframes`
+ from {
+ opacity: 0;
+ transform: translateY(40px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+`
+
+
+const slideInLeft = keyframes`
+ from {
+ opacity: 0;
+ transform: rotate(-4.7deg) translateX(-100px);
+ }
+ to {
+ opacity: 1;
+ transform: rotate(-4.7deg) translateX(50px);
+ }
+`
+
+const slideInRight = keyframes`
+ from {
+ opacity: 0;
+ transform: rotate(4.7deg) translateX(100px);
+ }
+ to {
+ opacity: 1;
+ transform: rotate(4.7deg) translateX(-50px);
+ }
+`
+
+
+const LeftHeroImg = styled(HeroImg)`
+ animation: ${slideInLeft} 1s ease forwards;
+ z-index: -1;
+`
+
+const CenterHeroImg = styled(HeroImg)`
+ animation: ${fadeUpCenter} 1s ease forwards;
+ z-index: 0;
+
+ &:hover {
+ transform: scale(1.05);
+ }
+`
+
+const RightHeroImg = styled(HeroImg)`
+ animation: ${slideInRight} 1s ease forwards;
+ z-index: -1;
+`
+
+const HeroImages = () => {
+ return (
+
+
+
+
+
+ )
+}
+
+export default HeroImages
\ No newline at end of file
diff --git a/src/components/LinkButton.jsx b/src/components/LinkButton.jsx
new file mode 100644
index 00000000..8d8182b6
--- /dev/null
+++ b/src/components/LinkButton.jsx
@@ -0,0 +1,51 @@
+import styled from "styled-components"
+
+const LinkButtonStyle = styled.a`
+ font-size: 18px;
+ border-radius: 12px;
+ border: 2px solid black;
+ background: #000;
+ color: white;
+ display: flex;
+ width: 100%;
+ max-width: 303px;
+ height: 48px;
+ padding: 0px 16px;
+ align-items: center;
+ gap: 16px;
+ flex-shrink: 0;
+ transition: transform 0.3s ease-in-out;
+
+ &:hover {
+ transform: scale(1.1);
+ }
+`
+
+const IconStyle = styled.span`
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 100%;
+ line-height: 0;
+ font-size: 32px;
+`
+
+const LinkButton = ({ link, linkUse, IconComponent, ...props }) => {
+ return (
+
+
+ {IconComponent && (
+
+
+
+ )}
+ {linkUse}
+
+ )
+}
+
+export default LinkButton
\ No newline at end of file
diff --git a/src/components/SocialIcons.jsx b/src/components/SocialIcons.jsx
new file mode 100644
index 00000000..e3589689
--- /dev/null
+++ b/src/components/SocialIcons.jsx
@@ -0,0 +1,193 @@
+import { useState } from "react"
+import { IoGlobeOutline, IoHeart, IoLogoCodepen, IoLogoGithub, IoLogoInstagram, IoLogoLinkedin, IoCameraOutline, IoCamera, IoCameraReverseOutline } from "react-icons/io5"
+import styled from "styled-components"
+import { media } from "../styles/media"
+
+const IconsContainer = styled.div`
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 32px;
+ flex-wrap: wrap;
+`
+
+const SocialIcon = styled.a`
+ font-size: 32px;
+ color: inherit;
+ transition: transform 0.3s ease, color 0.3s ease;
+
+ svg {
+ width: 1em;
+ height: 1em;
+ display: block;
+ }
+
+ &:hover {
+ transform: scale(1.2);
+ color: #0077ff;
+ }
+
+ /* Create a smooth underline animation */
+ &::after {
+ content: "";
+ position: absolute;
+ width: 0%;
+ height: 2px;
+ bottom: -6px;
+ left: 0;
+ background-color: #0077ff;
+ transition: width 0.3s ease;
+ }
+
+ &:hover::after {
+ width: 100%;
+ }
+
+ @media ${media.tablet} {
+ font-size: 40px;
+ }
+
+ @media ${media.desktop} {
+ font-size: 40px;
+ }
+
+`
+
+const HeartsIcon = styled.button`
+ font-size: 32px;
+ color: inherit;
+ transition: transform 0.6s ease;
+ perspective: 1000px; /* Needed for 3D effect */
+ border-color: transparent;
+ background: transparent;
+
+ svg {
+ width: 1em;
+ height: 1em;
+ display: block;
+ }
+
+ &:hover {
+ transform: scale(1.2);
+ color: #0077ff;
+ }
+
+ &::after {
+ content: "";
+ position: absolute;
+ width: 0%;
+ height: 2px;
+ bottom: -6px;
+ left: 0;
+ background-color: #0077ff;
+ transition: width 0.3s ease;
+ }
+
+ &:hover::after {
+ width: 100%;
+ }
+
+ &.spin {
+ animation: spinYColor 0.8s ease;
+ }
+
+ @keyframes spinYColor {
+ 0% {
+ transform: rotateY(0deg);
+ }
+ 50% {
+ transform: rotateY(180deg);
+ color: red;
+ }
+ 100% {
+ transform: rotateY(360deg);
+ }
+ }
+
+ @media ${media.tablet} {
+ font-size: 40px;
+ }
+
+ @media ${media.desktop} {
+ font-size: 40px;
+ }
+`
+export const LinkedinIcon = () => {
+ return (
+
+
+
+ )
+}
+
+export const GithubIconSVG = () =>
+export const GithubIcon = () => {
+ return (
+
+
+
+ )
+}
+
+export const CodepenIcon = () => {
+ return (
+
+
+
+ )
+}
+
+export const InstagramIcon = () => {
+ return (
+
+
+
+ )
+}
+
+export const HeartIcon = () => {
+ const [animateKey, setAnimateKey] = useState(0)
+
+ const handleClick = () => {
+ setAnimateKey((prev) => prev + 1)
+ }
+
+ return (
+
+
+
+ )
+}
+
+export const WebIconSVG = () =>
+export const WebIcon = () => {
+ return (
+
+
+
+ )
+}
+
+export const IconsList = {
+ linkedin: LinkedinIcon,
+ github: GithubIcon,
+ codepen: CodepenIcon,
+ instagram: InstagramIcon,
+ web: WebIcon,
+ heart: HeartIcon,
+}
+
+const SocialIcons = () => {
+return (
+
+
+
+
+ {/* */}
+
+
+
+ )
+}
+
+export default SocialIcons
\ No newline at end of file
diff --git a/src/components/StyledTags.jsx b/src/components/StyledTags.jsx
new file mode 100644
index 00000000..932ba2d8
--- /dev/null
+++ b/src/components/StyledTags.jsx
@@ -0,0 +1,43 @@
+import styled from "styled-components"
+import { media } from "../styles/media"
+
+const TagsContainer = styled.div`
+ display: flex;
+ flex-wrap: wrap;
+`
+
+const TechTag = styled.p`
+ border-radius: 4px;
+ max-width: 100%;
+ color: black;
+ border: 1px solid black;
+ padding: 2px 6px;
+ margin: 4px;
+ display: flex;
+ justify-content: center;
+ white-space: nowrap;
+
+ @media ${media.tablet}, ${media.desktop} {
+ flex: 0 0 auto;
+}
+`
+
+const StyledTags = ({ tags }) => {
+ if (!tags) return null
+
+ const tagList = Array.isArray(tags) ? tags : [tags]
+
+ if (tagList.length === 0) return null
+
+ return (
+
+ {tagList.map((tag, index) => {
+ return (
+ {tag}
+ )}
+ )}
+
+ )
+}
+
+export default StyledTags
\ No newline at end of file
diff --git a/src/data/articles.json b/src/data/articles.json
new file mode 100644
index 00000000..90ffc586
--- /dev/null
+++ b/src/data/articles.json
@@ -0,0 +1,18 @@
+{
+ "articles": [
+ {
+ "image": "images/abstract-unsplash.jpg",
+ "title": "Building Better UX in React",
+ "text": "A breakdown of accessible design patterns using modern React tools.",
+ "date": "May 2025",
+ "link": "https://external-link.com/article1"
+ },
+ {
+ "image": "images/abstract-unsplash.jpg",
+ "title": "From Design to Deployment",
+ "text": "What I’ve learned turning Figma designs into scalable apps.",
+ "date": "June 2025",
+ "link": "https://external-link.com/article2"
+ }
+ ]
+}
diff --git a/src/data/projects.json b/src/data/projects.json
index 7c426028..57f64e96 100644
--- a/src/data/projects.json
+++ b/src/data/projects.json
@@ -1,19 +1,36 @@
{
"projects": [
{
- "name": "Business site",
- "image": "https://images.unsplash.com/photo-1557008075-7f2c5efa4cfd?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2497&q=80",
+ "name": "Weather app",
+ "bio": "An interactive weather app that fetches current API data for today and a 4-day forecast. The app theme shifts with the time of day from daytime to nighttime colors and icons using Typescript/Javascript. ",
+ "image": "/images/weather-app.png",
"tags": [
"HTML5",
"CSS3",
- "JavaScript"
+ "JavaScript",
+ "TypeScript",
+ "APIs"
],
- "netlify": "link",
- "github": "link"
+ "netlify": "https://wind1weatherapp.netlify.app",
+ "github": "https://github.com/govargas/js-project-weather-app"
},
{
- "name": "Weather app",
- "image": "https://images.unsplash.com/photo-1520792532857-293bd046307a?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2370&q=80",
+ "name": "Accessibility For All",
+ "bio": "An easy to navigate, WCAG [AAA] rated site design, that offers users a quick and informative quiz on accessibility-friendly, aka a11y, guidelines.",
+ "image": "/images/a11y-app.png",
+ "tags": [
+ "HTML5",
+ "CSS3",
+ "JavaScript",
+ "Accessibility"
+ ],
+ "netlify": "https://teamwind1.netlify.app",
+ "github": "https://github.com/Bianka2112/js-project-accessibility"
+ },
+ {
+ "name": "Recipe Library app",
+ "bio": "Simple and clean app for getting fresh recipe inspirations. Users can choose popular cuisine filters or sort by time to narrow the options, as well as a fun, random recipe button. Almost entirely Javascript-built for functionality and features. ",
+ "image": "/images/recipe-library-app.png",
"tags": [
"HTML5",
"CSS3",
@@ -21,8 +38,21 @@
"TypeScript",
"APIs"
],
- "netlify": "link",
- "github": "link"
+ "netlify": "https://luminous-mandazi-4c7550.netlify.app/",
+ "github": "https://github.com/Bianka2112/js-project-recipe-library"
+ },
+ {
+ "name": "First self-coded project: The Stockholm Buzz",
+ "bio": "My original homemade, from scratch, business-inspired website fully coded with HTML and CSS and just a few tears (whether from joy, panic or relief remains a trade-secret). Updated to meet WCAG standards for an accessible user experience. ",
+ "image": "/images/stockholm-buzz-app.png",
+ "tags": [
+ "HTML5",
+ "CSS3",
+ "JavaScript",
+ "Accessibility"
+ ],
+ "netlify": "https://thestockholmbuzz.netlify.app/",
+ "github": "https://github.com/Bianka2112/js-project-business-site"
}
]
}
\ No newline at end of file
diff --git a/src/data/skills.json b/src/data/skills.json
new file mode 100644
index 00000000..905137a4
--- /dev/null
+++ b/src/data/skills.json
@@ -0,0 +1,48 @@
+{
+ "skills": [
+ {
+ "category": "Code",
+ "tags": [
+ "HTML5",
+ "CSS3",
+ "JavaScript ES6",
+ "TypeScript",
+ "APIs",
+ "Github",
+ "VS Code",
+ "Codepen"
+ ]
+ },
+ {
+ "category": "Toolbox",
+ "tags": [
+ "Adobe Photoshop",
+ "Adobe Lightroom",
+ "Capcut",
+ "Figma",
+ "Notion",
+ "Slack"
+ ]
+ },
+ {
+ "category": "Upcoming",
+ "tags": [
+ "Node.js",
+ "React",
+ "Styled Components",
+ "MongoDB"
+ ]
+ },
+ {
+ "category": "More",
+ "tags": [
+ "Leadership",
+ "Agile Methodology",
+ "Image Editing",
+ "Mobile-First",
+ "Responsive Design",
+ "Accessibility"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/index.css b/src/index.css
deleted file mode 100644
index 61010be6..00000000
--- a/src/index.css
+++ /dev/null
@@ -1,4 +0,0 @@
-body {
- background: pink;
- color: hotpink;
-}
\ No newline at end of file
diff --git a/src/main.jsx b/src/main.jsx
index ed109d76..c32d44a1 100644
--- a/src/main.jsx
+++ b/src/main.jsx
@@ -1,11 +1,9 @@
-import { StrictMode } from 'react'
-import { createRoot } from 'react-dom/client'
+import { StrictMode } from "react"
+import { createRoot } from "react-dom/client"
-import { App } from './App.jsx'
+import App from "./App.jsx"
-import './index.css'
-
-createRoot(document.getElementById('root')).render(
+createRoot(document.getElementById("root")).render(
,
diff --git a/src/sections/FeaturedProjects.jsx b/src/sections/FeaturedProjects.jsx
new file mode 100644
index 00000000..3aaeaab1
--- /dev/null
+++ b/src/sections/FeaturedProjects.jsx
@@ -0,0 +1,139 @@
+import styled from "styled-components"
+
+import Card from "../components/Card"
+import LinkButton from "../components/LinkButton"
+import { GithubIconSVG, IconsList, WebIconSVG } from "../components/SocialIcons"
+import StyledTags from "../components/StyledTags"
+import { media } from "../styles/media"
+
+const FeaturedSection = styled.main`
+ padding: 64px 16px;
+
+ @media ${media.tablet} {
+ padding: 64px 24px;
+ }
+
+ @media ${media.desktop} {
+ padding: 128px;
+ }
+`
+
+const SectionTitle = styled.h2`
+ text-align: center;
+ font-size: 48px;
+
+ @media ${media.desktop} {
+ font-size: 80px;
+ }
+`
+
+const ProjectsContainer = styled.div`
+ display: flex;
+ flex-direction: column;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: center;
+ padding-top: 64px;
+
+ @media ${media.desktop} {
+ flex-direction: ${({ $reverse }) => ($reverse ? "row-reverse" : "row")};
+ flex-wrap: nowrap;
+ padding-top: 128px;
+ gap: 125px;
+ max-width: 1200px;
+ margin: 0 auto;
+ }
+`
+
+const ProjectImage = styled.img`
+ width: 80%;
+ max-width: 600px;
+ border-radius: 12px;
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
+ object-fit: cover;
+
+ @media ${media.desktop} {
+ width: 50%;
+ /* max-width: 540px; */
+ height: auto;
+ }
+`
+
+const ProjectsTextContainer = styled.div`
+ display: flex;
+ flex-direction: column;
+ justify-content: start;
+ width: 100%;
+ padding-top: 64px;
+ gap: 32px;
+
+ @media ${media.tablet}{
+ min-width: 580px;
+ }
+
+ @media ${media.desktop} {
+ width: 50%;
+ padding: 0;
+ flex-shrink: 1;
+ }
+`
+
+const ProjectHeading = styled.h3`
+ font-size: 24px;
+
+ @media ${media.desktop} {
+ font-size: 30px;
+ }
+`
+
+const LinkContainer = styled.div`
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+`
+
+const FeaturedProjects = ({ projects }) => {
+ return (
+
+ Featured Projects
+
+ {projects.map((proj, index) => {
+ const isEven = index % 2 === 0;
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+ })}
+
+ )
+}
+
+export default FeaturedProjects
\ No newline at end of file
diff --git a/src/sections/Footer.jsx b/src/sections/Footer.jsx
new file mode 100644
index 00000000..43d2b51b
--- /dev/null
+++ b/src/sections/Footer.jsx
@@ -0,0 +1,56 @@
+import Contact from "../components/Contact"
+import SocialIcons from "../components/SocialIcons"
+import styled from "styled-components"
+import BiankaRomero from "../assets/BiankaRomero.jpg"
+import { media } from "../styles/media"
+
+const FooterContainer = styled.footer`
+ padding: 64px 16px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ text-align: center;
+ background-color: ${({ theme, $mode}) => theme.colors[$mode].background};
+ color: ${({ theme, $mode}) => theme.colors[$mode].text};
+
+ @media ${media.desktop} {
+ padding: 128px 16px;
+ }
+`
+
+const FooterTitle = styled.h2`
+ text-align: center;
+ margin-bottom: 16px;
+
+ @media ${media.tablet} {
+ font-size: 48px;
+ }
+
+ @media ${media.desktop} {
+ font-size: 80px;
+ }
+`
+
+const CircleImg = styled.img`
+ width: 164px;
+ height: 164px;
+ border-radius: 164px;
+ object-fit: cover;
+`
+
+const Footer = ({ mode = "dark" }) => {
+ return (
+
+ Let's Connect
+
+
+
+
+ )
+}
+
+export default Footer
\ No newline at end of file
diff --git a/src/sections/Header.jsx b/src/sections/Header.jsx
new file mode 100644
index 00000000..fee0683b
--- /dev/null
+++ b/src/sections/Header.jsx
@@ -0,0 +1,65 @@
+import Card from "../components/Card"
+import styled from "styled-components"
+import HeroImages from "../components/HeroImages"
+import { media } from "../styles/media"
+
+const HeroHeader = styled.header`
+ display: flex;
+ padding: 64px 16px;
+ flex-direction: column;
+ align-items: center;
+ text-align: center;
+
+ @media ${media.tablet} {
+ padding: 64px 24px;
+ }
+
+ @media ${media.desktop} {
+ padding-top: 128px;
+ padding-bottom: 64px;
+ max-width: 782px;
+ margin: 0 auto;
+ }
+`
+
+const TopLine = styled.h2`
+ font-size: 24px;
+
+ @media ${media.desktop} {
+ font-size: 30px;
+ }
+`
+
+const HeroName = styled.h1`
+ font-size: 52px;
+
+ @media ${media.desktop} {
+ font-size: 100px;
+ }
+`
+
+const HeaderTitle = styled.h2`
+ font-size: 20px;
+
+ @media ${media.tablet}, ${media.desktop} {
+ font-size: 30px;
+ }
+`
+
+
+const Header = () => {
+ return (
+
+ Hi there, I'm
+ Bianka L Romero
+
+
+
+ )
+}
+
+export default Header
diff --git a/src/sections/Reflections.jsx b/src/sections/Reflections.jsx
new file mode 100644
index 00000000..e51cc55a
--- /dev/null
+++ b/src/sections/Reflections.jsx
@@ -0,0 +1,136 @@
+import styled from "styled-components"
+import { media } from "../styles/media"
+import StyledTags from "../components/StyledTags"
+import LinkButton from "../components/LinkButton"
+import Card from "../components/Card"
+import { WebIconSVG } from "../components/SocialIcons"
+
+const ArticleSection = styled.section`
+ background: ${({ theme }) => theme.colors.background};
+ color: ${({ theme }) => theme.colors.primary};
+ padding: 64px 16px;
+
+@media ${media.tablet} {
+ padding: 64px 24px;
+}
+
+@media ${media.desktop} {
+ padding: 128px;
+}
+`
+
+const SectionTitle = styled.h2`
+ text-align: center;
+ font-size: 48px;
+
+ @media ${media.desktop} {
+ font-size: 80px;
+ }
+`
+
+const ArticlesContainer = styled.div`
+ display: flex;
+ flex-direction: column;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: center;
+ margin: 0 auto;
+ padding-top: 64px;
+ gap: 32px;
+
+ @media ${media.tablet} {
+ flex-direction: row;
+ flex-wrap: nowrap;
+ align-items: stretch;
+ }
+
+ @media ${media.desktop} {
+ flex-direction: row;
+ flex-wrap: nowrap;
+ align-items: stretch;
+ padding-top: 128px;
+ gap: 125px;
+ max-width: 1200px;
+ margin: 0 auto;
+ }
+`
+
+const ArticleImage = styled.img`
+ width: 100%;
+ height: 200px;
+ border-radius: 12px;
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
+ object-fit: cover;
+
+ @media ${media.tablet} {
+ width: 50%;
+ height: 100%;
+ flex: 1;
+ }
+
+ @media ${media.desktop} {
+ width: 50%;
+ height: auto;
+ }
+`
+
+const ArticlesTextContainer = styled.div`
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: start;
+ flex: 1;
+ width: 100%;
+ gap: 32px;
+
+`
+
+const LinkContainer = styled.div`
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+`
+const CardHeading = styled.h3`
+ font-size: 30px;
+`
+
+const Reflections = ({ articles }) => {
+ return (
+
+ Personal Reflections
+
+ {articles.map((article, index) => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ )
+ })}
+
+ )
+}
+
+export default Reflections
\ No newline at end of file
diff --git a/src/sections/Skills.jsx b/src/sections/Skills.jsx
new file mode 100644
index 00000000..2e809e68
--- /dev/null
+++ b/src/sections/Skills.jsx
@@ -0,0 +1,96 @@
+import Card from "../components/Card"
+import styled from "styled-components"
+import { media } from "../styles/media"
+
+const SkillsSection = styled.div`
+ padding: 64px 16px;
+ background: black;
+ color: white;
+ gap: 16px;
+
+ @media ${media.tablet} {
+ padding: 64px 24px;
+ }
+ @media ${media.desktop} {
+ padding: 128px 0;
+ }
+`
+
+const SectionTitle = styled.h2`
+ font-size: 48px;
+ padding-bottom: 40px;
+ text-align: center;
+
+ @media ${media.desktop} {
+ font-size: 80px;
+ }
+`
+
+const SkillsContainer = styled.section`
+ display: flex;
+ flex-wrap: wrap;
+ flex-direction: column;
+ align-content: start;
+ justify-content: center;
+ gap: 24px;
+
+ @media (min-width: 426px) {
+ align-content: center;
+ gap: 24px;
+ width: 100%;
+ justify-items: center;
+
+ & ul li {
+ align-self: stretch;
+ text-align: center;
+ }
+ }
+
+ @media ${media.desktop} {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+ gap: 24px;
+ width: 100%;
+ justify-items: center;
+ max-width: 1200px;
+ margin: 0 auto;
+
+ & ul li {
+ text-align: left;
+ }
+ }
+`
+
+const SkillTagTitles = styled.h3`
+ font-size: 16px;
+ border-radius: 4px;
+ border: 1px solid #FFF;
+ background: #000;
+ padding: 2px 6px;
+ margin-bottom: 16px;
+ display: flex;
+ justify-content: center;
+`
+
+const Skills = ({ skills }) => {
+ return (
+
+ Skills
+
+ {skills.map((skill) => {
+ return (
+
+ )
+ })
+ }
+
+
+ )
+}
+
+export default Skills
\ No newline at end of file
diff --git a/src/sections/Tech.jsx b/src/sections/Tech.jsx
new file mode 100644
index 00000000..a7d064ed
--- /dev/null
+++ b/src/sections/Tech.jsx
@@ -0,0 +1,48 @@
+import Card from "../components/Card"
+import styled from "styled-components"
+import { media } from "../styles/media"
+
+const TechSection = styled.div`
+ background: black;
+ color: white;
+ padding: 64px 16px;
+ text-align: center;
+ width: 100%;
+
+ @media ${media.tablet} {
+ padding: 64px 24px;
+ }
+ @media ${media.desktop} {
+ padding: 128px 0;
+ }
+`
+const TechTitle = styled.h2`
+ font-size: 60px;
+
+ @media ${media.desktop} {
+ font-size: 80px;
+ }
+`
+
+const CardContainer = styled.div`
+ @media ${media.desktop} {
+ max-width: 782px;
+ margin: 0 auto;
+ }
+`
+
+const Tech = () => {
+ return (
+
+
+
+
+
+ )
+}
+
+export default Tech
\ No newline at end of file
diff --git a/src/styles/GlobalStyle.jsx b/src/styles/GlobalStyle.jsx
new file mode 100644
index 00000000..e7896411
--- /dev/null
+++ b/src/styles/GlobalStyle.jsx
@@ -0,0 +1,57 @@
+import { createGlobalStyle } from "styled-components"
+
+export const GlobalStyle = createGlobalStyle`
+ * {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+ }
+
+ body {
+ font-family: "Poppins", "Arial", sans-serif;
+ width: 100%;
+ margin: auto;
+ margin-top: 20px;
+ margin-bottom: 20px;
+ }
+
+ a {
+ text-decoration: none;
+ color: inherit;
+ }
+
+ *:focus-visible {
+ outline: 2px solid blueviolet;
+ outline-offset: 2px;
+ }
+
+@keyframes slideInLeft {
+ from {
+ opacity: 0;
+ transform: translateX(-50px);
+ }
+ to {
+ opacity: 1;
+ transform: translateX(0)
+ }
+}
+
+@keyframes slideInRight {
+ from {
+ opacity: 0;
+ transform: translateX(50px);
+ }
+ to {
+ opacity: 1;
+ transform: translateX(0)
+ }
+}
+
+.slide-in-left {
+ animation: slideInLeft 0.8s ease-out forwards;
+}
+
+.slide-in-right {
+ animation: slideInRight 0.8s ease-out forwards;
+}
+`
\ No newline at end of file
diff --git a/src/styles/media.js b/src/styles/media.js
new file mode 100644
index 00000000..d8e9cf84
--- /dev/null
+++ b/src/styles/media.js
@@ -0,0 +1,5 @@
+export const media = {
+ mobile: "(max-width: 767px)",
+ tablet: "(min-width: 768px) and (max-width: 1023px)",
+ desktop: "(min-width: 1024px)"
+}
\ No newline at end of file
diff --git a/src/styles/theme.js b/src/styles/theme.js
new file mode 100644
index 00000000..546b4953
--- /dev/null
+++ b/src/styles/theme.js
@@ -0,0 +1,19 @@
+export const theme = {
+ spacing: {
+ none: "0px",
+ small: "16px",
+ medium: "32px",
+ large: "64px",
+ xlarge: "128px",
+ },
+ colors: {
+ light: {
+ background: "white",
+ text: "black"
+ },
+ dark: {
+ background: "black",
+ text: "white"
+ },
+ },
+}
\ No newline at end of file
diff --git a/vite.config.js b/vite.config.js
index 8b0f57b9..d133d633 100644
--- a/vite.config.js
+++ b/vite.config.js
@@ -3,5 +3,11 @@ import react from '@vitejs/plugin-react'
// https://vite.dev/config/
export default defineConfig({
- plugins: [react()],
+ plugins: [
+ react({
+ babel: {
+ plugins: [['babel-plugin-styled-components', { displayName: true }]]
+ }
+ })
+ ]
})