Rework theme menu (#5161)

* Change theme "button" to sub menu of all themes

* Add test for theme menu

* Prevent separator being added before View

* Refactor test

* Update locales [skip ci]

* Fix has-text vs text-is change breaking other tests

---------

Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: bymyself <cbyrne@comfy.org>
This commit is contained in:
pythongosssss
2025-09-06 11:09:58 +01:00
committed by GitHub
parent 0854194aa1
commit 0df7a53ead
14 changed files with 234 additions and 49 deletions

View File

@@ -28,29 +28,7 @@
@show="onMenuShow"
>
<template #item="{ item, props }">
<div
v-if="item.key === 'theme'"
class="flex items-center gap-4 px-4 py-5"
@click.stop.prevent
>
{{ item.label }}
<SelectButton
:options="[darkLabel, lightLabel]"
:model-value="activeTheme"
@click.stop.prevent
@update:model-value="onThemeChange"
>
<template #option="{ option }">
<div class="flex items-center gap-2">
<i v-if="option === lightLabel" class="pi pi-sun" />
<i v-if="option === darkLabel" class="pi pi-moon" />
<span>{{ option }}</span>
</div>
</template>
</SelectButton>
</div>
<a
v-else
class="p-menubar-item-link px-4 py-2"
v-bind="props.action"
:href="item.url"
@@ -95,7 +73,6 @@
<script setup lang="ts">
import type { MenuItem } from 'primevue/menuitem'
import SelectButton from 'primevue/selectbutton'
import TieredMenu, {
type TieredMenuMethods,
type TieredMenuState
@@ -106,6 +83,7 @@ import { useI18n } from 'vue-i18n'
import SubgraphBreadcrumb from '@/components/breadcrumb/SubgraphBreadcrumb.vue'
import SettingDialogContent from '@/components/dialog/content/SettingDialogContent.vue'
import SettingDialogHeader from '@/components/dialog/header/SettingDialogHeader.vue'
import { useColorPaletteService } from '@/services/colorPaletteService'
import { useDialogService } from '@/services/dialogService'
import { useCommandStore } from '@/stores/commandStore'
import { useDialogStore } from '@/stores/dialogStore'
@@ -121,6 +99,7 @@ import { normalizeI18nKey } from '@/utils/formatUtil'
import { whileMouseDown } from '@/utils/mouseDownUtil'
const colorPaletteStore = useColorPaletteStore()
const colorPaletteService = useColorPaletteService()
const menuItemsStore = useMenuItemStore()
const commandStore = useCommandStore()
const dialogStore = useDialogStore()
@@ -184,11 +163,26 @@ const showManageExtensions = async () => {
}
}
const extraMenuItems = computed<MenuItem[]>(() => [
const themeMenuItems = computed(() => {
return colorPaletteStore.palettes.map((palette) => ({
key: `theme-${palette.id}`,
label: palette.name,
parentPath: 'theme',
comfyCommand: {
active: () => colorPaletteStore.activePaletteId === palette.id
},
command: async () => {
await colorPaletteService.loadColorPalette(palette.id)
}
}))
})
const extraMenuItems = computed(() => [
{ separator: true },
{
key: 'theme',
label: t('menu.theme')
label: t('menu.theme'),
items: themeMenuItems.value
},
{ separator: true },
{
@@ -211,19 +205,6 @@ const extraMenuItems = computed<MenuItem[]>(() => [
}
])
const lightLabel = computed(() => t('menu.light'))
const darkLabel = computed(() => t('menu.dark'))
const activeTheme = computed(() => {
return colorPaletteStore.completedActivePalette.light_theme
? lightLabel.value
: darkLabel.value
})
const onThemeChange = async () => {
await commandStore.execute('Comfy.ToggleTheme')
}
const translatedItems = computed(() => {
const items = menuItemsStore.menuItems.map(translateMenuItem)
let helpIndex = items.findIndex((item) => item.key === 'Help')
@@ -308,7 +289,12 @@ const handleItemClick = (item: MenuItem, event: MouseEvent) => {
}
const hasActiveStateSiblings = (item: MenuItem): boolean => {
return menuItemsStore.menuItemHasActiveStateChildren[item.parentPath]
// Check if this item has siblings with active state (either from store or theme items)
return (
item.parentPath &&
(item.parentPath === 'theme' ||
menuItemsStore.menuItemHasActiveStateChildren[item.parentPath])
)
}
</script>
@@ -332,6 +318,18 @@ const hasActiveStateSiblings = (item: MenuItem): boolean => {
</style>
<style>
.comfy-command-menu {
--p-tieredmenu-item-focus-background: color-mix(
in srgb,
var(--fg-color) 15%,
transparent
);
--p-tieredmenu-item-active-background: color-mix(
in srgb,
var(--fg-color) 10%,
transparent
);
}
.comfy-command-menu ul {
background-color: var(--comfy-menu-secondary-bg) !important;
}

View File

@@ -23,6 +23,7 @@ export const CORE_MENU_COMMANDS = [
'Comfy.Memory.UnloadModelsAndExecutionCache'
]
],
[['View'], []],
[
['Help'],
[

View File

@@ -842,6 +842,7 @@
"Ungroup selected group nodes": "فك تجميع عقد المجموعة المحددة",
"Unlock Canvas": "فتح قفل اللوحة",
"Unpack the selected Subgraph": "فك تجميع الرسم البياني الفرعي المحدد",
"View": "عرض",
"Workflows": "سير العمل",
"Zoom In": "تكبير",
"Zoom Out": "تصغير",

View File

@@ -1004,6 +1004,7 @@
"menuLabels": {
"Workflow": "Workflow",
"Edit": "Edit",
"View": "View",
"Manager": "Manager",
"Help": "Help",
"Check for Updates": "Check for Updates",

View File

@@ -825,7 +825,11 @@
"Ungroup selected group nodes": "Desagrupar nodos de grupo seleccionados",
"Unload Models": "Descargar modelos",
"Unload Models and Execution Cache": "Descargar modelos y caché de ejecución",
"Unlock Canvas": "Desbloquear lienzo",
"Unpack the selected Subgraph": "Desempaquetar el Subgrafo seleccionado",
"View": "Ver",
"Workflow": "Flujo de trabajo",
"Workflows": "Flujos de trabajo",
"Zoom In": "Acercar",
"Zoom Out": "Alejar",
"Zoom to fit": "Ajustar al tamaño"

View File

@@ -825,7 +825,11 @@
"Ungroup selected group nodes": "Dégrouper les nœuds de groupe sélectionnés",
"Unload Models": "Décharger les modèles",
"Unload Models and Execution Cache": "Décharger les modèles et le cache d'exécution",
"Unlock Canvas": "Déverrouiller le canevas",
"Unpack the selected Subgraph": "Décompresser le Subgraph sélectionné",
"View": "Afficher",
"Workflow": "Flux de travail",
"Workflows": "Flux de travail",
"Zoom In": "Zoom avant",
"Zoom Out": "Zoom arrière",
"Zoom to fit": "Ajuster à l'écran"

View File

@@ -824,7 +824,11 @@
"Ungroup selected group nodes": "選択したグループノードのグループ解除",
"Unload Models": "モデルのアンロード",
"Unload Models and Execution Cache": "モデルと実行キャッシュのアンロード",
"Unlock Canvas": "キャンバスのロックを解除",
"Unpack the selected Subgraph": "選択したサブグラフを展開",
"View": "表示",
"Workflow": "ワークフロー",
"Workflows": "ワークフロー",
"Zoom In": "ズームイン",
"Zoom Out": "ズームアウト",
"Zoom to fit": "全体表示にズーム"

View File

@@ -827,7 +827,11 @@
"Ungroup selected group nodes": "선택한 그룹 노드 그룹 해제",
"Unload Models": "모델 언로드",
"Unload Models and Execution Cache": "모델 및 실행 캐시 언로드",
"Unlock Canvas": "캔버스 잠금 해제",
"Unpack the selected Subgraph": "선택한 서브그래프 풀기",
"View": "보기",
"Workflow": "워크플로",
"Workflows": "워크플로우",
"Zoom In": "확대",
"Zoom Out": "축소",
"Zoom to fit": "화면에 맞추기"

View File

@@ -825,7 +825,11 @@
"Ungroup selected group nodes": "Разгруппировать выбранные групповые ноды",
"Unload Models": "Выгрузить модели",
"Unload Models and Execution Cache": "Выгрузить модели и кэш выполнения",
"Unlock Canvas": "Разблокировать холст",
"Unpack the selected Subgraph": "Распаковать выбранный подграф",
"View": "Вид",
"Workflow": "Рабочий процесс",
"Workflows": "Рабочие процессы",
"Zoom In": "Увеличить",
"Zoom Out": "Уменьшить",
"Zoom to fit": "Масштабировать по размеру"

View File

@@ -825,7 +825,11 @@
"Ungroup selected group nodes": "取消群組選取的群組節點",
"Unload Models": "卸載模型",
"Unload Models and Execution Cache": "卸載模型與執行快取",
"Unlock Canvas": "解除鎖定畫布",
"Unpack the selected Subgraph": "解包所選子圖",
"View": "檢視",
"Workflow": "工作流程",
"Workflows": "工作流程",
"Zoom In": "放大",
"Zoom Out": "縮小"
},

View File

@@ -846,6 +846,7 @@
"Ungroup selected group nodes": "解散选中组节点",
"Unlock Canvas": "解除锁定画布",
"Unpack the selected Subgraph": "解包选中子图",
"View": "视图",
"Workflows": "工作流",
"Zoom In": "放大画面",
"Zoom Out": "缩小画面",