added theme switcher

This commit is contained in:
Abhimanyu Rana
2023-05-11 03:33:35 +05:30
parent 0799d877aa
commit 6ab88d7950
2 changed files with 106 additions and 0 deletions

View File

@@ -12,6 +12,7 @@ const { title } = Astro.props;
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<link rel="icon" type="image/svg+xml" href="/icon.png" />
<script src="./theme.js"></script>
<meta name="generator" content={Astro.generator} />
<title>{title}</title>
</head>
@@ -27,7 +28,12 @@ const { title } = Astro.props;
</script>
<body>
<button class="theme-toggle" id="theme-toggle" title="Toggles light & dark" aria-label="auto" aria-live="polite">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none"><path stroke="var(--icon-secondary)" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="1.5" d="M8.57 17.93A5.98 5.98 0 0 1 6 13c0-3.31 2.69-6 6-6s6 2.69 6 6c0 2.05-1.03 3.86-2.6 4.94M12 4V2M3 13H1m22 0h-2m-1.222-7.778-1.414 1.414m-12.728 0L4.222 5.222M4 18h16M8 21h8"/></svg>
</button>
<slot />
<div class="footer">∠( ᐛ 」∠)_</div>
</body>
</html>
<style is:global>
@@ -45,4 +51,46 @@ const { title } = Astro.props;
main { margin: auto; margin: var(--spacing-10);}
h1.title { margin-bottom: var(--spacing-10); color: var(--text-primary); margin-top: var(--spacing-16); }
section { margin-bottom: var(--spacing-10);}
/* theme toggle */
.theme-toggle {
--size: 2rem;
--icon-fill: var(--icon-secondary);
--icon-fill-hover: var(--icon-secondary);
background: none;
border: none;
padding: 0;
color: var(--icon-secondary);
inline-size: var(--size);
block-size: var(--size);
aspect-ratio: 1;
border-radius: 50%;
cursor: pointer;
touch-action: manipulation;
-webkit-tap-highlight-color: transparent;
position: fixed;
top: var(--spacing-05);
right: var(--spacing-05);
outline-offset: 5px;
@nest [data-theme="dark"] & {
--icon-fill: var(--icon-secondary);
--icon-fill-hover: var(--icon-secondary);
}
}
.footer {
padding: 2rem;
text-align: center;
font-weight: normal;
font-style: normal;
color: var(--text-secondary);
font-size: var(--desktop-body-sm);
line-height: var(--lh-desktop-body-sm);
}
</style>

58
src/layouts/theme.js Normal file
View File

@@ -0,0 +1,58 @@
const storageKey = 'theme-preference'
const onClick = () => {
// flip current value
theme.value = theme.value === 'light'
? 'dark'
: 'light'
setPreference()
}
const getColorPreference = () => {
if (localStorage.getItem(storageKey))
return localStorage.getItem(storageKey)
else
return window.matchMedia('(prefers-color-scheme: dark)').matches
? 'dark'
: 'light'
}
const setPreference = () => {
localStorage.setItem(storageKey, theme.value)
reflectPreference()
}
const reflectPreference = () => {
document.firstElementChild
.setAttribute('data-new-ui-theme', theme.value)
document
.querySelector('#theme-toggle')
?.setAttribute('aria-label', theme.value)
}
const theme = {
value: getColorPreference(),
}
// set early so no page flashes / CSS is made aware
reflectPreference()
window.onload = () => {
// set on load so screen readers can see latest value on the button
reflectPreference()
// now this script can find and listen for clicks on the control
document
.querySelector('#theme-toggle')
.addEventListener('click', onClick)
}
// sync with system changes
window
.matchMedia('(prefers-color-scheme: dark)')
.addEventListener('change', ({matches:isDark}) => {
theme.value = isDark ? 'dark' : 'light'
setPreference()
})