mirror of
https://github.com/hazemKrimi/personal-website.git
synced 2026-05-01 18:00:26 +00:00
Update website structure and styles
This commit is contained in:
@@ -1,17 +0,0 @@
|
||||
---
|
||||
title: 'Sample Blog Post'
|
||||
description: 'Sample description'
|
||||
author: 'Hazem Krimi'
|
||||
date: '2020-01-14'
|
||||
tags: ['sample']
|
||||
---
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean mattis dignissim orci, a aliquet leo vehicula in. Proin accumsan, justo luctus tristique ornare, tortor eros sodales arcu, quis maximus nunc tellus eu erat. Proin nisl lorem, congue at dignissim tempor, condimentum nec augue. Duis vulputate, metus eu luctus facilisis, elit mauris cursus felis, ullamcorper tempor diam est vel felis. Sed scelerisque, risus quis semper consectetur, eros lectus ornare turpis, et accumsan turpis nisi et erat. Donec sit amet elementum nunc. Nam eget dolor quis dolor rhoncus molestie id ut nisi. Vivamus suscipit ligula in sem tempor, sit amet lacinia augue luctus. Ut quis urna varius, volutpat sem eget, tincidunt augue. Duis porta dui nec sem tincidunt, ac porttitor magna molestie. Pellentesque massa ligula, malesuada ut urna nec, blandit volutpat libero. Cras sed laoreet massa.
|
||||
|
||||
Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Maecenas efficitur eros gravida turpis blandit suscipit. Nullam ante mauris, condimentum quis augue ut, convallis volutpat urna. Nulla ac quam orci. Proin at ligula volutpat, porttitor erat id, vestibulum quam. In scelerisque scelerisque arcu id ultricies. Suspendisse at lorem est.
|
||||
|
||||
In eget dolor faucibus, condimentum lectus ac, maximus justo. Curabitur interdum commodo dapibus. Quisque ante lectus, aliquam vel nisl ac, accumsan posuere elit. Fusce magna sem, sagittis vitae cursus at, tincidunt sit amet eros. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vestibulum blandit id nisi et accumsan. Vestibulum fringilla sollicitudin purus, et vehicula eros accumsan ut. Quisque eget tortor ac libero scelerisque interdum.
|
||||
|
||||
Curabitur tempor et lacus in tincidunt. Aliquam dolor ante, facilisis venenatis ante nec, congue bibendum elit. Nulla luctus condimentum sapien quis iaculis. Cras lorem leo, tristique ac neque in, tincidunt tincidunt lorem. Quisque consectetur, tellus sit amet dapibus convallis, ante dolor egestas sem, eget varius sapien nisi non elit. Maecenas elementum lacinia tellus eget placerat. Donec ac nulla neque. In felis nibh, aliquam a neque at, iaculis auctor risus. Donec rhoncus eu mi sit amet pretium. In hac habitasse platea dictumst. Donec laoreet porttitor blandit.
|
||||
|
||||
Duis dapibus volutpat nisl, id tempus dolor mattis efficitur. Pellentesque bibendum nulla mattis sem aliquam euismod. Sed ut justo porttitor, dictum felis a, consectetur arcu. Mauris et ultricies nisl. Morbi id lorem vel nibh ornare rhoncus. Fusce egestas, elit at venenatis tincidunt, lacus elit auctor dui, vel lobortis enim lacus blandit ligula. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Proin fringilla neque nisl, ut pulvinar tortor efficitur sed. Aliquam non turpis consectetur, fermentum orci sit amet, malesuada est. Etiam est dui, porttitor non erat eu, porttitor ultrices orci. Nam a dolor fermentum, vulputate tellus quis, cursus nunc. Sed placerat augue erat, ac lacinia risus accumsan et. In interdum placerat nisi.
|
||||
@@ -2,10 +2,9 @@
|
||||
title: 'React Weather App'
|
||||
description: 'Weather app made with React, TypeScript and OpenWeatherMap API'
|
||||
date: '2021-09-19'
|
||||
image: 'https://res.cloudinary.com/dun9hhyz1/image/upload/v1632077200/personal-website/portfolio/react-weather-app/tuxpi.com.1632076521_a0wxsq_hw299g.jpg'
|
||||
hideImage: true
|
||||
demo: 'https://hazemkrimi.github.io/react-weather-app'
|
||||
code: 'https://github.com/hazemKrimi/react-weather-app'
|
||||
tags: ['react', 'typescript', 'openweathermap']
|
||||
---
|
||||
|
||||
# About the project
|
||||
|
||||
@@ -17,7 +17,7 @@ const Card: FC<Props> = ({ title, description, image, tags, href, target, onClic
|
||||
return (
|
||||
<Link href={href} passHref>
|
||||
<StyledCard as='a' target={target} onClick={onClick} image={!!image}>
|
||||
<div>
|
||||
<div className='card-content'>
|
||||
<h3>{title}</h3>
|
||||
<p>{description}</p>
|
||||
{tags && (
|
||||
@@ -28,10 +28,10 @@ const Card: FC<Props> = ({ title, description, image, tags, href, target, onClic
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{image ? (
|
||||
<Image src={image} width='100%' height='100%' layout='responsive' />
|
||||
) : (
|
||||
<Image src='/no-image.png' width='100%' height='100%' layout='responsive' />
|
||||
{image && (
|
||||
<div className='card-image'>
|
||||
<Image src={image} layout='fill' objectFit='cover' />
|
||||
</div>
|
||||
)}
|
||||
</StyledCard>
|
||||
</Link>
|
||||
|
||||
@@ -4,12 +4,20 @@ export const StyledCard = styled.div<{ image: boolean }>`
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: auto 150px;
|
||||
grid-template-columns: ${({ image }) => (image ? 'auto 9.375rem' : 'auto')};
|
||||
align-items: stretch;
|
||||
transition: color 0ms ease-in-out;
|
||||
text-decoration: none;
|
||||
color: var(--text);
|
||||
|
||||
@media (max-width: 320px) {
|
||||
grid-template-columns: ${({ image }) => (image ? 'auto 7.813rem' : 'auto')};
|
||||
}
|
||||
|
||||
@media (min-width: 1440px) {
|
||||
grid-template-columns: ${({ image }) => (image ? 'auto 15.625rem' : 'auto')};
|
||||
}
|
||||
|
||||
&:hover {
|
||||
& > div {
|
||||
background: ${({ theme }) => theme.colors.blue};
|
||||
@@ -24,7 +32,7 @@ export const StyledCard = styled.div<{ image: boolean }>`
|
||||
}
|
||||
}
|
||||
|
||||
& > div {
|
||||
.card-content {
|
||||
padding: 1rem 0rem;
|
||||
background: var(--secondary-background);
|
||||
display: grid;
|
||||
@@ -35,6 +43,11 @@ export const StyledCard = styled.div<{ image: boolean }>`
|
||||
}
|
||||
}
|
||||
|
||||
.card-image {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
h3,
|
||||
p,
|
||||
.tags-wrapper {
|
||||
|
||||
@@ -37,13 +37,6 @@ const Footer: FC = () => {
|
||||
href='https://codepen.io/hazemkrimi'
|
||||
target='_blank'
|
||||
/>
|
||||
<IconButton
|
||||
icon={mode === 'dark' ? '/icons/light-dribbble.svg' : '/icons/dark-dribbble.svg'}
|
||||
width={16}
|
||||
height={16}
|
||||
href='https://dribbble.com/HazemKrimi'
|
||||
target='_blank'
|
||||
/>
|
||||
</div>
|
||||
<p>Hazem Krimi © {new Date().getFullYear()}</p>
|
||||
</StyledFooter>
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
import { FC, useContext } from 'react';
|
||||
import { ThemeContext } from '../../styles/theme';
|
||||
import { FC } from 'react';
|
||||
import { Wrapper } from './styles';
|
||||
import Image from 'next/image';
|
||||
|
||||
const Hero: FC = () => {
|
||||
const { mode } = useContext(ThemeContext);
|
||||
|
||||
return (
|
||||
const Hero: FC = () => (
|
||||
<Wrapper>
|
||||
<div className='intro'>
|
||||
<h2>Hi, I am Hazem</h2>
|
||||
@@ -14,16 +10,10 @@ const Hero: FC = () => {
|
||||
<h2 className='blue'>Software Developer</h2>
|
||||
<h2 className='blue'>Life Long Learner</h2>
|
||||
</div>
|
||||
<div className='illustration'>
|
||||
<Image
|
||||
src={mode === 'dark' ? '/dark-illustration.svg' : '/light-illustration.svg'}
|
||||
width='100%'
|
||||
height='100%'
|
||||
layout='responsive'
|
||||
/>
|
||||
<div className='photo'>
|
||||
<Image src='/photo.jpg' width={515} height={535} objectFit='cover' />
|
||||
</div>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default Hero;
|
||||
|
||||
@@ -3,16 +3,16 @@ import styled from 'styled-components';
|
||||
export const Wrapper = styled.div`
|
||||
min-height: 45vh;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-template-columns: 1fr 32.188rem;
|
||||
align-items: center;
|
||||
height: auto;
|
||||
text-align: left;
|
||||
|
||||
@media (max-width: 425px) {
|
||||
min-height: 65vh;
|
||||
grid-template-columns: auto;
|
||||
@media (max-width: 1024px) {
|
||||
min-height: 35vh;
|
||||
grid-template-columns: 1fr;
|
||||
|
||||
.illustration {
|
||||
.photo {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -29,15 +29,6 @@ export const Wrapper = styled.div`
|
||||
}
|
||||
}
|
||||
|
||||
.small {
|
||||
font-size: 1rem;
|
||||
font-weight: normal;
|
||||
|
||||
@media (min-width: 1440px) {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.blue {
|
||||
color: ${({ theme }) => theme.colors.blue};
|
||||
}
|
||||
|
||||
@@ -47,11 +47,6 @@ const MobileNav: FC<Props> = ({ open, close }) => {
|
||||
{mode === 'dark' ? 'Light Mode' : 'Dark Mode'}
|
||||
</Button>
|
||||
</div>
|
||||
<div className='mobile-button-wrapper'>
|
||||
<Button href='/about' onClick={() => close()}>
|
||||
About
|
||||
</Button>
|
||||
</div>
|
||||
<div className='mobile-button-wrapper'>
|
||||
<Button href='/portfolio' onClick={() => close()}>
|
||||
Portfolio
|
||||
@@ -62,6 +57,11 @@ const MobileNav: FC<Props> = ({ open, close }) => {
|
||||
Blog
|
||||
</Button>
|
||||
</div>
|
||||
<div className='mobile-button-wrapper'>
|
||||
<Button href='/contact' onClick={() => close()}>
|
||||
Contact
|
||||
</Button>
|
||||
</div>
|
||||
</Bar>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -30,9 +30,9 @@ const Nav: FC = () => {
|
||||
icon={mode === 'dark' ? '/icons/sun.svg' : '/icons/moon.svg'}
|
||||
onClick={toggle}
|
||||
/>
|
||||
<Button href='/about'>About</Button>
|
||||
<Button href='/portfolio'>Portfolio</Button>
|
||||
<Button href='/blog'>Blog</Button>
|
||||
<Button href='/contact'>Contact</Button>
|
||||
<Button href='/resume.pdf' target='_blank' variant='outline'>
|
||||
Resume
|
||||
</Button>
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import React, { FC, useContext, useState } from 'react';
|
||||
import { ThemeContext } from '../styles/theme';
|
||||
import React, { FC, useState } from 'react';
|
||||
import { useForm, ValidationError } from '@formspree/react';
|
||||
import Head from 'next/head';
|
||||
import { Wrapper } from '../styles/about';
|
||||
import Image from 'next/image';
|
||||
import Input from '../components/Input';
|
||||
import MDXButton from '../components/MDXButton';
|
||||
|
||||
const About: FC = () => {
|
||||
const { mode } = useContext(ThemeContext);
|
||||
const [form, setForm] = useState<{ name: string; email: string; message: string }>({
|
||||
name: '',
|
||||
email: '',
|
||||
@@ -51,22 +48,10 @@ const About: FC = () => {
|
||||
name='keywords'
|
||||
content='Hazem, Krimi, Developer, Software, Engineer, Web, Mobile, Frontend, Backend, Fullstack, JavaScript, React.js, React Native, Node.js, Portfolio, Blog, Tutorials, Tech News'
|
||||
/>
|
||||
<title>About | Hazem Krimi</title>
|
||||
<title>Contact | Hazem Krimi</title>
|
||||
</Head>
|
||||
<Wrapper>
|
||||
<div className='content'>
|
||||
<div>
|
||||
<h1>About Me</h1>
|
||||
<div className='about'>
|
||||
<p>
|
||||
I am a software developer and a student. I have experience as a full stack developer
|
||||
but I lean more to the front end and I have built a lot of web apps and some mobile
|
||||
apps. Also, I am always learning and experimenting with new technologies (currently
|
||||
learning about the ethereum blockchain) and other topics other than software
|
||||
engineering.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h1>Contact Me {submitted && <span className='success'>Message sent ✔️</span>}</h1>
|
||||
<form className='contact' onSubmit={handleSubmit}>
|
||||
@@ -116,9 +101,6 @@ const About: FC = () => {
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div className='photo'>
|
||||
<Image src='/picture.jpg' width='100%' height='100%' layout='responsive' />
|
||||
</div>
|
||||
</Wrapper>
|
||||
</>
|
||||
);
|
||||
+24
-17
@@ -52,39 +52,46 @@ const Index: FC<Props> = ({ blogPosts, portfolioProjects }) => {
|
||||
<Wrapper>
|
||||
<Hero />
|
||||
<div className='content'>
|
||||
<h1>About me</h1>
|
||||
<div className='about'>
|
||||
<p>
|
||||
I am a software developer. I have experience as a full stack developer but I lean more
|
||||
to the front end and I have built a lot of web apps and some mobile apps. Also, I am
|
||||
always learning and experimenting with new technologies (currently learning about the
|
||||
ethereum blockchain) and other topics other than software engineering.
|
||||
</p>
|
||||
</div>
|
||||
{portfolioProjects.length !== 0 && (
|
||||
<>
|
||||
<h1>Portfolio</h1>
|
||||
<Button href='/portfolio' className='blue'>
|
||||
See More
|
||||
</Button>
|
||||
<div className='portfolio'>
|
||||
<div className='projects-wrapper'>
|
||||
{portfolioProjects.length !== 0 ? (
|
||||
portfolioProjects
|
||||
.slice(0, 3)
|
||||
.map(({ slug, ...rest }) => (
|
||||
{portfolioProjects.slice(0, 3).map(({ slug, ...rest }) => (
|
||||
<Card {...rest} key={slug} href={`/portfolio/${slug}`} />
|
||||
))
|
||||
) : (
|
||||
<h4>Nothing for now</h4>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{blogPosts.length !== 0 && (
|
||||
<>
|
||||
<h1>Blog</h1>
|
||||
<Button href='/blog' className='blue'>
|
||||
See More
|
||||
</Button>
|
||||
<div className='blog'>
|
||||
<div className='articles-wrapper'>
|
||||
{blogPosts.length !== 0 ? (
|
||||
blogPosts
|
||||
.slice(0, 3)
|
||||
.map(({ slug, ...rest }) => <Card {...rest} key={slug} href={`/blog/${slug}`} />)
|
||||
) : (
|
||||
<h4>Nothing for now</h4>
|
||||
{blogPosts.slice(0, 3).map(({ slug, ...rest }) => (
|
||||
<Card {...rest} key={slug} href={`/blog/${slug}`} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Wrapper>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -88,7 +88,6 @@ const PortfolioProject: FC<Props> = ({ source, frontMatter }) => {
|
||||
<MDXButton variant='action' link={frontMatter.demo} target='_blank'>
|
||||
Demo
|
||||
</MDXButton>
|
||||
|
||||
<MDXButton variant='outline' link={frontMatter.code} target='_blank'>
|
||||
Source Code
|
||||
</MDXButton>
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-dribbble"><circle cx="12" cy="12" r="10"></circle><path d="M8.56 2.75c4.37 6.03 6.02 9.42 8.03 17.72m2.54-15.38c-3.72 4.35-8.94 5.66-16.88 5.85m19.5 1.9c-3.5-.93-6.63-.82-8.94 0-2.58.92-5.01 2.86-7.44 6.32"></path></svg>
|
||||
|
Before Width: | Height: | Size: 416 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-dribbble"><circle cx="12" cy="12" r="10"></circle><path d="M8.56 2.75c4.37 6.03 6.02 9.42 8.03 17.72m2.54-15.38c-3.72 4.35-8.94 5.66-16.88 5.85m19.5 1.9c-3.5-.93-6.63-.82-8.94 0-2.58.92-5.01 2.86-7.44 6.32"></path></svg>
|
||||
|
Before Width: | Height: | Size: 416 B |
Binary file not shown.
|
Before Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 75 KiB |
@@ -2,9 +2,6 @@ import styled from 'styled-components';
|
||||
|
||||
export const Wrapper = styled.div`
|
||||
padding: 1rem 0rem;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
column-gap: 2rem;
|
||||
|
||||
@media (max-width: 768px) {
|
||||
padding: 0rem;
|
||||
@@ -13,14 +10,6 @@ export const Wrapper = styled.div`
|
||||
row-gap: 1rem;
|
||||
}
|
||||
|
||||
.photo {
|
||||
order: initial;
|
||||
|
||||
@media (max-width: 768px) {
|
||||
order: -1;
|
||||
}
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 1.7rem;
|
||||
}
|
||||
@@ -30,7 +19,6 @@ export const Wrapper = styled.div`
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.about,
|
||||
.contact {
|
||||
margin: 1rem 0rem;
|
||||
|
||||
|
||||
@@ -29,8 +29,8 @@ export const Wrapper = styled.div`
|
||||
|
||||
.articles-wrapper {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||
grid-auto-rows: minmax(100px, auto);
|
||||
grid-template-columns: repeat(auto-fit, minmax(18.75rem, 1fr));
|
||||
grid-auto-rows: minmax(6.25rem, auto);
|
||||
align-items: stretch;
|
||||
justify-items: center;
|
||||
gap: 1rem;
|
||||
|
||||
+3
-2
@@ -27,6 +27,7 @@ export const Wrapper = styled.div`
|
||||
}
|
||||
}
|
||||
|
||||
.about,
|
||||
.portfolio,
|
||||
.blog {
|
||||
margin: 1rem 0rem;
|
||||
@@ -39,8 +40,8 @@ export const Wrapper = styled.div`
|
||||
.projects-wrapper,
|
||||
.articles-wrapper {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||
grid-auto-rows: minmax(100px, auto);
|
||||
grid-template-columns: repeat(auto-fit, minmax(18.75rem, 1fr));
|
||||
grid-auto-rows: minmax(6.25rem, auto);
|
||||
align-items: stretch;
|
||||
justify-items: center;
|
||||
gap: 1rem;
|
||||
|
||||
@@ -29,8 +29,8 @@ export const Wrapper = styled.div`
|
||||
|
||||
.projects-wrapper {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||
grid-auto-rows: minmax(100px, auto);
|
||||
grid-template-columns: repeat(auto-fit, minmax(18.75rem, 1fr));
|
||||
grid-auto-rows: minmax(6.25rem, auto);
|
||||
align-items: stretch;
|
||||
justify-items: center;
|
||||
gap: 1rem;
|
||||
|
||||
Reference in New Issue
Block a user