44 <nav class =" help-menu-section" role =" menubar" >
55 <button
66 v-for =" menuItem in menuItems"
7+ v-show =" menuItem.visible !== false"
78 :key =" menuItem.key"
89 type =" button"
910 class =" help-menu-item"
2930 @mouseenter =" onSubmenuHover"
3031 @mouseleave =" onSubmenuLeave"
3132 >
32- <template v-for =" submenuItem in submenuItems " :key =" submenuItem .key " >
33- <div v-if =" submenuItem.type === 'divider'" class =" submenu-divider" />
33+ <template
34+ v-for =" submenuItem in moreMenuItem ?.items "
35+ :key =" submenuItem .key "
36+ >
37+ <div
38+ v-if =" submenuItem.type === 'divider'"
39+ v-show =" submenuItem.visible !== false"
40+ class =" submenu-divider"
41+ />
3442 <button
3543 v-else
44+ v-show =" submenuItem.visible !== false"
3645 type =" button"
3746 class =" help-menu-item submenu-item"
38- :class =" { disabled: submenuItem.disabled }"
39- :disabled =" submenuItem.disabled"
4047 role =" menuitem"
4148 @click =" submenuItem.action"
4249 >
@@ -117,32 +124,28 @@ import { type CSSProperties, computed, nextTick, onMounted, ref } from 'vue'
117124import { useI18n } from ' vue-i18n'
118125
119126import { type ReleaseNote } from ' @/services/releaseService'
127+ import { useCommandStore } from ' @/stores/commandStore'
120128import { useReleaseStore } from ' @/stores/releaseStore'
121129import { electronAPI , isElectron } from ' @/utils/envUtil'
122130import { formatVersionAnchor } from ' @/utils/formatUtil'
123131
124132// Types
125133interface MenuItem {
126134 key: string
127- icon: string
128- label: string
129- action: () => void
130- }
131-
132- interface SubmenuItem {
133- key: string
134- type? : ' item' | ' divider'
135+ icon? : string
135136 label? : string
136137 action? : () => void
137- disabled? : boolean
138+ visible? : boolean
139+ type? : ' item' | ' divider'
140+ items? : MenuItem []
138141}
139142
140143// Constants
141144const EXTERNAL_LINKS = {
142145 DOCS: ' https://docs.comfy.org/' ,
143146 DISCORD: ' https://www.comfy.org/discord' ,
144147 GITHUB: ' https://github.com/comfyanonymous/ComfyUI' ,
145- DESKTOP_GUIDE: ' https://docs.comfy.org/installation/desktop ' ,
148+ DESKTOP_GUIDE: ' https://comfyorg.notion.site/ ' ,
146149 UPDATE_GUIDE: ' https://docs.comfy.org/installation/update_comfyui'
147150} as const
148151
@@ -164,6 +167,12 @@ const SUBMENU_CONFIG = {
164167// Composables
165168const { t, locale } = useI18n ()
166169const releaseStore = useReleaseStore ()
170+ const commandStore = useCommandStore ()
171+
172+ // Emits
173+ const emit = defineEmits <{
174+ close: []
175+ }>()
167176
168177// State
169178const isSubmenuVisible = ref (false )
@@ -174,66 +183,99 @@ let hoverTimeout: number | null = null
174183// Computed
175184const hasReleases = computed (() => releaseStore .releases .length > 0 )
176185
177- const menuItems = computed <MenuItem []>(() => [
178- {
179- key: ' docs' ,
180- icon: ' pi pi-book' ,
181- label: t (' helpCenter.docs' ),
182- action : () => openExternalLink (EXTERNAL_LINKS .DOCS )
183- },
184- {
185- key: ' discord' ,
186- icon: ' pi pi-discord' ,
187- label: ' Discord' ,
188- action : () => openExternalLink (EXTERNAL_LINKS .DISCORD )
189- },
190- {
191- key: ' github' ,
192- icon: ' pi pi-github' ,
193- label: t (' helpCenter.github' ),
194- action : () => openExternalLink (EXTERNAL_LINKS .GITHUB )
195- },
196- {
197- key: ' help' ,
198- icon: ' pi pi-question-circle' ,
199- label: t (' helpCenter.helpFeedback' ),
200- action : () => openExternalLink (EXTERNAL_LINKS .DISCORD )
201- },
202- {
203- key: ' more' ,
204- icon: ' ' ,
205- label: t (' helpCenter.more' ),
206- action : () => {} // No action for more item
207- }
208- ])
209-
210- const submenuItems = computed <SubmenuItem []>(() => [
211- {
212- key: ' desktop-guide' ,
213- type: ' item' ,
214- label: t (' helpCenter.desktopUserGuide' ),
215- action : () => openExternalLink (EXTERNAL_LINKS .DESKTOP_GUIDE ),
216- disabled: false
217- },
218- {
219- key: ' dev-tools' ,
220- type: ' item' ,
221- label: t (' helpCenter.openDevTools' ),
222- action: openDevTools ,
223- disabled: ! isElectron ()
224- },
225- {
226- key: ' divider-1' ,
227- type: ' divider'
228- },
229- {
230- key: ' reinstall' ,
231- type: ' item' ,
232- label: t (' helpCenter.reinstall' ),
233- action: onReinstall ,
234- disabled: ! isElectron ()
235- }
236- ])
186+ const moreMenuItem = computed (() =>
187+ menuItems .value .find ((item ) => item .key === ' more' )
188+ )
189+
190+ const menuItems = computed <MenuItem []>(() => {
191+ const moreItems: MenuItem [] = [
192+ {
193+ key: ' desktop-guide' ,
194+ type: ' item' ,
195+ label: t (' helpCenter.desktopUserGuide' ),
196+ action : () => {
197+ openExternalLink (EXTERNAL_LINKS .DESKTOP_GUIDE )
198+ emit (' close' )
199+ }
200+ },
201+ {
202+ key: ' dev-tools' ,
203+ type: ' item' ,
204+ label: t (' helpCenter.openDevTools' ),
205+ visible: isElectron (),
206+ action : () => {
207+ openDevTools ()
208+ emit (' close' )
209+ }
210+ },
211+ {
212+ key: ' divider-1' ,
213+ type: ' divider' ,
214+ visible: isElectron ()
215+ },
216+ {
217+ key: ' reinstall' ,
218+ type: ' item' ,
219+ label: t (' helpCenter.reinstall' ),
220+ visible: isElectron (),
221+ action : () => {
222+ onReinstall ()
223+ emit (' close' )
224+ }
225+ }
226+ ]
227+
228+ return [
229+ {
230+ key: ' docs' ,
231+ type: ' item' ,
232+ icon: ' pi pi-book' ,
233+ label: t (' helpCenter.docs' ),
234+ action : () => {
235+ openExternalLink (EXTERNAL_LINKS .DOCS )
236+ emit (' close' )
237+ }
238+ },
239+ {
240+ key: ' discord' ,
241+ type: ' item' ,
242+ icon: ' pi pi-discord' ,
243+ label: ' Discord' ,
244+ action : () => {
245+ openExternalLink (EXTERNAL_LINKS .DISCORD )
246+ emit (' close' )
247+ }
248+ },
249+ {
250+ key: ' github' ,
251+ type: ' item' ,
252+ icon: ' pi pi-github' ,
253+ label: t (' helpCenter.github' ),
254+ action : () => {
255+ openExternalLink (EXTERNAL_LINKS .GITHUB )
256+ emit (' close' )
257+ }
258+ },
259+ {
260+ key: ' help' ,
261+ type: ' item' ,
262+ icon: ' pi pi-question-circle' ,
263+ label: t (' helpCenter.helpFeedback' ),
264+ action : () => {
265+ void commandStore .execute (' Comfy.Feedback' )
266+ emit (' close' )
267+ }
268+ },
269+ {
270+ key: ' more' ,
271+ type: ' item' ,
272+ icon: ' ' ,
273+ label: t (' helpCenter.more' ),
274+ action : () => {}, // No action for more item
275+ items: moreItems
276+ }
277+ ]
278+ })
237279
238280// Utility Functions
239281const openExternalLink = (url : string ): void => {
@@ -251,8 +293,12 @@ const calculateSubmenuPosition = (button: HTMLElement): CSSProperties => {
251293 const rect = button .getBoundingClientRect ()
252294 const submenuWidth = 210 // Width defined in CSS
253295
254- // Get actual submenu height if available, otherwise use estimated height
255- const submenuHeight = submenuRef .value ?.offsetHeight || 120 // More realistic estimate for 2 items
296+ // Get actual submenu height if available, otherwise estimate based on visible item count
297+ const visibleItemCount =
298+ moreMenuItem .value ?.items ?.filter ((item ) => item .visible !== false )
299+ .length || 0
300+ const estimatedHeight = visibleItemCount * 48 + 16 // ~48px per item + padding
301+ const submenuHeight = submenuRef .value ?.offsetHeight || estimatedHeight
256302
257303 // Get viewport dimensions
258304 const viewportWidth = window .innerWidth
@@ -282,6 +328,8 @@ const calculateSubmenuPosition = (button: HTMLElement): CSSProperties => {
282328 top = SUBMENU_CONFIG .OFFSET_PX
283329 }
284330
331+ top -= 8
332+
285333 return {
286334 position: ' fixed' ,
287335 top: ` ${top }px ` ,
@@ -328,7 +376,13 @@ const onMenuItemHover = async (
328376 key : string ,
329377 event : MouseEvent
330378): Promise <void > => {
331- if (key !== ' more' ) return
379+ if (key !== ' more' || ! moreMenuItem .value ?.items ) return
380+
381+ // Don't show submenu if all items are hidden
382+ const hasVisibleItems = moreMenuItem .value .items .some (
383+ (item ) => item .visible !== false
384+ )
385+ if (! hasVisibleItems ) return
332386
333387 clearHoverTimeout ()
334388
@@ -380,10 +434,12 @@ const onReleaseClick = (release: ReleaseNote): void => {
380434 const versionAnchor = formatVersionAnchor (release .version )
381435 const changelogUrl = ` ${getChangelogUrl ()}#${versionAnchor } `
382436 openExternalLink (changelogUrl )
437+ emit (' close' )
383438}
384439
385440const onUpdate = (_ : ReleaseNote ): void => {
386441 openExternalLink (EXTERNAL_LINKS .UPDATE_GUIDE )
442+ emit (' close' )
387443}
388444
389445// Generate language-aware changelog URL
@@ -551,13 +607,6 @@ onMounted(async () => {
551607 box-shadow : none ;
552608}
553609
554- .submenu-item.disabled ,
555- .submenu-item :disabled {
556- opacity : 0.5 ;
557- cursor : not-allowed ;
558- pointer-events : none ;
559- }
560-
561610.submenu-divider {
562611 height : 1px ;
563612 background : #3e3e3e ;
0 commit comments