-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy paththeme_controller.js
More file actions
76 lines (63 loc) · 2.13 KB
/
theme_controller.js
File metadata and controls
76 lines (63 loc) · 2.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import { Controller } from "@hotwired/stimulus"
// Theme controller for dark mode with light/dark/system options
// Persists user preference in localStorage and respects system preferences
export default class extends Controller {
static targets = ["lightIcon", "darkIcon", "systemIcon"]
static values = { theme: { type: String, default: "system" } }
connect() {
// Load saved theme or default to system
this.themeValue = localStorage.getItem("theme") || "system"
this.applyTheme()
// Listen for system preference changes
this.mediaQuery = window.matchMedia("(prefers-color-scheme: dark)")
this.handleSystemChange = this.handleSystemChange.bind(this)
this.mediaQuery.addEventListener("change", this.handleSystemChange)
}
disconnect() {
this.mediaQuery.removeEventListener("change", this.handleSystemChange)
}
handleSystemChange(event) {
if (this.themeValue === "system") {
this.applyTheme()
}
}
setLight() {
this.themeValue = "light"
this.saveAndApply()
}
setDark() {
this.themeValue = "dark"
this.saveAndApply()
}
setSystem() {
this.themeValue = "system"
this.saveAndApply()
}
toggle() {
const themes = ["light", "dark", "system"]
const currentIndex = themes.indexOf(this.themeValue)
this.themeValue = themes[(currentIndex + 1) % themes.length]
this.saveAndApply()
}
saveAndApply() {
localStorage.setItem("theme", this.themeValue)
this.applyTheme()
}
applyTheme() {
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches
const isDark = this.themeValue === "dark" || (this.themeValue === "system" && prefersDark)
document.documentElement.classList.toggle("dark", isDark)
this.updateIcons()
}
updateIcons() {
if (this.hasLightIconTarget) {
this.lightIconTarget.classList.toggle("hidden", this.themeValue !== "light")
}
if (this.hasDarkIconTarget) {
this.darkIconTarget.classList.toggle("hidden", this.themeValue !== "dark")
}
if (this.hasSystemIconTarget) {
this.systemIconTarget.classList.toggle("hidden", this.themeValue !== "system")
}
}
}