+
+
+
+
+
+
diff --git a/src/extensions/core/cloudFeedbackTopbarButton.ts b/src/extensions/core/cloudFeedbackTopbarButton.ts
new file mode 100644
index 0000000000..144506d7ea
--- /dev/null
+++ b/src/extensions/core/cloudFeedbackTopbarButton.ts
@@ -0,0 +1,23 @@
+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 =
+ 'https://support.comfy.org/hc/en-us/requests/new?ticket_form_id=43066738713236'
+
+const buttons: ActionBarButton[] = [
+ {
+ icon: 'icon-[lucide--message-circle-question-mark]',
+ label: t('actionbar.feedback'),
+ tooltip: t('actionbar.feedbackTooltip'),
+ onClick: () => {
+ window.open(ZENDESK_FEEDBACK_URL, '_blank', 'noopener,noreferrer')
+ }
+ }
+]
+
+useExtensionService().registerExtension({
+ name: 'Comfy.Cloud.FeedbackButton',
+ actionBarButtons: buttons
+})
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')
diff --git a/src/locales/en/main.json b/src/locales/en/main.json
index a471b5f098..bcdd87c8cb 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/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
+ }
+})
diff --git a/src/types/comfy.ts b/src/types/comfy.ts
index db0760bbd8..436e504eff 100644
--- a/src/types/comfy.ts
+++ b/src/types/comfy.ts
@@ -57,6 +57,32 @@ 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]")
+ */
+ 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 +128,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