fix(settings): copy monolith's working theme dropdown pattern exactly

This commit is contained in:
Hibryda 2026-03-17 06:30:09 +01:00
parent c094983814
commit 1ac6b69311

View file

@ -40,7 +40,7 @@
let uiFontOpen = $state(false); let uiFontOpen = $state(false);
let termFontOpen = $state(false); let termFontOpen = $state(false);
let themeGroups = $derived(() => { let themeGroups = $derived.by(() => {
const map = new Map<string, typeof THEME_LIST>(); const map = new Map<string, typeof THEME_LIST>();
for (const t of THEME_LIST) { for (const t of THEME_LIST) {
if (!map.has(t.group)) map.set(t.group, []); if (!map.has(t.group)) map.set(t.group, []);
@ -115,17 +115,28 @@
<h3>Theme</h3> <h3>Theme</h3>
<div class="field" id="setting-theme"> <div class="field" id="setting-theme">
<div class="custom-dropdown"> <div class="custom-dropdown">
<button class="dropdown-btn" onclick={() => { uiFontOpen = false; termFontOpen = false; themeOpen = !themeOpen; }}> <button class="dropdown-btn" onclick={() => { uiFontOpen = false; termFontOpen = false; themeOpen = !themeOpen; }}
<span class="theme-dots">{@html (() => { const p = getPalette(selectedTheme); return [p.red, p.green, p.blue, p.yellow].map(c => `<span style="background:${c}" class="dot"></span>`).join(''); })()}</span> aria-haspopup="listbox" aria-expanded={themeOpen}>
<span class="theme-colors">
<span class="color-dot" style="background: {getPalette(selectedTheme).red};"></span>
<span class="color-dot" style="background: {getPalette(selectedTheme).green};"></span>
<span class="color-dot" style="background: {getPalette(selectedTheme).blue};"></span>
<span class="color-dot" style="background: {getPalette(selectedTheme).yellow};"></span>
</span>
{themeLabel} {themeLabel}
</button> </button>
{#if themeOpen} {#if themeOpen}
<div class="dropdown-menu theme-menu"> <div class="dropdown-menu theme-menu" role="listbox">
{#each themeGroups() as [group, themes]} {#each themeGroups as [group, themes]}
<div class="group-label">{group}</div> <div class="group-label">{group}</div>
{#each themes as t} {#each themes as t}
<button class="dropdown-item" class:active={t.id === selectedTheme} onclick={() => pickTheme(t.id)}> <button class="dropdown-item" class:active={t.id === selectedTheme} onclick={() => pickTheme(t.id)}>
<span class="theme-dots">{@html [t.palette.red, t.palette.green, t.palette.blue, t.palette.yellow].map(c => `<span style="background:${c}" class="dot"></span>`).join('')}</span> <span class="theme-colors">
<span class="color-dot" style="background: {getPalette(t.id).red};"></span>
<span class="color-dot" style="background: {getPalette(t.id).green};"></span>
<span class="color-dot" style="background: {getPalette(t.id).blue};"></span>
<span class="color-dot" style="background: {getPalette(t.id).yellow};"></span>
</span>
{t.label} {t.label}
</button> </button>
{/each} {/each}
@ -137,7 +148,7 @@
<h3>UI Font</h3> <h3>UI Font</h3>
<div class="field row" id="setting-ui-font"> <div class="field row" id="setting-ui-font">
<div class="dropdown flex1"> <div class="custom-dropdown flex1">
<button class="dropdown-btn" onclick={() => { themeOpen = false; termFontOpen = false; uiFontOpen = !uiFontOpen; }}>{uiFontLabel}</button> <button class="dropdown-btn" onclick={() => { themeOpen = false; termFontOpen = false; uiFontOpen = !uiFontOpen; }}>{uiFontLabel}</button>
{#if uiFontOpen} {#if uiFontOpen}
<div class="dropdown-menu"> <div class="dropdown-menu">
@ -156,7 +167,7 @@
<h3>Terminal Font</h3> <h3>Terminal Font</h3>
<div class="field row" id="setting-term-font"> <div class="field row" id="setting-term-font">
<div class="dropdown flex1"> <div class="custom-dropdown flex1">
<button class="dropdown-btn" onclick={() => { themeOpen = false; uiFontOpen = false; termFontOpen = !termFontOpen; }}>{termFontLabel}</button> <button class="dropdown-btn" onclick={() => { themeOpen = false; uiFontOpen = false; termFontOpen = !termFontOpen; }}>{termFontLabel}</button>
{#if termFontOpen} {#if termFontOpen}
<div class="dropdown-menu"> <div class="dropdown-menu">
@ -209,8 +220,8 @@
.dropdown-item:hover { background: var(--ctp-surface0); } .dropdown-item:hover { background: var(--ctp-surface0); }
.dropdown-item.active { color: var(--ctp-blue); } .dropdown-item.active { color: var(--ctp-blue); }
.group-label { padding: 0.25rem 0.625rem; font-size: 0.6875rem; color: var(--ctp-overlay0); font-weight: 600; text-transform: uppercase; } .group-label { padding: 0.25rem 0.625rem; font-size: 0.6875rem; color: var(--ctp-overlay0); font-weight: 600; text-transform: uppercase; }
.dot { display: inline-block; width: 0.5rem; height: 0.5rem; border-radius: 50%; } .color-dot { display: inline-block; width: 0.5rem; height: 0.5rem; border-radius: 50%; }
.theme-dots { display: flex; gap: 0.1875rem; } .theme-colors { display: flex; gap: 0.1875rem; }
.stepper { display: flex; align-items: center; gap: 0.25rem; } .stepper { display: flex; align-items: center; gap: 0.25rem; }
.stepper button { width: 1.5rem; height: 1.5rem; background: var(--ctp-surface0); border: none; border-radius: 0.1875rem; color: var(--ctp-text); cursor: pointer; font-size: 0.875rem; display: flex; align-items: center; justify-content: center; } .stepper button { width: 1.5rem; height: 1.5rem; background: var(--ctp-surface0); border: none; border-radius: 0.1875rem; color: var(--ctp-text); cursor: pointer; font-size: 0.875rem; display: flex; align-items: center; justify-content: center; }
.stepper button:hover { background: var(--ctp-surface1); } .stepper button:hover { background: var(--ctp-surface1); }