From d17951b37e2788e80864e3f6ab965b9c11e461e5 Mon Sep 17 00:00:00 2001 From: Hazem Krimi Date: Fri, 17 Dec 2021 16:59:45 +0100 Subject: [PATCH] Update folder structure for pages and some components --- components/Button/index.tsx | 33 ++++++ components/{Button.tsx => Button/styles.tsx} | 42 +------- components/Button/types.ts | 7 ++ components/Card.tsx | 102 ------------------ components/Card/index.tsx | 44 ++++++++ components/Card/styles.tsx | 59 ++++++++++ .../{CodeBlock.tsx => CodeBlock/index.tsx} | 25 +---- components/CodeBlock/styles.tsx | 24 +++++ components/{Footer.tsx => Footer/index.tsx} | 46 +------- components/Footer/styles.tsx | 41 +++++++ components/Hero.tsx | 72 ------------- components/Hero/index.tsx | 29 +++++ components/Hero/styles.tsx | 44 ++++++++ components/MDXButton/index.tsx | 39 +++++++ .../{MDXButton.tsx => MDXButton/styles.tsx} | 49 +-------- components/MDXButton/types.ts | 8 ++ .../{MobileNav.tsx => MobileNav/index.tsx} | 54 +--------- components/MobileNav/styles.tsx | 37 +++++++ components/MobileNav/types.ts | 9 ++ components/{Nav.tsx => Nav/index.tsx} | 68 +----------- components/Nav/styles.tsx | 59 ++++++++++ components/{All.ts => index.ts} | 4 +- pages/404.tsx | 26 +---- pages/about.tsx | 62 +---------- pages/blog/[slug].tsx | 95 +--------------- pages/blog/index.tsx | 36 +------ pages/index.tsx | 49 +-------- pages/portfolio/[slug].tsx | 83 +------------- pages/portfolio/index.tsx | 36 +------ pages/styles/404.tsx | 25 +++++ pages/styles/about.tsx | 61 +++++++++++ pages/styles/blog/index.tsx | 35 ++++++ pages/styles/blog/slug.tsx | 90 ++++++++++++++++ pages/styles/home.tsx | 48 +++++++++ pages/styles/portfolio/index.tsx | 35 ++++++ pages/styles/portfolio/slug.tsx | 78 ++++++++++++++ 36 files changed, 833 insertions(+), 821 deletions(-) create mode 100644 components/Button/index.tsx rename components/{Button.tsx => Button/styles.tsx} (61%) create mode 100644 components/Button/types.ts delete mode 100644 components/Card.tsx create mode 100644 components/Card/index.tsx create mode 100644 components/Card/styles.tsx rename components/{CodeBlock.tsx => CodeBlock/index.tsx} (70%) create mode 100644 components/CodeBlock/styles.tsx rename components/{Footer.tsx => Footer/index.tsx} (61%) create mode 100644 components/Footer/styles.tsx delete mode 100644 components/Hero.tsx create mode 100644 components/Hero/index.tsx create mode 100644 components/Hero/styles.tsx create mode 100644 components/MDXButton/index.tsx rename components/{MDXButton.tsx => MDXButton/styles.tsx} (59%) create mode 100644 components/MDXButton/types.ts rename components/{MobileNav.tsx => MobileNav/index.tsx} (61%) create mode 100644 components/MobileNav/styles.tsx create mode 100644 components/MobileNav/types.ts rename components/{Nav.tsx => Nav/index.tsx} (55%) create mode 100644 components/Nav/styles.tsx rename components/{All.ts => index.ts} (87%) create mode 100644 pages/styles/404.tsx create mode 100644 pages/styles/about.tsx create mode 100644 pages/styles/blog/index.tsx create mode 100644 pages/styles/blog/slug.tsx create mode 100644 pages/styles/home.tsx create mode 100644 pages/styles/portfolio/index.tsx create mode 100644 pages/styles/portfolio/slug.tsx diff --git a/components/Button/index.tsx b/components/Button/index.tsx new file mode 100644 index 0000000..92858ba --- /dev/null +++ b/components/Button/index.tsx @@ -0,0 +1,33 @@ +import { FC, useContext } from 'react'; +import { DarkModeContext } from '../../components/DarkMode'; +import { Props } from './types'; +import { Btn } from './styles'; +import Link from 'next/link'; + +const Button: FC = ({ + variant = 'text', + href, + target, + onClick, + children, + className +}) => { + const { dark } = useContext(DarkModeContext); + + return ( + + + {children} + + + ); +}; + +export default Button; diff --git a/components/Button.tsx b/components/Button/styles.tsx similarity index 61% rename from components/Button.tsx rename to components/Button/styles.tsx index 41fbcf5..d1fd87e 100644 --- a/components/Button.tsx +++ b/components/Button/styles.tsx @@ -1,17 +1,7 @@ -import { FC, useContext } from 'react'; -import { DarkModeContext } from '../components/DarkMode'; import styled from 'styled-components'; -import Link from 'next/link'; +import { Props } from './types'; -interface Props { - variant?: 'outline' | 'text'; - href: string; - target?: HTMLAnchorElement['target']; - onClick?: () => void; - dark?: boolean; -} - -const Btn = styled.button>` +export const Btn = styled.button>` position: relative; display: inline; cursor: pointer; @@ -53,31 +43,3 @@ const Btn = styled.button>` transform: scaleX(1); } `; - -const Button: FC = ({ - variant = 'text', - href, - target, - onClick, - children, - className -}) => { - const { dark } = useContext(DarkModeContext); - - return ( - - - {children} - - - ); -}; - -export default Button; diff --git a/components/Button/types.ts b/components/Button/types.ts new file mode 100644 index 0000000..4a93d13 --- /dev/null +++ b/components/Button/types.ts @@ -0,0 +1,7 @@ +export type Props = { + variant?: 'outline' | 'text'; + href: string; + target?: HTMLAnchorElement['target']; + onClick?: () => void; + dark?: boolean; +}; diff --git a/components/Card.tsx b/components/Card.tsx deleted file mode 100644 index 2a3b38d..0000000 --- a/components/Card.tsx +++ /dev/null @@ -1,102 +0,0 @@ -import { FC, useContext } from 'react'; -import { DarkModeContext } from '../components/DarkMode'; -import styled from 'styled-components'; -import Image from 'next/image'; -import Link from 'next/link'; - -interface Props { - title: string; - description: string; - image?: string; - tags?: string[]; - href: string; - target?: HTMLAnchorElement['target']; - onClick?: () => void; -} - -const StyledCard = styled.div<{ dark: boolean; image: boolean }>` - cursor: pointer; - width: 100%; - display: grid; - grid-template-columns: auto 150px; - align-items: stretch; - transition: color 0ms ease-in-out; - text-decoration: none; - color: var(--text); - - &:hover { - & > div { - background: ${({ theme }) => theme.colors.blue}; - color: ${({ theme }) => theme.colors.dark.text}; - } - - img { - filter: ${({ image }) => (image ? 'grayscale(80%)' : 'none')}; - } - } - - & > div { - padding: 1rem 0rem; - background: var(--secondary-background); - display: grid; - row-gap: 0.5rem; - - @media (max-width: 768px) { - padding: 0.75rem 0rem; - } - } - - h3, - p, - .tags-wrapper { - padding: 0rem 1rem; - - @media (max-width: 768px) { - padding: 0rem 0.5rem; - } - } - - h3 { - font-size: 1.3rem; - } - - .tags-wrapper { - display: flex; - flex-direction: row; - align-content: center; - flex-wrap: wrap; - } - - span { - font-size: 0.7rem; - } -`; - -const Card: FC = ({ title, description, image, tags, href, target, onClick }) => { - const { dark } = useContext(DarkModeContext); - - return ( - - -
-

{title}

-

{description}

- {tags && ( -
- {tags.map((tag, index) => ( - #{tag}  - ))} -
- )} -
- {image ? ( - - ) : ( - - )} -
- - ); -}; - -export default Card; diff --git a/components/Card/index.tsx b/components/Card/index.tsx new file mode 100644 index 0000000..f8989b7 --- /dev/null +++ b/components/Card/index.tsx @@ -0,0 +1,44 @@ +import { FC, useContext } from 'react'; +import { DarkModeContext } from '../../components/DarkMode'; +import { StyledCard } from './styles'; +import Image from 'next/image'; +import Link from 'next/link'; + +interface Props { + title: string; + description: string; + image?: string; + tags?: string[]; + href: string; + target?: HTMLAnchorElement['target']; + onClick?: () => void; +} + +const Card: FC = ({ title, description, image, tags, href, target, onClick }) => { + const { dark } = useContext(DarkModeContext); + + return ( + + +
+

{title}

+

{description}

+ {tags && ( +
+ {tags.map((tag, index) => ( + #{tag}  + ))} +
+ )} +
+ {image ? ( + + ) : ( + + )} +
+ + ); +}; + +export default Card; diff --git a/components/Card/styles.tsx b/components/Card/styles.tsx new file mode 100644 index 0000000..94c55bc --- /dev/null +++ b/components/Card/styles.tsx @@ -0,0 +1,59 @@ +import styled from 'styled-components'; + +export const StyledCard = styled.div<{ dark: boolean; image: boolean }>` + cursor: pointer; + width: 100%; + display: grid; + grid-template-columns: auto 150px; + align-items: stretch; + transition: color 0ms ease-in-out; + text-decoration: none; + color: var(--text); + + &:hover { + & > div { + background: ${({ theme }) => theme.colors.blue}; + color: ${({ theme }) => theme.colors.dark.text}; + } + + img { + filter: ${({ image }) => (image ? 'grayscale(80%)' : 'none')}; + } + } + + & > div { + padding: 1rem 0rem; + background: var(--secondary-background); + display: grid; + row-gap: 0.5rem; + + @media (max-width: 768px) { + padding: 0.75rem 0rem; + } + } + + h3, + p, + .tags-wrapper { + padding: 0rem 1rem; + + @media (max-width: 768px) { + padding: 0rem 0.5rem; + } + } + + h3 { + font-size: 1.3rem; + } + + .tags-wrapper { + display: flex; + flex-direction: row; + align-content: center; + flex-wrap: wrap; + } + + span { + font-size: 0.7rem; + } +`; diff --git a/components/CodeBlock.tsx b/components/CodeBlock/index.tsx similarity index 70% rename from components/CodeBlock.tsx rename to components/CodeBlock/index.tsx index 942eb08..6a38d70 100644 --- a/components/CodeBlock.tsx +++ b/components/CodeBlock/index.tsx @@ -1,30 +1,7 @@ import { FC } from 'react'; -import styled from 'styled-components'; import Highlight, { defaultProps, Language } from 'prism-react-renderer'; import theme from 'prism-react-renderer/themes/vsDark'; - -const Pre = styled.pre` - text-align: left; - margin: 1em 0; - padding: 0.5em; - overflow: scroll; -`; - -const Line = styled.div` - display: table-row; -`; - -const LineNo = styled.span` - display: table-cell; - text-align: right; - padding-right: 1em; - user-select: none; - opacity: 0.5; -`; - -const LineContent = styled.span` - display: table-cell; -`; +import { Line, LineContent, LineNo, Pre } from './styles'; const CodeBlock: FC<{ className: string }> = ({ children, className }) => { const language = className.replace(/language-/, '') as Language; diff --git a/components/CodeBlock/styles.tsx b/components/CodeBlock/styles.tsx new file mode 100644 index 0000000..710b89d --- /dev/null +++ b/components/CodeBlock/styles.tsx @@ -0,0 +1,24 @@ +import styled from 'styled-components'; + +export const Pre = styled.pre` + text-align: left; + margin: 1em 0; + padding: 0.5em; + overflow: scroll; +`; + +export const Line = styled.div` + display: table-row; +`; + +export const LineNo = styled.span` + display: table-cell; + text-align: right; + padding-right: 1em; + user-select: none; + opacity: 0.5; +`; + +export const LineContent = styled.span` + display: table-cell; +`; diff --git a/components/Footer.tsx b/components/Footer/index.tsx similarity index 61% rename from components/Footer.tsx rename to components/Footer/index.tsx index 5be825b..4d67a68 100644 --- a/components/Footer.tsx +++ b/components/Footer/index.tsx @@ -1,47 +1,7 @@ import { FC, useContext } from 'react'; -import { DarkModeContext } from '../components/DarkMode'; -import styled from 'styled-components'; -import IconButton from '../components/IconButton'; - -const StyledFooter = styled.footer` - position: absolute; - bottom: 0; - min-height: 100px; - width: 85%; - margin: auto; - display: grid; - grid-template-columns: repeat(2, 1fr); - column-gap: 2rem; - justify-content: flex-end; - align-content: center; - padding: 1rem 0rem; - - @media (max-width: 768px) { - width: 95%; - } - - .contact { - display: grid; - grid-template-columns: repeat(auto-fill, 16px); - column-gap: 1rem; - align-items: center; - justify-content: flex-start; - - * { - user-select: none; - } - - @media (max-width: 768px) { - column-gap: 0.5rem; - } - } - - p { - display: inline; - text-align: right; - font-weight: bold; - } -`; +import { DarkModeContext } from '../../components/DarkMode'; +import { StyledFooter } from './styles'; +import IconButton from '../../components/IconButton'; const Footer: FC = () => { const { dark } = useContext(DarkModeContext); diff --git a/components/Footer/styles.tsx b/components/Footer/styles.tsx new file mode 100644 index 0000000..9415778 --- /dev/null +++ b/components/Footer/styles.tsx @@ -0,0 +1,41 @@ +import styled from 'styled-components'; + +export const StyledFooter = styled.footer` + position: absolute; + bottom: 0; + min-height: 100px; + width: 85%; + margin: auto; + display: grid; + grid-template-columns: repeat(2, 1fr); + column-gap: 2rem; + justify-content: flex-end; + align-content: center; + padding: 1rem 0rem; + + @media (max-width: 768px) { + width: 95%; + } + + .contact { + display: grid; + grid-template-columns: repeat(auto-fill, 16px); + column-gap: 1rem; + align-items: center; + justify-content: flex-start; + + * { + user-select: none; + } + + @media (max-width: 768px) { + column-gap: 0.5rem; + } + } + + p { + display: inline; + text-align: right; + font-weight: bold; + } +`; diff --git a/components/Hero.tsx b/components/Hero.tsx deleted file mode 100644 index 4774a8d..0000000 --- a/components/Hero.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import { FC, useContext } from 'react'; -import { DarkModeContext } from '../components/DarkMode'; -import styled from 'styled-components'; -import Image from 'next/image'; - -const Wrapper = styled.div` - min-height: 45vh; - display: grid; - grid-template-columns: repeat(2, 1fr); - align-items: center; - height: auto; - text-align: left; - - @media (max-width: 425px) { - min-height: 65vh; - grid-template-columns: auto; - - .illustration { - display: none; - } - } - - h2 { - font-size: 1.5rem; - - @media (min-width: 1440px) { - font-size: 2rem; - } - - @media (min-width: 2560px) { - font-size: 3.5rem; - } - } - - .small { - font-size: 1rem; - font-weight: normal; - - @media (min-width: 1440px) { - font-size: 1.5rem; - } - } - - .blue { - color: ${({ theme }) => theme.colors.blue}; - } -`; - -const Hero: FC = () => { - const { dark } = useContext(DarkModeContext); - - return ( - -
-

Hi, I am Hazem

-

I Like Building Things

-

Software Developer

-

Life Long Learner

-
-
- -
-
- ); -}; - -export default Hero; diff --git a/components/Hero/index.tsx b/components/Hero/index.tsx new file mode 100644 index 0000000..58f07fa --- /dev/null +++ b/components/Hero/index.tsx @@ -0,0 +1,29 @@ +import { FC, useContext } from 'react'; +import { DarkModeContext } from '../../components/DarkMode'; +import { Wrapper } from './styles'; +import Image from 'next/image'; + +const Hero: FC = () => { + const { dark } = useContext(DarkModeContext); + + return ( + +
+

Hi, I am Hazem

+

I Like Building Things

+

Software Developer

+

Life Long Learner

+
+
+ +
+
+ ); +}; + +export default Hero; diff --git a/components/Hero/styles.tsx b/components/Hero/styles.tsx new file mode 100644 index 0000000..e1ca111 --- /dev/null +++ b/components/Hero/styles.tsx @@ -0,0 +1,44 @@ +import styled from 'styled-components'; + +export const Wrapper = styled.div` + min-height: 45vh; + display: grid; + grid-template-columns: repeat(2, 1fr); + align-items: center; + height: auto; + text-align: left; + + @media (max-width: 425px) { + min-height: 65vh; + grid-template-columns: auto; + + .illustration { + display: none; + } + } + + h2 { + font-size: 1.5rem; + + @media (min-width: 1440px) { + font-size: 2rem; + } + + @media (min-width: 2560px) { + font-size: 3.5rem; + } + } + + .small { + font-size: 1rem; + font-weight: normal; + + @media (min-width: 1440px) { + font-size: 1.5rem; + } + } + + .blue { + color: ${({ theme }) => theme.colors.blue}; + } +`; diff --git a/components/MDXButton/index.tsx b/components/MDXButton/index.tsx new file mode 100644 index 0000000..cbd2f13 --- /dev/null +++ b/components/MDXButton/index.tsx @@ -0,0 +1,39 @@ +import { FC, useContext } from 'react'; +import { DarkModeContext } from '../../components/DarkMode'; +import { Props } from './types'; +import { Btn } from './styles'; +import Link from 'next/link'; + +const MDXButton: FC = ({ + variant = 'text', + type = 'button', + link, + target, + children, + disabled, + className +}) => { + const { dark } = useContext(DarkModeContext); + + return link ? ( + + + {children} + + + ) : ( + + {children} + + ); +}; + +export default MDXButton; diff --git a/components/MDXButton.tsx b/components/MDXButton/styles.tsx similarity index 59% rename from components/MDXButton.tsx rename to components/MDXButton/styles.tsx index 9d41b30..91489b3 100644 --- a/components/MDXButton.tsx +++ b/components/MDXButton/styles.tsx @@ -1,18 +1,7 @@ -import { FC, useContext } from 'react'; -import { DarkModeContext } from '../components/DarkMode'; -import Link from 'next/link'; import styled from 'styled-components'; +import { Props } from './types'; -interface Props { - variant?: 'outline' | 'text' | 'action'; - type?: 'button' | 'submit'; - link?: string; - target?: HTMLAnchorElement['target']; - dark?: boolean; - disabled?: boolean; -} - -const Btn = styled.button` +export const Btn = styled.button` cursor: pointer; display: ${({ variant }) => ['action', 'outline'].includes(variant as string) ? 'block' : 'inline'}; @@ -46,37 +35,3 @@ const Btn = styled.button` ['action', 'outline'].includes(variant as string) ? '.5rem .75rem' : '0rem'}; } `; - -const MDXButton: FC = ({ - variant = 'text', - type = 'button', - link, - target, - children, - disabled, - className -}) => { - const { dark } = useContext(DarkModeContext); - - return link ? ( - - - {children} - - - ) : ( - - {children} - - ); -}; - -export default MDXButton; diff --git a/components/MDXButton/types.ts b/components/MDXButton/types.ts new file mode 100644 index 0000000..ad1343c --- /dev/null +++ b/components/MDXButton/types.ts @@ -0,0 +1,8 @@ +export type Props = { + variant?: 'outline' | 'text' | 'action'; + type?: 'button' | 'submit'; + link?: string; + target?: HTMLAnchorElement['target']; + dark?: boolean; + disabled?: boolean; +}; diff --git a/components/MobileNav.tsx b/components/MobileNav/index.tsx similarity index 61% rename from components/MobileNav.tsx rename to components/MobileNav/index.tsx index 044f085..5beebcc 100644 --- a/components/MobileNav.tsx +++ b/components/MobileNav/index.tsx @@ -1,53 +1,9 @@ import { FC, useContext, useRef, useEffect } from 'react'; -import { DarkModeContext } from './DarkMode'; -import styled from 'styled-components'; -import IconButton from './IconButton'; -import Button from './Button'; - -interface Props { - open: boolean; - close: () => void; -} - -interface StyledProps { - dark: boolean; - open: boolean; -} - -const Bar = styled.nav` - position: fixed; - z-index: 2; - top: 0; - right: 0; - transform-origin: right; - transform: ${({ open }) => (open ? 'translateX(0%)' : 'translateX(100%)')}; - width: 80%; - height: 100vh; - background: var(--text); - transition: transform 250ms ease-in-out; - display: grid; - grid-template-rows: 30% repeat(4, 50px); - padding: 1rem 1rem 5rem 1rem; - - @media (orientation: landscape) { - grid-template-rows: auto; - } - - .close { - justify-self: flex-end; - align-self: flex-start; - margin-top: 0.5rem; - } - - .mobile-button-wrapper { - display: flex; - margin: 0rem 1rem; - - a { - color: var(--text-inverted) !important; - } - } -`; +import { DarkModeContext } from '../DarkMode'; +import { Props } from './types'; +import { Bar } from './styles'; +import IconButton from '../IconButton'; +import Button from '../Button'; const MobileNav: FC = ({ open, close }) => { const { dark, toggle } = useContext(DarkModeContext); diff --git a/components/MobileNav/styles.tsx b/components/MobileNav/styles.tsx new file mode 100644 index 0000000..256bf39 --- /dev/null +++ b/components/MobileNav/styles.tsx @@ -0,0 +1,37 @@ +import styled from 'styled-components'; +import { StyledProps } from './types'; + +export const Bar = styled.nav` + position: fixed; + z-index: 2; + top: 0; + right: 0; + transform-origin: right; + transform: ${({ open }) => (open ? 'translateX(0%)' : 'translateX(100%)')}; + width: 80%; + height: 100vh; + background: var(--text); + transition: transform 250ms ease-in-out; + display: grid; + grid-template-rows: 30% repeat(4, 50px); + padding: 1rem 1rem 5rem 1rem; + + @media (orientation: landscape) { + grid-template-rows: auto; + } + + .close { + justify-self: flex-end; + align-self: flex-start; + margin-top: 0.5rem; + } + + .mobile-button-wrapper { + display: flex; + margin: 0rem 1rem; + + a { + color: var(--text-inverted) !important; + } + } +`; diff --git a/components/MobileNav/types.ts b/components/MobileNav/types.ts new file mode 100644 index 0000000..1ff2cf3 --- /dev/null +++ b/components/MobileNav/types.ts @@ -0,0 +1,9 @@ +export type Props = { + open: boolean; + close: () => void; +}; + +export type StyledProps = { + dark: boolean; + open: boolean; +}; diff --git a/components/Nav.tsx b/components/Nav/index.tsx similarity index 55% rename from components/Nav.tsx rename to components/Nav/index.tsx index c7c13df..0f658d6 100644 --- a/components/Nav.tsx +++ b/components/Nav/index.tsx @@ -1,69 +1,11 @@ import { FC, useContext, useState } from 'react'; -import { DarkModeContext } from './DarkMode'; -import styled from 'styled-components'; +import { DarkModeContext } from '../DarkMode'; +import { Bar } from './styles'; import Link from 'next/link'; import Image from 'next/image'; -import Button from './Button'; -import IconButton from './IconButton'; -import MobileNav from './MobileNav'; - -const Bar = styled.nav` - width: 100%; - display: grid; - grid-template-columns: auto 1fr; - align-items: center; - padding: 1rem 0rem; - - * { - user-select: none; - } - - h1 { - font-size: 1.7rem; - - @media (max-width: 768px) { - font-size: 1rem; - } - } - - div, - a.logo { - display: grid; - align-items: center; - column-gap: 1rem; - - @media (max-width: 768px) { - column-gap: 0.5rem; - } - } - - a.logo { - text-decoration: none; - color: var(--text); - cursor: pointer; - grid-template-columns: repeat(2, auto); - justify-content: flex-start; - } - - .buttons { - grid-template-columns: repeat(5, auto); - justify-content: flex-end; - - @media (max-width: 768px) { - display: none; - } - } - - .mobile-buttons { - display: none; - - @media (max-width: 768px) { - display: grid; - grid-template-columns: repeat(2, auto); - justify-content: flex-end; - } - } -`; +import Button from '../Button'; +import IconButton from '../IconButton'; +import MobileNav from '../MobileNav'; const Nav: FC = () => { const [mobileNavOpen, setMobileNavOpen] = useState(false); diff --git a/components/Nav/styles.tsx b/components/Nav/styles.tsx new file mode 100644 index 0000000..d0ae7c2 --- /dev/null +++ b/components/Nav/styles.tsx @@ -0,0 +1,59 @@ +import styled from 'styled-components'; + +export const Bar = styled.nav` + width: 100%; + display: grid; + grid-template-columns: auto 1fr; + align-items: center; + padding: 1rem 0rem; + + * { + user-select: none; + } + + h1 { + font-size: 1.7rem; + + @media (max-width: 768px) { + font-size: 1rem; + } + } + + div, + a.logo { + display: grid; + align-items: center; + column-gap: 1rem; + + @media (max-width: 768px) { + column-gap: 0.5rem; + } + } + + a.logo { + text-decoration: none; + color: var(--text); + cursor: pointer; + grid-template-columns: repeat(2, auto); + justify-content: flex-start; + } + + .buttons { + grid-template-columns: repeat(5, auto); + justify-content: flex-end; + + @media (max-width: 768px) { + display: none; + } + } + + .mobile-buttons { + display: none; + + @media (max-width: 768px) { + display: grid; + grid-template-columns: repeat(2, auto); + justify-content: flex-end; + } + } +`; diff --git a/components/All.ts b/components/index.ts similarity index 87% rename from components/All.ts rename to components/index.ts index 74ee299..66ad061 100644 --- a/components/All.ts +++ b/components/index.ts @@ -2,7 +2,7 @@ import { CodePen, Gist, YouTube, CodeSandbox, Vimeo, Tweet } from 'mdx-embed'; import Image from 'next/image'; import MDXButton from './MDXButton'; -const All = { +export default { Button: MDXButton, Image, CodePen, @@ -12,5 +12,3 @@ const All = { Tweet, YouTube }; - -export default All; diff --git a/pages/404.tsx b/pages/404.tsx index c14c894..616988f 100644 --- a/pages/404.tsx +++ b/pages/404.tsx @@ -1,32 +1,8 @@ import { FC } from 'react'; import { useRouter } from 'next/router'; -import styled from 'styled-components'; import Head from 'next/head'; import IconButton from '../components/IconButton'; - -const Wrapper = styled.div` - min-height: 75vh; - display: grid; - justify-items: center; - text-align: center; - - @media (max-width: 768px) { - min-height: 65vh; - } - - h1 { - font-size: 1.7rem; - align-self: flex-end; - } - - .back { - cursor: pointer; - color: #3f9aee; - display: flex; - align-items: center; - align-self: flex-start; - } -`; +import { Wrapper } from './styles/404'; const NotFound: FC = () => { const router = useRouter(); diff --git a/pages/about.tsx b/pages/about.tsx index 790efec..7e14280 100644 --- a/pages/about.tsx +++ b/pages/about.tsx @@ -2,71 +2,11 @@ import React, { FC, useContext, useState } from 'react'; import { DarkModeContext } from '../components/DarkMode'; import { useForm, ValidationError } from '@formspree/react'; import Head from 'next/head'; -import styled from 'styled-components'; +import { Wrapper } from './styles/about'; import Image from 'next/image'; import Input from '../components/Input'; import MDXButton from '../components/MDXButton'; -const Wrapper = styled.div<{ dark: boolean }>` - padding: 1rem 0rem; - display: grid; - grid-template-columns: repeat(2, 1fr); - column-gap: 2rem; - - @media (max-width: 768px) { - padding: 0rem; - grid-template-columns: auto; - column-gap: 0rem; - row-gap: 1rem; - } - - .photo { - order: initial; - - @media (max-width: 768px) { - order: -1; - } - } - - h1 { - font-size: 1.7rem; - } - - .content { - display: flex; - flex-direction: column; - } - - .about, - .contact { - margin: 1rem 0rem; - - @media (max-width: 768px) { - margin: 1rem 0rem; - } - } - - .success { - color: #73d26b; - align-self: center; - font-weight: normal; - } - - .contact { - display: grid; - grid-template-columns: auto; - row-gap: 1.5rem; - - .error { - color: #d75050; - } - - @media (max-width: 768px) { - row-gap: 0.5rem; - } - } -`; - const About: FC = () => { const { dark } = useContext(DarkModeContext); const [form, setForm] = useState<{ name: string; email: string; message: string }>({ diff --git a/pages/blog/[slug].tsx b/pages/blog/[slug].tsx index b1fb54b..672c8e7 100644 --- a/pages/blog/[slug].tsx +++ b/pages/blog/[slug].tsx @@ -7,9 +7,9 @@ import { MDXEmbedProvider } from 'mdx-embed'; import { GetStaticPaths, GetStaticProps } from 'next'; import renderToString from 'next-mdx-remote/render-to-string'; import hydrate from 'next-mdx-remote/hydrate'; -import styled from 'styled-components'; +import { Wrapper } from '../styles/blog/slug'; import matter from 'gray-matter'; -import AllComponents from '../../components/All'; +import components from '../../components'; import Head from 'next/head'; import IconButton from '../../components/IconButton'; import CodeBlock from '../../components/CodeBlock'; @@ -22,97 +22,6 @@ interface Props { text: string; } -const Wrapper = styled.div` - min-height: 75vh; - padding: 1rem 0rem; - display: grid; - grid-template-rows: auto 1fr; - row-gap: 2rem; - - @media (max-width: 768px) { - row-gap: 1rem; - } - - .meta { - .back { - cursor: pointer; - text-align: left; - color: #3f9aee; - display: inline-flex; - align-items: center; - } - - .image { - margin: 1rem 0rem; - } - - h1, - p, - .tags-wrapper { - text-align: left; - } - - h1 { - font-size: 2rem; - } - - h2 { - font-size: 1.2rem; - } - - .tags-wrapper { - display: flex; - flex-direction: row; - align-items: center; - flex-wrap: wrap; - } - } - - hr { - height: 0.1rem; - opacity: 0.3; - margin: 1rem auto 0rem auto; - - @media (max-width: 768px) { - margin: 1rem auto 0rem auto; - } - } - - .content { - h1 { - font-size: 1.5rem; - } - - h2 { - font-size: 1.3rem; - } - - h3 { - font-size: 1.1rem; - } - - & > * { - margin: 0.5rem 0rem; - } - - button { - margin: 1rem 0rem; - } - - p * { - width: 100%; - height: auto; - } - - ul, - ol { - margin-left: 1.5rem; - } - } -`; - -const components = AllComponents; - const BlogPost: FC = ({ source, frontMatter, text }) => { const content = hydrate(source, { components }); const router = useRouter(); diff --git a/pages/blog/index.tsx b/pages/blog/index.tsx index a8d2577..f2cdf4e 100644 --- a/pages/blog/index.tsx +++ b/pages/blog/index.tsx @@ -1,7 +1,7 @@ import React, { FC } from 'react'; import { useRouter } from 'next/router'; import { getBlogPosts } from '../../utils/blog'; -import styled from 'styled-components'; +import { Wrapper } from '../styles/blog'; import Card from '../../components/Card'; import IconButton from '../../components/IconButton'; import Head from 'next/head'; @@ -18,40 +18,6 @@ interface Props { }[]; } -const Wrapper = styled.div` - min-height: 75vh; - padding: 1rem 0rem; - - .back { - cursor: pointer; - text-align: left; - color: #3f9aee; - display: inline-flex; - align-items: center; - } - - h1 { - font-size: 1.7rem; - margin-bottom: 1rem; - } - - h4 { - font-size: 1.3rem; - grid-column: 1 / -1; - align-self: center; - justify-self: center; - } - - .articles-wrapper { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); - grid-auto-rows: minmax(100px, auto); - align-items: stretch; - justify-items: center; - gap: 1rem; - } -`; - const Index: FC = ({ blogPosts }) => { const router = useRouter(); diff --git a/pages/index.tsx b/pages/index.tsx index 893673f..6900b5c 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -2,7 +2,7 @@ import { FC } from 'react'; import { getPortfolioProjects } from '../utils/portfolio'; import { getBlogPosts } from '../utils/blog'; import { GetStaticProps } from 'next'; -import styled from 'styled-components'; +import { Wrapper } from './styles/home'; import Hero from '../components/Hero'; import Button from '../components/Button'; import Card from '../components/Card'; @@ -26,53 +26,6 @@ interface Props { }[]; } -const Wrapper = styled.div` - padding: 1rem 0rem; - display: grid; - grid-template-columns: auto; - row-gap: 1rem; - - h1 { - display: inline; - font-size: 1.7rem; - margin-right: 1rem; - } - - h4 { - font-size: 1.3rem; - grid-column: 1 / -1; - align-self: center; - justify-self: center; - } - - .blue { - color: ${({ theme }) => theme.colors.blue}; - - @media (max-width: 768px) { - margin-top: 0.5rem; - } - } - - .portfolio, - .blog { - margin: 1rem 0rem; - } - - .portfolio { - margin-bottom: 3rem; - } - - .projects-wrapper, - .articles-wrapper { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); - grid-auto-rows: minmax(100px, auto); - align-items: stretch; - justify-items: center; - gap: 1rem; - } -`; - const Index: FC = ({ blogPosts, portfolioProjects }) => { return ( <> diff --git a/pages/portfolio/[slug].tsx b/pages/portfolio/[slug].tsx index b134835..6030a82 100644 --- a/pages/portfolio/[slug].tsx +++ b/pages/portfolio/[slug].tsx @@ -7,9 +7,9 @@ import { MDXEmbedProvider } from 'mdx-embed'; import { GetStaticPaths, GetStaticProps } from 'next'; import renderToString from 'next-mdx-remote/render-to-string'; import hydrate from 'next-mdx-remote/hydrate'; -import styled from 'styled-components'; import matter from 'gray-matter'; -import AllComponents from '../../components/All'; +import components from '../../components'; +import { Wrapper } from '../styles/portfolio/slug'; import Head from 'next/head'; import IconButton from '../../components/IconButton'; import CodeBlock from '../../components/CodeBlock'; @@ -20,85 +20,6 @@ interface Props { frontMatter: any; } -const Wrapper = styled.div` - min-height: 75vh; - padding: 1rem 0rem; - display: grid; - grid-template-rows: auto 1fr; - row-gap: 2rem; - - @media (max-width: 768px) { - row-gap: 1rem; - } - - .meta { - .back { - cursor: pointer; - text-align: left; - color: #3f9aee; - display: inline-flex; - align-items: center; - } - - .image { - margin: 1rem 0rem; - } - - h1, - p { - text-align: left; - } - - h1 { - font-size: 2rem; - } - - h2 { - font-size: 1.2rem; - } - } - - hr { - height: 0.1rem; - opacity: 0.3; - margin: 1rem auto 0rem auto; - } - - .content { - h1 { - font-size: 1.5rem; - } - - h2 { - font-size: 1.3rem; - } - - h3 { - font-size: 1.1rem; - } - - & > * { - margin: 0.5rem 0rem; - } - - button { - margin: 1rem 0rem; - } - - p * { - width: 100%; - height: auto; - } - - ul, - ol { - margin-left: 1.5rem; - } - } -`; - -const components = AllComponents; - const PortfolioProject: FC = ({ source, frontMatter }) => { const content = hydrate(source, { components }); const router = useRouter(); diff --git a/pages/portfolio/index.tsx b/pages/portfolio/index.tsx index f290708..0af5e4b 100644 --- a/pages/portfolio/index.tsx +++ b/pages/portfolio/index.tsx @@ -1,7 +1,7 @@ import React, { FC } from 'react'; import { getPortfolioProjects } from '../../utils/portfolio'; import { useRouter } from 'next/router'; -import styled from 'styled-components'; +import { Wrapper } from '../styles/portfolio'; import Card from '../../components/Card'; import IconButton from '../../components/IconButton'; import Head from 'next/head'; @@ -17,40 +17,6 @@ interface Props { }[]; } -const Wrapper = styled.div` - min-height: 75vh; - padding: 1rem 0rem; - - .back { - cursor: pointer; - text-align: left; - color: #3f9aee; - display: inline-flex; - align-items: center; - } - - h1 { - font-size: 1.7rem; - margin-bottom: 1rem; - } - - h4 { - font-size: 1.3rem; - grid-column: 1 / -1; - align-self: center; - justify-self: center; - } - - .projects-wrapper { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); - grid-auto-rows: minmax(100px, auto); - align-items: stretch; - justify-items: center; - gap: 1rem; - } -`; - const Index: FC = ({ portfolioProjects }) => { const router = useRouter(); diff --git a/pages/styles/404.tsx b/pages/styles/404.tsx new file mode 100644 index 0000000..ab2058d --- /dev/null +++ b/pages/styles/404.tsx @@ -0,0 +1,25 @@ +import styled from 'styled-components'; + +export const Wrapper = styled.div` + min-height: 75vh; + display: grid; + justify-items: center; + text-align: center; + + @media (max-width: 768px) { + min-height: 65vh; + } + + h1 { + font-size: 1.7rem; + align-self: flex-end; + } + + .back { + cursor: pointer; + color: #3f9aee; + display: flex; + align-items: center; + align-self: flex-start; + } +`; diff --git a/pages/styles/about.tsx b/pages/styles/about.tsx new file mode 100644 index 0000000..b76621e --- /dev/null +++ b/pages/styles/about.tsx @@ -0,0 +1,61 @@ +import styled from 'styled-components'; + +export const Wrapper = styled.div<{ dark: boolean }>` + padding: 1rem 0rem; + display: grid; + grid-template-columns: repeat(2, 1fr); + column-gap: 2rem; + + @media (max-width: 768px) { + padding: 0rem; + grid-template-columns: auto; + column-gap: 0rem; + row-gap: 1rem; + } + + .photo { + order: initial; + + @media (max-width: 768px) { + order: -1; + } + } + + h1 { + font-size: 1.7rem; + } + + .content { + display: flex; + flex-direction: column; + } + + .about, + .contact { + margin: 1rem 0rem; + + @media (max-width: 768px) { + margin: 1rem 0rem; + } + } + + .success { + color: #73d26b; + align-self: center; + font-weight: normal; + } + + .contact { + display: grid; + grid-template-columns: auto; + row-gap: 1.5rem; + + .error { + color: #d75050; + } + + @media (max-width: 768px) { + row-gap: 0.5rem; + } + } +`; diff --git a/pages/styles/blog/index.tsx b/pages/styles/blog/index.tsx new file mode 100644 index 0000000..3db22d1 --- /dev/null +++ b/pages/styles/blog/index.tsx @@ -0,0 +1,35 @@ +import styled from 'styled-components'; + +export const Wrapper = styled.div` + min-height: 75vh; + padding: 1rem 0rem; + + .back { + cursor: pointer; + text-align: left; + color: #3f9aee; + display: inline-flex; + align-items: center; + } + + h1 { + font-size: 1.7rem; + margin-bottom: 1rem; + } + + h4 { + font-size: 1.3rem; + grid-column: 1 / -1; + align-self: center; + justify-self: center; + } + + .articles-wrapper { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); + grid-auto-rows: minmax(100px, auto); + align-items: stretch; + justify-items: center; + gap: 1rem; + } +`; diff --git a/pages/styles/blog/slug.tsx b/pages/styles/blog/slug.tsx new file mode 100644 index 0000000..6c7ee35 --- /dev/null +++ b/pages/styles/blog/slug.tsx @@ -0,0 +1,90 @@ +import styled from 'styled-components'; + +export const Wrapper = styled.div` + min-height: 75vh; + padding: 1rem 0rem; + display: grid; + grid-template-rows: auto 1fr; + row-gap: 2rem; + + @media (max-width: 768px) { + row-gap: 1rem; + } + + .meta { + .back { + cursor: pointer; + text-align: left; + color: #3f9aee; + display: inline-flex; + align-items: center; + } + + .image { + margin: 1rem 0rem; + } + + h1, + p, + .tags-wrapper { + text-align: left; + } + + h1 { + font-size: 2rem; + } + + h2 { + font-size: 1.2rem; + } + + .tags-wrapper { + display: flex; + flex-direction: row; + align-items: center; + flex-wrap: wrap; + } + } + + hr { + height: 0.1rem; + opacity: 0.3; + margin: 1rem auto 0rem auto; + + @media (max-width: 768px) { + margin: 1rem auto 0rem auto; + } + } + + .content { + h1 { + font-size: 1.5rem; + } + + h2 { + font-size: 1.3rem; + } + + h3 { + font-size: 1.1rem; + } + + & > * { + margin: 0.5rem 0rem; + } + + button { + margin: 1rem 0rem; + } + + p * { + width: 100%; + height: auto; + } + + ul, + ol { + margin-left: 1.5rem; + } + } +`; diff --git a/pages/styles/home.tsx b/pages/styles/home.tsx new file mode 100644 index 0000000..b9537a8 --- /dev/null +++ b/pages/styles/home.tsx @@ -0,0 +1,48 @@ +import styled from 'styled-components'; + +export const Wrapper = styled.div` + padding: 1rem 0rem; + display: grid; + grid-template-columns: auto; + row-gap: 1rem; + + h1 { + display: inline; + font-size: 1.7rem; + margin-right: 1rem; + } + + h4 { + font-size: 1.3rem; + grid-column: 1 / -1; + align-self: center; + justify-self: center; + } + + .blue { + color: ${({ theme }) => theme.colors.blue}; + + @media (max-width: 768px) { + margin-top: 0.5rem; + } + } + + .portfolio, + .blog { + margin: 1rem 0rem; + } + + .portfolio { + margin-bottom: 3rem; + } + + .projects-wrapper, + .articles-wrapper { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); + grid-auto-rows: minmax(100px, auto); + align-items: stretch; + justify-items: center; + gap: 1rem; + } +`; diff --git a/pages/styles/portfolio/index.tsx b/pages/styles/portfolio/index.tsx new file mode 100644 index 0000000..be58c53 --- /dev/null +++ b/pages/styles/portfolio/index.tsx @@ -0,0 +1,35 @@ +import styled from 'styled-components'; + +export const Wrapper = styled.div` + min-height: 75vh; + padding: 1rem 0rem; + + .back { + cursor: pointer; + text-align: left; + color: #3f9aee; + display: inline-flex; + align-items: center; + } + + h1 { + font-size: 1.7rem; + margin-bottom: 1rem; + } + + h4 { + font-size: 1.3rem; + grid-column: 1 / -1; + align-self: center; + justify-self: center; + } + + .projects-wrapper { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); + grid-auto-rows: minmax(100px, auto); + align-items: stretch; + justify-items: center; + gap: 1rem; + } +`; diff --git a/pages/styles/portfolio/slug.tsx b/pages/styles/portfolio/slug.tsx new file mode 100644 index 0000000..212f614 --- /dev/null +++ b/pages/styles/portfolio/slug.tsx @@ -0,0 +1,78 @@ +import styled from 'styled-components'; + +export const Wrapper = styled.div` + min-height: 75vh; + padding: 1rem 0rem; + display: grid; + grid-template-rows: auto 1fr; + row-gap: 2rem; + + @media (max-width: 768px) { + row-gap: 1rem; + } + + .meta { + .back { + cursor: pointer; + text-align: left; + color: #3f9aee; + display: inline-flex; + align-items: center; + } + + .image { + margin: 1rem 0rem; + } + + h1, + p { + text-align: left; + } + + h1 { + font-size: 2rem; + } + + h2 { + font-size: 1.2rem; + } + } + + hr { + height: 0.1rem; + opacity: 0.3; + margin: 1rem auto 0rem auto; + } + + .content { + h1 { + font-size: 1.5rem; + } + + h2 { + font-size: 1.3rem; + } + + h3 { + font-size: 1.1rem; + } + + & > * { + margin: 0.5rem 0rem; + } + + button { + margin: 1rem 0rem; + } + + p * { + width: 100%; + height: auto; + } + + ul, + ol { + margin-left: 1.5rem; + } + } +`;