fix(electrobun): replace native <select> with fully themed custom dropdowns

All 3 wizard selects (branch, group, shell) now use custom dropdown
components with --ctp-* themed menu, hover states, active highlight.
No native OS styling leaks through.
This commit is contained in:
Hibryda 2026-03-22 12:52:24 +01:00
parent f1f965f8b2
commit b7fc3a0f9b

View file

@ -59,6 +59,12 @@
let shellChoice = $state('bash');
const SHELLS = ['bash', 'zsh', 'fish', 'sh'];
let branchDDOpen = $state(false);
let groupDDOpen = $state(false);
let shellDDOpen = $state(false);
let branchLabel = $derived(selectedBranch || 'main');
let groupLabel = $derived(groups.find(g => g.id === selectedGroupId)?.name ?? 'Select');
function closeAllDD() { branchDDOpen = false; groupDDOpen = false; shellDDOpen = false; }
const EMOJI_GRID = ['📁', '🚀', '⚡', '🔧', '🌐', '📦', '🎯', '💡', '🔬', '🎨', '📊', '🛡️', '🤖', '🧪', '🏗️', '📝'];
// ── Step 3: Agent ──────────────────────────────────────────
@ -373,11 +379,17 @@
{#if isGitRepo && branches.length > 0}
<label class="wz-label">{t('wizard.step2.branch' as any)}</label>
<select class="wz-select" bind:value={selectedBranch}>
{#each branches as br}
<option value={br}>{br}</option>
{/each}
</select>
<div class="wz-dd" style="position:relative;">
<button class="wz-dd-btn" onclick={() => { closeAllDD(); branchDDOpen = !branchDDOpen; }}>
<span>{branchLabel}</span><span class="wz-dd-chev"></span>
</button>
<div class="wz-dd-menu" style:display={branchDDOpen ? 'block' : 'none'}>
{#each branches as br}
<button class="wz-dd-item" class:active={selectedBranch === br}
onclick={() => { selectedBranch = br; branchDDOpen = false; }}>{br}</button>
{/each}
</div>
</div>
<label class="wz-toggle-row">
<input type="checkbox" bind:checked={useWorktrees} />
@ -386,11 +398,17 @@
{/if}
<label class="wz-label">{t('wizard.step2.group' as any)}</label>
<select class="wz-select" bind:value={selectedGroupId}>
{#each groups as g}
<option value={g.id}>{g.name}</option>
{/each}
</select>
<div class="wz-dd" style="position:relative;">
<button class="wz-dd-btn" onclick={() => { closeAllDD(); groupDDOpen = !groupDDOpen; }}>
<span>{groupLabel}</span><span class="wz-dd-chev"></span>
</button>
<div class="wz-dd-menu" style:display={groupDDOpen ? 'block' : 'none'}>
{#each groups as g}
<button class="wz-dd-item" class:active={selectedGroupId === g.id}
onclick={() => { selectedGroupId = g.id; groupDDOpen = false; }}>{g.name}</button>
{/each}
</div>
</div>
<label class="wz-label">{t('wizard.step2.icon' as any)}</label>
<div class="wz-emoji-grid">
@ -401,11 +419,17 @@
</div>
<label class="wz-label">{t('wizard.step2.shell' as any)}</label>
<select class="wz-select" bind:value={shellChoice}>
{#each SHELLS as sh}
<option value={sh}>{sh}</option>
{/each}
</select>
<div class="wz-dd" style="position:relative;">
<button class="wz-dd-btn" onclick={() => { closeAllDD(); shellDDOpen = !shellDDOpen; }}>
<span>{shellChoice}</span><span class="wz-dd-chev"></span>
</button>
<div class="wz-dd-menu" style:display={shellDDOpen ? 'block' : 'none'}>
{#each SHELLS as sh}
<button class="wz-dd-item" class:active={shellChoice === sh}
onclick={() => { shellChoice = sh; shellDDOpen = false; }}>{sh}</button>
{/each}
</div>
</div>
<div class="wz-footer">
<button class="wz-btn secondary" onclick={goBack}>{t('wizard.back' as any)}</button>
@ -521,19 +545,31 @@
.wz-input:focus, .wz-select:focus, .wz-textarea:focus { outline: none; border-color: var(--ctp-blue); }
.wz-input::placeholder, .wz-textarea::placeholder { color: var(--ctp-overlay0); }
.wz-textarea { resize: vertical; min-height: 3rem; }
.wz-select {
cursor: pointer;
-webkit-appearance: none;
appearance: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23a6adc8' stroke-width='2'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 0.5rem center;
padding-right: 1.75rem;
/* Custom themed dropdown */
.wz-dd { width: 100%; }
.wz-dd-btn {
width: 100%; display: flex; align-items: center; justify-content: space-between;
padding: 0.375rem 0.5rem; background: var(--ctp-surface0);
border: 1px solid var(--ctp-surface1); border-radius: 0.25rem;
color: var(--ctp-text); font-size: 0.8125rem; font-family: var(--ui-font-family);
cursor: pointer; text-align: left;
}
.wz-select option {
background: var(--ctp-surface0);
color: var(--ctp-text);
.wz-dd-btn:hover { border-color: var(--ctp-surface2); }
.wz-dd-chev { color: var(--ctp-overlay1); font-size: 0.75rem; }
.wz-dd-menu {
position: absolute; top: 100%; left: 0; right: 0; z-index: 20;
background: var(--ctp-mantle); border: 1px solid var(--ctp-surface1);
border-radius: 0.25rem; margin-top: 0.125rem;
max-height: 10rem; overflow-y: auto;
box-shadow: 0 0.25rem 0.75rem color-mix(in srgb, var(--ctp-crust) 50%, transparent);
}
.wz-dd-item {
width: 100%; padding: 0.3125rem 0.5rem; background: none; border: none;
color: var(--ctp-text); font-size: 0.8125rem; font-family: var(--ui-font-family);
cursor: pointer; text-align: left;
}
.wz-dd-item:hover { background: var(--ctp-surface0); }
.wz-dd-item.active { color: var(--ctp-blue); background: color-mix(in srgb, var(--ctp-blue) 10%, transparent); }
/* Themed checkboxes */
input[type="checkbox"] {