diff options
Diffstat (limited to 'frontend-vanilla/src/main.ts')
| -rw-r--r-- | frontend-vanilla/src/main.ts | 52 |
1 files changed, 50 insertions, 2 deletions
diff --git a/frontend-vanilla/src/main.ts b/frontend-vanilla/src/main.ts index 9c8f2b3..fa74274 100644 --- a/frontend-vanilla/src/main.ts +++ b/frontend-vanilla/src/main.ts @@ -13,6 +13,24 @@ declare global { } } +// Style theme management: load/unload CSS files +const STYLE_THEMES = ['default', 'refined', 'terminal', 'codex', 'sakura'] as const; + +function loadStyleTheme(theme: string) { + // Remove any existing theme stylesheet + const existing = document.getElementById('style-theme-link'); + if (existing) existing.remove(); + + // 'default' means no extra stylesheet + if (theme === 'default') return; + + const link = document.createElement('link'); + link.id = 'style-theme-link'; + link.rel = 'stylesheet'; + link.href = `/v3/themes/${theme}.css`; + document.head.appendChild(link); +} + // Global App State let activeItemId: number | null = null; @@ -394,7 +412,20 @@ export function renderSettings() { <button class="${store.theme === 'dark' ? 'active' : ''}" data-theme="dark">Dark</button> </div> </div> - <div class="settings-group" style="margin-top: 1rem;"> + </section> + + <section class="settings-section"> + <h3>Style</h3> + <div class="settings-group"> + <div class="theme-options" id="style-theme-options"> + ${STYLE_THEMES.map(t => `<button class="${store.styleTheme === t ? 'active' : ''}" data-style-theme="${t}">${t.charAt(0).toUpperCase() + t.slice(1)}</button>`).join('\n ')} + </div> + </div> + </section> + + <section class="settings-section"> + <h3>Fonts</h3> + <div class="settings-group"> <label>System & headings</label> <select id="heading-font-selector" style="margin-bottom: 1rem;"> <option value="default" ${store.headingFontTheme === 'default' ? 'selected' : ''}>System (Helvetica Neue)</option> @@ -445,7 +476,7 @@ export function renderSettings() { // --- Listeners --- - // Theme + // Theme (light/dark) document.getElementById('theme-options')?.addEventListener('click', (e) => { const btn = (e.target as HTMLElement).closest('button'); if (btn) { @@ -454,6 +485,14 @@ export function renderSettings() { } }); + // Style Theme + document.getElementById('style-theme-options')?.addEventListener('click', (e) => { + const btn = (e.target as HTMLElement).closest('button'); + if (btn) { + store.setStyleTheme(btn.getAttribute('data-style-theme')!); + } + }); + // Heading Font document.getElementById('heading-font-selector')?.addEventListener('change', (e) => { store.setHeadingFontTheme((e.target as HTMLSelectElement).value); @@ -844,6 +883,14 @@ store.on('sidebar-toggle', () => { } }); +store.on('style-theme-updated', () => { + loadStyleTheme(store.styleTheme); + // Re-render settings if on settings page to update active state + if (router.getCurrentRoute().path === '/settings') { + renderSettings(); + } +}); + store.on('items-updated', renderItems); store.on('loading-state-changed', renderItems); @@ -864,6 +911,7 @@ export async function init() { } renderLayout(); + loadStyleTheme(store.styleTheme); renderFilters(); try { await Promise.all([fetchFeeds(), fetchTags()]); |
