diff --git a/browser_tests/tests/propertiesPanel/propertiesPanelPosition.spec.ts b/browser_tests/tests/propertiesPanel/propertiesPanelPosition.spec.ts
new file mode 100644
index 000000000..ee2c85eda
--- /dev/null
+++ b/browser_tests/tests/propertiesPanel/propertiesPanelPosition.spec.ts
@@ -0,0 +1,86 @@
+import { expect } from '@playwright/test'
+
+import { comfyPageFixture as test } from '../../fixtures/ComfyPage'
+
+test.describe('Properties panel position', () => {
+ test.beforeEach(async ({ comfyPage }) => {
+ // Open a sidebar tab to ensure sidebar is visible
+ await comfyPage.menu.nodeLibraryTab.open()
+ await comfyPage.actionbar.propertiesButton.click()
+ })
+
+ test('positions on the right when sidebar is on the left', async ({
+ comfyPage
+ }) => {
+ await comfyPage.setSetting('Comfy.Sidebar.Location', 'left')
+ await comfyPage.nextFrame()
+
+ const propertiesPanel = comfyPage.page.getByTestId('properties-panel')
+ const sidebar = comfyPage.page.locator('.side-bar-panel').first()
+
+ await expect(propertiesPanel).toBeVisible()
+ await expect(sidebar).toBeVisible()
+
+ const propsBoundingBox = await propertiesPanel.boundingBox()
+ const sidebarBoundingBox = await sidebar.boundingBox()
+
+ expect(propsBoundingBox).not.toBeNull()
+ expect(sidebarBoundingBox).not.toBeNull()
+
+ // Properties panel should be to the right of the sidebar
+ expect(propsBoundingBox!.x).toBeGreaterThan(
+ sidebarBoundingBox!.x + sidebarBoundingBox!.width
+ )
+ })
+
+ test('positions on the left when sidebar is on the right', async ({
+ comfyPage
+ }) => {
+ await comfyPage.setSetting('Comfy.Sidebar.Location', 'right')
+ await comfyPage.nextFrame()
+
+ const propertiesPanel = comfyPage.page.getByTestId('properties-panel')
+ const sidebar = comfyPage.page.locator('.side-bar-panel').first()
+
+ await expect(propertiesPanel).toBeVisible()
+ await expect(sidebar).toBeVisible()
+
+ const propsBoundingBox = await propertiesPanel.boundingBox()
+ const sidebarBoundingBox = await sidebar.boundingBox()
+
+ expect(propsBoundingBox).not.toBeNull()
+ expect(sidebarBoundingBox).not.toBeNull()
+
+ // Properties panel should be to the left of the sidebar
+ expect(propsBoundingBox!.x + propsBoundingBox!.width).toBeLessThan(
+ sidebarBoundingBox!.x
+ )
+ })
+
+ test('close button icon updates based on sidebar location', async ({
+ comfyPage
+ }) => {
+ const propertiesPanel = comfyPage.page.getByTestId('properties-panel')
+
+ // When sidebar is on the left, panel is on the right
+ await comfyPage.setSetting('Comfy.Sidebar.Location', 'left')
+ await comfyPage.nextFrame()
+
+ await expect(propertiesPanel).toBeVisible()
+ const closeButtonLeft = propertiesPanel
+ .locator('button[aria-pressed]')
+ .locator('i')
+ await expect(closeButtonLeft).toBeVisible()
+ await expect(closeButtonLeft).toHaveClass(/lucide--panel-right/)
+
+ // When sidebar is on the right, panel is on the left
+ await comfyPage.setSetting('Comfy.Sidebar.Location', 'right')
+ await comfyPage.nextFrame()
+
+ const closeButtonRight = propertiesPanel
+ .locator('button[aria-pressed]')
+ .locator('i')
+ await expect(closeButtonRight).toBeVisible()
+ await expect(closeButtonRight).toHaveClass(/lucide--panel-left/)
+ })
+})
diff --git a/src/components/LiteGraphCanvasSplitterOverlay.vue b/src/components/LiteGraphCanvasSplitterOverlay.vue
index 4d56e623b..4a7695d18 100644
--- a/src/components/LiteGraphCanvasSplitterOverlay.vue
+++ b/src/components/LiteGraphCanvasSplitterOverlay.vue
@@ -22,29 +22,38 @@
state-storage="local"
@resizestart="onResizestart"
>
+
+
+
@@ -73,38 +82,33 @@
+
+
-
-
-
@@ -117,6 +121,7 @@ import Splitter from 'primevue/splitter'
import type { SplitterResizeStartEvent } from 'primevue/splitter'
import SplitterPanel from 'primevue/splitterpanel'
import { computed } from 'vue'
+import { useI18n } from 'vue-i18n'
import { useSettingStore } from '@/platform/settings/settingStore'
import { useBottomPanelStore } from '@/stores/workspace/bottomPanelStore'
@@ -128,6 +133,7 @@ const workspaceStore = useWorkspaceStore()
const settingStore = useSettingStore()
const rightSidePanelStore = useRightSidePanelStore()
const sidebarTabStore = useSidebarTabStore()
+const { t } = useI18n()
const sidebarLocation = computed<'left' | 'right'>(() =>
settingStore.get('Comfy.Sidebar.Location')
)
@@ -159,12 +165,25 @@ function onResizestart({ originalEvent: event }: SplitterResizeStartEvent) {
}
/*
- * Force refresh the splitter when right panel visibility changes to recalculate the width
+ * Force refresh the splitter when right panel visibility or sidebar location changes
+ * to recalculate the width and panel order
*/
const splitterRefreshKey = computed(() => {
- return rightSidePanelVisible.value
- ? 'main-splitter-with-right-panel'
- : 'main-splitter'
+ return `main-splitter${rightSidePanelVisible.value ? '-with-right-panel' : ''}-${sidebarLocation.value}`
+})
+
+const firstPanelStyle = computed(() => {
+ if (sidebarLocation.value === 'left') {
+ return { display: sidebarPanelVisible.value ? 'flex' : 'none' }
+ }
+ return undefined
+})
+
+const lastPanelStyle = computed(() => {
+ if (sidebarLocation.value === 'right') {
+ return { display: sidebarPanelVisible.value ? 'flex' : 'none' }
+ }
+ return undefined
})
diff --git a/src/components/rightSidePanel/RightSidePanel.vue b/src/components/rightSidePanel/RightSidePanel.vue
index 50dc9de33..4eb2ae31b 100644
--- a/src/components/rightSidePanel/RightSidePanel.vue
+++ b/src/components/rightSidePanel/RightSidePanel.vue
@@ -9,6 +9,7 @@ import TabList from '@/components/tab/TabList.vue'
import Button from '@/components/ui/button/Button.vue'
import { SubgraphNode } from '@/lib/litegraph/src/litegraph'
import type { LGraphNode } from '@/lib/litegraph/src/litegraph'
+import { useSettingStore } from '@/platform/settings/settingStore'
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
import { useRightSidePanelStore } from '@/stores/workspace/rightSidePanelStore'
import type { RightSidePanelTab } from '@/stores/workspace/rightSidePanelStore'
@@ -22,11 +23,23 @@ import SubgraphEditor from './subgraph/SubgraphEditor.vue'
const canvasStore = useCanvasStore()
const rightSidePanelStore = useRightSidePanelStore()
+const settingStore = useSettingStore()
const { t } = useI18n()
const { selectedItems } = storeToRefs(canvasStore)
const { activeTab, isEditingSubgraph } = storeToRefs(rightSidePanelStore)
+const sidebarLocation = computed<'left' | 'right'>(() =>
+ settingStore.get('Comfy.Sidebar.Location')
+)
+
+// Panel is on the left when sidebar is on the right, and vice versa
+const panelIcon = computed(() =>
+ sidebarLocation.value === 'right'
+ ? 'icon-[lucide--panel-left]'
+ : 'icon-[lucide--panel-right]'
+)
+
const hasSelection = computed(() => selectedItems.value.length > 0)
const selectedNodes = computed((): LGraphNode[] => {
@@ -160,7 +173,7 @@ function handleTitleCancel() {
:aria-label="t('rightSidePanel.togglePanel')"
@click="closePanel"
>
-
+
diff --git a/src/locales/en/main.json b/src/locales/en/main.json
index af70861a3..a1f15efe8 100644
--- a/src/locales/en/main.json
+++ b/src/locales/en/main.json
@@ -648,6 +648,7 @@
"box": "Box"
},
"sideToolbar": {
+ "sidebar": "Sidebar",
"themeToggle": "Toggle Theme",
"helpCenter": "Help Center",
"logout": "Logout",