feat: theme switch web component

This commit is contained in:
Cory Dransfeldt 2024-02-27 13:47:04 -08:00
parent d4dda8061e
commit d2f00d4ca0
No known key found for this signature in database
6 changed files with 82 additions and 79 deletions

View file

@ -1,6 +1,6 @@
{
"name": "coryd.dev",
"version": "6.5.14",
"version": "6.6.0",
"description": "The source for my personal site. Built using 11ty and hosted on Netlify.",
"type": "module",
"scripts": {

View file

@ -13,9 +13,7 @@
<meta property="og:url" content="{{ fullUrl }}" />
<meta
property="og:image"
content="{%- if schema == 'blog' %}{{ meta.url }}/assets/img/social-preview/{{
title | slugify
}}-preview.jpeg{%- else -%}{{ meta.meta_data.opengraph_default }}{% endif -%}"
content="{%- if schema == 'blog' %}{{ meta.url }}/assets/img/social-preview/{{ title | slugify }}-preview.jpeg{%- else -%}{{ meta.meta_data.opengraph_default }}{% endif -%}"
/>
<meta property="og:image" content="{{ image | getPostImage }}">
<meta name="theme-color" content="{{ meta.themeColor }}" />
@ -82,28 +80,10 @@
</script>
{% endif %}
<script defer data-domain="coryd.dev" src="/js/script.js"></script>
<script>
window.plausible = window.plausible || function() { (window.plausible.q = window.plausible.q || []).push(arguments) }
</script>
<script>window.plausible = window.plausible || function() {(window.plausible.q = window.plausible.q || []).push(arguments)}</script>
<noscript>
<style>
.client-side {
display: none
}
</style>
<style>.client-side {display:none}</style>
</noscript>
</head>
<body>
{% capture theme %}
{% render "../assets/scripts/theme.js" %}
{% endcapture %}
<script>{{ theme }}</script>
{{ content }}
{% capture js %}
{% render "../assets/scripts/theme-handler.js" %}
{% endcapture %}
<script>
{{ js }}
</script>
</body>
<body>{{ content }}</body>
</html>

View file

@ -1,11 +1,17 @@
<li class="theme__toggle client-side">
<span class="placeholder">
{% tablericon "placeholder" "Toggle theme placeholder" %}
</span>
<span class="light">
{% tablericon "sun" "Toggle light theme" %}
</span>
<span class="dark">
{% tablericon "moon" "Toggle dark theme" %}
</span>
<script type="module" src="/assets/scripts/components/theme-toggle.js"></script>
<template id="theme-toggle-template">
<div class="theme__toggle">
<span class="placeholder">
{% tablericon "placeholder" "Toggle theme placeholder" %}
</span>
<span class="light">
{% tablericon "sun" "Toggle light theme" %}
</span>
<span class="dark">
{% tablericon "moon" "Toggle dark theme" %}
</span>
</div>
</template>
<li class="client-side">
<theme-toggle></theme-toggle>
</li>

View file

@ -0,0 +1,61 @@
const themeToggleTemplate = document.createElement('template')
themeToggleTemplate.innerHTML = `
<button class="theme__toggle">
<span class="placeholder"></span>
<span class="light"></span>
<span class="dark"></span>
</button>
`
themeToggleTemplate.id = "theme-toggle-template"
if (!document.getElementById(themeToggleTemplate.id)) document.body.appendChild(themeToggleTemplate)
class ThemeToggle extends HTMLElement {
static register(tagName) {
if ("customElements" in window) customElements.define(tagName || "theme-toggle", ThemeToggle)
}
async connectedCallback() {
this.append(this.template)
const btn = this.querySelector('.theme__toggle')
const setTheme = (isOnLoad) => {
const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)').matches
const currentTheme = localStorage?.getItem('theme')
let theme
if (!currentTheme) localStorage?.setItem('theme', (prefersDarkScheme ? 'dark' : 'light'))
if (isOnLoad) {
if (currentTheme === 'dark') {
document.body.classList.add('theme__dark')
} else if (currentTheme === 'light') {
document.body.classList.add('theme__light')
} else if (prefersDarkScheme) {
document.body.classList.add('theme__dark')
} else if (!prefersDarkScheme) {
document.body.classList.add('theme__light')
}
}
if (prefersDarkScheme) {
theme = document.body.classList.contains('theme__light') ? 'light' : 'dark'
} else {
theme = document.body.classList.contains('theme__dark') ? 'dark' : 'light'
}
localStorage?.setItem('theme', theme)
}
setTheme(true);
btn.addEventListener('click', () => {
document.body.classList.toggle('theme__light')
document.body.classList.toggle('theme__dark')
setTheme()
})
}
get template() {
return document.getElementById(themeToggleTemplate.id).content.cloneNode(true)
}
}
ThemeToggle.register()

View file

@ -1,20 +0,0 @@
;(async function() {
const btn = document.querySelector('.theme__toggle');
btn.addEventListener('click', () => {
document.body.classList.toggle('theme__light');
document.body.classList.toggle('theme__dark');
const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)').matches;
const currentTheme = localStorage?.getItem('theme');
let theme;
if (!currentTheme) localStorage?.setItem('theme', (prefersDarkScheme ? 'dark' : 'light'))
if (prefersDarkScheme) {
theme = document.body.classList.contains('theme__light') ? 'light' : 'dark';
} else {
theme = document.body.classList.contains('theme__dark') ? 'dark' : 'light';
}
localStorage?.setItem('theme', theme);
});
})()

View file

@ -1,24 +0,0 @@
;(function() {
const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)').matches;
const currentTheme = localStorage?.getItem('theme');
let theme;
if (!currentTheme) localStorage?.setItem('theme', (prefersDarkScheme ? 'dark' : 'light'))
if (currentTheme === 'dark') {
document.body.classList.add('theme__dark');
} else if (currentTheme === 'light') {
document.body.classList.add('theme__light');
} else if (prefersDarkScheme) {
document.body.classList.add('theme__dark');
} else if (!prefersDarkScheme) {
document.body.classList.add('theme__light');
}
if (prefersDarkScheme) {
theme = document.body.classList.contains('theme__light') ? 'light' : 'dark';
} else {
theme = document.body.classList.contains('theme__dark') ? 'dark' : 'light';
}
localStorage?.setItem('theme', theme);
})()