63 lines
1.9 KiB
JavaScript
Raw Normal View History

2025-12-04 20:29:35 +01:00
/**
* @fileoverview Theme Selector Component for Rantii
* @author retoor <retoor@molodetz.nl>
* @description UI for selecting application color themes
* @keywords theme, selector, dark, light, appearance
*/
import { BaseComponent } from './base-component.js';
import { THEMES } from '../services/theme.js';
class ThemeSelector extends BaseComponent {
init() {
this.themeChangeHandler = () => this.render();
this.render();
this.bindEvents();
}
render() {
const currentTheme = this.getTheme()?.getTheme() || 'dark';
const themes = Object.entries(THEMES);
this.setHtml(`
<div class="theme-selector">
<label class="theme-label">Theme</label>
<div class="theme-options">
${themes.map(([key, theme]) => `
<button class="theme-option ${key === currentTheme ? 'active' : ''}"
data-theme="${key}"
aria-pressed="${key === currentTheme}">
<span class="theme-preview theme-preview-${key}"></span>
<span class="theme-name">${theme.name}</span>
</button>
`).join('')}
</div>
</div>
`);
}
bindEvents() {
this.on(this, 'click', this.handleClick);
window.addEventListener('rantii:theme-change', this.themeChangeHandler);
}
onDisconnected() {
window.removeEventListener('rantii:theme-change', this.themeChangeHandler);
}
handleClick(e) {
const option = e.target.closest('.theme-option');
if (!option) return;
const theme = option.dataset.theme;
if (theme) {
this.getTheme()?.setTheme(theme);
this.render();
}
}
}
customElements.define('theme-selector', ThemeSelector);
export { ThemeSelector };