mirror of
https://github.com/ChenQihan666/MyBlog-Next.git
synced 2026-08-14 19:41:02 +08:00
refactor: update toggle theme function for better structure and a11y
Move theme switch js codes in Layout.astro file to external js file (toggle-theme.js). Update .prettierignore to exclude the new toggle-theme.js file. Update base.css for new data-theme attribute.
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
# Except these files & folders
|
# Except these files & folders
|
||||||
!/src
|
!/src
|
||||||
|
!/public
|
||||||
!/.github
|
!/.github
|
||||||
!tsconfig.json
|
!tsconfig.json
|
||||||
!astro.config.mjs
|
!astro.config.mjs
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
const primaryColorScheme = ""; // "light" | "dark"
|
||||||
|
|
||||||
|
// Get theme data from local storage
|
||||||
|
const currentTheme = localStorage.getItem("theme");
|
||||||
|
|
||||||
|
function getPreferTheme() {
|
||||||
|
// return theme value in local storage if it is set
|
||||||
|
if (currentTheme) return currentTheme;
|
||||||
|
|
||||||
|
// return primary color scheme if it is set
|
||||||
|
if (primaryColorScheme) return primaryColorScheme;
|
||||||
|
|
||||||
|
// return user device's prefer color scheme
|
||||||
|
return window.matchMedia("(prefers-color-scheme: dark)").matches
|
||||||
|
? "dark"
|
||||||
|
: "light";
|
||||||
|
}
|
||||||
|
|
||||||
|
let themeValue = getPreferTheme();
|
||||||
|
|
||||||
|
function setPreference() {
|
||||||
|
localStorage.setItem("theme", themeValue);
|
||||||
|
reflectPreference();
|
||||||
|
}
|
||||||
|
|
||||||
|
function reflectPreference() {
|
||||||
|
document.firstElementChild.setAttribute("data-theme", themeValue);
|
||||||
|
|
||||||
|
document.querySelector("#theme-btn")?.setAttribute("aria-label", themeValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set early so no page flashes / CSS is made aware
|
||||||
|
reflectPreference();
|
||||||
|
|
||||||
|
window.onload = () => {
|
||||||
|
// set on load so screen readers can get the latest value on the button
|
||||||
|
reflectPreference();
|
||||||
|
|
||||||
|
// now this script can find and listen for clicks on the control
|
||||||
|
document.querySelector("#theme-btn").addEventListener("click", () => {
|
||||||
|
themeValue = themeValue === "light" ? "dark" : "light";
|
||||||
|
setPreference();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// sync with system changes
|
||||||
|
window
|
||||||
|
.matchMedia("(prefers-color-scheme: dark)")
|
||||||
|
.addEventListener("change", ({ matches: isDark }) => {
|
||||||
|
themeValue = isDark ? "dark" : "light";
|
||||||
|
setPreference();
|
||||||
|
});
|
||||||
@@ -61,45 +61,7 @@ const socialImageURL = new URL(
|
|||||||
onload="this.onload=null;this.rel='stylesheet'"
|
onload="this.onload=null;this.rel='stylesheet'"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<script is:inline>
|
<script is:inline src="/toggle-theme.js"></script>
|
||||||
const primaryColorScheme = "none"; // "light" | "dark" | "none"
|
|
||||||
|
|
||||||
const darkModeMediaQuery = window.matchMedia(
|
|
||||||
"(prefers-color-scheme: dark)"
|
|
||||||
).matches;
|
|
||||||
|
|
||||||
// Get theme data from local storage
|
|
||||||
const currentTheme = localStorage.getItem("theme");
|
|
||||||
|
|
||||||
let theme;
|
|
||||||
|
|
||||||
// Set theme to 'theme-dark' if currentTheme is 'dark'
|
|
||||||
if (currentTheme) {
|
|
||||||
theme = currentTheme === "dark" ? "theme-dark" : "";
|
|
||||||
} else {
|
|
||||||
// If primary color scheme is dark
|
|
||||||
// or primary color scheme is not set and prefers-color-scheme is dark
|
|
||||||
// choose dark mode
|
|
||||||
if (
|
|
||||||
primaryColorScheme === "dark" ||
|
|
||||||
(primaryColorScheme === "none" && darkModeMediaQuery)
|
|
||||||
) {
|
|
||||||
theme = "theme-dark";
|
|
||||||
}
|
|
||||||
// If primary color scheme is light
|
|
||||||
// choose light mode
|
|
||||||
else if (primaryColorScheme === "light") {
|
|
||||||
theme = "";
|
|
||||||
}
|
|
||||||
// fallback to prefers-color-scheme
|
|
||||||
else {
|
|
||||||
theme = darkModeMediaQuery ? "theme-dark" : "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Put dark class on html tag to enable dark mode
|
|
||||||
document.querySelector("html").className = theme;
|
|
||||||
</script>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<slot />
|
<slot />
|
||||||
|
|||||||
+7
-5
@@ -3,7 +3,8 @@
|
|||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
:root {
|
:root,
|
||||||
|
html[data-theme="light"] {
|
||||||
--color-fill: 251, 254, 251;
|
--color-fill: 251, 254, 251;
|
||||||
--color-text-base: 40, 39, 40;
|
--color-text-base: 40, 39, 40;
|
||||||
--color-accent: 0, 108, 172;
|
--color-accent: 0, 108, 172;
|
||||||
@@ -11,7 +12,7 @@
|
|||||||
--color-card-muted: 205, 205, 205;
|
--color-card-muted: 205, 205, 205;
|
||||||
--color-border: 236, 233, 233;
|
--color-border: 236, 233, 233;
|
||||||
}
|
}
|
||||||
.theme-dark {
|
html[data-theme="dark"] {
|
||||||
--color-fill: 47, 55, 65;
|
--color-fill: 47, 55, 65;
|
||||||
--color-text-base: 230, 230, 230;
|
--color-text-base: 230, 230, 230;
|
||||||
--color-accent: 26, 217, 217;
|
--color-accent: 26, 217, 217;
|
||||||
@@ -20,11 +21,11 @@
|
|||||||
--color-border: 59, 70, 85;
|
--color-border: 59, 70, 85;
|
||||||
}
|
}
|
||||||
#sun-svg,
|
#sun-svg,
|
||||||
.theme-dark #moon-svg {
|
html[data-theme="dark"] #moon-svg {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
#moon-svg,
|
#moon-svg,
|
||||||
.theme-dark #sun-svg {
|
html[data-theme="dark"] #sun-svg {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
body {
|
body {
|
||||||
@@ -36,7 +37,8 @@
|
|||||||
@apply max-w-3xl mx-auto px-4;
|
@apply max-w-3xl mx-auto px-4;
|
||||||
}
|
}
|
||||||
a {
|
a {
|
||||||
@apply outline-offset-1 outline-skin-fill outline-2 focus-visible:outline-dashed focus-visible:no-underline;
|
@apply outline-offset-1 outline-skin-fill outline-2
|
||||||
|
focus-visible:outline-dashed focus-visible:no-underline;
|
||||||
}
|
}
|
||||||
svg {
|
svg {
|
||||||
@apply w-6 h-6 inline-block fill-skin-base group-hover:fill-skin-accent;
|
@apply w-6 h-6 inline-block fill-skin-base group-hover:fill-skin-accent;
|
||||||
|
|||||||
Reference in New Issue
Block a user