darkmode scripts
This commit is contained in:
parent
782a29f2f8
commit
22332f4205
@ -1,6 +1,6 @@
|
|||||||
import { QuartzConfig } from "./quartz/cfg"
|
import { QuartzConfig } from "./quartz/cfg"
|
||||||
import * as Head from "./quartz/components/Head"
|
import Head from "./quartz/components/Head"
|
||||||
import * as Header from "./quartz/components/Header"
|
import Header from "./quartz/components/Header"
|
||||||
import {
|
import {
|
||||||
ContentPage,
|
ContentPage,
|
||||||
CreatedModifiedDate,
|
CreatedModifiedDate,
|
||||||
|
@ -74,6 +74,7 @@ yargs(hideBin(process.argv))
|
|||||||
const transpiled = await esbuild.build({
|
const transpiled = await esbuild.build({
|
||||||
stdin: {
|
stdin: {
|
||||||
contents: text,
|
contents: text,
|
||||||
|
loader: 'ts',
|
||||||
sourcefile: path.relative(path.resolve('.'), args.path),
|
sourcefile: path.relative(path.resolve('.'), args.path),
|
||||||
},
|
},
|
||||||
write: false,
|
write: false,
|
||||||
|
@ -59,7 +59,7 @@ export default async function buildQuartz(argv: Argv, version: string) {
|
|||||||
const server = http.createServer(async (req, res) => {
|
const server = http.createServer(async (req, res) => {
|
||||||
return serveHandler(req, res, {
|
return serveHandler(req, res, {
|
||||||
public: output,
|
public: output,
|
||||||
directoryListing: false
|
directoryListing: false,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
server.listen(argv.port)
|
server.listen(argv.port)
|
||||||
|
47
quartz/components/Darkmode.tsx
Normal file
47
quartz/components/Darkmode.tsx
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import darkmodeScript from "./scripts/darkmode.inline"
|
||||||
|
import styles from '../styles/darkmode.scss'
|
||||||
|
|
||||||
|
export default function Darkmode() {
|
||||||
|
return <div class="darkmode">
|
||||||
|
<input class="toggle" id="darkmode-toggle" type="checkbox" tabIndex={-1} />
|
||||||
|
<label id="toggle-label-light" for="darkmode-toggle" tabIndex={-1}>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||||
|
version="1.1"
|
||||||
|
id="dayIcon"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
viewBox="0 0 35 35"
|
||||||
|
style="enable-background:new 0 0 35 35;"
|
||||||
|
xmlSpace="preserve"
|
||||||
|
>
|
||||||
|
<title>Light mode</title>
|
||||||
|
<path
|
||||||
|
d="M6,17.5C6,16.672,5.328,16,4.5,16h-3C0.672,16,0,16.672,0,17.5 S0.672,19,1.5,19h3C5.328,19,6,18.328,6,17.5z M7.5,26c-0.414,0-0.789,0.168-1.061,0.439l-2,2C4.168,28.711,4,29.086,4,29.5 C4,30.328,4.671,31,5.5,31c0.414,0,0.789-0.168,1.06-0.44l2-2C8.832,28.289,9,27.914,9,27.5C9,26.672,8.329,26,7.5,26z M17.5,6 C18.329,6,19,5.328,19,4.5v-3C19,0.672,18.329,0,17.5,0S16,0.672,16,1.5v3C16,5.328,16.671,6,17.5,6z M27.5,9 c0.414,0,0.789-0.168,1.06-0.439l2-2C30.832,6.289,31,5.914,31,5.5C31,4.672,30.329,4,29.5,4c-0.414,0-0.789,0.168-1.061,0.44 l-2,2C26.168,6.711,26,7.086,26,7.5C26,8.328,26.671,9,27.5,9z M6.439,8.561C6.711,8.832,7.086,9,7.5,9C8.328,9,9,8.328,9,7.5 c0-0.414-0.168-0.789-0.439-1.061l-2-2C6.289,4.168,5.914,4,5.5,4C4.672,4,4,4.672,4,5.5c0,0.414,0.168,0.789,0.439,1.06 L6.439,8.561z M33.5,16h-3c-0.828,0-1.5,0.672-1.5,1.5s0.672,1.5,1.5,1.5h3c0.828,0,1.5-0.672,1.5-1.5S34.328,16,33.5,16z M28.561,26.439C28.289,26.168,27.914,26,27.5,26c-0.828,0-1.5,0.672-1.5,1.5c0,0.414,0.168,0.789,0.439,1.06l2,2 C28.711,30.832,29.086,31,29.5,31c0.828,0,1.5-0.672,1.5-1.5c0-0.414-0.168-0.789-0.439-1.061L28.561,26.439z M17.5,29 c-0.829,0-1.5,0.672-1.5,1.5v3c0,0.828,0.671,1.5,1.5,1.5s1.5-0.672,1.5-1.5v-3C19,29.672,18.329,29,17.5,29z M17.5,7 C11.71,7,7,11.71,7,17.5S11.71,28,17.5,28S28,23.29,28,17.5S23.29,7,17.5,7z M17.5,25c-4.136,0-7.5-3.364-7.5-7.5 c0-4.136,3.364-7.5,7.5-7.5c4.136,0,7.5,3.364,7.5,7.5C25,21.636,21.636,25,17.5,25z"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
</label>
|
||||||
|
<label id="toggle-label-dark" for="darkmode-toggle" tabIndex={-1}>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||||
|
version="1.1"
|
||||||
|
id="nightIcon"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
viewBox="0 0 100 100"
|
||||||
|
style="enable-background='new 0 0 100 100'"
|
||||||
|
xmlSpace="preserve"
|
||||||
|
>
|
||||||
|
<title>Dark mode</title>
|
||||||
|
<path
|
||||||
|
d="M96.76,66.458c-0.853-0.852-2.15-1.064-3.23-0.534c-6.063,2.991-12.858,4.571-19.655,4.571 C62.022,70.495,50.88,65.88,42.5,57.5C29.043,44.043,25.658,23.536,34.076,6.47c0.532-1.08,0.318-2.379-0.534-3.23 c-0.851-0.852-2.15-1.064-3.23-0.534c-4.918,2.427-9.375,5.619-13.246,9.491c-9.447,9.447-14.65,22.008-14.65,35.369 c0,13.36,5.203,25.921,14.65,35.368s22.008,14.65,35.368,14.65c13.361,0,25.921-5.203,35.369-14.65 c3.872-3.871,7.064-8.328,9.491-13.246C97.826,68.608,97.611,67.309,96.76,66.458z"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
Darkmode.beforeDOMLoaded = darkmodeScript
|
||||||
|
Darkmode.css = styles
|
@ -8,7 +8,7 @@ export interface HeadProps {
|
|||||||
externalResources: StaticResources
|
externalResources: StaticResources
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Component({ title, description, slug, externalResources }: HeadProps) {
|
export default function Head({ title, description, slug, externalResources }: HeadProps) {
|
||||||
const { css, js } = externalResources
|
const { css, js } = externalResources
|
||||||
const baseDir = resolveToRoot(slug)
|
const baseDir = resolveToRoot(slug)
|
||||||
const iconPath = baseDir + "/static/icon.png"
|
const iconPath = baseDir + "/static/icon.png"
|
||||||
|
@ -1,14 +1,20 @@
|
|||||||
import { resolveToRoot } from "../path"
|
import { resolveToRoot } from "../path"
|
||||||
|
import Darkmode from "./Darkmode"
|
||||||
|
import style from '../styles/header.scss'
|
||||||
|
|
||||||
export interface HeaderProps {
|
export interface HeaderProps {
|
||||||
title: string
|
title: string
|
||||||
slug: string
|
slug: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Component({ title, slug }: HeaderProps) {
|
export default function Header({ title, slug }: HeaderProps) {
|
||||||
const baseDir = resolveToRoot(slug)
|
const baseDir = resolveToRoot(slug)
|
||||||
return <header>
|
return <header>
|
||||||
<h1><a href={baseDir}>{title}</a></h1>
|
<h1><a href={baseDir}>{title}</a></h1>
|
||||||
|
<div class="spacer"></div>
|
||||||
|
<Darkmode />
|
||||||
</header>
|
</header>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Header.beforeDOMLoaded = Darkmode.beforeDOMLoaded
|
||||||
|
Header.css = style + Darkmode.css
|
||||||
|
@ -1,3 +1,25 @@
|
|||||||
export default "Darkmode"
|
export default "Darkmode"
|
||||||
|
|
||||||
console.log("HELLOOOO FROM CONSOLE")
|
const currentTheme = localStorage.getItem("theme")
|
||||||
|
const theme =
|
||||||
|
currentTheme ??
|
||||||
|
(window.matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark")
|
||||||
|
|
||||||
|
document.documentElement.setAttribute("saved-theme", theme)
|
||||||
|
|
||||||
|
window.addEventListener("DOMContentLoaded", () => {
|
||||||
|
const toggleSwitch = document.querySelector("#darkmode-toggle") as HTMLInputElement
|
||||||
|
toggleSwitch.addEventListener("change", (e: any) => {
|
||||||
|
if (e.target.checked) {
|
||||||
|
document.documentElement.setAttribute("saved-theme", "dark")
|
||||||
|
localStorage.setItem("theme", "dark")
|
||||||
|
} else {
|
||||||
|
document.documentElement.setAttribute("saved-theme", "light")
|
||||||
|
localStorage.setItem("theme", "light")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (theme === "dark") {
|
||||||
|
toggleSwitch.checked = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { ComponentType } from "preact"
|
import { ComponentType } from "preact"
|
||||||
|
|
||||||
export type QuartzComponent<Props> = {
|
export type QuartzComponent<Props> = ComponentType<Props> & {
|
||||||
Component: ComponentType<Props>
|
|
||||||
css?: string,
|
css?: string,
|
||||||
beforeDOMLoaded?: string,
|
beforeDOMLoaded?: string,
|
||||||
afterDOMLoaded?: string,
|
afterDOMLoaded?: string,
|
||||||
|
@ -48,14 +48,14 @@ export class ContentPage extends QuartzEmitterPlugin {
|
|||||||
|
|
||||||
const title = file.data.frontmatter?.title
|
const title = file.data.frontmatter?.title
|
||||||
const doc = <html>
|
const doc = <html>
|
||||||
<Head.Component
|
<Head
|
||||||
title={title ?? "Untitled"}
|
title={title ?? "Untitled"}
|
||||||
description={file.data.description ?? "No description provided"}
|
description={file.data.description ?? "No description provided"}
|
||||||
slug={file.data.slug!}
|
slug={file.data.slug!}
|
||||||
externalResources={pageResources} />
|
externalResources={pageResources} />
|
||||||
<body>
|
<body>
|
||||||
<div id="quartz-root" class="page">
|
<div id="quartz-root" class="page">
|
||||||
<Header.Component title={cfg.siteTitle} slug={file.data.slug!} />
|
<Header title={cfg.siteTitle} slug={file.data.slug!} />
|
||||||
<article>
|
<article>
|
||||||
{file.data.slug !== "index" && <h1>{title}</h1>}
|
{file.data.slug !== "index" && <h1>{title}</h1>}
|
||||||
{content}
|
{content}
|
||||||
|
@ -24,7 +24,7 @@ body {
|
|||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
p, ul, text, a, tr, td, li, ol, ul {
|
p, ul, text, a, tr, td, li, ol, ul, .katex {
|
||||||
color: var(--darkgray);
|
color: var(--darkgray);
|
||||||
fill: var(--darkgray);
|
fill: var(--darkgray);
|
||||||
}
|
}
|
||||||
@ -67,7 +67,7 @@ a {
|
|||||||
}
|
}
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
margin-left: 0;
|
margin: 1rem 0;
|
||||||
border-left: 3px solid var(--secondary);
|
border-left: 3px solid var(--secondary);
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
transition: border-color 0.2s ease;
|
transition: border-color 0.2s ease;
|
||||||
@ -134,7 +134,7 @@ pre {
|
|||||||
& > code {
|
& > code {
|
||||||
background: none;
|
background: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
font-size: 0.9rem;
|
font-size: 0.85rem;
|
||||||
counter-reset: line;
|
counter-reset: line;
|
||||||
counter-increment: line 0;
|
counter-increment: line 0;
|
||||||
display: grid;
|
display: grid;
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
background-color: var(--bg);
|
background-color: var(--bg);
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
padding: 0 0.7rem;
|
padding: 0 1rem;
|
||||||
|
|
||||||
&[data-callout="note"] {
|
&[data-callout="note"] {
|
||||||
--color: #448aff;
|
--color: #448aff;
|
||||||
|
45
quartz/styles/darkmode.scss
Normal file
45
quartz/styles/darkmode.scss
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
.darkmode {
|
||||||
|
float: right;
|
||||||
|
padding: 1rem;
|
||||||
|
min-width: 30px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
@media all and (max-width: 450px) {
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > .toggle {
|
||||||
|
display: none;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
& svg {
|
||||||
|
cursor: pointer;
|
||||||
|
opacity: 0;
|
||||||
|
position: absolute;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
top: calc(50% - 10px);
|
||||||
|
margin: 0 7px;
|
||||||
|
fill: var(--darkgray);
|
||||||
|
transition: opacity 0.1s ease;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[saved-theme="dark"] .toggle ~ label {
|
||||||
|
& > #dayIcon {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
& > #nightIcon {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:root .toggle ~ label {
|
||||||
|
& > #dayIcon {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
& > #nightIcon {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
10
quartz/styles/header.scss
Normal file
10
quartz/styles/header.scss
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
margin: 1em 0 2em 0;
|
||||||
|
& > h1 {
|
||||||
|
margin: 0;
|
||||||
|
flex: auto;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user