WIP system theme integration

This commit is contained in:
Daniel Flanagan 2023-05-23 11:59:29 -05:00
parent 0074b5cc4a
commit 91701b25f5
Signed by: lytedev
GPG key ID: 5B2020A0F9921EF4
7 changed files with 193 additions and 130 deletions

View file

@ -7,11 +7,12 @@
<title>{{ block "title" . }}{{ .Site.Title }}{{ end }}</title> <title>{{ block "title" . }}{{ .Site.Title }}{{ end }}</title>
<link rel="shortcut icon" href="/icon.png" /> <link rel="shortcut icon" href="/icon.png" />
<link defer rel="stylesheet" href="/styles.css" /> <link defer rel="stylesheet" href="/styles.css" />
<script defer src="/global.js"></script> <link rel="preload" href="/font/iosevkalytewebmin/iosevkalyteweb-regular.subset.woff2" as="font" type="font/woff2" crossorigin>
<link rel="modulepreload" href="/theme.mjs" as="font" type="font/woff2" crossorigin>
<script defer type="module" src="/global.mjs"></script>
<script async defer data-domain="lyte.dev" src="https://a.lyte.dev/js/plausible.js"></script> <script async defer data-domain="lyte.dev" src="https://a.lyte.dev/js/plausible.js"></script>
<script defer src="//instant.page/5.1.0" type="module" integrity="sha384-by67kQnR+pyfy8yWP4kPO12fHKRLHZPfEsiSXR8u2IKcTdxD805MGUXBzVPnkLHw"></script>
</head> </head>
<body> <body class="system-theme">
<header> <header>
<a href="#start-of-content" class="hide-unless-focused">Skip to Content</a> <a href="#start-of-content" class="hide-unless-focused">Skip to Content</a>
<section> <section>
@ -33,10 +34,10 @@
{{ end }} {{ end }}
</section> </section>
<section style="position:absolute;height:100%;right:0"> <section style="position:absolute;height:100%;right:0">
<button class="no-bg theme-toggler js-only centerize" aria-label="toggle theme"> <button id="theme-toggler" class="no-bg theme-toggler js-only centerize" title="toggle theme" aria-label="toggle theme">
{{ partial "theme-toggle.html" . }} {{ partial "theme-toggle.html" . }}
</button> </button>
<button class="no-bg align-toggler js-only hidden-on-mobile centerize" aria-label="toggle alignment"> <button id="align-toggler" class="no-bg align-toggler js-only hidden-on-mobile centerize" title="toggle alignment" aria-label="toggle alignment">
{{ partial "align-toggle.html" . }} {{ partial "align-toggle.html" . }}
</button> </button>
</section> </section>
@ -95,5 +96,6 @@
</li> </li>
</ul> </ul>
</footer> </footer>
<script src="//instant.page/5.2.0" type="module" integrity="sha384-jnZyxPjiipYXnSU0ygqeac2q7CVYMbh84q0uHVRRxEtvFPiQYbXWUorga2aqZJ0z"></script>
</body> </body>
</html> </html>

View file

@ -1,6 +1,6 @@
<svg class="hide-in-align-left" width="24" height="24" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <svg class="hide-in-align-center" width="24" height="24" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25H12" /> <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25H12" />
</svg> </svg>
<svg class="hide-in-align-center" width="24" height="24" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <svg class="hide-in-align-left" width="24" height="24" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" /> <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
</svg> </svg>

Before

Width:  |  Height:  |  Size: 556 B

After

Width:  |  Height:  |  Size: 556 B

View file

@ -1,6 +1,9 @@
<svg class="hide-in-light-theme" height="24" width="24" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <svg class="only-in-light-theme" height="24" width="24" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 3v2.25m6.364.386l-1.591 1.591M21 12h-2.25m-.386 6.364l-1.591-1.591M12 18.75V21m-4.773-4.227l-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0z" /> <path stroke-linecap="round" stroke-linejoin="round" d="M12 3v2.25m6.364.386l-1.591 1.591M21 12h-2.25m-.386 6.364l-1.591-1.591M12 18.75V21m-4.773-4.227l-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0z" />
</svg> </svg>
<svg class="hide-in-dark-theme" height="24" width="24" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <svg class="only-in-dark-theme" height="24" width="24" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M21.752 15.002A9.718 9.718 0 0118 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 003 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 009.002-5.998z" /> <path stroke-linecap="round" stroke-linejoin="round" d="M21.752 15.002A9.718 9.718 0 0118 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 003 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 009.002-5.998z" />
</svg> </svg>
<svg class="only-in-system-theme" height="24" width="24" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182m0-4.991v4.99" />
</svg>

Before

Width:  |  Height:  |  Size: 838 B

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -1,9 +1,10 @@
/* catppuccin colors */ /* catppuccin colors */
latte = { latte = {
red: #d20f39, red: #d20f39,
yellow: #df8e1d, yellow: #df8e1d,
green: #40a02b, green: #40a02b,
sapphire: #209fb5, sapphire: #1e66f5, // blue
mauve: #8839ef, mauve: #8839ef,
} }
@ -15,36 +16,62 @@ mocha = {
mauve: #cba6f7, mauve: #cba6f7,
} }
light-syntax = { /* TODO: everything should be a catppuccin color or based on one */
brd: rgba(255, 255, 255, 0.2),
bg: #e6e9ef, light-theme = {
ledg: rgba(0, 0, 0, 0.1), --syntax-brd: rgba(255, 255, 255, 0.2),
sh: #6c6f85, --syntax-bg: #e6e9ef,
name: latte['green'], --syntax-ledg: rgba(0, 0, 0, 0.1),
mag: latte['red'], --syntax-sh: #6c6f85,
lit: latte['mauve'], --syntax-name: latte['green'],
lits: latte['yellow'], --syntax-mag: latte['red'],
aq: latte['sapphire'], --syntax-lit: latte['mauve'],
err: latte['red'], --syntax-lits: latte['yellow'],
--syntax-aq: latte['sapphire'],
--syntax-err: latte['red'],
--icon-shadow: #fff,
--heading-fg: #4c4f69,
--link-fg: latte['sapphire'],
--link-visited-fg: alpha(latte['mauve'], 1.0),
--bg: #eff1f5,
--header-bg: rgba(255, 255, 255, 0.1),
--header-hover-bg: rgba(255, 255, 255, 0.2),
--fg: #4c4f69,
--inline-code-bg: rgba(0,0,0,0.08),
--input-bg: #dce0e8,
--input-hover-bg: rgba(0, 0, 0, 0.16),
--input-focus-bg: var(--input-bg),
--button-bg: var(--input-bg),
--button-hover-bg: var(--input-hover-bg),
--button-focus-bg: var(--input-bg),
} }
dark-syntax = { dark-theme = {
brd: rgba(255, 255, 255, 0.2), --syntax-brd: rgba(255, 255, 255, 0.2),
bg: #181825, --syntax-bg: #181825,
ledg: #313244, --syntax-ledg: #313244,
sh: #6c7086, --syntax-sh: #6c7086,
name: mocha['green'], --icon-shadow: #000,
mag: mocha['red'], --syntax-name: mocha['green'],
lit: mocha['mauve'], --syntax-mag: mocha['red'],
lits: mocha['yellow'], --syntax-lit: mocha['mauve'],
aq: mocha['sapphire'], --syntax-lits: mocha['yellow'],
err: mocha['red'], --syntax-aq: mocha['sapphire'],
} --syntax-err: mocha['red'],
--bg: #1e1e2e,
theme-colors = { --header-bg: rgba(255, 255, 255, 0.03),
icon-shadow: #fff, --header-hover-bg: rgba(255, 255, 255, 0.06),
link-visited-fg: #5c5f77, --fg: #cdd6f4,
link-fg: #209fb5, --heading-fg: #cdd6f4,
--link-fg: mocha['sapphire'],
--link-visited-fg: alpha(mocha['mauve'], 1.0),
--inline-code-bg: rgba(255,255,255,0.05),
--input-bg: #181825,
--input-hover-bg: #313244,
--input-focus-bg: #45475a,
--button-bg: var(--input-bg),
--button-hover-bg: var(--input-hover-bg),
--button-focus-bg: var(--input-bg),
} }
:root :root
@ -54,53 +81,15 @@ theme-colors = {
--pc #df3c59 --pc #df3c59
--pcd #8e293b --pcd #8e293b
light-theme = :root, body.dark-theme
for k, v in light-syntax {dark-theme}
--syntax-{k}: v
for k2, v2 in theme-colors
{unquote("--" + k2)}: v2
--heading-fg #4c4f69
--bg #eff1f5
--header-bg rgba(255, 255, 255, 0.1)
--header-hover-bg rgba(255, 255, 255, 0.2)
--fg #4c4f69
--inline-code-bg rgba(0,0,0,0.08)
--input-bg #dce0e8
--input-hover-bg rgba(0, 0, 0, 0.16)
--input-focus-bg var(--input-bg)
--button-bg var(--input-bg)
--button-hover-bg var(--input-hover-bg)
--button-focus-bg var(--input-bg)
dark-theme = body.light-theme
for k, v in dark-syntax
--syntax-{k}: v
for k2, v2 in theme-colors
{unquote("--" + k2)}: invert(v2)
--bg #1e1e2e
--header-bg rgba(255, 255, 255, 0.03)
--header-hover-bg rgba(255, 255, 255, 0.06)
--fg #cdd6f4
--heading-fg #cdd6f4
--link-visited-fg #a6adc8
--link-fg #74c7ec
--inline-code-bg rgba(255,255,255,0.05)
--input-bg #181825
--input-hover-bg #313244
--input-focus-bg #45475a
--button-bg var(--input-bg)
--button-hover-bg var(--input-hover-bg)
--button-focus-bg var(--input-bg)
:root, body.light-theme
{light-theme} {light-theme}
body.dark-theme
{dark-theme}
:root :root
@media (prefers-color-scheme dark) @media (prefers-color-scheme light)
{dark-theme} {light-theme}
:root :root
@media (max-width: 600px) @media (max-width: 600px)
@ -110,13 +99,20 @@ body.dark-theme
display none display none
@media (prefers-color-scheme dark) @media (prefers-color-scheme dark)
.hide-in-dark-theme .hide-in-dark-theme { display: inherit }
display none .hide-in-light-theme { display: none }
.hide-in-light-theme { display: inherit } body.light-theme .hide-in-dark-theme { display: none }
body.light-theme .hide-in-dark-theme { display: inherit } body.dark-theme .hide-in-light-theme { display: inherit }
body.dark-theme .hide-in-light-theme { display: none }
body.dark-theme .hide-in-dark-theme { display: none } body.dark-theme .hide-in-dark-theme { display: inherit }
body.dark-theme .hide-in-light-theme { display: inherit } body.dark-theme .hide-in-light-theme { display: none }
body.light-theme .hide-in-dark-theme { display: inherit } body.light-theme .hide-in-dark-theme { display: none }
body.light-theme .hide-in-light-theme { display: none } body.light-theme .hide-in-light-theme { display: inherit }
body .only-in-light-theme { display: none }
body .only-in-dark-theme { display: none }
body .only-in-system-theme { display: none }
body.dark-theme .only-in-dark-theme { display: inherit }
body.light-theme .only-in-light-theme { display: inherit }
body.system-theme .only-in-system-theme { display: inherit }

24
static/align.mjs Normal file
View file

@ -0,0 +1,24 @@
const initAlign = () => {
const cur = localStorage.getItem("align");
const prev = cur == "center" ? "left" : "center";
document.body.classList.add("align-" + cur);
document.body.classList.remove("align-" + prev);
};
if (localStorage.getItem("align") === null) {
localStorage.setItem("align", "center");
}
initAlign();
const toggleAlign = (ev) => {
localStorage.setItem(
"align",
localStorage.getItem("align") == "center" ? "left" : "center",
);
initAlign();
if (!!ev.target) ev.preventDefault();
return false;
};

View file

@ -1,45 +1,20 @@
const body = document.body; import { Theme } from "./theme.mjs";
const queryAll = (sel) => document.querySelectorAll(sel);
const initTheme = () => { document.querySelectorAll(".js-only").forEach((a) =>
const curTheme = localStorage.getItem("theme"); a.classList.remove("js-only")
const oldTheme = curTheme == "dark" ? "light" : "dark"; );
body.classList.add(`${curTheme}-theme`); document.querySelectorAll(".js-disabled-only").forEach((a) => a.remove());
body.classList.remove(`${oldTheme}-theme`);
}; const theme = new Theme();
document.querySelectorAll(".theme-toggler").forEach((a) =>
if (localStorage.getItem("theme") === null) { a.addEventListener("click", () => theme.cycle())
localStorage.setItem(
"theme",
window.matchMedia("(prefers-color-scheme: dark)").matches
? "dark"
: "light",
);
}
initTheme();
const toggleTheme = (ev) => {
localStorage.setItem(
"theme",
localStorage.getItem("theme") == "dark" ? "light" : "dark",
);
initTheme();
if (!!ev.target) ev.preventDefault();
return false;
};
queryAll(".theme-toggler").forEach((a) =>
a.addEventListener("click", toggleTheme)
); );
queryAll(".js-only").forEach((a) => a.classList.remove("js-only"));
queryAll(".js-disabled-only").forEach((a) => a.remove());
const initAlign = () => { const initAlign = () => {
const cur = localStorage.getItem("align"); const cur = localStorage.getItem("align");
const prev = cur == "center" ? "left" : "center"; const prev = cur == "center" ? "left" : "center";
body.classList.add("align-" + cur); document.body.classList.add("align-" + cur);
body.classList.remove("align-" + prev); document.body.classList.remove("align-" + prev);
}; };
if (localStorage.getItem("align") === null) { if (localStorage.getItem("align") === null) {
@ -58,13 +33,13 @@ const toggleAlign = (ev) => {
return false; return false;
}; };
queryAll(".align-toggler").forEach((a) => document.querySelectorAll(".align-toggler").forEach((a) =>
a.addEventListener("click", toggleAlign) a.addEventListener("click", toggleAlign)
); );
window.addEventListener("load", (_ev) => { window.addEventListener("load", (_ev) => {
const selector = [1, 2, 3, 4, 5, 6].map((n) => `h${n}[id]`).join(","); const selector = [1, 2, 3, 4, 5, 6].map((n) => `h${n}[id]`).join(",");
queryAll(selector).forEach((el) => { document.querySelectorAll(selector).forEach((el) => {
const anchorLink = document.createElement("a"); const anchorLink = document.createElement("a");
anchorLink.classList.add("anchor-link"); anchorLink.classList.add("anchor-link");
anchorLink.textContent = "§"; anchorLink.textContent = "§";

63
static/theme.mjs Normal file
View file

@ -0,0 +1,63 @@
const DARK = "dark"
const LIGHT = "light"
const SYSTEM = "system"
const DEFAULT_THEME = SYSTEM
const parseTheme = (themeName) => {
const s = (typeof (themeName) === 'string') ? themeName.toLowerCase().trim() : themeName
if (s == "light" || s == LIGHT) return LIGHT
else if (s == "dark" || s == DARK) return DARK
else return SYSTEM
}
const oppositeOf = (theme) => {
if (theme == LIGHT) return DARK
else if (theme == DARK) return LIGHT
else return null
}
export class Theme {
#theme = DEFAULT_THEME
#defaultPreference = LIGHT
constructor(initialThemeName = undefined) {
if (!initialThemeName) initialThemeName = localStorage.getItem("theme")
this.#defaultPreference = window.matchMedia("(prefers-color-scheme: light)").matches ? LIGHT : DARK
this.theme = parseTheme(initialThemeName)
}
cycle() {
this.theme = this.getNext()
}
getNext() {
if (this.theme == SYSTEM) {
return oppositeOf(this.#defaultPreference)
} else {
if (this.theme == this.#defaultPreference) {
return SYSTEM
} else {
return oppositeOf(this.#theme)
}
}
}
toggle() {
// unused on this page
}
set theme(themeName) {
localStorage.setItem("theme", themeName)
this.#theme = parseTheme(themeName)
document.body.classList.remove(`light-theme`)
document.body.classList.remove(`dark-theme`)
document.body.classList.remove(`system-theme`)
console.log(this, this.getNext())
document.body.classList.add(`${this.#theme}-theme`)
}
get theme() {
return this.#theme
}
}