Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
# Portfolio
Link netlify: https://portfoliofrida.netlify.app/

50 changes: 39 additions & 11 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,41 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Portfolio</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>

<head>
<meta charset="UTF-8" />
<link
rel="icon"
type="image/svg+xml"
href="/vite.svg"
/>
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>

<!--font poppins-->
<link
rel="preconnect"
href="https://fonts.googleapis.com"
>
<link
rel="preconnect"
href="https://fonts.gstatic.com"
crossorigin
>
<link
href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap"
rel="stylesheet"
>
<title>Portfolio</title>
</head>

<body>
<div id="root"></div>
<script
type="module"
src="/src/main.jsx"
></script>
</body>

</html>
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@
},
"dependencies": {
"react": "^19.0.0",
"react-dom": "^19.0.0"
"react-dom": "^19.0.0",
"react-markdown": "^10.1.0",
"styled-components": "^6.1.19"
},
"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.7.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",
Expand Down
1 change: 1 addition & 0 deletions public/blogposts/post-1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Det här är mitt senaste blogginlägg.
1 change: 1 addition & 0 deletions public/blogposts/post-2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Det här är mitt andra blogginlägg.
1 change: 1 addition & 0 deletions public/blogposts/post-3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Det här är mitt första blogginlägg.
Empty file added public/blogposts/post-4.md
Empty file.
22 changes: 18 additions & 4 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
import React from "react";
import "./index.css";
import { Header } from "./components/sections/Header";
import { Tech } from "./components/sections/Tech";
import { Projects } from "./components/sections/Projects";
import { Skills } from "./components/sections/Skills";
import { Blog } from "./components/sections/Blog";
import { Contacts } from "./components/sections/Contacts";


export const App = () => {
return (
<>
<h1>Portfolio</h1>
<p>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.</p>
<Header />
<Tech />
<Projects />
<Skills />
<Blog />
<Contacts />
</>
)
}
);
};
23 changes: 23 additions & 0 deletions src/components/BlogData.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import placeHolderImg from "../img/placeholderimg.png"

export const blogData = [
{
name: "Blog post",
framework: ["July 14th"],
description: "/blogposts/post-1.md",
image: placeHolderImg,
},

{
name: "Blog post",
framework: ["July 8th"],
description: "/blogposts/post-2.md",
image: placeHolderImg,
},
{
name: "Blog post",
framework: ["July 1st"],
description: "/blogposts/post-3.md",
image: placeHolderImg,
},
];
25 changes: 25 additions & 0 deletions src/components/UI/SectionTitle.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import styled from "styled-components";

// Section title h1
export const SectionTitle = styled.h1`
margin-bottom: 24px;
font-size: 60px;
font-weight: bold;
text-align: center;
color: ${({ theme, dark }) =>
dark ? theme.surface.dark.text : theme.surface.light.text};
`;

export const SubTitle = styled.h2`
font-size: ${({ theme }) => theme.typography.h2.fontSize};
font-weight: ${({ theme }) => theme.typography.h2.fontWeight};
color: ${({ theme, dark }) =>
dark ? theme.surface.dark.text : theme.surface.light.text};
`;

export const Text = styled.p`
font-size: ${({ theme }) => theme.typography.p.fontSize};
font-weight: ${({ theme }) => theme.typography.p.fontWeight};
color: ${({ theme, dark }) =>
dark ? theme.surface.dark.text : theme.surface.light.text};
`;
88 changes: 88 additions & 0 deletions src/components/items/BlogCard.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import React, { useState, useEffect } from "react";
import styled from "styled-components";
import { SectionTitle, SubTitle, Text } from "../UI/SectionTitle";
import { theme } from "../../theme";
import { FrameWork } from "./frameworkbtn";
import { DemoIcon } from "../../img/icons";
import { ActionButton } from "../items/Buttons";
import ReactMarkdown from "react-markdown";

// for styling component items
const WrapperBlog = styled.article`
display: grid;
gap: 1rem;
grid-template-columns: 1fr;
border-radius: 12px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
padding: 1rem;
text-align: left;

@media(min-width: ${theme.breakpoints.tablet}) {
grid-template-columns: 1fr 1fr;
padding: 3rem;

}
`;
const BlogImage = styled.img`
width: 100%;
border-radius: 12px;
@media(min-width: ${theme.breakpoints.tablet}){
width: 80%;
}


`;
const BlogInfo = styled.div`
display: flex;
flex-direction: column;
`;

const ButtonIcon = styled.span`
display: flex;
align-items: center;
margin-left: 6px;

svg {
width: 20px;
height: 20px;
}
`;

export const BlogPost = ({ blog }) => {
const [content, setContent] = useState("");
const [isOpen, setIsOpen] = useState(false);

useEffect(() => {
if (blog.description) {
fetch(blog.description)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole fetching of local markdown files feels a bit funky. You could have just imported them :)

.then((res) => res.text())
.then((text) => setContent(text));
}
}, [blog.description]);

// to open and close blog posts
const toggleOpen = () => setIsOpen(prev => !prev);

return (
<WrapperBlog>
<BlogImage src={blog.image} alt={`picture of blog post ${name}`} />
<BlogInfo>
<FrameWork frameworks={blog.framework} />
<SubTitle>{blog.name}</SubTitle>


{isOpen && ( //get blog post from public/blogposts path
<Text>
<ReactMarkdown>{content}</ReactMarkdown>
</Text>
)}

<ActionButton onClick={toggleOpen}>
<ButtonIcon><DemoIcon /></ButtonIcon> {isOpen ? "Hide Article" : "Read Article"}
</ActionButton>
</BlogInfo>
</WrapperBlog>
);
};


53 changes: 53 additions & 0 deletions src/components/items/Buttons.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import styled from "styled-components";


const ButtonBase = styled.div`
background: black;
color: white;
display: flex;
align-items: center;
width: 60%;
max-width: 303px;
border-radius: 12px;
font-size: 16px;
font-family: inherit;
padding: 4px 12px;
gap: 16px;
margin-bottom: 13px;
text-decoration: none;
cursor: pointer;

svg {
width: 20px;
height: 20px;
}

&:hover {
transform: scale(1.1);
}
`;

// for demo + github links
export const LinkButton = styled(ButtonBase).attrs({ as: "a" })`
text-decoration: underline;
`;

// for read article
export const ActionButton = styled(ButtonBase).attrs({ as: "button" })`
`;



//show more/less buttons:
export const ToggleButton = styled(ButtonBase).attrs({ as: "button" })`
background-color: ${({ $active }) => ($active ? "black" : "white")};
color: ${({ $active }) => ($active ? "white" : "black")};
border: 1px solid black;
border-radius: 12px;
padding: 4px 12px;
font-size: 16px;
width: auto;
display: flex;
margin: 30px auto 0;
cursor: pointer;
`;
85 changes: 85 additions & 0 deletions src/components/items/ProjectCard.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import React from "react";
import styled from "styled-components";
import { SectionTitle, SubTitle, Text } from "../UI/SectionTitle";
import { theme } from "../../theme";
import { FrameWork } from "./frameworkbtn";
import { LinkButton } from "../items/Buttons";
import { DemoIcon, GithubIcon } from "../../img/icons";

// for styling component items
const Card = styled.div`
display: grid;
grid-template-columns: 1fr;
gap: 40px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
border-radius: 12px;
padding: 1rem;
text-align: left;
margin-bottom: 20px;

@media (min-width: ${theme.breakpoints.tablet}){
padding: 5rem;
}

@media (min-width: ${theme.breakpoints.desktop}) {
grid-template-columns: 1fr 1fr;
gap: 10px;
margin-bottom: 40px;
padding: 5rem;

&:nth-child(even) {
direction: rtl;

img,
div {
direction: ltr;
}
}
}
`;

//project image
const ProjectImage = styled.img`
width: 100%;
border-radius: 12px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);

@media (min-width: ${theme.breakpoints.desktop}) {
width: 80%;
}
`;

//project content
const ProjectInfo = styled.div``;

//button icon
const ButtonIcon = styled.div`
display: flex;
align-items: center;
margin-left: 6px;

svg {
width: 20px;
height: 20px;
}
`;


export const ProjectCard = ({ project }) => (
<Card>
<ProjectImage src={project.image} alt={`picture of project ${name}`} />
<ProjectInfo>
<FrameWork frameworks={project.framework} />
<SubTitle>{project.name}</SubTitle>
<Text>{project.description}</Text>
<div>
<LinkButton href={project.demoLink}>
<ButtonIcon><DemoIcon aria-hidden="true" /></ButtonIcon> Live Demo
</LinkButton>
<LinkButton href={project.githubLink}>
<ButtonIcon><GithubIcon aria-hidden="true" /></ButtonIcon> Github
</LinkButton>
</div>
</ProjectInfo>
</Card>
);
Loading