Subgraph/workflow breadcrumbs menu updates (#7852)

## Summary
For users who don't use subgraphs, the workflow name in the top left can
be unnecessarily obstructive so this updated collapses it to a simple
icon until a subgraph is entered.

## Changes

- Add menu button to WorkflowTab for quick workflow actions
- Add menu and back button to SubgraphBreadcrumb
- Extract shared menu items to useBreadcrumbMenu composable
- Add Comfy.RenameWorkflow command for renaming persisted workflows
- Menu always shows root workflow menu, even when in subgraph

## Screenshots (if applicable)

<img width="399" height="396" alt="image"
src="https://github.com/user-attachments/assets/701ab60e-790f-4d1e-a817-dc42b2d98712"
/>
<img width="569" height="381" alt="image"
src="https://github.com/user-attachments/assets/fcea3ab0-8388-4c72-a649-1428c1defd6a"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7852-Subgraph-workflow-breadcrumbs-menu-updates-2df6d73d3650815b8490ca0a9a92d540)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
pythongosssss
2026-01-12 23:08:28 +00:00
committed by GitHub
parent 965ab674d5
commit dfb78b2e87
33 changed files with 479 additions and 146 deletions

View File

@@ -0,0 +1,65 @@
<template>
<span class="relative inline-flex items-center justify-center size-[1em]">
<i :class="mainIcon" class="text-[1em]" />
<i
:class="
cn(
subIcon,
'absolute leading-none pointer-events-none',
positionX === 'left' ? 'left-0' : 'right-0',
positionY === 'top' ? 'top-0' : 'bottom-0'
)
"
:style="subIconStyle"
/>
</span>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { cn } from '@/utils/tailwindUtil'
type Position = 'top' | 'bottom' | 'left' | 'right'
export interface OverlayIconProps {
mainIcon: string
subIcon: string
positionX?: Position
positionY?: Position
offsetX?: number
offsetY?: number
subIconScale?: number
}
const {
mainIcon,
subIcon,
positionX = 'right',
positionY = 'bottom',
offsetX = 0,
offsetY = 0,
subIconScale = 0.6
} = defineProps<OverlayIconProps>()
const textShadow = [
`-1px -1px 0 rgba(0, 0, 0, 0.7)`,
`1px -1px 0 rgba(0, 0, 0, 0.7)`,
`-1px 1px 0 rgba(0, 0, 0, 0.7)`,
`1px 1px 0 rgba(0, 0, 0, 0.7)`,
`-1px 0 0 rgba(0, 0, 0, 0.7)`,
`1px 0 0 rgba(0, 0, 0, 0.7)`,
`0 -1px 0 rgba(0, 0, 0, 0.7)`,
`0 1px 0 rgba(0, 0, 0, 0.7)`
].join(', ')
const subIconStyle = computed(() => ({
fontSize: `${subIconScale}em`,
textShadow,
...(offsetX !== 0 && {
[positionX === 'left' ? 'left' : 'right']: `${offsetX}px`
}),
...(offsetY !== 0 && {
[positionY === 'top' ? 'top' : 'bottom']: `${offsetY}px`
})
}))
</script>