1
mirror of https://github.com/jakejarvis/jarv.is.git synced 2026-04-18 19:18:43 -04:00

fix unnoticeable background color bug in dark mode

This commit is contained in:
2022-02-05 14:50:29 -05:00
parent ca7d21b3d2
commit 42a7ff1bdc
26 changed files with 118 additions and 81 deletions

View File

@@ -1,9 +1,9 @@
import classNames from "classnames"; import classNames from "classnames";
import type { BlockquoteHTMLAttributes } from "react"; import type { HTMLAttributes } from "react";
import styles from "./Blockquote.module.css"; import styles from "./Blockquote.module.css";
type Props = BlockquoteHTMLAttributes<HTMLElement>; type Props = HTMLAttributes<HTMLElement>;
const Blockquote = ({ className, ...rest }: Props) => ( const Blockquote = ({ className, ...rest }: Props) => (
<blockquote className={classNames(styles.blockquote, className)} {...rest} /> <blockquote className={classNames(styles.blockquote, className)} {...rest} />

View File

@@ -7,6 +7,7 @@
background-color: var(--code-background); background-color: var(--code-background);
border: 1px solid var(--kinda-light); border: 1px solid var(--kinda-light);
border-radius: var(--rounded-edge-radius); border-radius: var(--rounded-edge-radius);
/* light-dark theme switch fading */ /* light-dark theme switch fading */
transition: background 0.25s ease, border 0.25s ease; transition: background 0.25s ease, border 0.25s ease;
} }
@@ -32,6 +33,7 @@
border: 1px solid var(--kinda-light); border: 1px solid var(--kinda-light);
border-top-right-radius: var(--rounded-edge-radius); border-top-right-radius: var(--rounded-edge-radius);
border-end-start-radius: var(--rounded-edge-radius); border-end-start-radius: var(--rounded-edge-radius);
/* light-dark theme switch fading */ /* light-dark theme switch fading */
transition: background 0.25s ease, border 0.25s ease; transition: background 0.25s ease, border 0.25s ease;
} }

View File

@@ -1,12 +1,10 @@
import classNames from "classnames"; import classNames from "classnames";
import CopyButton from "../CopyButton/CopyButton"; import CopyButton from "../CopyButton/CopyButton";
import type { PropsWithChildren } from "react"; import type { HTMLAttributes } from "react";
import styles from "./CodeBlock.module.css"; import styles from "./CodeBlock.module.css";
type Props = PropsWithChildren<{ type Props = HTMLAttributes<HTMLElement>;
className?: string;
}>;
const CodeBlock = ({ children, className, ...rest }: Props) => { const CodeBlock = ({ children, className, ...rest }: Props) => {
if (className?.split(" ").includes("code-highlight")) { if (className?.split(" ").includes("code-highlight")) {

View File

@@ -3,20 +3,21 @@ import { useTheme } from "next-themes";
import classNames from "classnames"; import classNames from "classnames";
import { Giscus } from "@giscus/react"; import { Giscus } from "@giscus/react";
import { giscusConfig } from "../../lib/config"; import { giscusConfig } from "../../lib/config";
import type { PropsWithChildren, HTMLAttributes } from "react";
import type { GiscusProps } from "@giscus/react"; import type { GiscusProps } from "@giscus/react";
import styles from "./Comments.module.css"; import styles from "./Comments.module.css";
type Props = { type Props = HTMLAttributes<HTMLDivElement> &
title: string; PropsWithChildren<{
className?: string; title: string;
}; }>;
const Comments = ({ title, className }: Props) => { const Comments = ({ title, className, ...rest }: Props) => {
const { resolvedTheme } = useTheme(); const { resolvedTheme } = useTheme();
return ( return (
<div className={classNames(styles.wrapper, className)}> <div className={classNames(styles.wrapper, className)} {...rest}>
<Giscus <Giscus
{...(giscusConfig as GiscusProps)} {...(giscusConfig as GiscusProps)}
term={title} term={title}

View File

@@ -7,6 +7,7 @@
color: var(--text); color: var(--text);
background-color: var(--super-duper-light); background-color: var(--super-duper-light);
border-color: var(--light); border-color: var(--light);
/* light-dark theme switch fading */ /* light-dark theme switch fading */
transition: background 0.25s ease; transition: background 0.25s ease;
} }

View File

@@ -1,6 +1,7 @@
.content { .content {
font-size: 0.9em; font-size: 0.9em;
line-height: 1.7; line-height: 1.7;
color: var(--text);
} }
@media screen and (max-width: 768px) { @media screen and (max-width: 768px) {

View File

@@ -1,11 +1,9 @@
import classNames from "classnames"; import classNames from "classnames";
import type { PropsWithChildren } from "react"; import type { HTMLAttributes } from "react";
import styles from "./Content.module.css"; import styles from "./Content.module.css";
type Props = PropsWithChildren<{ type Props = HTMLAttributes<HTMLDivElement>;
className?: string;
}>;
const Content = ({ className, ...rest }: Props) => <div className={classNames(styles.content, className)} {...rest} />; const Content = ({ className, ...rest }: Props) => <div className={classNames(styles.content, className)} {...rest} />;

View File

@@ -2,7 +2,9 @@
width: 100%; width: 100%;
padding: 1.25em 1.5em; padding: 1.25em 1.5em;
border-top: 1px solid var(--kinda-light); border-top: 1px solid var(--kinda-light);
background-color: var(--background-outer);
color: var(--medium-dark); color: var(--medium-dark);
/* light-dark theme switch fading */ /* light-dark theme switch fading */
transition: color 0.25s ease, background 0.25s ease, border 0.25s ease; transition: color 0.25s ease, background 0.25s ease, border 0.25s ease;
} }

View File

@@ -3,11 +3,14 @@ import Link from "next/link";
import classNames from "classnames"; import classNames from "classnames";
import { HeartIcon, NextjsLogo } from "../Icons"; import { HeartIcon, NextjsLogo } from "../Icons";
import * as config from "../../lib/config"; import * as config from "../../lib/config";
import type { HTMLAttributes } from "react";
import styles from "./Footer.module.css"; import styles from "./Footer.module.css";
const Footer = () => ( type Props = HTMLAttributes<HTMLDivElement>;
<footer className={styles.footer}>
const Footer = ({ className, ...rest }: Props) => (
<footer className={classNames(styles.footer, className)} {...rest}>
<div className={styles.row}> <div className={styles.row}>
<div className={styles.license}> <div className={styles.license}>
Content{" "} Content{" "}

View File

@@ -8,6 +8,7 @@
background-color: var(--background-header); background-color: var(--background-header);
backdrop-filter: saturate(180%) blur(5px); backdrop-filter: saturate(180%) blur(5px);
z-index: 1000; z-index: 1000;
/* light-dark theme switch fading */ /* light-dark theme switch fading */
transition: color 0.25s ease, background 0.25s ease, border 0.25s ease; transition: color 0.25s ease, background 0.25s ease, border 0.25s ease;
} }

View File

@@ -1,11 +1,15 @@
import { memo } from "react"; import { memo } from "react";
import classNames from "classnames";
import Selfie from "../Selfie/Selfie"; import Selfie from "../Selfie/Selfie";
import Menu from "../Menu/Menu"; import Menu from "../Menu/Menu";
import type { HTMLAttributes } from "react";
import styles from "./Header.module.css"; import styles from "./Header.module.css";
const Header = () => ( type Props = HTMLAttributes<HTMLDivElement>;
<header className={styles.header}>
const Header = ({ className }: Props) => (
<header className={classNames(styles.header, className)}>
<nav className={styles.nav}> <nav className={styles.nav}>
<Selfie className={styles.selfie} /> <Selfie className={styles.selfie} />
<Menu className={styles.menu} /> <Menu className={styles.menu} />

View File

@@ -1,9 +1,10 @@
import classNames from "classnames"; import classNames from "classnames";
import { IframeHTMLAttributes } from "react"; import { HTMLAttributes } from "react";
import styles from "./IFrame.module.css"; import styles from "./IFrame.module.css";
type Props = IframeHTMLAttributes<HTMLElement> & { type Props = HTMLAttributes<HTMLIFrameElement> & {
src: string;
height: number; height: number;
width?: number; // defaults to 100% width?: number; // defaults to 100%
allowScripts?: boolean; allowScripts?: boolean;

View File

@@ -1,10 +1,12 @@
.main { .flex {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.default {
width: 100%; width: 100%;
padding: 1.5em; padding: 1.5em;
color: var(--text);
background-color: var(--background-inner);
/* light-dark theme switch fading */
transition: color 0.25s ease, background 0.25s ease, border 0.25s ease;
} }
.container { .container {
@@ -13,6 +15,11 @@
display: block; display: block;
} }
/* footer needs to fill the remaining vertical screen space. doing it here to keep flex stuff together. */
.footer {
flex: 1;
}
@media screen and (max-width: 768px) { @media screen and (max-width: 768px) {
.main { .main {
padding: 1.25em; padding: 1.25em;

View File

@@ -4,16 +4,16 @@ import classNames from "classnames";
import Header from "../Header/Header"; import Header from "../Header/Header";
import Footer from "../Footer/Footer"; import Footer from "../Footer/Footer";
import { themeColors } from "../../lib/config"; import { themeColors } from "../../lib/config";
import type { PropsWithChildren } from "react"; import type { PropsWithChildren, HTMLAttributes } from "react";
import styles from "./Layout.module.css"; import styles from "./Layout.module.css";
type Props = PropsWithChildren<{ type Props = HTMLAttributes<HTMLDivElement> &
noContainer?: boolean; // pass true to disable default `<main>` container styles with padding, etc. PropsWithChildren<{
className?: string; noContainer?: boolean; // pass true to disable default `<main>` container styles with padding, etc.
}>; }>;
const Layout = ({ noContainer, className, children }: Props) => { const Layout = ({ noContainer, className, children, ...rest }: Props) => {
const { resolvedTheme } = useTheme(); const { resolvedTheme } = useTheme();
return ( return (
@@ -24,17 +24,20 @@ const Layout = ({ noContainer, className, children }: Props) => {
</Head> </Head>
)} )}
<Header /> <div className={classNames(styles.flex, className)} {...rest}>
<Header />
{noContainer ? ( {/* passing `noContainer={true}` to Layout allows 100% control of the content area on a per-page basis */}
<main className={className}>{children}</main> {noContainer ? (
) : ( <>{children}</>
<main className={classNames(styles.main, className)}> ) : (
<div className={styles.container}>{children}</div> <main className={styles.default}>
</main> <div className={styles.container}>{children}</div>
)} </main>
)}
<Footer /> <Footer className={styles.footer} />
</div>
</> </>
); );
}; };

View File

@@ -1,5 +1,5 @@
.meta { .meta {
display: flex; display: inline-flex;
flex-wrap: wrap; flex-wrap: wrap;
font-size: 0.825em; font-size: 0.825em;
line-height: 2.3; line-height: 2.3;

View File

@@ -1,10 +1,11 @@
import Link from "next/link"; import Link from "next/link";
import classNames from "classnames"; import classNames from "classnames";
import type { HTMLAttributes } from "react";
import type { NoteMetaType } from "../../types"; import type { NoteMetaType } from "../../types";
import styles from "./NoteTitle.module.css"; import styles from "./NoteTitle.module.css";
type Props = Pick<NoteMetaType, "slug" | "htmlTitle"> & { className?: string }; type Props = Pick<NoteMetaType, "slug" | "htmlTitle"> & HTMLAttributes<HTMLAnchorElement>;
const NoteTitle = ({ slug, htmlTitle, className, ...rest }: Props) => ( const NoteTitle = ({ slug, htmlTitle, className, ...rest }: Props) => (
<h1 className={classNames(styles.title, className)}> <h1 className={classNames(styles.title, className)}>

View File

@@ -1,11 +1,11 @@
import classNames from "classnames"; import classNames from "classnames";
import { OctocatOcticon } from "../Icons"; import { OctocatOcticon } from "../Icons";
import type { HTMLAttributes } from "react";
import styles from "./OctocatLink.module.css"; import styles from "./OctocatLink.module.css";
type Props = { type Props = HTMLAttributes<HTMLAnchorElement> & {
repo: string; repo: string;
className?: string;
}; };
const OctocatLink = ({ repo, className, ...rest }: Props) => ( const OctocatLink = ({ repo, className, ...rest }: Props) => (

View File

@@ -2,22 +2,20 @@ import { useRouter } from "next/router";
import Link from "next/link"; import Link from "next/link";
import classNames from "classnames"; import classNames from "classnames";
import { baseUrl } from "../../lib/config"; import { baseUrl } from "../../lib/config";
import type { PropsWithChildren } from "react"; import type { HTMLAttributes } from "react";
import styles from "./PageTitle.module.css"; import styles from "./PageTitle.module.css";
type Props = PropsWithChildren<{ type Props = HTMLAttributes<HTMLHeadingElement>;
className?: string;
}>;
const PageTitle = ({ className, ...rest }: Props) => { const PageTitle = ({ className, ...rest }: Props) => {
const router = useRouter(); const router = useRouter();
const canonical = `${baseUrl}${router.pathname}/`; const canonical = `${baseUrl}${router.pathname}/`;
return ( return (
<h1 className={classNames(styles.title, className)}> <h1 className={classNames(styles.title, className)} {...rest}>
<Link href={canonical}> <Link href={canonical}>
<a className={styles.link} {...rest} /> <a className={styles.link} />
</Link> </Link>
</h1> </h1>
); );

View File

@@ -6,6 +6,7 @@
font-size: 0.85em; font-size: 0.85em;
color: var(--medium-dark); color: var(--medium-dark);
border-color: var(--kinda-light); border-color: var(--kinda-light);
/* light-dark theme switch fading */ /* light-dark theme switch fading */
transition: border 0.25s ease; transition: border 0.25s ease;
} }

View File

@@ -2,8 +2,8 @@ import Tweet from "react-tweet-embed";
type Props = { type Props = {
id: string; id: string;
className?: string;
options?: object; options?: object;
className?: string;
}; };
const TweetEmbed = ({ id, className, options }: Props) => ( const TweetEmbed = ({ id, className, options }: Props) => (

View File

@@ -1,9 +1,10 @@
import classNames from "classnames"; import classNames from "classnames";
import ReactPlayer from "react-player/file"; import ReactPlayer from "react-player/file";
import type { FilePlayerProps } from "react-player/file";
import styles from "./Video.module.css"; import styles from "./Video.module.css";
type Props = { type Props = Partial<FilePlayerProps> & {
webm?: string; webm?: string;
mp4?: string; mp4?: string;
thumbnail?: string; thumbnail?: string;

View File

@@ -1,8 +1,4 @@
.wallpaper { .wallpaper {
display: flex;
justify-content: center;
align-items: center;
padding: 1.5em 0;
width: 100%; width: 100%;
min-height: 400px; min-height: 400px;
} }

View File

@@ -1,15 +1,15 @@
import { useEffect, useRef } from "react"; import { useEffect, useRef } from "react";
import classNames from "classnames/bind"; import classNames from "classnames/bind";
import type { PropsWithChildren } from "react"; import type { PropsWithChildren, HTMLAttributes } from "react";
import styles from "./Wallpaper.module.css"; import styles from "./Wallpaper.module.css";
const cx = classNames.bind(styles); const cx = classNames.bind(styles);
type Props = PropsWithChildren<{ type Props = HTMLAttributes<HTMLDivElement> &
image: string; PropsWithChildren<{
tile?: boolean; image: string;
className?: string; tile?: boolean;
}>; }>;
const Wallpaper = ({ image, tile, className, ...rest }: Props) => { const Wallpaper = ({ image, tile, className, ...rest }: Props) => {
const bgRef = useRef<HTMLDivElement>(null); const bgRef = useRef<HTMLDivElement>(null);
@@ -18,7 +18,7 @@ const Wallpaper = ({ image, tile, className, ...rest }: Props) => {
bgRef.current.style.backgroundImage = `url(${image})`; bgRef.current.style.backgroundImage = `url(${image})`;
}, []); // eslint-disable-line react-hooks/exhaustive-deps }, []); // eslint-disable-line react-hooks/exhaustive-deps
return <div ref={bgRef} className={cx(styles.wallpaper, { tile: !!tile }, className)} {...rest} />; return <main ref={bgRef} className={cx(styles.wallpaper, { tile: !!tile }, className)} {...rest} />;
}; };
export default Wallpaper; export default Wallpaper;

View File

@@ -1,9 +1,10 @@
import classNames from "classnames"; import classNames from "classnames";
import ReactPlayer from "react-player/youtube"; import ReactPlayer from "react-player/youtube";
import type { YouTubePlayerProps } from "react-player/youtube";
import styles from "./YouTubeEmbed.module.css"; import styles from "./YouTubeEmbed.module.css";
type Props = { type Props = Partial<YouTubePlayerProps> & {
id: string; id: string;
className?: string; className?: string;
}; };

View File

@@ -36,22 +36,39 @@ const Y2K = () => {
}} }}
/> />
{/* set a random retro wallpaper tile for the content area */} <VNC server="wss://y2k.jrvs.io" />
<Wallpaper image={`/static/images/y2k/tiles/tile_${Math.floor(20 * Math.random())}.png`} tile>
<VNC server="wss://y2k.jrvs.io" />
</Wallpaper>
<style jsx global>{`
/* make the viewport a bit larger by un-sticking the nav bar */
header {
position: relative !important;
}
`}</style>
</> </>
); );
}; };
// disable layout's default styles so the wallpaper component can go edge-to-edge // disable layout's default styles so the wallpaper component can go edge-to-edge:
Y2K.getLayout = (page: ReactElement) => <Layout noContainer>{page}</Layout>; Y2K.getLayout = (page: ReactElement) => {
// set a random retro Windows ME desktop tile for the entire content area
const randomTile = `/static/images/y2k/tiles/tile_${Math.floor(20 * Math.random())}.png`;
return (
<Layout noContainer>
<Wallpaper
image={randomTile}
tile
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
padding: "1.5em 0",
}}
>
{page}
</Wallpaper>
{/* also make the viewport a bit larger by un-sticking the nav bar */}
<style jsx global>{`
header {
position: relative !important;
}
`}</style>
</Layout>
);
};
export default Y2K; export default Y2K;

View File

@@ -2,8 +2,8 @@ body {
width: 100%; width: 100%;
height: 100%; height: 100%;
margin: 0 auto; margin: 0 auto;
color: var(--text); background-color: var(--background-inner);
background-color: var(--background-outer);
/* light-dark theme switch fading */ /* light-dark theme switch fading */
transition: background 0.25s ease; transition: background 0.25s ease;
} }