-
Notifications
You must be signed in to change notification settings - Fork 55
Portfolio project Irisdzg #48
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
7429120
815334d
6fe980d
c1fa76f
e8cb97f
0bab2ec
39d8682
bd2fb33
0154114
38da078
1937e84
6734fac
073c773
dcf461b
029e263
7a3dce4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,19 @@ | ||
| # Portfolio | ||
| Personal Portfolio – React & Styled Components | ||
|
|
||
| This is my personal portfolio website built with React, Styled Components. | ||
| It showcases my projects, skills, and background as a frontend developer. | ||
|
|
||
| Hero Section | ||
| -Displays my name, photo, intro text, and personal tagline. | ||
|
|
||
| Projects Section | ||
| -Renders each project from a data file | ||
| -Shows an image, description, tags, and links to GitHub + Live demo | ||
| -Mobile-friendly layout that flips image + text for alternating projects | ||
|
|
||
| Skills & Tech Section | ||
| -Lists my technical skills and tools, grouped into categories for clarity. | ||
|
|
||
| Footer | ||
| -Includes contact details and social icons. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,31 @@ | ||
| export const App = () => { | ||
| import React from 'react'; | ||
| import { GlobalStyle } from './GlobalStyles'; | ||
|
|
||
| // Import Components | ||
| import HeroSection from './components/HeroSection'; | ||
| import TechSection from './components/TechSection'; | ||
| import ProjectsSection from './components/ProjectsSection'; | ||
| import SkillsSection from './components/SkillsSection'; | ||
| import Footer from './components/Footer'; | ||
| import ArticlesSection from './components/ArticlesSection'; | ||
|
|
||
| // Import Data | ||
| import { userData, techSkills, projects, skillsCategories, articles } from './data/portfolioData'; | ||
|
|
||
| function 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> | ||
| <GlobalStyle /> | ||
|
|
||
| <HeroSection user={userData} /> | ||
| <TechSection tech={techSkills} /> | ||
| <ProjectsSection list={projects} /> | ||
| <ArticlesSection articles={articles} /> | ||
| <SkillsSection categories={skillsCategories} /> | ||
| <Footer user={userData} /> | ||
|
|
||
| </> | ||
| ) | ||
| ); | ||
| } | ||
|
|
||
| export default App; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| // src/GlobalStyles.js | ||
| import { createGlobalStyle } from 'styled-components'; | ||
|
|
||
| export const GlobalStyle = createGlobalStyle` | ||
| /* Importing the font Montserrat */ | ||
| * { | ||
| box-sizing: border-box; | ||
| margin: 0; | ||
| padding: 0; | ||
| } | ||
| body { | ||
| font-family: 'Montserrat', sans-serif; | ||
| background-color: #fff; | ||
| color: #333; | ||
| line-height: 1.6; | ||
| } | ||
| a { | ||
| text-decoration: none; | ||
| color: inherit; | ||
| } | ||
| `; | ||
|
Comment on lines
+4
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great job setting up the global styles. One small suggestion: you might consider adding a :root section for things like colors, fonts, or spacing. This makes it easier to update styles in one place later on. For example: Then you could use these variables in your styles, which can make future changes much quicker and more consistent. Overall, really solid work! 😏👍 |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,128 @@ | ||
| import React from 'react'; | ||
| import styled from 'styled-components'; | ||
| import { SquareArrowOutUpRight } from 'lucide-react'; | ||
|
|
||
| const Section = styled.section` | ||
| padding: 100px 20px; | ||
| background-color: #000; | ||
| `; | ||
|
|
||
| const SectionTitle = styled.h2` | ||
| text-align: center; | ||
| font-size: 3rem; | ||
| font-weight: 800; | ||
| margin-bottom: 60px; | ||
| color: #fff; | ||
| `; | ||
|
|
||
| const Container = styled.div` | ||
| max-width: 800px; | ||
| margin: 0 auto; | ||
| display: flex; | ||
| flex-direction: column; | ||
| gap: 60px; | ||
| `; | ||
|
|
||
| const ArticleCard = styled.article` | ||
| display: flex; | ||
| gap: 30px; | ||
| align-items: flex-start; | ||
| @media (max-width: 768px) { | ||
| flex-direction: column; | ||
| } | ||
| `; | ||
|
|
||
| const ImageContainer = styled.div` | ||
| flex: 0 0 300px; | ||
| img { | ||
| width: 100%; | ||
| height: 200px; | ||
| object-fit: cover; | ||
| box-shadow: 10px 10px 0px 0px #eee; | ||
| } | ||
| @media (max-width: 768px) { | ||
| flex: 1; | ||
| width: 100%; | ||
| img { height: 250px; } | ||
| } | ||
| `; | ||
|
|
||
| const Content = styled.div` | ||
| flex: 1; | ||
| display: flex; | ||
| flex-direction: column; | ||
| justify-content: center; | ||
| `; | ||
|
|
||
| const DateText = styled.span` | ||
| color: #fff; | ||
| font-size: 0.8rem; | ||
| font-weight: 700; | ||
| text-transform: uppercase; | ||
| margin-bottom: 10px; | ||
| display: block; | ||
| `; | ||
|
|
||
| const Title = styled.h3` | ||
| color: #fff; | ||
| font-size: 1.5rem; | ||
| font-weight: 800; | ||
| margin-bottom: 10px; | ||
| line-height: 1.3; | ||
| `; | ||
|
|
||
| const Description = styled.p` | ||
| font-size: 1.1rem; | ||
| color: #fff; | ||
| margin-bottom: 20px; | ||
| line-height: 1.6; | ||
| `; | ||
|
|
||
| const ReadButton = styled.a` | ||
| display: inline-flex; | ||
| align-items: center; | ||
| gap: 8px; | ||
| background-color: #fff; | ||
| color: #000; | ||
| padding: 10px 24px; | ||
| border-radius: 30px; | ||
| font-weight: 600; | ||
| font-size: 0.9rem; | ||
| width: fit-content; | ||
| &:hover { | ||
| background-color: #333; | ||
| transform: translateY(-2px); | ||
| transition: 0.2s; | ||
| } | ||
| `; | ||
|
|
||
| export default function ArticlesSection({ articles }) { | ||
| if (!articles || articles.length === 0) return null; | ||
|
|
||
| return ( | ||
| <Section> | ||
| <SectionTitle>My Words</SectionTitle> | ||
| <Container> | ||
| {articles.map((article) => ( | ||
| <ArticleCard key={article.id}> | ||
| <ImageContainer> | ||
| <img src={article.image} alt={article.title} /> | ||
| </ImageContainer> | ||
| <Content> | ||
| <DateText>{article.date}</DateText> | ||
| <Title>{article.title}</Title> | ||
| <Description>{article.description}</Description> | ||
| <ReadButton href={article.link} target="_blank" rel="noopener noreferrer"> | ||
| Read Article <SquareArrowOutUpRight size={16} /> | ||
| </ReadButton> | ||
| </Content> | ||
| </ArticleCard> | ||
| ))} | ||
| </Container> | ||
| </Section> | ||
| ); | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Really nice work on the ArticlesSection component! The layout is clean, responsive, and easy to read. I like the responsive adjustments for mobile look solid! 😀 A couple of suggestions: Colors & spacing – you could consider moving repeated values like #fff, #000, and spacing units into a :root or theme variables. This would make it easier to tweak styles globally later. And the image sizes – right now the images have fixed heights. Maybe using min-height or making them fully responsive could help avoid cropping issues on unusual image dimensions. |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| import React from 'react'; | ||
| import styled from 'styled-components'; | ||
| import { Linkedin, Github } from "lucide-react"; | ||
|
|
||
| const FooterWrap = styled.footer` | ||
| background: #000; | ||
| color: #fff; | ||
| padding: 80px 20px; | ||
| text-align: center; | ||
| `; | ||
|
|
||
| const FooterTitle = styled.h2` | ||
| font-size: 3rem; | ||
| margin-bottom: 40px; | ||
| `; | ||
|
|
||
| const ProfilePic = styled.img` | ||
| width: 80px; | ||
| height: 80px; | ||
| border-radius: 50%; | ||
| margin-bottom: 20px; | ||
| `; | ||
|
|
||
| const Socials = styled.div` | ||
| display: flex; | ||
| gap: 20px; | ||
| justify-content: center; | ||
| margin-top: 30px; | ||
| `; | ||
|
|
||
| const SocialLink = styled.a` | ||
| color: #fff; | ||
| transition: opacity 0.2s ease; | ||
| } | ||
| `; | ||
|
|
||
| export default function Footer({ user }) { | ||
| return ( | ||
| <FooterWrap> | ||
|
|
||
| <FooterTitle>Let's Talk</FooterTitle> | ||
|
|
||
| <ProfilePic | ||
| src={user.profileImage} | ||
| alt={`${user.name}'s profile photo`} | ||
| /> | ||
|
|
||
| <h3>{user.name}</h3> | ||
| <p>{user.phone}</p> | ||
| <p>{user.email}</p> | ||
|
|
||
| <Socials> | ||
| <SocialLink href={user.socials.linkedin} aria-label="LinkedIn profile"> | ||
| <Linkedin /> | ||
| </SocialLink> | ||
|
|
||
| <SocialLink href={user.socials.github} aria-label="GitHub profile"> | ||
| <Github /> | ||
| </SocialLink> | ||
| </Socials> | ||
|
|
||
| </FooterWrap> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice job on the Footer component! The structure is easy to follow. I like that you included alt text for the profile image and aria-labels for the social links — accessibility attention is always a plus 🌹 |
||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| import React from 'react'; | ||
| import styled from 'styled-components'; | ||
|
|
||
| const Section = styled.header` | ||
| padding: 100px 20px; | ||
| text-align: center; | ||
| background: white; | ||
| `; | ||
|
|
||
| const SmallHeading = styled.p` | ||
| text-transform: uppercase; | ||
| letter-spacing: 2px; | ||
| font-size: 3rem; | ||
| font-weight: 700; | ||
| color: #555; | ||
| margin-bottom: 15px; | ||
| `; | ||
|
|
||
| const Name = styled.h1` | ||
| font-size: 3.5rem; | ||
| font-weight: 800; | ||
| margin-bottom: 30px; | ||
| color: #000; | ||
|
|
||
| @media (max-width: 768px) { | ||
| font-size: 2.5rem; | ||
| } | ||
| `; | ||
|
|
||
| const ProfileImg = styled.img` | ||
| width: 280px; | ||
| height: 280px; | ||
| border-radius: 50%; | ||
| object-fit: cover; | ||
| margin: 0 auto 30px; | ||
| `; | ||
|
|
||
| // This styles the "intro" (Bold text) | ||
| const MainIntro = styled.h2` | ||
| font-size: 1.5rem; | ||
| font-weight: 700; | ||
| max-width: 600px; | ||
| margin: 0 auto 20px; | ||
| line-height: 1.4; | ||
| `; | ||
|
|
||
| // This styles the "subIntro" (Lighter text) | ||
| const SubText = styled.p` | ||
| font-size: 1.1rem; | ||
| color: #666; | ||
| max-width: 500px; | ||
| margin: 0 auto; | ||
| line-height: 1.6; | ||
| `; | ||
|
|
||
| export default function HeroSection({ user }) { | ||
| return ( | ||
| <Section> | ||
| <SmallHeading>Nihao, I'm</SmallHeading> | ||
|
|
||
| <Name>{user.name}</Name> | ||
|
|
||
| <ProfileImg src={user.profileImage} alt={user.name} /> | ||
|
|
||
| {/* 1. The Bold Intro */} | ||
| <MainIntro>{user.intro}</MainIntro> | ||
|
|
||
| {/* 2. The Lighter Sub-Intro */} | ||
| <SubText>{user.subIntro}</SubText> | ||
| </Section> | ||
| ); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you try out postcss and tailwind as well and forgot to remove the packages? :)