-
Notifications
You must be signed in to change notification settings - Fork 435
feat: right side panel #6952
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: right side panel #6952
Changes from 23 commits
9056052
2f2f65a
cd3e809
c1bbb7b
fd6defc
1677667
7e9ece2
ff1b9ad
2c33757
464c9b2
828c836
d47af09
56f8f29
8370166
f2fcdd5
e10a0b9
0159622
4be493c
aa429ee
3774b6c
d7fa9a9
cc34422
952f4a1
560339b
0a22d28
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,10 +14,10 @@ | |
| </div> | ||
|
|
||
| <Splitter | ||
| key="main-splitter-stable" | ||
| :key="splitterRefreshKey" | ||
| class="splitter-overlay flex-1 overflow-hidden" | ||
| :pt:gutter="sidebarPanelVisible ? '' : 'hidden'" | ||
| :state-key="sidebarStateKey || 'main-splitter'" | ||
| :pt:gutter="getSplitterGutterClasses" | ||
| :state-key="sidebarStateKey" | ||
| state-storage="local" | ||
| > | ||
| <SplitterPanel | ||
|
|
@@ -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> | ||
|
Comment on lines
+84
to
+92
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: find src -name "LiteGraphCanvasSplitterOverlay.vue" -type fRepository: Comfy-Org/ComfyUI_frontend Length of output: 119 🏁 Script executed: wc -l src/components/LiteGraphCanvasSplitterOverlay.vueRepository: Comfy-Org/ComfyUI_frontend Length of output: 123 🏁 Script executed: cat -n src/components/LiteGraphCanvasSplitterOverlay.vueRepository: Comfy-Org/ComfyUI_frontend Length of output: 7416 🏁 Script executed: head -n 220 src/components/LiteGraphCanvasSplitterOverlay.vue | cat -nRepository: Comfy-Org/ComfyUI_frontend Length of output: 7416 🏁 Script executed: cat src/components/LiteGraphCanvasSplitterOverlay.vueRepository: Comfy-Org/ComfyUI_frontend Length of output: 5988 🏁 Script executed: sed -n '170,185p' src/components/LiteGraphCanvasSplitterOverlay.vueRepository: Comfy-Org/ComfyUI_frontend Length of output: 338 🏁 Script executed: sed -n '60,180p' src/components/LiteGraphCanvasSplitterOverlay.vue | cat -nRepository: Comfy-Org/ComfyUI_frontend Length of output: 4310 🏁 Script executed: sed -n '1,100p' src/components/LiteGraphCanvasSplitterOverlay.vue | tail -n 50Repository: Comfy-Org/ComfyUI_frontend Length of output: 1545 🏁 Script executed: grep -n "sidebarLocation" src/components/LiteGraphCanvasSplitterOverlay.vueRepository: Comfy-Org/ComfyUI_frontend Length of output: 613 🏁 Script executed: sed -n '1,65p' src/components/LiteGraphCanvasSplitterOverlay.vue | cat -nRepository: Comfy-Org/ComfyUI_frontend Length of output: 2581 🏁 Script executed: grep -n "topPositionedSidebar\|leftPositionedSidebar\|rightPositionedSidebar" src/components/LiteGraphCanvasSplitterOverlay.vueRepository: Comfy-Org/ComfyUI_frontend Length of output: 52 🏁 Script executed: grep -rn "sidebarLocation.*right\|right.*sidebar" src/components/LiteGraphCanvasSplitterOverlay.vueRepository: Comfy-Org/ComfyUI_frontend Length of output: 377 🏁 Script executed: sed -n '1,65p' src/components/LiteGraphCanvasSplitterOverlay.vue | cat -nRepository: Comfy-Org/ComfyUI_frontend Length of output: 2581 🏁 Script executed: head -n 70 src/components/LiteGraphCanvasSplitterOverlay.vueRepository: Comfy-Org/ComfyUI_frontend Length of output: 2293 🏁 Script executed: grep -A5 -B5 "topPositionedSidebar\|leftPositionedSidebar" src/components/LiteGraphCanvasSplitterOverlay.vue | head -n 30Repository: Comfy-Org/ComfyUI_frontend Length of output: 52 🏁 Script executed: sed -n '20,45p' src/components/LiteGraphCanvasSplitterOverlay.vueRepository: Comfy-Org/ComfyUI_frontend Length of output: 886 🏁 Script executed: sed -n '15,50p' src/components/LiteGraphCanvasSplitterOverlay.vueRepository: Comfy-Org/ComfyUI_frontend Length of output: 1206 🏁 Script executed: grep -A3 "sidebarLocation" src/components/LiteGraphCanvasSplitterOverlay.vue | head -n 10Repository: Comfy-Org/ComfyUI_frontend Length of output: 377 🏁 Script executed: python3 << 'EOF'
with open('src/components/LiteGraphCanvasSplitterOverlay.vue', 'r') as f:
content = f.read()
# Find the props section
import re
props_match = re.search(r'defineProps.*?\{.*?\}(?=\s*[\n);])', content, re.DOTALL)
if props_match:
print(props_match.group(0)[:1500])
EOFRepository: Comfy-Org/ComfyUI_frontend Length of output: 156 🏁 Script executed: ast-grep --pattern 'defineProps<$_>()'Repository: Comfy-Org/ComfyUI_frontend Length of output: 52 🏁 Script executed: grep -n "computed" src/components/LiteGraphCanvasSplitterOverlay.vueRepository: Comfy-Org/ComfyUI_frontend Length of output: 553 🏁 Script executed: sed -n '20,65p' src/components/LiteGraphCanvasSplitterOverlay.vue | cat -nRepository: Comfy-Org/ComfyUI_frontend Length of output: 1878 🏁 Script executed: grep -rn "sidebarLocation.*=.*['\"]right" src/ --include="*.vue" --include="*.ts" | head -n 20Repository: Comfy-Org/ComfyUI_frontend Length of output: 1420 🏁 Script executed: grep -rn "sidebarLocation" src/ --include="*.vue" --include="*.ts" | grep -E "(type|interface|as const|enum)" | head -n 20Repository: Comfy-Org/ComfyUI_frontend Length of output: 52 🏁 Script executed: find src -name "*store*" -o -name "*settings*" | grep -E "\.(ts|js|vue)$"Repository: Comfy-Org/ComfyUI_frontend Length of output: 96 🏁 Script executed: grep -rn "sidebarLocation" src/stores src/composables --include="*.ts" 2>/dev/null | head -n 20Repository: Comfy-Org/ComfyUI_frontend Length of output: 52 🏁 Script executed: find . -name "*.test.*" -o -name "*.spec.*" | grep -i "LiteGraphCanvasSplitterOverlay\|splitter"Repository: Comfy-Org/ComfyUI_frontend Length of output: 52 🏁 Script executed: find . -path "*/node_modules" -prune -o -type f -name "*.spec.*" -print | head -n 20Repository: Comfy-Org/ComfyUI_frontend Length of output: 920 🏁 Script executed: sed -n '60,120p' src/components/LiteGraphCanvasSplitterOverlay.vue | cat -nRepository: Comfy-Org/ComfyUI_frontend Length of output: 2309 🏁 Script executed: sed -n '84,120p' src/components/LiteGraphCanvasSplitterOverlay.vue | cat -nRepository: Comfy-Org/ComfyUI_frontend Length of output: 1502 🏁 Script executed: find src/components -name "*Sidebar*" -o -name "*sidebar*" | head -n 10Repository: Comfy-Org/ComfyUI_frontend Length of output: 534 🏁 Script executed: ls -la src/components/ | grep -i sidebarRepository: Comfy-Org/ComfyUI_frontend Length of output: 127 🏁 Script executed: grep -rn "LiteGraphCanvasSplitterOverlay" src/ --include="*.vue" --include="*.ts" | grep -v "import"Repository: Comfy-Org/ComfyUI_frontend Length of output: 240 🏁 Script executed: grep -rn "LiteGraphCanvasSplitterOverlay" src/ --include="*.vue" -A5 -B2 | head -n 40Repository: Comfy-Org/ComfyUI_frontend Length of output: 2044 🏁 Script executed: grep -n "rightPositionedSidebar\|const.*sidebar\|computed.*sidebar" src/components/LiteGraphCanvasSplitterOverlay.vueRepository: Comfy-Org/ComfyUI_frontend Length of output: 217 Right-side panel can coexist with right-positioned sidebar, creating layout constraints When
Test this layout on smaller viewports to verify the main canvas remains usable and gutter handles discoverable when both right-side panels are visible. Consider whether adaptive sizing or constraints are needed when both panels are enabled. 🤖 Prompt for AI Agents |
||
| </Splitter> | ||
| </div> | ||
| </div> | ||
|
|
@@ -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') | ||
| ) | ||
|
|
@@ -109,6 +121,7 @@ const sidebarPanelVisible = computed( | |
| const bottomPanelVisible = computed( | ||
| () => useBottomPanelStore().bottomPanelVisible | ||
| ) | ||
| const rightSidePanelVisible = computed(() => rightSidePanelStore.isOpen) | ||
| const activeSidebarTabId = computed( | ||
| () => useSidebarTabStore().activeSidebarTabId | ||
| ) | ||
|
|
@@ -120,6 +133,21 @@ const sidebarStateKey = computed(() => { | |
| // When no tab is active, use a default key to maintain state | ||
| return activeSidebarTabId.value ?? 'default-sidebar' | ||
| }) | ||
| /** | ||
| * Force refresh the splitter when right panel visibility changes to recalculate the width | ||
| */ | ||
| const splitterRefreshKey = computed(() => { | ||
| return rightSidePanelVisible.value | ||
| ? 'main-splitter-with-right-panel' | ||
| : '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> | ||
|
|
@@ -135,10 +163,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); | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -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
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove The button is only rendered when the panel is closed ( Consider one of these approaches:
Apply this diff to remove the unnecessary <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
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <QueueProgressOverlay | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| v-model:expanded="isQueueOverlayExpanded" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -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() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -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(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
cat -n src/components/LiteGraphCanvasSplitterOverlay.vue | head -100Repository: Comfy-Org/ComfyUI_frontend
Length of output: 3799
🏁 Script executed:
Repository: Comfy-Org/ComfyUI_frontend
Length of output: 757
🏁 Script executed:
Repository: Comfy-Org/ComfyUI_frontend
Length of output: 686
🏁 Script executed:
Repository: Comfy-Org/ComfyUI_frontend
Length of output: 825
🏁 Script executed:
Repository: Comfy-Org/ComfyUI_frontend
Length of output: 97
🏁 Script executed:
Repository: Comfy-Org/ComfyUI_frontend
Length of output: 97
🏁 Script executed:
Repository: Comfy-Org/ComfyUI_frontend
Length of output: 1629
🏁 Script executed:
Repository: Comfy-Org/ComfyUI_frontend
Length of output: 362
🏁 Script executed:
Repository: Comfy-Org/ComfyUI_frontend
Length of output: 1752
🏁 Script executed:
Repository: Comfy-Org/ComfyUI_frontend
Length of output: 97
🏁 Script executed:
Repository: Comfy-Org/ComfyUI_frontend
Length of output: 300
🏁 Script executed:
Repository: Comfy-Org/ComfyUI_frontend
Length of output: 1543
🏁 Script executed:
Repository: Comfy-Org/ComfyUI_frontend
Length of output: 625
🏁 Script executed:
Repository: Comfy-Org/ComfyUI_frontend
Length of output: 52
Include
rightSidePanelVisiblein thesidebarStateKeyto prevent localStorage state mismatch when the right panel opens/closes.When
rightSidePanelVisiblechanges,splitterRefreshKeyforces a Splitter remount, butsidebarStateKeyremains unchanged (derived only fromunifiedWidthandactiveSidebarTabId). The Splitter then loads saved sizes from localStorage using the samestate-key, even though the panel configuration has changed (3 panels → 4 panels, or vice versa). This causes PrimeVue to apply sizes saved for the old layout to the new layout, resulting in misaligned widths.Consider:
rightSidePanelVisibleto thesidebarStateKeycomputation so each configuration has its own persisted state, orstate-keywhen the right panel is presentAlso,
getSplitterGutterClassesreturns an empty string; this could be simplified to a literal""unless you expect to add dynamic classes later.🤖 Prompt for AI Agents