Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
39 changes: 37 additions & 2 deletions src/components/LiteGraphCanvasSplitterOverlay.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
<Splitter
key="main-splitter-stable"
class="splitter-overlay flex-1 overflow-hidden"
:pt:gutter="sidebarPanelVisible ? '' : 'hidden'"
:state-key="sidebarStateKey || 'main-splitter'"
:pt:gutter="getSplitterGutterClasses"
:state-key="mainSplitterStateKey"
state-storage="local"
>
<SplitterPanel
Expand Down Expand Up @@ -80,6 +80,16 @@
name="side-bar-panel"
/>
</SplitterPanel>

<!-- Right Side Panel - independent of sidebar -->
<SplitterPanel
v-if="rightSidePanelVisible"
class="right-side-panel pointer-events-auto"
:min-size="15"
:size="20"
>
<slot name="right-side-panel" />
</SplitterPanel>
</Splitter>
</div>
</div>
Expand All @@ -92,9 +102,11 @@ import { computed } from 'vue'

import { useSettingStore } from '@/platform/settings/settingStore'
import { useBottomPanelStore } from '@/stores/workspace/bottomPanelStore'
import { useRightSidePanelStore } from '@/stores/workspace/rightSidePanelStore'
import { useSidebarTabStore } from '@/stores/workspace/sidebarTabStore'

const settingStore = useSettingStore()
const rightSidePanelStore = useRightSidePanelStore()
const sidebarLocation = computed<'left' | 'right'>(() =>
settingStore.get('Comfy.Sidebar.Location')
)
Expand All @@ -109,6 +121,7 @@ const sidebarPanelVisible = computed(
const bottomPanelVisible = computed(
() => useBottomPanelStore().bottomPanelVisible
)
const rightSidePanelVisible = computed(() => rightSidePanelStore.isOpen)
const activeSidebarTabId = computed(
() => useSidebarTabStore().activeSidebarTabId
)
Expand All @@ -120,6 +133,18 @@ const sidebarStateKey = computed(() => {
// When no tab is active, use a default key to maintain state
return activeSidebarTabId.value ?? 'default-sidebar'
})

// Main splitter state key should be independent of right panel state
// to avoid affecting sidebar width when right panel opens/closes
const mainSplitterStateKey = computed(() => {
return sidebarStateKey.value || 'main-splitter'
})

// Gutter visibility should be controlled by CSS targeting specific gutters
const getSplitterGutterClasses = computed(() => {
// Empty string - let individual gutter styles handle visibility
return ''
})
</script>

<style scoped>
Expand All @@ -135,10 +160,20 @@ const sidebarStateKey = computed(() => {
background-color: var(--p-primary-color);
}

/* Hide sidebar gutter when sidebar is not visible */
:deep(.side-bar-panel[style*='display: none'] + .p-splitter-gutter),
:deep(.p-splitter-gutter + .side-bar-panel[style*='display: none']) {
display: none;
}

.side-bar-panel {
background-color: var(--bg-color);
}

.right-side-panel {
background-color: var(--bg-color);
}

.bottom-panel {
background-color: var(--comfy-menu-bg);
border: 1px solid var(--p-panel-border-color);
Expand Down
26 changes: 26 additions & 0 deletions src/components/TopMenuSection.vue
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,20 @@
</IconButton>
<CurrentUserButton v-if="isLoggedIn" class="shrink-0" />
<LoginButton v-else-if="isDesktop" />
<IconButton
v-if="!isRightSidePanelOpen"
v-tooltip.bottom="rightSidePanelTooltipConfig"
type="transparent"
size="sm"
class="mr-2 transition-colors duration-200 ease-in-out hover:bg-secondary-background-hover focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-background"
:aria-pressed="isRightSidePanelOpen"
:aria-label="t('rightSidePanel.togglePanel')"
@click="toggleRightSidePanel"
>
<i
class="icon-[lucide--panel-right] block size-4 text-muted-foreground"
/>
</IconButton>
Comment on lines +47 to +60
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove aria-pressed or keep button always visible for consistency.

The button is only rendered when the panel is closed (v-if="!isRightSidePanelOpen"), which means aria-pressed will always be false when the button is visible. This doesn't follow accessibility best practices for toggle buttons.

Consider one of these approaches:

  1. Recommended: Remove the aria-pressed attribute since the button's visibility already indicates state
  2. Alternative: Keep the button always visible (like the queue history button on lines 23-44) and toggle aria-pressed between true/false

Apply this diff to remove the unnecessary aria-pressed attribute:

         <IconButton
           v-if="!isRightSidePanelOpen"
           v-tooltip.bottom="rightSidePanelTooltipConfig"
           type="transparent"
           size="sm"
           class="mr-2 transition-colors duration-200 ease-in-out hover:bg-secondary-background-hover focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-background"
-          :aria-pressed="isRightSidePanelOpen"
           :aria-label="t('rightSidePanel.togglePanel')"
           @click="toggleRightSidePanel"
         >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<IconButton
v-if="!isRightSidePanelOpen"
v-tooltip.bottom="rightSidePanelTooltipConfig"
type="transparent"
size="sm"
class="mr-2 transition-colors duration-200 ease-in-out hover:bg-secondary-background-hover focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-background"
:aria-pressed="isRightSidePanelOpen"
:aria-label="t('rightSidePanel.togglePanel')"
@click="toggleRightSidePanel"
>
<i
class="icon-[lucide--panel-right] block size-4 text-muted-foreground"
/>
</IconButton>
<IconButton
v-if="!isRightSidePanelOpen"
v-tooltip.bottom="rightSidePanelTooltipConfig"
type="transparent"
size="sm"
class="mr-2 transition-colors duration-200 ease-in-out hover:bg-secondary-background-hover focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-background"
:aria-label="t('rightSidePanel.togglePanel')"
@click="toggleRightSidePanel"
>
<i
class="icon-[lucide--panel-right] block size-4 text-muted-foreground"
/>
</IconButton>
🤖 Prompt for AI Agents
In src/components/TopMenuSection.vue around lines 47 to 60, the IconButton is
conditionally rendered only when the right side panel is closed so aria-pressed
will always be false; remove the unnecessary :aria-pressed binding to avoid a
misleading toggle attribute, keeping the rest of the props and event handler
intact (or alternatively render the button unconditionally and keep
:aria-pressed toggling if you prefer the always-visible pattern).

</div>
<QueueProgressOverlay
v-model:expanded="isQueueOverlayExpanded"
Expand All @@ -68,10 +82,12 @@ import { useCurrentUser } from '@/composables/auth/useCurrentUser'
import { buildTooltipConfig } from '@/composables/useTooltipConfig'
import { app } from '@/scripts/app'
import { useQueueStore } from '@/stores/queueStore'
import { useRightSidePanelStore } from '@/stores/workspace/rightSidePanelStore'
import { useWorkspaceStore } from '@/stores/workspaceStore'
import { isElectron } from '@/utils/envUtil'

const workspaceStore = useWorkspaceStore()
const rightSidePanelStore = useRightSidePanelStore()
const { isLoggedIn } = useCurrentUser()
const isDesktop = isElectron()
const { t } = useI18n()
Expand All @@ -88,6 +104,16 @@ const queueHistoryButtonBackgroundClass = computed(() =>
: 'bg-secondary-background'
)

// Right side panel toggle
const isRightSidePanelOpen = computed(() => rightSidePanelStore.isOpen)
const rightSidePanelTooltipConfig = computed(() =>
buildTooltipConfig(t('rightSidePanel.togglePanel'))
)

const toggleRightSidePanel = () => {
rightSidePanelStore.togglePanel()
}

// Maintain support for legacy topbar elements attached by custom scripts
const legacyCommandsContainerRef = ref<HTMLElement>()
onMounted(() => {
Expand Down
4 changes: 4 additions & 0 deletions src/components/graph/GraphCanvas.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
<template v-if="showUI" #bottom-panel>
<BottomPanel />
</template>
<template v-if="showUI" #right-side-panel>
<NodePropertiesPanel />
</template>
<template #graph-canvas-panel>
<GraphCanvasMenu v-if="canvasMenuEnabled" class="pointer-events-auto" />
<MiniMap
Expand Down Expand Up @@ -110,6 +113,7 @@ import NodeTooltip from '@/components/graph/NodeTooltip.vue'
import SelectionToolbox from '@/components/graph/SelectionToolbox.vue'
import TitleEditor from '@/components/graph/TitleEditor.vue'
import NodeOptions from '@/components/graph/selectionToolbox/NodeOptions.vue'
import NodePropertiesPanel from '@/components/rightSidePanel/RightSidePanel.vue'
import NodeSearchboxPopover from '@/components/searchbox/NodeSearchBoxPopover.vue'
import SideToolbar from '@/components/sidebar/SideToolbar.vue'
import TopbarBadges from '@/components/topbar/TopbarBadges.vue'
Expand Down
10 changes: 8 additions & 2 deletions src/components/graph/selectionToolbox/ConfigureSubgraph.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,17 @@
severity="secondary"
text
icon="icon-[lucide--settings-2]"
@click="showSubgraphNodeDialog"
@click="handleClick"
/>
</template>
<script setup lang="ts">
import Button from 'primevue/button'

import { showSubgraphNodeDialog } from '@/core/graph/subgraph/useSubgraphNodeDialog'
import { useRightSidePanelStore } from '@/stores/workspace/rightSidePanelStore'

const rightSidePanelStore = useRightSidePanelStore()

const handleClick = () => {
rightSidePanelStore.openPanel('subgraph')
}
</script>
Loading