aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/ThemeToggle.astro
diff options
context:
space:
mode:
authoraman333nolawz <amananudhiu@gmail.com>2026-03-02 21:49:13 +0530
committeraman333nolawz <amananudhiu@gmail.com>2026-03-02 21:49:13 +0530
commitd41eff9eccf66644c4c60f53cb516bf079937a28 (patch)
tree248a0863a3181369f943d678ec4273911d35efac /src/components/ThemeToggle.astro
Using astro-erudite for static site generation
Diffstat (limited to 'src/components/ThemeToggle.astro')
-rw-r--r--src/components/ThemeToggle.astro72
1 files changed, 72 insertions, 0 deletions
diff --git a/src/components/ThemeToggle.astro b/src/components/ThemeToggle.astro
new file mode 100644
index 0000000..f7b0926
--- /dev/null
+++ b/src/components/ThemeToggle.astro
@@ -0,0 +1,72 @@
+---
+import { Button } from '@/components/ui/button'
+import { Icon } from 'astro-icon/components'
+---
+
+<Button
+ id="theme-toggle"
+ variant="ghost"
+ size="icon"
+ title="Toggle theme"
+ className="-my-2 -me-2 size-8"
+>
+ <Icon name="lucide:sun" class="size-4 dark:hidden" />
+ <Icon name="lucide:moon" class="absolute hidden size-4 dark:block" />
+ <span class="sr-only">Toggle theme</span>
+</Button>
+
+<script is:inline data-astro-rerun>
+ ;(() => {
+ const theme = (() => {
+ const stored = localStorage?.getItem('theme') ?? ''
+ if (['dark', 'light'].includes(stored)) return stored
+ return window.matchMedia('(prefers-color-scheme: dark)').matches
+ ? 'dark'
+ : 'light'
+ })()
+
+ document.documentElement.setAttribute('data-theme', theme)
+ window.localStorage.setItem('theme', theme)
+ })()
+</script>
+
+<script>
+ function handleToggleClick() {
+ const element = document.documentElement
+ const currentTheme = element.getAttribute('data-theme')
+ const newTheme = currentTheme === 'dark' ? 'light' : 'dark'
+
+ element.classList.add('[&_*]:transition-none')
+ element.setAttribute('data-theme', newTheme)
+ window.getComputedStyle(element).getPropertyValue('opacity')
+
+ requestAnimationFrame(() => {
+ element.classList.remove('[&_*]:transition-none')
+ })
+
+ localStorage.setItem('theme', newTheme)
+ }
+
+ function initThemeToggle() {
+ document
+ .getElementById('theme-toggle')
+ ?.addEventListener('click', handleToggleClick)
+ }
+
+ initThemeToggle()
+
+ document.addEventListener('astro:after-swap', () => {
+ const storedTheme = localStorage.getItem('theme') || 'light'
+ const element = document.documentElement
+
+ element.classList.add('[&_*]:transition-none')
+ window.getComputedStyle(element).getPropertyValue('opacity')
+ element.setAttribute('data-theme', storedTheme)
+
+ requestAnimationFrame(() => {
+ element.classList.remove('[&_*]:transition-none')
+ })
+
+ initThemeToggle()
+ })
+</script>