fix select ui

This commit is contained in:
Julian Freeman
2026-04-03 19:02:04 -04:00
parent 41494ebad0
commit 136a5c186c

View File

@@ -33,6 +33,19 @@ const newSessionPartner = ref<Participant>({
tone: 'Auto-detect'
});
// Custom Dropdown States for Modal
const meLangDropdownOpen = ref(false);
const meGenderDropdownOpen = ref(false);
const partnerLangDropdownOpen = ref(false);
const partnerGenderDropdownOpen = ref(false);
const closeAllModalDropdowns = () => {
meLangDropdownOpen.value = false;
meGenderDropdownOpen.value = false;
partnerLangDropdownOpen.value = false;
partnerGenderDropdownOpen.value = false;
};
// Current active session
const activeSession = computed(() =>
settings.chatSessions.find(s => s.id === settings.activeSessionId) || null
@@ -179,6 +192,7 @@ const translateMessage = async (sender: 'me' | 'partner') => {
const handleGlobalClick = () => {
myToneDropdownOpen.value = false;
closeAllModalDropdowns();
};
onMounted(() => window.addEventListener('click', handleGlobalClick));
@@ -464,8 +478,8 @@ onUnmounted(() => window.removeEventListener('click', handleGlobalClick));
leave-to-class="opacity-0 scale-95"
>
<div v-if="isCreatingSession" class="absolute inset-0 z-[100] flex items-center justify-center p-6 bg-slate-900/20 backdrop-blur-sm">
<div class="w-full max-w-lg bg-white dark:bg-slate-900 rounded-3xl shadow-2xl border dark:border-slate-800 overflow-hidden">
<div class="p-6 border-b dark:border-slate-800 flex items-center justify-between bg-slate-50 dark:bg-slate-950">
<div class="w-full max-w-lg bg-white dark:bg-slate-900 rounded-3xl shadow-2xl border dark:border-slate-800">
<div class="p-6 border-b dark:border-slate-800 flex items-center justify-between bg-slate-50 dark:bg-slate-950 rounded-t-3xl">
<h3 class="text-lg font-bold dark:text-slate-100 flex items-center gap-2">
<Plus class="w-5 h-5 text-blue-500" />
创建新会话
@@ -486,17 +500,41 @@ onUnmounted(() => window.removeEventListener('click', handleGlobalClick));
</div>
<div class="space-y-1.5">
<label class="text-[10px] font-bold text-slate-400 uppercase">使用语言</label>
<select v-model="newSessionMe.language" class="w-full px-4 py-2.5 bg-slate-50 dark:bg-slate-800 border dark:border-slate-700 rounded-xl outline-none focus:ring-2 focus:ring-blue-500/20 text-sm dark:text-slate-200 appearance-none">
<option v-for="lang in LANGUAGES" :key="lang.code" :value="lang">{{ lang.displayName }}</option>
</select>
<div class="relative">
<button
@click.stop="closeAllModalDropdowns(); meLangDropdownOpen = !meLangDropdownOpen"
class="w-full flex items-center justify-between px-4 py-2.5 bg-slate-50 dark:bg-slate-800 border dark:border-slate-700 rounded-xl text-sm dark:text-slate-200"
>
{{ newSessionMe.language.displayName }}
<ChevronDown class="w-4 h-4 text-slate-400" />
</button>
<div v-if="meLangDropdownOpen" class="absolute left-0 top-full mt-1 w-full max-h-60 overflow-y-auto bg-white dark:bg-slate-800 border dark:border-slate-700 rounded-xl shadow-xl z-[110] py-2 custom-scrollbar">
<button v-for="lang in LANGUAGES" :key="lang.code" @click="newSessionMe.language = lang; meLangDropdownOpen = false" class="w-full px-4 py-2 text-sm text-left hover:bg-slate-100 dark:hover:bg-slate-700 dark:text-slate-200 transition-colors flex items-center justify-between">
{{ lang.displayName }}
<Check v-if="newSessionMe.language.code === lang.code" class="w-3.5 h-3.5 text-blue-500" />
</button>
</div>
</div>
</div>
</div>
<div class="grid grid-cols-2 gap-4">
<div class="space-y-1.5">
<label class="text-[10px] font-bold text-slate-400 uppercase">性别</label>
<select v-model="newSessionMe.gender" class="w-full px-4 py-2.5 bg-slate-50 dark:bg-slate-800 border dark:border-slate-700 rounded-xl outline-none focus:ring-2 focus:ring-blue-500/20 text-sm dark:text-slate-200 appearance-none">
<option v-for="opt in SPEAKER_IDENTITY_OPTIONS" :key="opt.value" :value="opt.value">{{ opt.label }}</option>
</select>
<div class="relative">
<button
@click.stop="closeAllModalDropdowns(); meGenderDropdownOpen = !meGenderDropdownOpen"
class="w-full flex items-center justify-between px-4 py-2.5 bg-slate-50 dark:bg-slate-800 border dark:border-slate-700 rounded-xl text-sm dark:text-slate-200"
>
{{ SPEAKER_IDENTITY_OPTIONS.find(o => o.value === newSessionMe.gender)?.label }}
<ChevronDown class="w-4 h-4 text-slate-400" />
</button>
<div v-if="meGenderDropdownOpen" class="absolute left-0 top-full mt-1 w-full bg-white dark:bg-slate-800 border dark:border-slate-700 rounded-xl shadow-xl z-[110] py-2">
<button v-for="opt in SPEAKER_IDENTITY_OPTIONS" :key="opt.value" @click="newSessionMe.gender = opt.value; meGenderDropdownOpen = false" class="w-full px-4 py-2 text-sm text-left hover:bg-slate-100 dark:hover:bg-slate-700 dark:text-slate-200 transition-colors flex items-center justify-between">
{{ opt.label }}
<Check v-if="newSessionMe.gender === opt.value" class="w-3.5 h-3.5 text-blue-500" />
</button>
</div>
</div>
</div>
</div>
</section>
@@ -511,17 +549,41 @@ onUnmounted(() => window.removeEventListener('click', handleGlobalClick));
</div>
<div class="space-y-1.5">
<label class="text-[10px] font-bold text-slate-400 uppercase">使用语言</label>
<select v-model="newSessionPartner.language" class="w-full px-4 py-2.5 bg-slate-50 dark:bg-slate-800 border dark:border-slate-700 rounded-xl outline-none focus:ring-2 focus:ring-blue-500/20 text-sm dark:text-slate-200 appearance-none">
<option v-for="lang in LANGUAGES" :key="lang.code" :value="lang">{{ lang.displayName }}</option>
</select>
<div class="relative">
<button
@click.stop="closeAllModalDropdowns(); partnerLangDropdownOpen = !partnerLangDropdownOpen"
class="w-full flex items-center justify-between px-4 py-2.5 bg-slate-50 dark:bg-slate-800 border dark:border-slate-700 rounded-xl text-sm dark:text-slate-200"
>
{{ newSessionPartner.language.displayName }}
<ChevronDown class="w-4 h-4 text-slate-400" />
</button>
<div v-if="partnerLangDropdownOpen" class="absolute left-0 top-full mt-1 w-full max-h-60 overflow-y-auto bg-white dark:bg-slate-800 border dark:border-slate-700 rounded-xl shadow-xl z-[110] py-2 custom-scrollbar">
<button v-for="lang in LANGUAGES" :key="lang.code" @click="newSessionPartner.language = lang; partnerLangDropdownOpen = false" class="w-full px-4 py-2 text-sm text-left hover:bg-slate-100 dark:hover:bg-slate-700 dark:text-slate-200 transition-colors flex items-center justify-between">
{{ lang.displayName }}
<Check v-if="newSessionPartner.language.code === lang.code" class="w-3.5 h-3.5 text-blue-500" />
</button>
</div>
</div>
</div>
</div>
<div class="grid grid-cols-2 gap-4">
<div class="space-y-1.5">
<label class="text-[10px] font-bold text-slate-400 uppercase">性别</label>
<select v-model="newSessionPartner.gender" class="w-full px-4 py-2.5 bg-slate-50 dark:bg-slate-800 border dark:border-slate-700 rounded-xl outline-none focus:ring-2 focus:ring-blue-500/20 text-sm dark:text-slate-200 appearance-none">
<option v-for="opt in SPEAKER_IDENTITY_OPTIONS" :key="opt.value" :value="opt.value">{{ opt.label }}</option>
</select>
<div class="relative">
<button
@click.stop="closeAllModalDropdowns(); partnerGenderDropdownOpen = !partnerGenderDropdownOpen"
class="w-full flex items-center justify-between px-4 py-2.5 bg-slate-50 dark:bg-slate-800 border dark:border-slate-700 rounded-xl text-sm dark:text-slate-200"
>
{{ SPEAKER_IDENTITY_OPTIONS.find(o => o.value === newSessionPartner.gender)?.label }}
<ChevronDown class="w-4 h-4 text-slate-400" />
</button>
<div v-if="partnerGenderDropdownOpen" class="absolute left-0 top-full mt-1 w-full bg-white dark:bg-slate-800 border dark:border-slate-700 rounded-xl shadow-xl z-[110] py-2">
<button v-for="opt in SPEAKER_IDENTITY_OPTIONS" :key="opt.value" @click="newSessionPartner.gender = opt.value; partnerGenderDropdownOpen = false" class="w-full px-4 py-2 text-sm text-left hover:bg-slate-100 dark:hover:bg-slate-700 dark:text-slate-200 transition-colors flex items-center justify-between">
{{ opt.label }}
<Check v-if="newSessionPartner.gender === opt.value" class="w-3.5 h-3.5 text-blue-500" />
</button>
</div>
</div>
</div>
</div>
</section>