Add Dark Mode and Blogposts

This commit is contained in:
Joshua 2022-08-10 00:35:26 +02:00
parent ee6735181b
commit 1953b1706f
24 changed files with 427 additions and 44 deletions

View file

@ -2,13 +2,16 @@ import Icon from "components/Icon";
import Link from "next/link";
import styles from "styles/Button.module.sass";
import { SocialButton } from "utils/types";
import { useTheme } from 'next-themes'
const Button = (props: SocialButton) => {
const { resolvedTheme: theme } = useTheme()
return (
<>
<Link href={props.url}>
<a>
<div className={styles.button}>
<div data-theme={theme} className={styles.button}>
<Icon className={styles.icon} icon={props.icon} />
<div className={styles.platform_username}>
<p className={styles.platform}>{props.platform}</p>

6
components/Date.tsx Normal file
View file

@ -0,0 +1,6 @@
import { parseISO, format } from 'date-fns';
export default function Date({ dateString }) {
const date = parseISO(dateString);
return <time dateTime={dateString}>{format(date, 'LLLL d, yyyy')}</time>;
}

View file

@ -2,10 +2,13 @@
import { useLanyard } from "use-lanyard";
import styles from "styles/Lanyard.module.sass";
import Image from "next/image";
import { useTheme } from 'next-themes'
const Lanyard = () => {
const id = process.env.NEXT_DISCORD_ID || "318044130796109825";
const lanyard = useLanyard(id).data;
const { resolvedTheme: theme } = useTheme()
if (!lanyard?.listening_to_spotify) return;
let artists;
@ -18,9 +21,12 @@ const Lanyard = () => {
artists = lanyard.spotify.artist.split(";").join(",");
}
console.log("lanyard", theme)
return (
<>
<div className={[styles.container, styles.badge].join(" ")}>
<div data-theme={theme} className={[styles.container, styles.badge].join(" ")}>
<Image
className={styles.albumart}
src={lanyard.spotify.album_art_url}

11
components/Link.tsx Normal file
View file

@ -0,0 +1,11 @@
import NextLink from "next/link";
const Link = ({ to, name }: { to: string; name: string }) => {
return (
<NextLink href={to} target={'_blank'}>
<a target={'_blank'}> {name} </a>
</NextLink>
);
};
export default Link;

14
components/Navbar.tsx Normal file
View file

@ -0,0 +1,14 @@
import Title from "./Title";
import styles from "../styles/Navbar.module.sass";
const Navbar = () => {
return (
<>
<div className={styles.center}>
<Title />
</div>
</>
);
};
export default Navbar;

62
components/Post.tsx Normal file
View file

@ -0,0 +1,62 @@
import Icon from "components/Icon";
import Link from "next/link";
import styles from "styles/Posts.module.sass";
import { useTheme } from "next-themes";
import Date from "./Date";
const Post = ({ title, date, tag }) => {
const { resolvedTheme: theme } = useTheme();
return (
<>
<div data-theme={theme} className={styles.post}>
<div className={styles.title_date}>
<p className={styles.title}>{title}</p>
<p className={styles.date}>
<Date dateString={date} />
</p>
</div>
{tag ? <p data-theme={theme} className={styles.tag}>{tag}</p> : undefined}
</div>
</>
);
};
export default Post;
{
/* <Link href={props.url}> */
}
{
/* <a> */
}
{
/* <div data-theme={theme} className={styles.button}> */
}
{
/* <Icon className={styles.icon} icon={props.icon} /> */
}
{
/* <div className={styles.platform_username}> */
}
{
/* <p className={styles.platform}>{props.platform}</p> */
}
{
/* <p className={styles.username}> {props.username} </p> */
}
{
/* </div> */
}
{
/* <Icon className={styles.link} icon="arrow-up-right" /> */
}
{
/* </div> */
}
{
/* </a> */
}
{
/* </Link> */
}

18
components/PostGrid.tsx Normal file
View file

@ -0,0 +1,18 @@
import Post from "./Post";
import styles from "styles/Posts.module.sass";
import { SocialButton } from "utils/types";
import { CSSProperties } from "react";
const PostGrid = ({ posts, style }: { posts: any; style?: CSSProperties }) => {
return (
<>
<div className={styles.grid} style={style}>
{posts.map((post, index) => {
return <Post {...post} />;
})}
</div>
</>
);
};
export default PostGrid;

View file

@ -1,13 +1,21 @@
import Image from "next/image";
import styles from "styles/Title.module.sass";
import { useTheme } from 'next-themes'
const Title = () => {
return (
<>
<h1 className={styles.title}>
Lio's Domain
</h1>
</>
)
}
const { resolvedTheme: theme } = useTheme()
const logo_size = 150;
return (
<>
<Image
src={`/logos/${theme || "dark"}.svg`}
width={logo_size}
height={logo_size / 4}
className={styles.title}
/>
</>
);
};
export default Title
export default Title;

View file

@ -1,11 +1,16 @@
import React from 'react'
import React from "react";
import { ThemeProvider } from "next-themes";
// import { AppProps } from 'next/app'
// import 'tailwindcss/tailwind.css'
import '../styles/main.sass'
import "../styles/main.sass";
function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
return (
<ThemeProvider>
<Component {...pageProps} />
</ThemeProvider>
);
}
export default MyApp
export default MyApp;

35
pages/blog/[slug].tsx Normal file
View file

@ -0,0 +1,35 @@
import Date from "components/Date"
import { getAllPostIDs, getPostData } from "utils/shared/posts"
export default function Blog({data}) {
return (
<>
{data.slug}
<br />
{data.title}
<br />
<Date dateString={data.date} />
<br />
<div className="content" dangerouslySetInnerHTML={{__html: data.content}} />
</>
)
}
export async function getStaticPaths() {
const paths = getAllPostIDs()
// console.log(paths)
return {
paths,
fallback: false,
};
}
export async function getStaticProps({ params }) {
const data = await getPostData(params.slug);
// console.log(data)
return {
props: {
data,
},
};
}

View file

@ -1,30 +1,44 @@
import ButtonGrid from "components/ButtonGrid";
import Lanyard from "components/Lanyard";
import Title from "components/Title";
import Navbar from "components/Navbar";
import getProfiles from "utils/shared/profiles";
import { getAllPostIDs, getPostData,getSortedPosts } from "utils/shared/posts";
import { SocialButton } from "utils/types";
import styles from "styles/Index.module.sass";
import Link from "components/Link";
import Post from "components/Post";
import PostGrid from "components/PostGrid";
export async function getStaticProps() {
const profiles = await getProfiles();
const posts = await getSortedPosts();
return {
props: {
profiles,
posts
},
};
}
const IndexPage = (props: { profiles: SocialButton[] }) => (
<>
<div className={styles.center}>
<Title />
<div>
<p>Profiles</p>
<ButtonGrid Buttons={props.profiles} />
const IndexPage = (props: { profiles: SocialButton[]; posts: Array<any> }) => {
// console.log(props.posts);
return (
<>
<div className={styles.center}>
<Navbar />
<div>
<p>Profiles</p>
<ButtonGrid Buttons={props.profiles} />
</div>
<div>
<p>Posts</p>
<PostGrid posts={props.posts}/>
</div>
</div>
</div>
<Lanyard />
</>
);
<Lanyard />
</>
);
};
export default IndexPage;

20
posts/second-post.mdx Normal file
View file

@ -0,0 +1,20 @@
---
title: "Second Post"
date: "2020-01-03"
tag: "random"
---
We recommend using **Static Generation** (with and without data) whenever possible because your page can be built once and served by CDN, which makes it much faster than having a server render the page on every request.
You can use Static Generation for many types of pages, including:
- Marketing pages
- Blog posts
- E-commerce product listings
- Help and documentation
You should ask yourself: "Can I pre-render this page **ahead** of a user's request?" If the answer is yes, then you should choose Static Generation.
On the other hand, Static Generation is **not** a good idea if you cannot pre-render a page ahead of a user's request. Maybe your page shows frequently updated data, and the page content changes on every request.
In that case, you can use **Server-Side Rendering**. It will be slower, but the pre-rendered page will always be up-to-date. Or you can skip pre-rendering and use client-side JavaScript to populate data.

19
posts/ssg-ssr.mdx Normal file
View file

@ -0,0 +1,19 @@
---
title: "First Post"
date: "2020-01-02"
---
We recommend using **Static Generation** (with and without data) whenever possible because your page can be built once and served by CDN, which makes it much faster than having a server render the page on every request.
You can use Static Generation for many types of pages, including:
- Marketing pages
- Blog posts
- E-commerce product listings
- Help and documentation
You should ask yourself: "Can I pre-render this page **ahead** of a user's request?" If the answer is yes, then you should choose Static Generation.
On the other hand, Static Generation is **not** a good idea if you cannot pre-render a page ahead of a user's request. Maybe your page shows frequently updated data, and the page content changes on every request.
In that case, you can use **Server-Side Rendering**. It will be slower, but the pre-rendered page will always be up-to-date. Or you can skip pre-rendering and use client-side JavaScript to populate data.

3
public/logos/dark.svg Normal file
View file

@ -0,0 +1,3 @@
<svg width="246" height="105" viewBox="0 0 246 105" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M67.2791 73.05H53.1791C41.9291 73.05 32.7791 63.9 32.7791 52.5V20.55C32.7791 9.14999 23.4791 -7.15256e-06 12.2291 -7.15256e-06H2.6291C1.5791 -7.15256e-06 0.829102 0.899999 0.829102 1.94999V52.5C0.829102 81.45 24.2291 105 53.1791 105H67.2791C68.3291 105 69.2291 104.1 69.2291 103.05V75C69.2291 73.95 68.3291 73.05 67.2791 73.05ZM100.079 -7.15256e-06H90.4787C89.4287 -7.15256e-06 88.6787 0.899999 88.6787 1.94999V84.45C88.6787 95.85 97.8287 105 109.079 105H118.679C119.729 105 120.629 104.1 120.629 103.05V20.55C120.629 9.14999 111.329 -7.15256e-06 100.079 -7.15256e-06ZM140.2 20.55V84.6C140.2 95.85 149.35 105 160.6 105H224.5C235.9 105 245.05 95.85 245.05 84.6V20.55C245.05 9.3 235.9 -7.15256e-06 224.5 -7.15256e-06H160.6C149.35 -7.15256e-06 140.2 9.3 140.2 20.55ZM211.15 73.05H174.1C172.9 73.05 172.15 72.3 172.15 71.1V34.05C172.15 32.85 172.9 32.1 174.1 32.1H211.15C212.35 32.1 213.1 32.85 213.1 34.05V71.1C213.1 72.3 212.35 73.05 211.15 73.05Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

3
public/logos/light.svg Normal file
View file

@ -0,0 +1,3 @@
<svg width="246" height="105" viewBox="0 0 246 105" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M67.2791 73.05H53.1791C41.9291 73.05 32.7791 63.9 32.7791 52.5V20.55C32.7791 9.14999 23.4791 -7.15256e-06 12.2291 -7.15256e-06H2.6291C1.5791 -7.15256e-06 0.829102 0.899999 0.829102 1.94999V52.5C0.829102 81.45 24.2291 105 53.1791 105H67.2791C68.3291 105 69.2291 104.1 69.2291 103.05V75C69.2291 73.95 68.3291 73.05 67.2791 73.05ZM100.079 -7.15256e-06H90.4787C89.4287 -7.15256e-06 88.6787 0.899999 88.6787 1.94999V84.45C88.6787 95.85 97.8287 105 109.079 105H118.679C119.729 105 120.629 104.1 120.629 103.05V20.55C120.629 9.14999 111.329 -7.15256e-06 100.079 -7.15256e-06ZM140.2 20.55V84.6C140.2 95.85 149.35 105 160.6 105H224.5C235.9 105 245.05 95.85 245.05 84.6V20.55C245.05 9.3 235.9 -7.15256e-06 224.5 -7.15256e-06H160.6C149.35 -7.15256e-06 140.2 9.3 140.2 20.55ZM211.15 73.05H174.1C172.9 73.05 172.15 72.3 172.15 71.1V34.05C172.15 32.85 172.9 32.1 174.1 32.1H211.15C212.35 32.1 213.1 32.85 213.1 34.05V71.1C213.1 72.3 212.35 73.05 211.15 73.05Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -1,13 +1,27 @@
@import "./_variables"
.button
display: flex
background-color: #191919
align-items: center
transition: all .2s
&:hover
background-color: white
color: black
transform: translateY(-0.3em)
background: $background-dark-buttons
color: $text-dark-buttons
&[data-theme="light"]
background: $background-light-buttons
color: $text-light-buttons
.button:hover
transform: translateY(-0.3em)
background: $background-dark-buttons-hover
color: $text-dark-buttons-hover
&[data-theme="light"]
background: $background-light-buttons-hover
color: $text-light-buttons-hover
// & > .platform_username > .username
// color: $username-dark-hover
// &[data-theme="light"]
// color: $username-light-hover
// TODO: FIX THE HOVER FOR USERNAMES
.icon
padding: 10px
@ -21,7 +35,9 @@
.platform
font-weight: lighter
.username
color: grey
color: $username-dark
&[data-theme="light"]
color: $username-light
.grid
display: grid

View file

@ -1,3 +1,6 @@
@import "./_variables"
.container
position: absolute
bottom: 0
@ -5,10 +8,13 @@
margin: 10px
display: inline-flex
align-items: center
background-color: #222
max-width: 50rem
border-radius: .5rem
animation: skeleton-loading 2s linear infinite alternate
background: $background-dark-lanyard
color: $text-dark-lanyard
&[data-theme="light"]
background: $background-light-lanyard
color: $text-light-lanyard
.albumart
border-radius: 20px
@ -34,7 +40,7 @@
text-align: center
line-height: 18px
border-radius: 50%
box-shadow: 0 0 1px #333
// box-shadow: 0 0 1px #333
animation: pulse 4s linear infinite alternate
@keyframes pulse

0
styles/Link.module.sass Normal file
View file

View file

@ -0,0 +1,7 @@
.center
align-content: center
justify-content: center
margin-top: 2rem
padding-top: 3rem
padding-bottom: 2.5rem
border-radius: .5rem

48
styles/Posts.module.sass Normal file
View file

@ -0,0 +1,48 @@
@import "./_variables"
.post
display: flex
align-items: center
transition: all .2s
background: $background-dark-buttons
color: $text-dark-buttons
&[data-theme="light"]
background: $background-light-buttons
color: $text-light-buttons
.post:hover
transform: translateY(-0.3em)
background: $background-dark-buttons-hover
color: $text-dark-buttons-hover
&[data-theme="light"]
background: $background-light-buttons-hover
color: $text-light-buttons-hover
> .tag
color: $tag-text-dark-hover
&[data-theme="light"]
color: $tag-text-light-hover
.icon
padding: 10px
.tag
padding-right: 2rem
margin-left: auto
color: $tag-text-dark
&[data-theme="light"]
color: $tag-text-light
.title_date
line-height: .5rem
padding-left: 1rem
.title
font-weight: lighter
.date
color: $username-dark
&[data-theme="light"]
color: $username-light
.grid
display: grid
gap: .5rem
grid-template-columns: 1

View file

@ -1,5 +1,5 @@
.title
display: inline-flex
font-size: 3rem
// display: inline-flex
// font-size: 3rem
margin-top: 5rem
background-image: linear-gradient(to top, transparent 0.15em, rgb(0, 0, 0) 0.15em, rgb(0, 0, 0) 0.6em, transparent 0.6em)
// background-image: linear-gradient(to top, transparent 0.15em, rgb(0, 0, 0) 0.15em, rgb(0, 0, 0) 0.6em, transparent 0.6em)

29
styles/_variables.sass Normal file
View file

@ -0,0 +1,29 @@
$text-light: #222
$text-dark: #ccc
$background-light: #ededed
$background-dark: #111
$text-light-lanyard: #222
$text-dark-lanyard: #ccc
$background-light-lanyard: #b5b5b5
$background-dark-lanyard: #222
$text-light-buttons: #000000
$text-dark-buttons: #ccc
$background-light-buttons: #b5b5b5
$background-dark-buttons: #191919
$text-light-buttons-hover: #ccc
$text-dark-buttons-hover: #222
$background-light-buttons-hover: #191919
$background-dark-buttons-hover: #b5b5b5
$username-light: black
$username-dark: grey
$username-light-hover: blue
$username-dark-hover: red
$tag-text-dark: grey
$tag-text-light: black
$tag-text-dark-hover: black
$tag-text-light-hover: grey

View file

@ -1,3 +1,5 @@
@import "./_variables"
a
text-decoration: none
color: white
@ -5,11 +7,13 @@ a
// padding: 0
// margin: 0
body
background: #111
color: white
html
font-family: "Flachbau"
background: $background-dark
color: $text-dark
&[data-theme="light"]
background: $background-light
color: $text-light
@font-face
font-family: "Flachbau"

46
utils/shared/posts.ts Normal file
View file

@ -0,0 +1,46 @@
import { remark } from "remark";
import html from "remark-html";
import fs from "fs";
import path from "path";
import matter from "gray-matter";
export async function getPostData(slug) {
const fullPath = path.join("posts", `${slug}.mdx`);
const fileContents = fs.readFileSync(fullPath, "utf8");
// Use gray-matter to parse the post metadata section
const matterResult = matter(fileContents);
// Use remark to convert markdown into HTML string
const processedContent = await remark()
.use(html)
.process(matterResult.content);
const contentHtml = processedContent.toString();
// Combine the data with the id and contentHtml
return {
slug,
content: contentHtml,
...matterResult.data,
};
}
export async function getSortedPosts() {
const allPosts = getAllPostIDs()
let Posts = []
for (const Post of allPosts) {
Posts.push(await getPostData(Post.params.slug))
}
return Posts
}
export function getAllPostIDs() {
const n = fs.readdirSync("posts/");
return n.map((f) => {
return {
params: {
slug: f.replace(/\.mdx$/, ""),
},
};
});
}