mirror of
https://github.com/hazemKrimi/personal-website.git
synced 2026-05-01 18:00:26 +00:00
Update card and content pages layout
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
title: 'Sample Portfolio Project'
|
title: 'Sample Portfolio Project'
|
||||||
description: 'Sample description'
|
description: 'Sample description'
|
||||||
date: '2020-01-14'
|
date: '2020-01-14'
|
||||||
|
image: 'https://res.cloudinary.com/dun9hhyz1/image/upload/v1630772436/personal-website/portfolio/sample_jpdjsw.jpg'
|
||||||
---
|
---
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|||||||
+27
-17
@@ -11,29 +11,35 @@ interface Props {
|
|||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const StyledCard = styled.div<{ dark: boolean }>`
|
const StyledCard = styled.div<{ dark: boolean; image: boolean }>`
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 1rem 0rem;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: grid;
|
display: grid;
|
||||||
align-items: center;
|
grid-template-columns: auto 150px;
|
||||||
background: ${({ dark, theme }) => (dark ? '#2f2f2f' : theme.colors.dark.text)};
|
align-items: stretch;
|
||||||
box-shadow: ${({ dark }) => !dark && `1px 1px 10px 0px rgba(0, 0, 0, 0.15)`};
|
box-shadow: ${({ dark }) => !dark && `1px 1px 10px 0px rgba(0, 0, 0, 0.15)`};
|
||||||
transition: box-shadow 250ms ease-in-out, color 0ms ease-in-out;
|
transition: box-shadow 250ms ease-in-out, color 0ms ease-in-out;
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
padding: 0.5rem 0rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: #1573ca;
|
& > div {
|
||||||
color: ${({ theme }) => theme.colors.dark.text};
|
background: #1573ca;
|
||||||
box-shadow: ${({ dark }) => !dark && '5px 2px 26px 6px rgba(21, 115, 202, 0.30)'};
|
color: ${({ theme }) => theme.colors.dark.text};
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
filter: ${({ image }) => (image ? 'grayscale(80%)' : 'none')};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
div {
|
& > div {
|
||||||
|
padding: 1rem 0rem;
|
||||||
|
background: ${({ dark, theme }) => (dark ? '#2f2f2f' : theme.colors.dark.text)};
|
||||||
display: grid;
|
display: grid;
|
||||||
row-gap: 0.5rem;
|
row-gap: 0.5rem;
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
padding: 0.75rem 0rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
h3,
|
h3,
|
||||||
@@ -66,19 +72,23 @@ const Card: FC<Props> = ({ title, description, image, tags, onClick }) => {
|
|||||||
const { dark } = useContext(DarkModeContext);
|
const { dark } = useContext(DarkModeContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledCard dark={dark} onClick={onClick}>
|
<StyledCard dark={dark} onClick={onClick} image={!!image}>
|
||||||
<div>
|
<div>
|
||||||
<h3>{title}</h3>
|
<h3>{title}</h3>
|
||||||
{image && (
|
|
||||||
<Image src={image} className='image' width='auto' height='auto' layout='responsive' />
|
|
||||||
)}
|
|
||||||
<p>{description}</p>
|
<p>{description}</p>
|
||||||
{tags && (
|
{tags && (
|
||||||
<div className='tags-wrapper'>
|
<div className='tags-wrapper'>
|
||||||
{tags && tags.map((tag, index) => <span key={index}>#{tag} </span>)}
|
{tags.map((tag, index) => (
|
||||||
|
<span key={index}>#{tag} </span>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
{image ? (
|
||||||
|
<Image src={image} width={100} height={100} layout='responsive' />
|
||||||
|
) : (
|
||||||
|
<Image src='/no-image.png' width={100} height={100} layout='responsive' />
|
||||||
|
)}
|
||||||
</StyledCard>
|
</StyledCard>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
+5
-1
@@ -1,6 +1,10 @@
|
|||||||
const withMDX = require('@next/mdx')({
|
const withMDX = require('@next/mdx')({
|
||||||
extension: /\.mdx?$/
|
extension: /\.mdx?$/
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = withMDX({
|
module.exports = withMDX({
|
||||||
pageExtensions: ['ts', 'tsx', 'md', 'mdx']
|
pageExtensions: ['ts', 'tsx', 'md', 'mdx'],
|
||||||
|
images: {
|
||||||
|
domains: ['res.cloudinary.com']
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
+2
-2
@@ -56,9 +56,9 @@ const NotFound: FC = () => {
|
|||||||
</Head>
|
</Head>
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<h1>404: This page could not be found</h1>
|
<h1>404: This page could not be found</h1>
|
||||||
<div className='back' onClick={() => router.back()}>
|
<div className='back' onClick={() => router.push('/')}>
|
||||||
<IconButton icon='/icons/arrow-left.svg' />
|
<IconButton icon='/icons/arrow-left.svg' />
|
||||||
<span>Go Back</span>
|
<span>Go Home</span>
|
||||||
</div>
|
</div>
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
</>
|
</>
|
||||||
|
|||||||
+24
-2
@@ -41,6 +41,23 @@ const Wrapper = styled.div`
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.image {
|
||||||
|
height: 0;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
padding-top: calc(591.44 / 1127.34 * 100%);
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
|
||||||
|
img {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
h1,
|
h1,
|
||||||
p,
|
p,
|
||||||
.tags-wrapper {
|
.tags-wrapper {
|
||||||
@@ -145,6 +162,11 @@ const BlogPost: FC<Props> = ({ source, frontMatter, text }) => {
|
|||||||
</Head>
|
</Head>
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<div className='meta'>
|
<div className='meta'>
|
||||||
|
{frontMatter.image ? (
|
||||||
|
<div className='image'>
|
||||||
|
<img src={frontMatter.image} alt='portfolio project image' />
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
<div className='back' onClick={() => router.back()}>
|
<div className='back' onClick={() => router.back()}>
|
||||||
<IconButton icon='/icons/arrow-left.svg' />
|
<IconButton icon='/icons/arrow-left.svg' />
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
@@ -154,13 +176,13 @@ const BlogPost: FC<Props> = ({ source, frontMatter, text }) => {
|
|||||||
<p>
|
<p>
|
||||||
By <b>{frontMatter.author}</b> on <b>{frontMatter.date}</b> ({stats.text})
|
By <b>{frontMatter.author}</b> on <b>{frontMatter.date}</b> ({stats.text})
|
||||||
</p>
|
</p>
|
||||||
{frontMatter.tags && (
|
{frontMatter.tags ? (
|
||||||
<div className='tags-wrapper'>
|
<div className='tags-wrapper'>
|
||||||
{frontMatter.tags.map((tag: string, index: number) => (
|
{frontMatter.tags.map((tag: string, index: number) => (
|
||||||
<span key={index}>#{tag} </span>
|
<span key={index}>#{tag} </span>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
) : null}
|
||||||
<hr />
|
<hr />
|
||||||
</div>
|
</div>
|
||||||
<MDXProvider components={{ code: CodeBlock }}>
|
<MDXProvider components={{ code: CodeBlock }}>
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ interface Props {
|
|||||||
title: string;
|
title: string;
|
||||||
author: string;
|
author: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
image?: string;
|
||||||
slug: string;
|
slug: string;
|
||||||
date: string;
|
date: string;
|
||||||
tags?: string[];
|
tags?: string[];
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { FC, useEffect } from 'react';
|
import { FC, useEffect, useRef } from 'react';
|
||||||
import { getPortfolioPorjectsSlugs, getPortfolioProjectdata } from '../../utils/portfolio';
|
import { getPortfolioPorjectsSlugs, getPortfolioProjectdata } from '../../utils/portfolio';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { MdxRemote } from 'next-mdx-remote/types';
|
import { MdxRemote } from 'next-mdx-remote/types';
|
||||||
@@ -39,6 +39,23 @@ const Wrapper = styled.div`
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.image {
|
||||||
|
height: 0;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
padding-top: calc(591.44 / 1127.34 * 100%);
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
|
||||||
|
img {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
h1,
|
h1,
|
||||||
p {
|
p {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
@@ -88,6 +105,7 @@ const components = AllComponents;
|
|||||||
const PortfolioProject: FC<Props> = ({ source, frontMatter }) => {
|
const PortfolioProject: FC<Props> = ({ source, frontMatter }) => {
|
||||||
const content = hydrate(source, { components });
|
const content = hydrate(source, { components });
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const metaRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
@@ -125,20 +143,25 @@ const PortfolioProject: FC<Props> = ({ source, frontMatter }) => {
|
|||||||
<title>{frontMatter.title} | Hazem Krimi</title>
|
<title>{frontMatter.title} | Hazem Krimi</title>
|
||||||
</Head>
|
</Head>
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<div className='meta'>
|
<div className='meta' ref={metaRef}>
|
||||||
|
{frontMatter.image ? (
|
||||||
|
<div className='image'>
|
||||||
|
<img src={frontMatter.image} alt='portfolio project image' />
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
<div className='back' onClick={() => router.back()}>
|
<div className='back' onClick={() => router.back()}>
|
||||||
<IconButton icon='/icons/arrow-left.svg' />
|
<IconButton icon='/icons/arrow-left.svg' />
|
||||||
<span>Back</span>
|
<span>Back</span>
|
||||||
</div>
|
</div>
|
||||||
<h1>{frontMatter.title}</h1>
|
<h1>{frontMatter.title}</h1>
|
||||||
<p>{frontMatter.description}</p>
|
<p>{frontMatter.description}</p>
|
||||||
{frontMatter.tags && (
|
{frontMatter.tags ? (
|
||||||
<div className='tags-wrapper'>
|
<div className='tags-wrapper'>
|
||||||
{frontMatter.tags.map((tag: string, index: number) => (
|
{frontMatter.tags.map((tag: string, index: number) => (
|
||||||
<span key={index}>#{tag} </span>
|
<span key={index}>#{tag} </span>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
) : null}
|
||||||
<hr />
|
<hr />
|
||||||
</div>
|
</div>
|
||||||
<MDXProvider components={{ code: CodeBlock }}>
|
<MDXProvider components={{ code: CodeBlock }}>
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ interface Props {
|
|||||||
portfolioProjects: {
|
portfolioProjects: {
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
image?: string;
|
||||||
slug: string;
|
slug: string;
|
||||||
date: string;
|
date: string;
|
||||||
tags?: string[];
|
tags?: string[];
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
@@ -15,6 +15,7 @@ export const getBlogPosts = () => {
|
|||||||
const { data } = matter(fileContents);
|
const { data } = matter(fileContents);
|
||||||
|
|
||||||
const options = { month: 'long', day: 'numeric', year: 'numeric' };
|
const options = { month: 'long', day: 'numeric', year: 'numeric' };
|
||||||
|
// @ts-ignore
|
||||||
const formattedDate = new Date(data.date).toLocaleDateString('en-IN', options);
|
const formattedDate = new Date(data.date).toLocaleDateString('en-IN', options);
|
||||||
|
|
||||||
const frontmatter = {
|
const frontmatter = {
|
||||||
|
|||||||
Reference in New Issue
Block a user