From f36f2b5c168b42b7040da5f650df75f44be2df0b Mon Sep 17 00:00:00 2001 From: Sabrina Medwinter Date: Fri, 2 Feb 2024 06:20:41 -0500 Subject: [PATCH] SM-Index-Redesign (#55) * styling: remove distracting background image * chore: Remove stalled projects from index * chore: Clean formatting * styling: Use local fonts * refactor: Add help txt+styling to scrolldown hint * feat: Index Redesign - Stage 1 * chore: Change blog post summary * chore: Rename modules and move to proper location * refactor: Clarify element classes * refactor: Add container to button element * build: Update react types --- frontend/package.json | 2 +- .../src/components/blog/articles.module.scss | 40 ------ frontend/src/components/hero/hero.tsx | 23 ++-- .../components/projects/latestProjects.tsx | 2 +- .../src/components/projects/projectsList.tsx | 2 +- frontend/src/components/scrollDown.tsx | 10 +- frontend/src/pages/blog.tsx | 120 ++++++++++++++---- frontend/src/pages/index.tsx | 3 +- frontend/src/pages/posts/[slug].tsx | 97 +++++++------- frontend/src/styles/_typography.scss | 6 +- frontend/src/styles/global.scss | 2 +- .../styles/modules/BlogSummary.module.scss | 111 ++++++++++++++++ ...{button.module.scss => Button.module.scss} | 19 +++ frontend/src/styles/modules/Hero.module.scss | 62 +++++++++ .../src/styles/modules/ScrollDown.module.scss | 35 +++-- frontend/src/styles/modules/hero.module.scss | 93 -------------- 16 files changed, 376 insertions(+), 251 deletions(-) create mode 100644 frontend/src/styles/modules/BlogSummary.module.scss rename frontend/src/styles/modules/{button.module.scss => Button.module.scss} (73%) create mode 100644 frontend/src/styles/modules/Hero.module.scss delete mode 100644 frontend/src/styles/modules/hero.module.scss diff --git a/frontend/package.json b/frontend/package.json index 72badc3fb..8e5405c8d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -42,7 +42,7 @@ "@semantic-release/npm": "^10.0.3", "@semantic-release/release-notes-generator": "^11.0.1", "@types/node": "18.11.9", - "@types/react": "18.0.24", + "@types/react": "^18.2.51", "@types/react-dom": "18.0.8", "@vercel/analytics": "^1.0.2", "animate.css": "^4.1.1", diff --git a/frontend/src/components/blog/articles.module.scss b/frontend/src/components/blog/articles.module.scss index 951f077bf..5a6fc8a2e 100644 --- a/frontend/src/components/blog/articles.module.scss +++ b/frontend/src/components/blog/articles.module.scss @@ -210,43 +210,3 @@ .link { color: var(--accent); } - -.list { - - &__section { - padding: 1rem 0; - } - - &__section div { - display: flex; - flex-wrap: wrap; - } - - &__date { - display: flex; - align-items: center; - margin-right: 0.5rem; - } - - &__date:nth-of-type(odd) { - color: var(--primary); - } - - &__date:nth-of-type(even) { - color: var(--secondary); - } - - &__title { - font-weight: 400; - font-size: 1rem; - margin: 0; - } - - &__description { - margin: 0; - font-weight: 400; - font-size: 00.9rem; - padding-top: 0.5rem; - opacity: 0.75; - } -} diff --git a/frontend/src/components/hero/hero.tsx b/frontend/src/components/hero/hero.tsx index f88df8005..25386cce7 100644 --- a/frontend/src/components/hero/hero.tsx +++ b/frontend/src/components/hero/hero.tsx @@ -2,38 +2,33 @@ import Link from 'next/link'; import { HeroModel } from '@components/threeJS/HeroModel'; import HeroName from '@components/hero/heroName/heroName'; import { ScrollDown } from '@components/scrollDown'; -import styles from '@styles/modules/hero.module.scss'; -import button from '@styles/modules/button.module.scss'; +import hero from '@styles/modules/Hero.module.scss'; +import button from '@styles/modules/Button.module.scss'; const Hero = () => { return (
-
-
+
+
-
+

Web developer
based in Kingston, Jamaica.

- - {/*

- An ongoing journey of exploration drives me to constantly embrace novel technologies and refine my - skillset. -

*/} - {/* TODO: rewrite cringe paragraph */}
-
+
Need a service? @@ -41,7 +36,7 @@ const Hero = () => {
-
+
diff --git a/frontend/src/components/projects/latestProjects.tsx b/frontend/src/components/projects/latestProjects.tsx index 59005cbdd..8a65b821d 100644 --- a/frontend/src/components/projects/latestProjects.tsx +++ b/frontend/src/components/projects/latestProjects.tsx @@ -2,7 +2,7 @@ import Projects from '@data/projectsData'; import styled from '@emotion/styled'; import { FaToolbox, FaLanguage, FaGithub } from 'react-icons/fa6'; import Link from 'next/link'; -import button from '@styles/modules/button.module.scss'; +import button from '@styles/modules/Button.module.scss'; // TODO convert to scss modules const ProjectCard = styled.div` diff --git a/frontend/src/components/projects/projectsList.tsx b/frontend/src/components/projects/projectsList.tsx index 8de4905fd..4ee936aec 100644 --- a/frontend/src/components/projects/projectsList.tsx +++ b/frontend/src/components/projects/projectsList.tsx @@ -138,7 +138,7 @@ export const LatestProject = () => { loader={({ src, width }) => `${src}?w=${width}`} sizes="100vw" style={{ - width: 'clamp(250px, 100%, 1080px)', + width: 'clamp(250px, 100%, 480px)', height: 'clamp(200px, 100%, 500px)', margin: '0 auto', display: 'flex', diff --git a/frontend/src/components/scrollDown.tsx b/frontend/src/components/scrollDown.tsx index 4e5f840ee..005a9e89c 100644 --- a/frontend/src/components/scrollDown.tsx +++ b/frontend/src/components/scrollDown.tsx @@ -1,8 +1,10 @@ -import styles from '@styles/modules/ScrollDown.module.scss'; +import mouse from '@styles/modules/ScrollDown.module.scss'; + export const ScrollDown = () => { return ( -
-
-
+
+ scroll down +
+
); }; diff --git a/frontend/src/pages/blog.tsx b/frontend/src/pages/blog.tsx index 942ec3617..b1b3e2530 100644 --- a/frontend/src/pages/blog.tsx +++ b/frontend/src/pages/blog.tsx @@ -5,6 +5,7 @@ import Link from 'next/link'; import styles from '@components/blog/articles.module.scss'; import { useMemo } from 'react'; import { LatestProject } from '@components/projects'; +import blog from '@styles/modules/BlogSummary.module.scss' export type PostType = { [x: string]: any; @@ -133,24 +134,8 @@ export const BlogPage = ({ posts }: PostType): JSX.Element => { ); }; -export const BlogList = ({ posts }: PostType): JSX.Element => { - return ( - <> - {posts.length > 0 && ( -
-
-

Latest Posts

-
- {posts.slice(0, 4).map( - (post) => - !post.tags.includes('log') && ( - - {/* {post.coverImage && ( + +{/* {post.coverImage && (
{ />
)} */} -
-

{post.title}

-

{post.description}

- - {/* {post.tags && ( + {/* {post.tags && (
{post.tags.slice(0, 2).map((tag) => ( @@ -178,17 +159,102 @@ export const BlogList = ({ posts }: PostType): JSX.Element => { ))}
)} */} + +export const BlogList = ({ posts }: PostType): JSX.Element => { + useMemo(() => { + const removeDupicates = (data) => { + return data.filter((value, i) => data.indexOf(value) === i); + }; + + posts.forEach((post) => { + const [yearDate, monthDate, dayDate] = post.date.split(' ')[0].split('-'); + + let year: Year | undefined = years.find((year) => year.date === yearDate); + if (!year) { + year = { + date: yearDate, + months: [], + }; + years.push(year); + } + + let month = year.months.find((month) => month.date === monthDate); + if (!month) { + const monthIndex = parseInt(monthDate) - 1; + const monthName = monthNames[monthIndex]; + month = { + date: monthDate, + name: monthName, + posts: [], + }; + year.months.push(month); + } + + month.posts.push({ + ...post, + date: dayDate, + }); + }); + + years + .sort((a, b) => parseInt(b.date) - parseInt(a.date)) + .forEach((year) => { + year.months + .sort((a, b) => parseInt(b.date) - parseInt(a.date)) + .forEach((month) => { + month.posts.sort((a, b) => parseInt(b.date) - parseInt(a.date)); + }); + }); + + years.forEach((year) => { + year.months.forEach((month) => { + year.months.forEach((month) => { + removeDupicates(month.posts); + }); + }); + }); + }, [posts]); + + return ( + <> + {posts.length > 0 && ( +
+
+

Latest Posts

+
+ {years.map((year) => ( +
    +
  • + {year.months.map((month, i) => ( +
      +
    • +

      + {month.name} {i === 0 && year.date} +

      +
    • + {month.posts.map((post,i) => ( + +
      +
      + {post.date} +

      {post.title}

      +
      +

      {post.description}

      - ), - )} + ))} +
    + ))} +
  • +
+ ))}
{posts.length > 4 && More Posts ⟶}
-
+ {/*

Latest Creation

-
+
*/}
)} diff --git a/frontend/src/pages/index.tsx b/frontend/src/pages/index.tsx index 93617a784..fbce80b2e 100644 --- a/frontend/src/pages/index.tsx +++ b/frontend/src/pages/index.tsx @@ -1,7 +1,7 @@ import Page from '@containers/layout/page'; import Hero from '@components/hero/hero'; // import { SiteBackground } from '@components/threeJS/scene'; -import ProjectList, { OtherProjects } from '@components/projects/projectsList'; +import ProjectList from '@components/projects/projectsList'; import { BlogList, PostType } from './blog'; import { getAllPosts } from '@utils/api'; import { GetStaticProps } from 'next/types'; @@ -14,7 +14,6 @@ export const Home = ({ posts }: PostType): JSX.Element => { {/* TODO: move blog posts to Sanity} */} - {/* */} diff --git a/frontend/src/pages/posts/[slug].tsx b/frontend/src/pages/posts/[slug].tsx index cf57dfcbe..75dca0e2e 100644 --- a/frontend/src/pages/posts/[slug].tsx +++ b/frontend/src/pages/posts/[slug].tsx @@ -1,6 +1,6 @@ import Page from '@containers/layout/BlogPage'; import Head from 'next/head'; -import { Key, useEffect, useState } from 'react'; +import { Key, useEffect, useState } from 'react'; import { CustomComponents } from '@components/blog/customElements'; import { format, parseISO } from 'date-fns'; import fs from 'fs'; @@ -8,7 +8,7 @@ import matter from 'gray-matter'; import { GetStaticPaths, GetStaticProps } from 'next'; import { MDXRemote, MDXRemoteSerializeResult } from 'next-mdx-remote'; import { serialize } from 'next-mdx-remote/serialize'; -import { remarkCodeHike } from "@code-hike/mdx" +import { remarkCodeHike } from '@code-hike/mdx'; import path from 'path'; import { PostType } from '@pages/blog'; @@ -27,10 +27,10 @@ type PostPageProps = { }; type HeadingProps = { - id: Key | any, - text: ReactNode, - level: string, -} + id: Key | any; + text: ReactNode; + level: string; +}; const getClassName = (level: string) => { switch (level) { @@ -53,18 +53,18 @@ const PostPage = ({ source, frontMatter }: PostPageProps): JSX.Element => { const headingList = Array.from(headings).map((heading) => ({ id: heading.id, text: heading.textContent, - level: heading.tagName + level: heading.tagName, })); setHeadings(headingList); }, []); return ( - +
- + @@ -72,7 +72,6 @@ const PostPage = ({ source, frontMatter }: PostPageProps): JSX.Element => {
-

{frontMatter.title}

@@ -101,11 +100,11 @@ const PostPage = ({ source, frontMatter }: PostPageProps): JSX.Element => { onClick={(e) => { e.preventDefault(); activeHeader.scrollIntoView({ - behavior: 'smooth' + behavior: 'smooth', }); }} style={{ - fontWeight: activeId === heading.id ? 'bold' : 'normal' + fontWeight: activeId === heading.id ? 'bold' : 'normal', }} > {heading.text} @@ -118,6 +117,8 @@ const PostPage = ({ source, frontMatter }: PostPageProps): JSX.Element => {
+
+
); }; @@ -128,48 +129,44 @@ export const getStaticProps: GetStaticProps = async ({ params }) => { const { content, data } = matter(source); - const mdxSource = await serialize( - content, - { - mdxOptions: { - remarkPlugins: [ - [ - remarkCodeHike, - { - autoImport: false, - // @todo make a custom theme - theme: "github-dark-dimmed", - lineNumbers: true, - showCopyButton: true, - autoLink: true, - staticMediaQuery: "not screen, (max-width: 768px)", - - }, - ], + const mdxSource = await serialize(content, { + mdxOptions: { + remarkPlugins: [ + [ + remarkCodeHike, + { + autoImport: false, + // @todo make a custom theme + theme: 'github-dark-dimmed', + lineNumbers: true, + showCopyButton: true, + autoLink: true, + staticMediaQuery: 'not screen, (max-width: 768px)', + }, ], - rehypePlugins: [ - rehypeSlug, - [ - rehypeAutolinkHeadings, - { - properties: { - className: ['anchor'] - } - } - ] + ], + rehypePlugins: [ + rehypeSlug, + [ + rehypeAutolinkHeadings, + { + properties: { + className: ['anchor'], + }, + }, ], - format: 'mdx', - useDynamicImport: true, - }, - // made available to the arguments of any custom mdx component - scope: data - } - ); + ], + format: 'mdx', + useDynamicImport: true, + }, + // made available to the arguments of any custom mdx component + scope: data, + }); return { props: { source: mdxSource, - frontMatter: data - } + frontMatter: data, + }, }; }; @@ -182,7 +179,7 @@ export const getStaticPaths: GetStaticPaths = async () => { return { paths, - fallback: false + fallback: false, }; }; diff --git a/frontend/src/styles/_typography.scss b/frontend/src/styles/_typography.scss index a00100a40..c2c9bb8ad 100644 --- a/frontend/src/styles/_typography.scss +++ b/frontend/src/styles/_typography.scss @@ -16,6 +16,6 @@ src: local("Fira Code Regular"), url(../assets/fonts/FiraCode-Regular.ttf); } -$primary-font: "Inter", Arial, Helvetica, sans-serif; -$accent-font: "Sims Sans SC", 'Bebas Neue', 'Open Sans', Arial, Helvetica, sans-serif; -$secondary-font: 'Bebas Neue', "Fira Code", monospace; +$primary-font: "Proxima Nova", Arial, Helvetica, sans-serif; +$accent-font: "Sims Sans SC", 'Bebas Neue', 'Open Sans', Arial, sans-serif; +$secondary-font:"Fira Code", monospace; diff --git a/frontend/src/styles/global.scss b/frontend/src/styles/global.scss index 071ceee21..b6930422e 100644 --- a/frontend/src/styles/global.scss +++ b/frontend/src/styles/global.scss @@ -101,7 +101,7 @@ html { body { background-color: var(--backgroundColor); - background-image: var(--backgroundImage); + // background-image: var(--backgroundImage); background-repeat: repeat; } diff --git a/frontend/src/styles/modules/BlogSummary.module.scss b/frontend/src/styles/modules/BlogSummary.module.scss new file mode 100644 index 000000000..4ba4a40bc --- /dev/null +++ b/frontend/src/styles/modules/BlogSummary.module.scss @@ -0,0 +1,111 @@ +@import '@styles/mediaQuery'; + + +.blogSection { + display: grid; + grid-template-columns: 12; + grid-template-rows: 12; + grid-gap: 10px; +} + +.log { + font-style: oblique; + + border-radius: var(--borderRadius); + width: fit-content; + + + &__date { + font-weight: 400; + font-size: 0.9rem; + color: var(--textColorFade); + } + + &__title { + padding: 0; + margin: 1rem 0; + color: var(--text); + font-family: var(--headingFont); + font-weight: 500; + line-height: 1; + font-size: 1.3rem; + // background-color: var(--backgroundColor); + text-transform: capitalize; + + @include breakpoint-range($from: mobile, $to: tablet) { + font-size: 1.5rem; + margin-left: 2rem; + } + } + + &__description { + font-size: 1rem; + font-weight: 400; + line-height: 1rem; + color: var(--textColor); + // background-color: var(--backgroundColor); + + @include breakpoint-range($from: mobile) { + font-size: 0.8rem; + } + } +} + +.nolist { + list-style: none; +} + +.month { + display: flex; + justify-content: space-between; + font-size: 1.4rem; + font-weight: 600; + list-style: none; + margin: 0.5rem 0; +} + +.link { + color: var(--accent); +} + +.list { + + &__section { + padding: 1rem 0; + max-width: 35rem; + } + + &__section div { + display: flex; + flex-wrap: wrap; + } + + &__date { + display: flex; + align-items: center; + margin-right: 0.5rem; + } + + &__date:nth-of-type(odd) { + color: var(--primary); + } + + &__date:nth-of-type(even) { + color: var(--secondary); + } + + &__title { + font-weight: 400; + font-size: 1rem; + margin: 0; + } + + &__description { + margin: 0; + font-weight: 400; + font-size: 00.9rem; + padding-top: 0.5rem; + opacity: 0.75; + text-align: left; + } +} diff --git a/frontend/src/styles/modules/button.module.scss b/frontend/src/styles/modules/Button.module.scss similarity index 73% rename from frontend/src/styles/modules/button.module.scss rename to frontend/src/styles/modules/Button.module.scss index c80eb183c..cb1305b9e 100644 --- a/frontend/src/styles/modules/button.module.scss +++ b/frontend/src/styles/modules/Button.module.scss @@ -1,5 +1,24 @@ @import '@styles/mediaQuery'; +.container { + display: flex; + gap: 1rem; + + @include breakpoint-range($from: mobile) { + flex-direction: column; + width: clamp(10rem,80%,30rem); + margin: 1rem; + justify-content: center; + gap: 1rem; + } + + @include breakpoint-range($from: desktopSmall) { + flex-direction: row; + width: clamp(20rem,100%,35rem); + margin: 0.5rem auto; + } +} + .primary, .secondary { align-items: center; diff --git a/frontend/src/styles/modules/Hero.module.scss b/frontend/src/styles/modules/Hero.module.scss new file mode 100644 index 000000000..4e9ce94f0 --- /dev/null +++ b/frontend/src/styles/modules/Hero.module.scss @@ -0,0 +1,62 @@ +@import '@styles/mediaQuery'; + +.container { + display: flex; + flex-wrap: wrap; + place-items: center; + margin: 0 auto; + + @include breakpoint-range($from: mobile, $to: desktopSmall) { + flex-direction: column; + } + + @include breakpoint-range($from: desktopSmall, $to: desktopLarge) { + flex-direction: row; + } +} + +.section { + height: auto; + width: fit-content; + display: flex; + flex-direction: column; + flex-wrap: wrap; + place-items: center; + margin: 0 auto; +} + +.cta { + @extend .section; + + .text { + padding: var(--paddingContainer); + border-radius: var(--borderRadius); + font-weight: 300; + max-width: 25rem; + text-align: center; + } + + @include breakpoint-range($from: desktop) { + position: absolute; + bottom: 10%; + left: 10%; + } +} + +.model { + @extend .section; + + @include breakpoint-range($from: mobile) { + display: none + } + + @include breakpoint-range($from: tablet) { + display: flex; + } + + @include breakpoint-range($from: desktop) { + position: absolute; + bottom: 30%; + right: 8%; + } +} diff --git a/frontend/src/styles/modules/ScrollDown.module.scss b/frontend/src/styles/modules/ScrollDown.module.scss index c06d41051..23b8da6b4 100644 --- a/frontend/src/styles/modules/ScrollDown.module.scss +++ b/frontend/src/styles/modules/ScrollDown.module.scss @@ -1,19 +1,34 @@ @import '@styles/mediaQuery'; .field { - display: flex; + display: flex; align-items: center; - justify-content: space-around; width: 100%; scale: 0.55; -} + // opacity: 0.6; + + & .label { + margin: 1rem; + text-transform: uppercase; + letter-spacing: 1px; + color: var(--textColorFade); + } + + @include breakpoint-range($from: mobile) { + flex-direction: column;; + } -.field > .field__label { - width: 100%; - text-align: center; + @include breakpoint-range($from: desktop) { + width: fit-content; + flex-direction: row; + position: absolute; + right: 3%; + bottom: 5%; + } } .mouse { + display: block; opacity: 0.8; width: 50px; height: 85px; @@ -34,14 +49,6 @@ animation: wheel 2s infinite; -webkit-animation: wheel 2s infinite; } - - @include breakpoint-range($from: mobile, $to: tablet) { - display: none; - } - - @include breakpoint-range($from: tablet) { - display: block; - } } diff --git a/frontend/src/styles/modules/hero.module.scss b/frontend/src/styles/modules/hero.module.scss deleted file mode 100644 index 6b1e44ed4..000000000 --- a/frontend/src/styles/modules/hero.module.scss +++ /dev/null @@ -1,93 +0,0 @@ -@import '@styles/mediaQuery'; - -.container { - display: flex; - flex-wrap: wrap; - place-items: center; - margin: 0 auto; - - @include breakpoint-range($from: mobile, $to: desktopSmall) { - flex-direction: column; - } - - @include breakpoint-range($from: desktopSmall, $to: desktopLarge) { - flex-direction: row; - } -} - - - -.button-container { - display: flex; - margin: 1rem auto; - - @include breakpoint-range($from: mobile, $to: desktopSmall) { - flex-direction: column; - width: 80%; - margin: 1rem; - max-width: 30rem; - justify-content: center; - gap: 1rem; - } - - @include breakpoint-range($from: desktopSmall) { - flex-direction: row; - max-width: 35rem; - width: 100%; - } -} - -.heroSection { - height: auto; - width: fit-content; - display: flex; - flex-direction: column; - flex-wrap: wrap; - place-items: center; - margin: 0 auto; - - .text-container { - padding: var(--paddingContainer); - border-radius: var(--borderRadius); - font-weight: 300; - max-width: 25rem; - } - - b { - font-weight: 600; - } - - p { - padding: 0; - } - - @include breakpoint-range($from: mobile, $to: desktopSmall) { - &:last-child { - display: none; - } - } - - @include breakpoint-range($from: desktopSmall) { - &:last-child { - display: block; - } - } -} - -.glassmorphic { - flex: 1 1 10rem; - padding: var(--paddingContainer); - color: var(--textColor); - background: rgba(var(--backgroundColor), 0.2); - box-shadow: var(--boxShadow); - border-radius: var(--borderRadius); - border: var(--border); - /* From https://css.glass */ - background: rgba(255, 255, 255, 0.07); - border-radius: var(--borderRadius); - @supports ((-webkit-backdrop-filter: none) or (backdrop-filter: none)) { - // background-color: rgba(255, 255, 255, .5); - -webkit-backdrop-filter: blur(20px); - backdrop-filter: blur(20px); -} -}