Add new blog components and post

This commit is contained in:
Kevin Kandlbinder 2022-02-05 17:16:03 +00:00 committed by GitHub
parent b35ad08052
commit a352600428
16 changed files with 440 additions and 5 deletions

View file

@ -1,6 +1,6 @@
@use "sass:map";
$layoutWidth: 1200px;
$layoutWidth: 1100px;
$layoutPadding: 20px;
$mainFont: "Fira Code", monospace;

View file

@ -0,0 +1,58 @@
import React, { useEffect, useRef, useState } from "react";
import anime, { AnimeTimelineInstance } from "animejs";
import _uniqueId from 'lodash/uniqueId';
import {useMediaQuery} from '@react-hook/media-query'
import * as styles from "./Chatbox.module.scss";
const Chatblah = () => {
const animeRef = useRef<AnimeTimelineInstance>(null)
const [myId,] = useState(_uniqueId)
const reduceMotion = useMediaQuery("(prefers-reduced-motion: reduce)")
useEffect(() => {
if(typeof window === "undefined") return; // Don't run on static build
if(reduceMotion) return; // Don't run the animation for users who prefer reduced motion
const speed = 0.25;
const delay = anime.random(100/speed, 1000/speed);
animeRef.current = anime.timeline({
targets: "#chatblah-"+myId,
loop: true,
easing: "easeInOutSine"
})
const tl = animeRef.current
tl.add({
duration: 250/speed,
opacity: [0, .25],
easing: "linear"
}, delay).add({
duration: 1000/speed,
rotate: [anime.random(-5, 5)+"deg", anime.random(-10, 10)+"deg"],
translateY: [0, anime.random(0, -2)+"px"],
translateX: [0, anime.random(-2, 2)+"px"],
}, delay).add({
duration: 500/speed,
opacity: [.25, 0],
easing: "linear"
}, delay+(500/speed))
return () => {
if(animeRef.current) {
animeRef.current.pause();
animeRef.current = null;
}
}
}, [myId, reduceMotion])
return <div className={styles.chatBlah} id={"chatblah-"+myId}>
<span>blah</span>
</div>
}
export default Chatblah

View file

@ -0,0 +1,138 @@
@use "sass:math";
@use "sass:map";
@import "../../globals";
.screenReader {
opacity: 0.001;
width: 1px;
height: 1px;
margin: -1px;
position: absolute;
overflow: hidden;
white-space: nowrap;
padding: 0;
}
.chatbox {
display: flex;
flex-direction: column;
padding: $layoutPadding;
margin: $layoutPadding (-$layoutPadding);
background-color: rgba(gray, 0.1);
border-radius: 10px;
&.openBottom {
border-radius: 10px 10px 0 0;
margin-bottom: 20px;
background-image: linear-gradient(
to top,
$background,
transparent 20px
);
}
&.openBoth {
border-radius: 0;
margin-top: 20px;
margin-bottom: 20px;
background-image: linear-gradient(to top, $background, transparent 20px),
linear-gradient(to bottom, $background, transparent 20px);
}
&.openTop {
border-radius: 0 0 10px 10px;
margin-top: 20px;
background-image: linear-gradient(
to bottom,
$background,
transparent 20px
);
}
@media (prefers-color-scheme: light) {
&.openBottom {
background-image: linear-gradient(
to top,
$lightBackground,
transparent 20px
);
}
&.openBoth {
background-image: linear-gradient(
to top,
$lightBackground,
transparent 20px
),
linear-gradient(to bottom, $lightBackground, transparent 20px);
}
&.openTop {
background-image: linear-gradient(
to bottom,
$lightBackground,
transparent 20px
);
}
}
}
.chatnotice {
display: flex;
justify-content: center;
margin: math.div($layoutPadding, 2) $layoutPadding;
> span {
max-width: 500px;
opacity: 0.75;
font-style: italic;
text-align: center;
}
}
.chatmsg {
display: flex;
flex-direction: column;
margin: 0 $layoutPadding;
align-items: flex-start;
--msg-color: #{map.get($theme, "blue")};
&.alignRight {
align-items: flex-end;
--msg-color: #{$accentColor};
}
.name {
margin: 5px;
}
.chatbubble {
position: relative;
padding: math.div($layoutPadding, 2) $layoutPadding;
border-radius: 10px;
border: thin solid var(--msg-color);
max-width: 700px;
hr {
display: block;
margin: math.div($layoutPadding, 2) (-$layoutPadding);
border: none;
border-top: thin solid var(--msg-color);
}
}
}
.chatBlah {
display: inline-block;
margin: 0 5px;
opacity: 0.25;
&:first-child {
margin-left: 0;
}
}

View file

@ -0,0 +1,11 @@
export const alignRight: string;
export const chatBlah: string;
export const chatbox: string;
export const chatbubble: string;
export const chatmsg: string;
export const chatnotice: string;
export const name: string;
export const openBoth: string;
export const openBottom: string;
export const openTop: string;
export const screenReader: string;

View file

@ -0,0 +1,20 @@
import React from "react";
import { useTranslation } from "react-i18next";
import * as styles from "./Chatbox.module.scss";
type ChatboxProps = {
open?: string
}
const Chatbox = ({children, open}: React.PropsWithChildren<ChatboxProps>) => {
const {t} = useTranslation();
return <div className={styles.chatbox + (open === "top" ? " " + styles.openTop : "") + (open === "bottom" ? " " + styles.openBottom : "") + (open === "both" ? " " + styles.openBoth : "")}>
<span className={styles.screenReader}>-- {open === "top" || open === "both" ? t("blog.scambox.chatbox.resume") : t("blog.scambox.chatbox.begin")} --</span>
{children}
<span className={styles.screenReader}>-- {open === "bottom" || open === "both" ? t("blog.scambox.chatbox.interrupt") : t("blog.scambox.chatbox.end")} --</span>
</div>
}
export default Chatbox

View file

@ -0,0 +1,27 @@
import React from "react";
import { useTranslation } from "react-i18next";
import * as styles from "./Chatbox.module.scss"
type ChatmsgProps = {
name?: string,
timestamp?: string,
color?: string,
dir: string
}
const Chatmsg = (props: React.PropsWithChildren<ChatmsgProps>) => {
const {t} = useTranslation();
return <div className={styles.chatmsg + (props.dir === "out" ? " " + styles.alignRight : "")}>
{props.name && <span className={styles.name}>{props.name}<span className={styles.screenReader}> {t("blog.scambox.chatbox.says")}</span></span>}
<div className={styles.chatbubble}>
<div>
{props.children}
</div>
{props.timestamp && <span>{props.timestamp}</span>}
</div>
</div>
}
export default Chatmsg

View file

@ -0,0 +1,11 @@
import React from "react";
import * as styles from "./Chatbox.module.scss"
const Chatnotice = (props: React.PropsWithChildren<{}>) => {
return <div className={styles.chatnotice}>
<span>{props.children}</span>
</div>
}
export default Chatnotice

View file

@ -4,6 +4,11 @@
* {
box-sizing: border-box;
@media (prefers-reduced-motion: reduce) {
animation: none !important;
transition: none !important;
}
}
body,

View file

@ -20,6 +20,7 @@ import {
Phone,
} from "lucide-react";
import { useTranslation } from "react-i18next";
import { useMediaQuery } from "@react-hook/media-query";
//import * as particleConfig from "./index.particles.json";
export const query = graphql`
@ -62,9 +63,11 @@ export const query = graphql`
const IndexPage = (props) => {
const { t } = useTranslation();
const reduceMotion = useMediaQuery("(prefers-reduced-motion: reduce)")
React.useEffect(() => {
if (typeof window === "undefined") return;
if (reduceMotion) return;
anime({
targets: [
@ -95,7 +98,7 @@ const IndexPage = (props) => {
/*if (typeof window !== "undefined")
// eslint-disable-next-line no-undef
window.setTimeout(loadTsParticles, 1000);*/
}, []);
}, [reduceMotion]);
let meta = props.data.site.siteMetadata;

View file

@ -2,6 +2,8 @@
.postSection {
flex-grow: 1;
max-width: 1000px;
margin: 0 auto;
> article {
img {

View file

@ -22,7 +22,7 @@ const BlogPost = ({ data }) => {
<script type="application/ld+json">
{JSON.stringify({
"@context": "https://schema.org",
"@type": "NewsArticle",
"@type": "BlogPosting",
headline: data.mdx.frontmatter.title,
datePublished: data.mdx.frontmatter.publishedIso,
dateModified: data.mdx.frontmatter.publishedIso,
@ -30,6 +30,7 @@ const BlogPost = ({ data }) => {
{
"@type": "Person",
name: data.mdx.frontmatter.author.name,
url: "https://kevink.dev/blog/"
},
],
})}