Skip to content

Instantly share code, notes, and snippets.

@srsgores
Created May 23, 2025 05:41
Show Gist options
  • Save srsgores/45cf450307eacafaf35ce0ceb39b0e3f to your computer and use it in GitHub Desktop.
Save srsgores/45cf450307eacafaf35ce0ceb39b0e3f to your computer and use it in GitHub Desktop.
Theme Toggle
---
const {class: className, ...attributes} = Astro.props;
import {Icon} from "astro-icon/components";
const FORM_ID = "theme-toggle-form";
const FORM_THEME_NAME = "theme";
const FORM_THEME_TOGGLE_ID = "theme-toggle-checkbox";
---
<form id={FORM_ID} class:list={["inline-block", className]} {...attributes}>
<input type="checkbox" name={FORM_THEME_NAME} id={FORM_THEME_TOGGLE_ID} class="sr-only" />
<label for={FORM_THEME_TOGGLE_ID} class="py-4 px-6 rounded hover:bg-gray-200 dark:hover:bg-neutral-700 focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-indigo-500 cursor-pointer" title="Toggle theme">
<Icon name="heroicons:sun" class="inline-block dark:hidden" />
<Icon name="heroicons:moon" class="hidden dark:inline-block" />
</label>
<output for={FORM_THEME_TOGGLE_ID} class="sr-only"></output>
<footer>
<button type="submit" class="sr-only">Toggle theme</button>
</footer>
</form>
<script define:vars={{FORM_ID, FORM_THEME_NAME}}>
const THEME_DARK = "dark";
const THEME_LIGHT = "light";
const initializeToggle = function(astroPageLoadEvent) {
const $themeToggleForm = astroPageLoadEvent.target.getElementById(FORM_ID);
if ($themeToggleForm) {
const $themeToggle = $themeToggleForm.querySelector(`input[name="${FORM_THEME_NAME}"]`);
const currentTheme = document.documentElement.attributes.getNamedItem("data-theme")?.value;
const $themeStatus = $themeToggleForm.querySelector(`output[for="${FORM_THEME_NAME}"]`);
$themeToggle.checked = currentTheme === THEME_DARK;
$themeStatus.textContent = $themeToggle.checked ? THEME_DARK : THEME_LIGHT;
$themeToggleForm.addEventListener("change", function() {
const updatedTheme = $themeToggle.checked ? THEME_DARK : THEME_LIGHT;
document.dispatchEvent(new CustomEvent("set-theme", {detail: updatedTheme}));
$themeStatus.textContent = updatedTheme;
});
}
}
document.addEventListener("astro:page-load", initializeToggle);
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment