Dark mode

This commit is contained in:
Maxi Ferreira 2021-12-01 09:17:42 -08:00
parent 3c0917a765
commit 0498fc62fc
12 changed files with 145 additions and 14 deletions

1
TODO
View File

@ -8,3 +8,4 @@
[x] Reading time [x] Reading time
[x] Bio component [x] Bio component
[x] Add social image [x] Add social image
[ ] Add hero image to one of the posts

View File

@ -1,2 +1,2 @@
User-agent: * User-agent: *
Disallow: / Allow: /

View File

@ -41,3 +41,14 @@ const socialUrl = Astro.site.href + 'assets/social.png'
<!-- Styles --> <!-- Styles -->
<link rel="stylesheet" href={Astro.resolve('../styles/global.css')} /> <link rel="stylesheet" href={Astro.resolve('../styles/global.css')} />
<link rel="stylesheet" href={Astro.resolve('../styles/highlight.css')} /> <link rel="stylesheet" href={Astro.resolve('../styles/highlight.css')} />
<!-- This is intentionally inlined to avoid FOUC -->
<script>
const root = document.documentElement;
const theme = localStorage.getItem('theme');
if (theme === 'dark' || (!theme) && window.matchMedia('(prefers-color-scheme: dark)').matches) {
root.classList.add('theme-dark');
} else {
root.classList.remove('theme-dark');
}
</script>

View File

@ -1,14 +1,14 @@
<footer> <footer>
<span> <span>
&copy; {new Date().getFullYear()} Your Blog. &copy; {new Date().getFullYear()} Your Blog.
Powered by <a href="https://astro.build" target="_blank">Astro</a>. Powered by <a href="https://astro.build" target="_blank" rel="noopener">Astro</a>.
Template by <a href="https://www.twitter.com/Charca" target="_blank">Maxi Ferreira</a>. Template by <a href="https://www.twitter.com/Charca" target="_blank" rel="noopener">Maxi Ferreira</a>.
</span> </span>
</footer> </footer>
<style> <style>
footer { footer {
color: #AAA; color: var(--text-secondary);
font-size: 1em; font-size: 1em;
font-family: var(--font-family-sans); font-family: var(--font-family-sans);
margin: 1em auto; margin: 1em auto;

View File

@ -1,7 +1,7 @@
<style> <style>
img { img {
display: block; display: block;
height: 50px; width: 75px;
} }
</style> </style>

View File

@ -1,4 +1,5 @@
--- ---
import ThemeToggleButton from './ThemeToggleButton.svelte';
const { current = '' } = Astro.props; const { current = '' } = Astro.props;
--- ---
@ -34,7 +35,7 @@ const { current = '' } = Astro.props;
bottom: 0; bottom: 0;
width: 100%; width: 100%;
height: 2px; height: 2px;
background: #AAA; background: var(--text-secondary);
transform: scaleX(0); transform: scaleX(0);
} }
@ -52,4 +53,5 @@ const { current = '' } = Astro.props;
<a class={current === "" ? "selected" : ""} href='/'>home</a> <a class={current === "" ? "selected" : ""} href='/'>home</a>
<a class={current === "about" ? "selected" : ""} href='/about'>about</a> <a class={current === "about" ? "selected" : ""} href='/about'>about</a>
<a class={current === "blog" ? "selected" : ""} href='/blog'>blog</a> <a class={current === "blog" ? "selected" : ""} href='/blog'>blog</a>
<ThemeToggleButton client:load />
</nav> </nav>

View File

@ -0,0 +1,65 @@
<script>
const rootEl = typeof document !== 'undefined' ? document.documentElement : null;
const themes = ['light', 'dark'];
let theme = ''
if (typeof localStorage !== 'undefined' && localStorage.getItem('theme')) {
theme = localStorage.getItem('theme');
} else if (typeof window !== 'undefined' && window.matchMedia('(prefers-color-scheme: dark)').matches) {
theme = 'dark';
}
function handleChange(event) {
theme = event.target.value;
localStorage.setItem('theme', theme);
}
$: if (rootEl && theme === 'light') {
rootEl.classList.remove('theme-dark');
} else if (rootEl && theme === 'dark') {
rootEl.classList.add('theme-dark');
}
const icons = [
`<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fill-rule="evenodd"
d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"
clip-rule="evenodd"
/>
</svg>`,
`<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
viewBox="0 0 20 20"
fill="currentColor"
>
<path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" />
</svg>`,
];
</script>
<div class="theme-toggle">
{#each themes as t, i}
<label class={theme === t ? 'checked' : ''}>
{@html icons[i]}
<input
type="radio"
name="theme-toggle"
checked={theme === t}
value={t}
title={`Use ${t} theme`}
aria-label={`Use ${t} theme`}
on:change={handleChange}
/>
</label>
{/each}
</div>

View File

@ -12,7 +12,10 @@ const permalink = `${Astro.site.href}about`;
<figure> <figure>
<img src="/assets/about-illustration.webp" alt="Illustration of a notebook"> <img src="/assets/about-illustration.webp" alt="Illustration of a notebook">
<figcaption> <figcaption>
Illustration by <a href="https://icons8.com/illustrations/author/5c07e68d82bcbc0092519bb6">Icons 8</a> from <a href="https://icons8.com/illustrations">Ouch!</a> Illustration by
<a href="https://icons8.com/illustrations/author/5c07e68d82bcbc0092519bb6" target="_blank" rel="noopener">Icons 8</a>
from
<a href="https://icons8.com/illustrations" target="_blank" rel="noopener">Ouch!</a>
</figcaption> </figcaption>
</figure> </figure>
<p>Text placeholder via <a href="https://jeffsum.com/" target="_blank">Jeffsum</a>.</p> <p>Text placeholder via <a href="https://jeffsum.com/" target="_blank">Jeffsum</a>.</p>

View File

@ -41,7 +41,7 @@ const permalink = `${Astro.site.href}${slug}`;
} }
header p { header p {
color: #AAA; color: var(--text-secondary);
text-transform: uppercase; text-transform: uppercase;
font-family: var(--font-family-sans); font-family: var(--font-family-sans);
font-weight: 600; font-weight: 600;

View File

@ -40,7 +40,7 @@ allPosts = allPosts.sort((a, b) => new Date(b.publishDate).valueOf() - new Date(
} }
.post-item-date { .post-item-date {
color: #AAA; color: var(--text-secondary);
text-align: left; text-align: left;
text-transform: uppercase; text-transform: uppercase;
margin-right: 16px; margin-right: 16px;

View File

@ -10,13 +10,16 @@ const permalink = Astro.site.href;
<div class="home-container"> <div class="home-container">
<div class="home-copy"> <div class="home-copy">
<h1>Welcome to your new Astro Blog</h1> <h1>Welcome to your new Astro Blog</h1>
<p>Check out the docs on <a href="https://www.github.com/Charca/astro-blog-template" target="_blank">GitHub</a> to get started.</p> <p>Check out the docs on <a href="https://www.github.com/Charca/astro-blog-template" target="_blank" rel="noopener">GitHub</a> to get started.</p>
</div> </div>
<figure> <figure>
<img alt='Illustration of person reading a book' src='/assets/home-illustration.webp'> <img alt='Illustration of person reading a book' src='/assets/home-illustration.webp'>
<figcaption> <figcaption>
Illustration by <a href="https://icons8.com/illustrations/author/5c07e68d82bcbc0092519bb6">Icons 8</a> from <a href="https://icons8.com/illustrations">Ouch!</a> Illustration by
<a href="https://icons8.com/illustrations/author/5c07e68d82bcbc0092519bb6" target="_blank" rel="noopener">Icons 8</a>
from
<a href="https://icons8.com/illustrations" target="_blank" rel="noopener">Ouch!</a>
</figcaption> </figcaption>
</figure> </figure>
</div> </div>
@ -54,11 +57,13 @@ const permalink = Astro.site.href;
figcaption { figcaption {
font-size: .8em; font-size: .8em;
font-style: italic; font-style: italic;
text-align: left;
} }
img { img {
width: 100%; width: 100%;
max-width: 550px; max-width: 550px;
margin-bottom: 1em;
} }
@media (max-width: 1200px) { @media (max-width: 1200px) {

View File

@ -1,16 +1,18 @@
:root { :root {
--background-body: #fff; --background-body: #fff;
--text-main: #36393b; --text-main: #36393b;
--text-secondary: #6b6f72;
--primary-color: #548E9B; --primary-color: #548E9B;
--font-family-serif: Merriweather, serif; --font-family-serif: Merriweather, serif;
--font-family-sans: 'Fira Sans', sans-serif; --font-family-sans: 'Fira Sans', sans-serif;
} }
/* :root { :root.theme-dark {
--background-body: #36393b; --background-body: #202122;
--text-main: #fff; --text-main: #fff;
--text-secondary: #ccc;
--primary-color: #548E9B; --primary-color: #548E9B;
} */ }
*, *:before, *:after { *, *:before, *:after {
box-sizing: border-box; box-sizing: border-box;
@ -189,6 +191,48 @@ td {
margin: 1em 0; margin: 1em 0;
} }
.theme-toggle {
display: inline-flex;
align-items: center;
height: 100%;
padding: 0.33em 0.67em;
padding-top: 8px;
margin-left: 10px;
gap: 0.6em;
border-radius: 99em;
background-color: var(--theme-code-inline-bg);
}
.theme-toggle > label:focus-within {
outline: 2px solid transparent;
box-shadow: 0 0 0 0.08em var(--theme-accent), 0 0 0 0.12em white;
}
.theme-toggle > label {
color: var(--theme-code-inline-text);
position: relative;
display: flex;
align-items: center;
justify-content: center;
opacity: 0.5;
cursor: pointer;
}
.theme-toggle .checked {
color: var(--theme-accent);
opacity: 1;
}
input[name='theme-toggle'] {
position: absolute;
opacity: 0;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: -1;
}
@media (max-width: 1020px) { @media (max-width: 1020px) {
h1 { h1 {
font-size: 3em; font-size: 3em;