blob: 7e428fad5d20c73129a95973c9e904b0636f16f0 [file] [log] [blame]
bankseanae3724e2025-07-18 16:52:37 +00001import { html } from "lit";
2import { customElement, state } from "lit/decorators.js";
3import { SketchTailwindElement } from "./sketch-tailwind-element.js";
4import { ThemeService, ThemeMode } from "./theme-service.js";
5
6@customElement("sketch-theme-toggle")
7export class SketchThemeToggle extends SketchTailwindElement {
8 @state() private currentTheme: ThemeMode = "system";
9 @state() private effectiveTheme: "light" | "dark" = "light";
10
11 private themeService = ThemeService.getInstance();
12
13 connectedCallback() {
14 super.connectedCallback();
15 this.updateThemeState();
16
17 // Listen for theme changes from other sources
18 document.addEventListener("theme-changed", this.handleThemeChange);
19 }
20
21 disconnectedCallback() {
22 super.disconnectedCallback();
23 document.removeEventListener("theme-changed", this.handleThemeChange);
24 }
25
26 private handleThemeChange = (e: CustomEvent) => {
27 this.currentTheme = e.detail.theme;
28 this.effectiveTheme = e.detail.effectiveTheme;
29 };
30
31 private updateThemeState() {
32 this.currentTheme = this.themeService.getTheme();
33 this.effectiveTheme = this.themeService.getEffectiveTheme();
34 }
35
36 private toggleTheme() {
37 this.themeService.toggleTheme();
38 }
39
40 private getThemeIcon(): string {
41 switch (this.currentTheme) {
42 case "light":
43 return "\u2600\ufe0f"; // Sun
44 case "dark":
45 return "\ud83c\udf19"; // Moon
46 case "system":
47 return "\ud83d\udcbb"; // Computer/Laptop
48 default:
49 return "\ud83d\udcbb";
50 }
51 }
52
53 private getThemeLabel(): string {
54 switch (this.currentTheme) {
55 case "light":
56 return "Light mode";
57 case "dark":
58 return "Dark mode";
59 case "system":
60 return `System theme (${this.effectiveTheme})`;
61 default:
62 return "System theme";
63 }
64 }
65
66 private getNextThemeLabel(): string {
67 switch (this.currentTheme) {
68 case "light":
69 return "Switch to dark mode";
70 case "dark":
71 return "Switch to system theme";
72 case "system":
73 return "Switch to light mode";
74 default:
75 return "Switch theme";
76 }
77 }
78
79 render() {
80 return html`
81 <button
82 @click=${this.toggleTheme}
83 class="p-2 rounded-md border border-gray-300 dark:border-gray-600
84 bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-200
85 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors
86 focus:outline-none focus:ring-2 focus:ring-blue-500"
87 title="${this.getThemeLabel()} - ${this.getNextThemeLabel()}"
88 aria-label="${this.getNextThemeLabel()}"
89 >
90 ${this.getThemeIcon()}
91 </button>
92 `;
93 }
94}
95
96declare global {
97 interface HTMLElementTagNameMap {
98 "sketch-theme-toggle": SketchThemeToggle;
99 }
100}