From 95074766dac18ba089cc6aaf649e6479a1be01fe Mon Sep 17 00:00:00 2001 From: Johnpaul Date: Fri, 7 Nov 2025 01:00:06 +0100 Subject: [PATCH 01/11] [feat] Add ActionBarButton interface to extension API Add new ActionBarButton interface with support for: - Lucide icon integration - Optional label text - Custom CSS classes - Tooltip support - Click handlers --- src/types/comfy.ts | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/types/comfy.ts b/src/types/comfy.ts index db0760bbd8..b0cc69d3e0 100644 --- a/src/types/comfy.ts +++ b/src/types/comfy.ts @@ -57,6 +57,29 @@ export interface TopbarBadge { tooltip?: string } +export interface ActionBarButton { + /** + * Icon class to display (e.g., "icon-[lucide--message-circle-question-mark]") + */ + icon: string + /** + * Optional label text to display next to the icon + */ + label?: string + /** + * Optional tooltip text to show on hover + */ + tooltip?: string + /** + * Optional CSS classes to apply to the button + */ + class?: string + /** + * Click handler for the button + */ + onClick: () => void +} + export type MissingNodeType = | string // Primarily used by group nodes. @@ -102,6 +125,10 @@ export interface ComfyExtension { * Badges to add to the top bar */ topbarBadges?: TopbarBadge[] + /** + * Buttons to add to the action bar + */ + actionBarButtons?: ActionBarButton[] /** * Allows any initialisation, e.g. loading resources. Called after the canvas is created but before nodes are added * @param app The ComfyUI app instance From f8fe51a0f46c8d65667889a20b1caf9079fa2561 Mon Sep 17 00:00:00 2001 From: Johnpaul Date: Fri, 7 Nov 2025 01:02:56 +0100 Subject: [PATCH 02/11] [feat] Add action bar button store for extension buttons Create Pinia store to aggregate action bar buttons from all extensions. Uses computed property to dynamically collect buttons from extension store. --- src/stores/actionBarButtonStore.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/stores/actionBarButtonStore.ts diff --git a/src/stores/actionBarButtonStore.ts b/src/stores/actionBarButtonStore.ts new file mode 100644 index 0000000000..cb2730e13b --- /dev/null +++ b/src/stores/actionBarButtonStore.ts @@ -0,0 +1,18 @@ +import { defineStore } from 'pinia' +import { computed } from 'vue' + +import type { ActionBarButton } from '@/types/comfy' + +import { useExtensionStore } from './extensionStore' + +export const useActionBarButtonStore = defineStore('actionBarButton', () => { + const extensionStore = useExtensionStore() + + const buttons = computed(() => + extensionStore.extensions.flatMap((e) => e.actionBarButtons ?? []) + ) + + return { + buttons + } +}) From 055aeff608794eaaccf9d14c96383bd5266c2c52 Mon Sep 17 00:00:00 2001 From: Johnpaul Date: Fri, 7 Nov 2025 01:03:17 +0100 Subject: [PATCH 03/11] [feat] Add ActionBarButtons component for action bar Create component to render action bar buttons with: - Lucide icon support via template slot - Optional label display - Custom styling via class prop - Secondary severity for neutral colors - Tooltip support --- src/components/topbar/ActionBarButtons.vue | 28 ++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/components/topbar/ActionBarButtons.vue diff --git a/src/components/topbar/ActionBarButtons.vue b/src/components/topbar/ActionBarButtons.vue new file mode 100644 index 0000000000..cf84eace22 --- /dev/null +++ b/src/components/topbar/ActionBarButtons.vue @@ -0,0 +1,28 @@ + + + From 9941922cb9f9f2458e3a9094296b41b8dd44e6b6 Mon Sep 17 00:00:00 2001 From: Johnpaul Date: Fri, 7 Nov 2025 01:03:35 +0100 Subject: [PATCH 04/11] [feat] Integrate ActionBarButtons into action bar container Add ActionBarButtons component at the start of the action bar container. Buttons will appear before legacy elements, ComfyActionbar, and user controls. --- src/components/TopMenuSection.vue | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/TopMenuSection.vue b/src/components/TopMenuSection.vue index 438bfaa951..d170305a4d 100644 --- a/src/components/TopMenuSection.vue +++ b/src/components/TopMenuSection.vue @@ -7,6 +7,7 @@
+
Date: Fri, 7 Nov 2025 01:04:04 +0100 Subject: [PATCH 05/11] [feat] Add cloud feedback button extension Add cloud-only extension that registers a feedback button in the action bar. - Uses message-circle-question-mark Lucide icon - Opens Zendesk feedback URL in new tab - Displays 'Feedback' label --- .../core/cloudFeedbackTopbarButton.ts | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/extensions/core/cloudFeedbackTopbarButton.ts diff --git a/src/extensions/core/cloudFeedbackTopbarButton.ts b/src/extensions/core/cloudFeedbackTopbarButton.ts new file mode 100644 index 0000000000..4e2a2cc648 --- /dev/null +++ b/src/extensions/core/cloudFeedbackTopbarButton.ts @@ -0,0 +1,24 @@ +import type { ActionBarButton } from '@/types/comfy' +import { useExtensionService } from '@/services/extensionService' + +// Zendesk feedback URL - update this with the actual URL +const ZENDESK_FEEDBACK_URL = + 'https://comfyorg.zendesk.com/hc/en-us/requests/new' + +const buttons: ActionBarButton[] = [ + { + icon: 'icon-[lucide--message-circle-question-mark]', + label: 'Feedback', + tooltip: 'Feedback', + onClick: () => { + window.open(ZENDESK_FEEDBACK_URL, '_blank', 'noopener,noreferrer') + } + } +] + +useExtensionService().registerExtension({ + name: 'Comfy.Cloud.FeedbackButton', + get actionBarButtons() { + return buttons + } +}) From 663a212f661e9333e08174b7c9bedd9168c77c67 Mon Sep 17 00:00:00 2001 From: Johnpaul Date: Fri, 7 Nov 2025 01:04:46 +0100 Subject: [PATCH 06/11] [feat] Register cloud feedback button extension Import cloudFeedbackTopbarButton extension. Extension loads unconditionally to support action bar buttons API. --- src/extensions/core/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/extensions/core/index.ts b/src/extensions/core/index.ts index a11a61abbf..95802ff4ee 100644 --- a/src/extensions/core/index.ts +++ b/src/extensions/core/index.ts @@ -29,6 +29,7 @@ if (isCloud) { await import('./cloudRemoteConfig') await import('./cloudBadges') await import('./cloudSessionCookie') + await import('./cloudFeedbackTopbarButton') if (window.__CONFIG__?.subscription_required) { await import('./cloudSubscription') From 3282bde0ab0990524ecb66791107f9e7a8a509d3 Mon Sep 17 00:00:00 2001 From: Johnpaul Date: Fri, 7 Nov 2025 01:09:06 +0100 Subject: [PATCH 07/11] [fix] Use i18n translation for feedback button text Replace hardcoded 'Feedback' string with t('g.feedback') translation. Ensures proper localization support for the feedback button. --- src/extensions/core/cloudFeedbackTopbarButton.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/extensions/core/cloudFeedbackTopbarButton.ts b/src/extensions/core/cloudFeedbackTopbarButton.ts index 4e2a2cc648..8fafce7965 100644 --- a/src/extensions/core/cloudFeedbackTopbarButton.ts +++ b/src/extensions/core/cloudFeedbackTopbarButton.ts @@ -1,5 +1,6 @@ -import type { ActionBarButton } from '@/types/comfy' +import { t } from '@/i18n' import { useExtensionService } from '@/services/extensionService' +import type { ActionBarButton } from '@/types/comfy' // Zendesk feedback URL - update this with the actual URL const ZENDESK_FEEDBACK_URL = @@ -8,8 +9,8 @@ const ZENDESK_FEEDBACK_URL = const buttons: ActionBarButton[] = [ { icon: 'icon-[lucide--message-circle-question-mark]', - label: 'Feedback', - tooltip: 'Feedback', + label: t('g.feedback'), + tooltip: t('g.feedback'), onClick: () => { window.open(ZENDESK_FEEDBACK_URL, '_blank', 'noopener,noreferrer') } From 1fe9b0f146b7119f368670a08205849f830317be Mon Sep 17 00:00:00 2001 From: Johnpaul Date: Fri, 7 Nov 2025 01:49:25 +0100 Subject: [PATCH 08/11] update zendesk feedback url --- src/extensions/core/cloudFeedbackTopbarButton.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extensions/core/cloudFeedbackTopbarButton.ts b/src/extensions/core/cloudFeedbackTopbarButton.ts index 8fafce7965..eaeb2345a0 100644 --- a/src/extensions/core/cloudFeedbackTopbarButton.ts +++ b/src/extensions/core/cloudFeedbackTopbarButton.ts @@ -4,7 +4,7 @@ import type { ActionBarButton } from '@/types/comfy' // Zendesk feedback URL - update this with the actual URL const ZENDESK_FEEDBACK_URL = - 'https://comfyorg.zendesk.com/hc/en-us/requests/new' + 'https://support.comfy.org/hc/en-us/requests/new?ticket_form_id=43066738713236' const buttons: ActionBarButton[] = [ { From 5f54ed44ba18a9483456955f29c18e81bca09d0c Mon Sep 17 00:00:00 2001 From: Johnpaul Date: Fri, 7 Nov 2025 07:19:45 +0100 Subject: [PATCH 09/11] fix claude review comments --- src/extensions/core/cloudFeedbackTopbarButton.ts | 8 +++----- src/locales/en/main.json | 4 +++- src/types/comfy.ts | 3 +++ 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/extensions/core/cloudFeedbackTopbarButton.ts b/src/extensions/core/cloudFeedbackTopbarButton.ts index eaeb2345a0..144506d7ea 100644 --- a/src/extensions/core/cloudFeedbackTopbarButton.ts +++ b/src/extensions/core/cloudFeedbackTopbarButton.ts @@ -9,8 +9,8 @@ const ZENDESK_FEEDBACK_URL = const buttons: ActionBarButton[] = [ { icon: 'icon-[lucide--message-circle-question-mark]', - label: t('g.feedback'), - tooltip: t('g.feedback'), + label: t('actionbar.feedback'), + tooltip: t('actionbar.feedbackTooltip'), onClick: () => { window.open(ZENDESK_FEEDBACK_URL, '_blank', 'noopener,noreferrer') } @@ -19,7 +19,5 @@ const buttons: ActionBarButton[] = [ useExtensionService().registerExtension({ name: 'Comfy.Cloud.FeedbackButton', - get actionBarButtons() { - return buttons - } + actionBarButtons: buttons }) diff --git a/src/locales/en/main.json b/src/locales/en/main.json index a471b5f098..8d56e8961a 100644 --- a/src/locales/en/main.json +++ b/src/locales/en/main.json @@ -2282,7 +2282,9 @@ } }, "actionbar": { - "dockToTop": "Dock to top" + "dockToTop": "Dock to top", + "feedback": "Feedback", + "feedbackTOoltip": "Feedback" }, "desktopDialogs": { "": { diff --git a/src/types/comfy.ts b/src/types/comfy.ts index b0cc69d3e0..436e504eff 100644 --- a/src/types/comfy.ts +++ b/src/types/comfy.ts @@ -57,6 +57,9 @@ export interface TopbarBadge { tooltip?: string } +/* + * Action bar button definition: add buttons to the action bar + */ export interface ActionBarButton { /** * Icon class to display (e.g., "icon-[lucide--message-circle-question-mark]") From 45fa1d71f988c5f40d8b1d297ec70404b945ee0c Mon Sep 17 00:00:00 2001 From: Johnpaul Date: Fri, 7 Nov 2025 07:24:28 +0100 Subject: [PATCH 10/11] fix i18n --- src/locales/en/main.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/locales/en/main.json b/src/locales/en/main.json index 8d56e8961a..bcdd87c8cb 100644 --- a/src/locales/en/main.json +++ b/src/locales/en/main.json @@ -2284,7 +2284,7 @@ "actionbar": { "dockToTop": "Dock to top", "feedback": "Feedback", - "feedbackTOoltip": "Feedback" + "feedbackTooltip": "Feedback" }, "desktopDialogs": { "": { From 9dcc4d44854721af8dd9094d5e0c64bca425909f Mon Sep 17 00:00:00 2001 From: Johnpaul Date: Fri, 7 Nov 2025 07:27:18 +0100 Subject: [PATCH 11/11] add aria label --- src/components/topbar/ActionBarButtons.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/topbar/ActionBarButtons.vue b/src/components/topbar/ActionBarButtons.vue index cf84eace22..81b5c42ad0 100644 --- a/src/components/topbar/ActionBarButtons.vue +++ b/src/components/topbar/ActionBarButtons.vue @@ -5,6 +5,7 @@ :key="index" v-tooltip.bottom="button.tooltip" :label="button.label" + :aria-label="button.tooltip || button.label" :class="button.class" text rounded