Files
ComfyUI_frontend/src/components/dialog/content/setting/keybinding/KeybindingPresetToolbar.vue
Johnpaul 5a4a33aee0 feat: add keybinding preset UI with toolbar, menu, and header teleport
Add KeybindingPresetToolbar with preset selector dropdown, save changes
button, and import option. Integrate into KeybindingPanel with teleported
search box and more-options menu in the settings dialog header row.
2026-03-09 23:23:45 +01:00

113 lines
3.6 KiB
Vue

<template>
<div class="flex items-center justify-between">
<Select v-model="selectedPreset">
<SelectTrigger class="w-64">
<SelectValue :placeholder="$t('g.keybindingPresets.default')">
{{ displayLabel }}
</SelectValue>
</SelectTrigger>
<SelectContent
disable-portal
class="max-w-64 min-w-0 **:[[role=listbox]]:gap-1"
>
<div class="max-w-60">
<SelectItem
value="default"
class="max-w-60 p-2 data-[state=checked]:bg-transparent"
>
{{ $t('g.keybindingPresets.default') }}
</SelectItem>
<SelectItem
v-for="name in presetNames"
:key="name"
:value="name"
class="max-w-60 p-2 data-[state=checked]:bg-transparent"
>
{{ name }}
</SelectItem>
<SelectSeparator class="max-w-60" />
<button
class="relative flex w-full max-w-60 cursor-pointer select-none items-center justify-between gap-3 rounded-sm border-none bg-transparent p-2 text-sm outline-none hover:bg-secondary-background-hover focus:bg-secondary-background-hover"
@click.stop="handleImportFromDropdown"
>
<span class="truncate">
{{ $t('g.keybindingPresets.importKeybindingPreset') }}
</span>
<i
class="icon-[lucide--download] shrink-0 text-base-foreground"
aria-hidden="true"
/>
</button>
</div>
</SelectContent>
</Select>
<Button v-if="showSaveButton" size="lg" @click="handleSavePreset">
{{ $t('g.keybindingPresets.saveChanges') }}
</Button>
</div>
</template>
<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import Button from '@/components/ui/button/Button.vue'
import Select from '@/components/ui/select/Select.vue'
import SelectContent from '@/components/ui/select/SelectContent.vue'
import SelectItem from '@/components/ui/select/SelectItem.vue'
import SelectSeparator from '@/components/ui/select/SelectSeparator.vue'
import SelectTrigger from '@/components/ui/select/SelectTrigger.vue'
import SelectValue from '@/components/ui/select/SelectValue.vue'
import { useKeybindingPresetService } from '@/platform/keybindings/presetService'
import { useKeybindingStore } from '@/platform/keybindings/keybindingStore'
const { presetNames, onPresetsChanged } = defineProps<{
presetNames: string[]
onPresetsChanged: () => void
}>()
const { t } = useI18n()
const keybindingStore = useKeybindingStore()
const presetService = useKeybindingPresetService()
const selectedPreset = ref(keybindingStore.currentPresetName)
const displayLabel = computed(() => {
const name =
selectedPreset.value === 'default'
? t('g.keybindingPresets.default')
: selectedPreset.value
return keybindingStore.isCurrentPresetModified ? `${name} *` : name
})
watch(selectedPreset, async (newValue, oldValue) => {
if (newValue !== oldValue) {
await presetService.switchPreset(newValue)
selectedPreset.value = keybindingStore.currentPresetName
onPresetsChanged()
}
})
watch(
() => keybindingStore.currentPresetName,
(name) => {
selectedPreset.value = name
}
)
const showSaveButton = computed(
() =>
keybindingStore.currentPresetName !== 'default' &&
keybindingStore.isCurrentPresetModified
)
async function handleSavePreset() {
await presetService.savePreset(keybindingStore.currentPresetName)
}
async function handleImportFromDropdown() {
await presetService.importPreset()
onPresetsChanged()
}
</script>