diff --git a/README.md b/README.md
index 200f4282..e5ca4404 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,4 @@
# Portfolio
+
+Netlify link: https://portfolio-kasia.netlify.app/
+
diff --git a/package.json b/package.json
index 48911600..a7c1bffd 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,5 @@
{
- "name": "project",
+ "name": "js-project-portfolio",
"private": true,
"version": "0.0.0",
"type": "module",
@@ -11,7 +11,8 @@
},
"dependencies": {
"react": "^19.0.0",
- "react-dom": "^19.0.0"
+ "react-dom": "^19.0.0",
+ "styled-components": "^6.1.18"
},
"devDependencies": {
"@eslint/js": "^9.21.0",
diff --git a/src/App.jsx b/src/App.jsx
index a161d8d3..8d65fd85 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -1,8 +1,29 @@
+import { Introduction } from "./components/about/Introduction";
+import { Tech } from "./components/Tech";
+import { Projects } from "./components/projects/Projects";
+import { Skills } from "./components/Skills";
+import { Contact } from "./components/about/Contact";
+import { Footer } from "./components/Footer";
+
+import { styled } from "styled-components";
+
+const StyledDiv = styled.div`
+ body {
+ margin: 0;
+ }
+`;
+
export 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.
- >
- )
-}
+
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/src/assets/arrowdown.svg b/src/assets/arrowdown.svg
new file mode 100644
index 00000000..2d0660ba
--- /dev/null
+++ b/src/assets/arrowdown.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/src/assets/profilePhoto.jpg b/src/assets/profilePhoto.jpg
new file mode 100644
index 00000000..546d01d2
Binary files /dev/null and b/src/assets/profilePhoto.jpg differ
diff --git a/src/assets/projects/accessibility_site.png b/src/assets/projects/accessibility_site.png
new file mode 100644
index 00000000..e184a4b4
Binary files /dev/null and b/src/assets/projects/accessibility_site.png differ
diff --git a/src/assets/projects/business_site.png b/src/assets/projects/business_site.png
new file mode 100644
index 00000000..1dda8267
Binary files /dev/null and b/src/assets/projects/business_site.png differ
diff --git a/src/assets/projects/happy_thoughts.png b/src/assets/projects/happy_thoughts.png
new file mode 100644
index 00000000..9d2815bb
Binary files /dev/null and b/src/assets/projects/happy_thoughts.png differ
diff --git a/src/assets/projects/movie_browser.png b/src/assets/projects/movie_browser.png
new file mode 100644
index 00000000..b6104f95
Binary files /dev/null and b/src/assets/projects/movie_browser.png differ
diff --git a/src/assets/projects/recipe_library.png b/src/assets/projects/recipe_library.png
new file mode 100644
index 00000000..5274c5af
Binary files /dev/null and b/src/assets/projects/recipe_library.png differ
diff --git a/src/assets/projects/weather_app.png b/src/assets/projects/weather_app.png
new file mode 100644
index 00000000..42361983
Binary files /dev/null and b/src/assets/projects/weather_app.png differ
diff --git a/src/components/Footer.jsx b/src/components/Footer.jsx
new file mode 100644
index 00000000..d8f36f28
--- /dev/null
+++ b/src/components/Footer.jsx
@@ -0,0 +1,80 @@
+//import "./Footer.css"
+import { styled } from "styled-components";
+
+const StyledFooter = styled.footer`
+ .ticker-wrap {
+ width: 100%;
+ height: 80px;
+ margin: 0 auto;
+ overflow: hidden;
+ white-space: nowrap;
+ bottom: 0;
+ height: 114px;
+ background-color: var(--color-foreground);
+ }
+
+ .ticker {
+ display: inline-block;
+ margin-top: 5px;
+ animation: marquee 40s linear infinite;
+ }
+ .item-collection-1 {
+ position: relative;
+ left: 0%;
+ animation: swap 40s linear infinite;
+ }
+
+ .item {
+ display: inline-block;
+ color: var(--color-white);
+ font-family: "Montserrat", sans-serif;
+ font-size: 26.038px;
+ font-weight: 600;
+ padding-top: 41px;
+ padding-bottom: 35px;
+ }
+
+ /* Transition */
+ @keyframes marquee {
+ 0% {
+ transform: translateX(0);
+ }
+ 100% {
+ transform: translateX(-100%);
+ }
+ }
+
+ @keyframes swap {
+ 0%,
+ 50% {
+ left: 0%;
+ }
+ 50.01%,
+ 100% {
+ left: 100%;
+ }
+ }
+`;
+
+export const Footer = () => {
+ return (
+
+
+
+
+ Kasia Wolkowicz · Frontend Developer ·
+ Kasia Wolkowicz · Frontend Developer ·
+ Kasia Wolkowicz · Frontend Devełoper ·
+ Kasia Wolkowicz · Frontend Developer ·
+
+
+ Kasia Wolkowicz · Frontend Developer ·
+ Kasia Wolkowicz · Frontend Developer ·
+ Kasia Wolkowicz · Frontend Developer ·
+ Kasia Wolkowicz · Frontend Developer ·
+
+
+
+
+ );
+};
diff --git a/src/components/PageTopic.jsx b/src/components/PageTopic.jsx
new file mode 100644
index 00000000..4345d5b4
--- /dev/null
+++ b/src/components/PageTopic.jsx
@@ -0,0 +1,5 @@
+export const PageTopic = ({pageTopic, className})=>{
+ return (
+ {pageTopic}
+ )
+}
\ No newline at end of file
diff --git a/src/components/Skills.jsx b/src/components/Skills.jsx
new file mode 100644
index 00000000..7a1b1b9c
--- /dev/null
+++ b/src/components/Skills.jsx
@@ -0,0 +1,187 @@
+import { PageTopic } from "./PageTopic";
+import { styled } from "styled-components";
+
+const StyledSection = styled.section`
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ width: 100%;
+ background-color: var(--color-background);
+ padding: 128px 16px 157px 16px;
+ gap: 64px;
+
+ .skills {
+ font-size: 56px;
+ font-weight: 700;
+ color: var(--color-white);
+ }
+
+ .skill-container {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ gap: 64px;
+ }
+
+ .skillbox {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 16px;
+ }
+
+ .listbox p {
+ font-size: 18px;
+ color: var(--color-white);
+ font-weight: 400;
+ font-family: "Hind", sans-serif;
+ line-height: normal;
+ text-align: center;
+ padding: 2px;
+ }
+
+ .listbox p:hover {
+ background-color: var(--color-foreground);
+ cursor: default;
+ }
+
+ .skill-container h3 {
+ font-size: 24px;
+ font-weight: 600;
+ }
+
+ .code-head {
+ color: var(--color-white);
+ background-color: var(--color-code);
+ }
+
+ .toolbox-head {
+ color: var(--color-white);
+ background-color: var(--color-background);
+ }
+
+ .upcoming-head {
+ color: var(--color-white);
+ background-color: var(--color-upcoming);
+ }
+
+ .more-head {
+ color: var(--color-foreground);
+ background-color: var(--color-more);
+ }
+
+ .skill-container h3:hover {
+ background-color: var(--color-test);
+ color: var(--color-code);
+ cursor: default;
+ }
+
+ @media (min-width: 667px) and (max-width: 1024px) {
+ padding: 128px 32px 148px 32px;
+ width: auto;
+
+ .skill-container {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ align-items: flex-start;
+ gap: 64px;
+ }
+
+ .skillbox {
+ align-items: flex-start;
+ }
+
+ .listbox p {
+ text-align: left;
+ }
+ }
+
+ @media (min-width: 1025px) {
+ padding: 128px 161px;
+ gap: 128px;
+
+ .skill-container {
+ display: flex;
+ flex-direction: row;
+ align-items: flex-start;
+ justify-content: space-between;
+ }
+
+ .skills {
+ font-size: 80px;
+ }
+
+ .listbox p {
+ text-align: left;
+ }
+
+ .skill-container h3 {
+ font-size: 32px;
+ }
+
+ .skillbox {
+ align-items: flex-start;
+ gap: 8px;
+ }
+ }
+`;
+
+export const Skills = () => {
+ return (
+
+
+
+
+
Code
+
+
React
+
Global State Management
+
DOM Manipulation
+
Javascript ES6
+
HTML5
+
CSS3
+
Tailwind CSS
+
Styled Components
+
Node
+
REST API
+
Authentication
+
+
+
+
Toolbox
+
+
GitHub
+
Git
+
Postman
+
VS code
+
Netlify
+
Figma
+
Chrome dev tools
+
+
+
+
+
More
+
+
Problem-Solving
+
Agile methodology
+
Accessibility
+
Responsive Design
+
Team work
+
Mob programming
+
Pair programming
+
Remote working
+
Design hand-off
+
+
+
+
+ );
+};
diff --git a/src/components/Tech.jsx b/src/components/Tech.jsx
new file mode 100644
index 00000000..2c979b80
--- /dev/null
+++ b/src/components/Tech.jsx
@@ -0,0 +1,75 @@
+import { PageTopic } from "./PageTopic";
+import { styled } from "styled-components";
+
+const StyledSection = styled.section`
+ padding: 128px 16px;
+ background-color: var(--color-background);
+ width: 100%;
+
+ .tech-container {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ gap: 64px;
+ }
+
+ .tech {
+ color: var(--color-white);
+ font-size: 80px;
+ font-weight: 700;
+ font-family: "Montserrat", sans-serif;
+ text-align: center;
+ }
+
+ .tech-details {
+ color: var(--color-white);
+ font-size: 32px;
+ font-weight: 600;
+ font-family: "Hind", sans-serif;
+ text-align: left;
+ }
+
+ @media (min-width: 667px) and (max-width: 1024px) {
+ padding: 256px 32px;
+
+ .tech-details {
+ text-align: center;
+ }
+ }
+
+ @media (min-width: 1025px) {
+ padding: 0px 161px;
+ height: 980px;
+ display: flex;
+
+ .tech-container {
+ flex-direction: row;
+ gap: 124px;
+ justify-content: center;
+ align-items: center;
+ }
+
+ .tech {
+ font-size: 80px;
+ }
+
+ .tech-details {
+ font-size: 32px;
+ }
+ }
+`;
+
+export const Tech = () => {
+ return (
+
+
+
+
+ HTML, CSS, Flexbox, JavaScript, ES6, JSX, React, React Hooks, Node.js,
+ Web Accessibility, APIs, mob-programming, pair-programming, GitHub.
+
+
+
+ );
+};
diff --git a/src/components/about/Contact.jsx b/src/components/about/Contact.jsx
new file mode 100644
index 00000000..dd31b92f
--- /dev/null
+++ b/src/components/about/Contact.jsx
@@ -0,0 +1,127 @@
+import { PageTopic } from '../PageTopic'
+import { Linkedin } from '../icons/Linkedin'
+import { Github } from '../icons/Github'
+import { Instagram } from '../icons/Instagram'
+import { ProfilePhoto } from './ProfilePhoto'
+import { styled } from 'styled-components'
+
+
+const StyledContact = styled.section`
+display: flex;
+flex-direction: column;
+justify-content: center;
+align-items: center;
+padding: 128px 16px;
+gap: 64px;
+background-color: var(--color-white);
+
+.contact {
+ color: var(--color-foreground);
+ font-family: "Montserrat", sans-serif;
+ font-size: 56px;
+ font-weight: 700;
+}
+
+.contactContent {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ gap: 40px;
+}
+.info{
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 16px;
+}
+
+.name{
+ font-size: 30px;
+ color: var(--color-foreground);
+ font-family: "Montserrat", sans-serif;
+ font-weight: 600;
+}
+
+.location,
+.email{
+ color: var(--color-foreground);
+ font-family: "Montserrat", sans-serif;
+ font-size: 24px;
+ font-weight: 600;
+}
+
+.contactIcons {
+ display: flex;
+ justify-content: center;
+ align-items: space-around;
+ gap: 45px;
+}
+
+.contactIcons a:hover {
+ svg path {
+ fill: var(--color-foreground)
+ }
+}
+
+@media (min-width:667px) and (max-width:1024px) {
+ .contact-wrapper {
+ padding: 128px 32px;
+ }
+ .location,
+ .email{
+ font-size: 20px;
+ }
+}
+
+@media (min-width: 1025px) {
+ .contact-wrapper {
+ padding: 100px 162px 100px 161px;
+ gap: 80px;
+ }
+
+ .contact {
+ font-size: 80px;
+ }
+
+ .name {
+ font-size: 35px;
+ }
+
+ .location,
+ .email{
+ font-size: 20px;
+ }
+}
+`
+
+export const Contact = () => {
+ const linkedin = "https://www.linkedin.com/in/kasiawolko/"
+ const github = "https://github.com/Kasssiiii"
+ const instagram = "https://www.instagram.com/kasia_wolko/"
+
+ return (
+
+
+
+
+
+
Kasia Wolkowicz
+
🖈Based in Stockholm, Sweden
+
✉ kasia.gru@gmail.com
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/components/about/Introduction.jsx b/src/components/about/Introduction.jsx
new file mode 100644
index 00000000..b97b39f7
--- /dev/null
+++ b/src/components/about/Introduction.jsx
@@ -0,0 +1,147 @@
+//import './Introduction.css'
+import arrow from "/arrowdown.svg";
+import { ProfilePhoto } from "./ProfilePhoto";
+import { styled } from "styled-components";
+
+const StyledSection = styled.section`
+ display: flex;
+ padding: 64px 16px;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ gap: 32px;
+ width: 100%;
+ background-color: var(--color-white);
+
+ .intro-box {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ align-self: stretch;
+ }
+
+ .dev-name {
+ color: var(--color-foreground);
+ font-size: 32px;
+ font-weight: 600;
+ font-family: "Montserrat", sans-serif;
+ align-self: flex-start;
+ }
+
+ .dev-title {
+ color: var(--color-foreground);
+ font-size: 80px;
+ font-weight: 700;
+ font-family: "Montserrat", sans-serif;
+ align-self: flex-start;
+ }
+
+ .dev-intro {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ gap: 22px;
+ align-self: stretch;
+ text-align: left;
+ word-wrap: break-word;
+ color: var(--color-black);
+ font-size: 18px;
+ font-weight: 400;
+ font-family: "Hind", sans-serif;
+ }
+
+ .arrow {
+ animation: move 2s linear infinite;
+ }
+
+ @keyframes move {
+ 0%,
+ 100% {
+ transform: translateY(0);
+ }
+
+ 25%,
+ 75% {
+ transform: translateY(-10px);
+ }
+ }
+
+ @media (min-width: 667px) and (max-width: 1024px) {
+ padding: 128px 32px 30px 32px;
+
+ .dev-name {
+ font-size: 28px;
+ }
+
+ .dev-title {
+ font-size: 52px;
+ }
+ }
+
+ @media (min-width: 1025px) {
+ padding: 332px 161px 100px 161px;
+
+ .dev-name {
+ font-size: 36px;
+ }
+
+ .dev-title {
+ font-size: 70px;
+ }
+ }
+
+ @media (min-width: 667px) {
+ display: grid;
+ grid-template-columns: repeat(7, auto);
+ grid-template-rows: repeat(3, auto);
+
+ .intro-box {
+ grid-area: 1/1/2/8;
+ }
+
+ .dev-photo {
+ grid-area: 2/1/3/3;
+ }
+
+ .dev-intro {
+ grid-area: 2/3/3/9;
+ font-size: 20px;
+ }
+
+ .arrow {
+ grid-area: 3/5/4/6;
+ align-items: center;
+ }
+ }
+`;
+
+export const Introduction = () => {
+ return (
+
+
+
Hi, I'm Kasia Wolkowicz
+ Frontend Developer
+
+
+
+
+
+ I'm a Front-End Developer with a strong focus on accessibility, clean
+ code, and creating user-friendly digital experiences. With a
+ background in payroll, financial services, and office administration,
+ I bring a unique mix of technical skill and business insight to every
+ project I work on.
+
+
+ Whether I’m coding a responsive layout, improving performance, or
+ making sure a site works for users with assistive tech, I care deeply
+ about the details. Currently levelling up my JavaScript and React
+ skills while contributing to projects that make a difference.
+
+
+
+
+
+ );
+};
diff --git a/src/components/about/ProfilePhoto.jsx b/src/components/about/ProfilePhoto.jsx
new file mode 100644
index 00000000..c926000d
--- /dev/null
+++ b/src/components/about/ProfilePhoto.jsx
@@ -0,0 +1,17 @@
+import profilePhotoFile from "/profilePhoto.jpg"
+import { styled } from 'styled-components'
+
+const StyledImg = styled.img`
+ width: 164px;
+ height: 164px;
+ border-radius: 50%;
+ aspect-ratio: 1/1;
+ object-fit: cover;
+`;
+
+// retain className for layout of intro section
+export const ProfilePhoto = ({className} ) => {
+ return (
+
+ );
+};
\ No newline at end of file
diff --git a/src/components/icons/Code.jsx b/src/components/icons/Code.jsx
new file mode 100644
index 00000000..84f4032b
--- /dev/null
+++ b/src/components/icons/Code.jsx
@@ -0,0 +1,19 @@
+export const Code = ({fill= "#000000"}) => {
+ return(
+
+
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/components/icons/Demo.jsx b/src/components/icons/Demo.jsx
new file mode 100644
index 00000000..6a7410d5
--- /dev/null
+++ b/src/components/icons/Demo.jsx
@@ -0,0 +1,19 @@
+export const Demo = ({fill= "#000000"}) => {
+ return(
+
+
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/components/icons/Github.jsx b/src/components/icons/Github.jsx
new file mode 100644
index 00000000..3e6cba64
--- /dev/null
+++ b/src/components/icons/Github.jsx
@@ -0,0 +1,23 @@
+export const Github = ({fill="#D0D0D0"}) => {
+ return(
+
+
+
+
+
+ )
+
+}
+
+
+
diff --git a/src/components/icons/Instagram.jsx b/src/components/icons/Instagram.jsx
new file mode 100644
index 00000000..8561498b
--- /dev/null
+++ b/src/components/icons/Instagram.jsx
@@ -0,0 +1,16 @@
+export const Instagram =({fill="#D0D0D0"})=>{
+ return(
+
+
+
+
+
+ )
+
+}
diff --git a/src/components/icons/Linkedin.jsx b/src/components/icons/Linkedin.jsx
new file mode 100644
index 00000000..e00ed0cd
--- /dev/null
+++ b/src/components/icons/Linkedin.jsx
@@ -0,0 +1,16 @@
+export const Linkedin = ({fill="#D0D0D0"}) => {
+ return(
+
+
+
+
+
+ )
+}
diff --git a/src/components/projects/Project.jsx b/src/components/projects/Project.jsx
new file mode 100644
index 00000000..739425f4
--- /dev/null
+++ b/src/components/projects/Project.jsx
@@ -0,0 +1,223 @@
+import { ProjectTitle } from "./ProjectTitle";
+import { Tag } from "./Tag";
+import { Demo } from "../icons/Demo";
+import { Code } from "../icons/Code";
+import { styled } from "styled-components";
+
+const StyledDiv = styled.div`
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 24px;
+
+ .projectSnippet {
+ width: 343px;
+ height: 200px;
+ object-fit: contain;
+ object-position: top;
+ border-radius: 13px;
+ }
+
+ .detail-box {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 24px;
+ align-self: stretch;
+ overflow: visible;
+ }
+
+ .detail {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 16px;
+ }
+
+ .description {
+ font-size: 18px;
+ font-weight: 400;
+ font-family: "Hind", sans-serif;
+ color: var(--color-black);
+ text-align: left;
+ word-wrap: break-word;
+ }
+
+ .tag {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: flex-start;
+ gap: 4px;
+ }
+
+ .btn {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ align-self: stretch;
+ width: 430px;
+ gap: 32px;
+ }
+
+ .btn a {
+ display: flex;
+ flex-direction: row;
+ padding-right: 16px;
+ align-items: center;
+ gap: 7px;
+ color: var(--color-dark);
+ font-family: "Montserrat", sans-serif;
+ font-size: 20px;
+ font-style: normal;
+ font-weight: 600;
+ line-height: normal;
+ text-decoration: none;
+ }
+
+ #liveDemoBtn,
+ #viewCodeBtn {
+ :hover {
+ background-color: var(--color-foreground);
+ border-radius: 40px;
+ color: var(--color-light);
+ svg path {
+ fill: var(--color-light);
+ }
+ }
+ }
+
+ #liveDemoBtn,
+ #viewCodeBtn {
+ border-radius: 40px;
+ background-color: var(--color-light);
+ svg path {
+ fill: var(--color-dark);
+ }
+ }
+
+ @media (max-width: 666px) {
+ .btn {
+ display: flex;
+ padding-right: 16px;
+ align-items: center;
+ gap: 7px;
+ }
+
+ .btn a {
+ font-size: 15px;
+ }
+ }
+
+ @media (min-width: 667px) {
+ .btn a {
+ font-size: 15px;
+ }
+ }
+
+ @media (min-width: 667px) and (max-width: 1024px) {
+ .project-wrapper {
+ padding: 128px 32px;
+ }
+
+ .projectSnippet {
+ width: 200px;
+ height: 280px;
+ }
+
+ flex-direction: row;
+
+ .detail-box {
+ justify-content: space-between;
+ }
+
+ .btn {
+ flex-direction: row;
+ gap: 32px;
+ }
+
+ .project {
+ align-self: self-start;
+ }
+ }
+
+ @media (min-width: 1025px) {
+ .project-wrapper {
+ padding: 128px 161px 124px 161px;
+ }
+
+ .project {
+ font-size: 80px;
+ }
+
+ .projectSnippet {
+ width: 408px;
+ height: 280px;
+ }
+
+ .project-container {
+ gap: 128px;
+ }
+
+ flex-direction: row;
+
+ .detail-box {
+ justify-content: space-between;
+ }
+
+ .btn {
+ flex-direction: row;
+ gap: 32px;
+ }
+
+ .project {
+ align-self: self-start;
+ }
+ }
+`;
+
+export const Project = ({
+ projectName,
+ projectIntro,
+ topics,
+ demoLink,
+ codeLink,
+ image,
+ alt,
+}) => {
+ const title = projectName.replaceAll("-", " ");
+ return (
+
+
+
+
+
+
+
+
+ {projectIntro}{" "}
+
+
+ {topics.map(
+ (topic) =>
+ topic !== "portfolio" &&
+ )}
+
+
+
+
+
+ );
+};
diff --git a/src/components/projects/ProjectTitle.jsx b/src/components/projects/ProjectTitle.jsx
new file mode 100644
index 00000000..f1a662fd
--- /dev/null
+++ b/src/components/projects/ProjectTitle.jsx
@@ -0,0 +1,16 @@
+import { styled } from "styled-components";
+
+const StyledHeader = styled.h3`
+ font-size: 24px;
+ font-weight: 600;
+ font-family: "Montserrat", sans-serif;
+ color: var(--color-black);
+
+ @media (min-width: 1025px) {
+ font-size: 32px;
+ }
+`;
+
+export const ProjectTitle = ({ title }) => {
+ return {title} ;
+};
diff --git a/src/components/projects/Projects.jsx b/src/components/projects/Projects.jsx
new file mode 100644
index 00000000..fc0aad08
--- /dev/null
+++ b/src/components/projects/Projects.jsx
@@ -0,0 +1,76 @@
+import { Project } from "./Project";
+import { PageTopic } from "../PageTopic";
+import { styled } from "styled-components";
+
+import projects from "../../data/projects.json";
+
+const StyledSection = styled.section`
+ display: flex;
+ padding: 128px 16px 208px 16px;
+ flex-direction: column;
+ align-items: center;
+ gap: 64px;
+ background-color: var(--color-white);
+ width: 100%;
+ overflow: scroll;
+
+ .project {
+ color: var(--color-black);
+ font-size: 56px;
+ font-family: "Montserrat", sans-serif;
+ align-self: center;
+ }
+
+ .project-container {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 64px;
+ align-self: stretch;
+ }
+
+ @media (min-width: 667px) and (max-width: 1024px) {
+ padding: 128px 32px;
+
+ .project {
+ align-self: self-start;
+ }
+ }
+
+ @media (min-width: 1025px) {
+ padding: 128px 161px 124px 161px;
+
+ .project {
+ font-size: 80px;
+ align-self: self-start;
+ }
+
+ .project-container {
+ gap: 128px;
+ }
+ }
+`;
+
+export const Projects = () => {
+ return (
+
+
+
+ {projects.projects.map((project) => {
+ return (
+
+ );
+ })}
+
+
+ );
+};
diff --git a/src/components/projects/Tag.jsx b/src/components/projects/Tag.jsx
new file mode 100644
index 00000000..06bea570
--- /dev/null
+++ b/src/components/projects/Tag.jsx
@@ -0,0 +1,18 @@
+import { styled } from "styled-components";
+
+const StyledP = styled.p`
+ list-style: none;
+ color: var(--color-white);
+ background-color: var(--color-black);
+ width: fit-content;
+ align-items: center;
+ text-align: left;
+ padding: 2px 6px;
+ font-family: "Hind", sans-serif;
+ font-size: 16px;
+ border-radius: 5px;
+`;
+
+export const Tag = ({ topic }) => {
+ return {topic} ;
+};
diff --git a/src/data/projects.json b/src/data/projects.json
index 7c426028..3c05bfb4 100644
--- a/src/data/projects.json
+++ b/src/data/projects.json
@@ -1,28 +1,95 @@
{
"projects": [
{
+ "key": 1,
"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",
+ "image": "/projects/business_site.png",
+ "alt": "project's business site screenshot",
"tags": [
"HTML5",
"CSS3",
"JavaScript"
],
- "netlify": "link",
- "github": "link"
+ "netlify": "https://js-buss-site-2025.netlify.app/",
+ "github": "https://github.com/Kasssiiii/js-project-business-site",
+ "about": "A static website listing properties for rent. Built with vanilla HTML, CSS, and JavaScript, this project showcases rental listings and provides basic interactivity for browsing."
},
{
- "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",
+ "key": 2,
+ "name": "Recipe Library",
+ "image": "/projects/recipe_library.png",
+ "alt": "project's recipe library screenshot",
"tags": [
"HTML5",
"CSS3",
"JavaScript",
- "TypeScript",
"APIs"
],
- "netlify": "link",
- "github": "link"
+ "netlify": "https://js-recipe-libr.netlify.app/",
+ "github": "https://github.com/Kasssiiii/js-project-recipe-library",
+ "about": "A browser for cooking recipes using data from Spoonacular API. The app allows users to filter, sort, and explore sample recipes using vanilla HTML, CSS, and JavaScript."
+ },
+ {
+ "key": 3,
+ "name": "Weather App",
+ "image": "/projects/weather_app.png",
+ "alt": "weather app screenshot",
+ "tags": [
+ "HTML5",
+ "CSS3",
+ "JavaScript",
+ "APIs",
+ "Team Project"
+ ],
+ "netlify": "https://nordicweatherapp.netlify.app/",
+ "github": "https://github.com/JasminHed/newjs-project-weather-app",
+ "about": "A modern weather application that provides current conditions and a 4-day forecast for cities worldwide. Built using OpenWeatherMap API and JavaScript, this group project helped me learn how to work with external APIs, handle JSON data, manage loading/error states, and create a clean responsive layout."
+ },
+ {
+ "key": 4,
+ "name": "Accessibility Site",
+ "image": "/projects/accessibility_site.png",
+ "alt": "accessibility site screenshot",
+ "tags": [
+ "HTML5",
+ "CSS3",
+ "JavaScript",
+ "Accessibility",
+ "Team Project"
+ ],
+ "netlify": "https://teamwind1.netlify.app/",
+ "github": "https://github.com/Bianka2112/js-project-accessibility",
+ "about": "A website focused on demonstrating best practices in web accessibility. This group project includes semantic HTML, keyboard navigation, proper contrast ratios, and ARIA roles to ensure inclusive user experience. Also features a quiz about web accessibility."
+ },
+ {
+ "key": 5,
+ "name": "Movie Browser",
+ "image": "/projects/movie_browser.png",
+ "alt": "movie browser screenshot",
+ "tags": [
+ "React",
+ "JavaScript",
+ "APIs",
+ "CSS3"
+ ],
+ "netlify": "https://movies-js-kasia.netlify.app//",
+ "github": "https://github.com/Kasssiiii/js-project-movies",
+ "about": "A movie browsing app using data from The Movie Database (TMDb) API. Built with React, the app displays currently playing movies in cinemas and allows users to explore popular titles with a responsive, modern UI."
+ },
+ {
+ "key": 6,
+ "name": "Happy Thoughts",
+ "image": "/projects/happy_thoughts.png",
+ "alt": "happy thoughts screenshot",
+ "tags": [
+ "React",
+ "JavaScript",
+ "CSS3",
+ "APIs"
+ ],
+ "netlify": "https://happy-thoughts-js.netlify.app/",
+ "github": "https://github.com/Kasssiiii/js-project-happy-thoughts",
+ "about": "A Twitter-style web app for posting positive messages. Users can sign in and share happy thoughts publicly. Built with React and a custom API, the project focuses on state management, forms, and real-time updates."
}
]
-}
\ No newline at end of file
+}
diff --git a/src/index.css b/src/index.css
index 61010be6..e4e6b4a3 100644
--- a/src/index.css
+++ b/src/index.css
@@ -1,4 +1,28 @@
body {
background: pink;
color: hotpink;
+}
+
+:root{
+ font-synthesis: none;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ --color-foreground: #2B4B27;
+ --color-white: #ffffff;
+ --color-black: #000000;
+ --color-background: #2B4B27;
+ --color-light: #f5f5f5;
+ --color-dark: #333333;
+ --color-test: pink;
+ --color-code: #eb5577;
+ --color-upcoming: #426d51;
+ --color-more: #FFDE30;
+
+ text-align: center;
+ font-family: "Montserrat", sans-serif, "Hind", sans-serif;
+}
+
+* {
+ box-sizing: border-box;
+ margin: 0;
}
\ No newline at end of file
diff --git a/vite.config.js b/vite.config.js
index 8b0f57b9..d3a3108d 100644
--- a/vite.config.js
+++ b/vite.config.js
@@ -4,4 +4,5 @@ import react from '@vitejs/plugin-react'
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
+ publicDir: 'src/assets',
})