fix: improve rendering menu

This commit is contained in:
2026-03-12 12:22:47 +01:00
parent 49a80e8d91
commit 57207fa082
2 changed files with 33 additions and 41 deletions

View File

@@ -30,11 +30,13 @@ type Props = {
insertTagsLabel?: string insertTagsLabel?: string
/** Extra content in Node menu (e.g. Export submenu for render nodes), before the separator */ /** Extra content in Node menu (e.g. Export submenu for render nodes), before the separator */
nodeMenuExtraContent?: React.ReactNode nodeMenuExtraContent?: React.ReactNode
/** When set, renders a top-level "Output" menu with this content (e.g. render node: preview/raw, viewport, export) */
outputMenuContent?: React.ReactNode
/** When set, renders a top-level "Data" menu with this content (e.g. data nodes) */ /** When set, renders a top-level "Data" menu with this content (e.g. data nodes) */
dataMenuContent?: React.ReactNode dataMenuContent?: React.ReactNode
} }
export function NodeMenubar({ nodeId, nodeType, editInputsContent, inputsMenuContent, insertTagsContent, insertMenuLabel = 'Insert', insertContentDirect, insertTagsLabel = 'Tags', nodeMenuExtraContent, dataMenuContent }: Props) { export function NodeMenubar({ nodeId, nodeType, editInputsContent, inputsMenuContent, insertTagsContent, insertMenuLabel = 'Insert', insertContentDirect, insertTagsLabel = 'Tags', nodeMenuExtraContent, outputMenuContent, dataMenuContent }: Props) {
const ctx = useContext(FlowContext) const ctx = useContext(FlowContext)
const nodes = ctx?.nodes ?? [] const nodes = ctx?.nodes ?? []
const setNodes = ctx?.setNodes const setNodes = ctx?.setNodes
@@ -73,6 +75,16 @@ export function NodeMenubar({ nodeId, nodeType, editInputsContent, inputsMenuCon
</MenubarItem> </MenubarItem>
</MenubarContent> </MenubarContent>
</MenubarMenu> </MenubarMenu>
{outputMenuContent != null && (
<MenubarMenu>
<MenubarTrigger className="px-1.5 py-0 text-xs">
Output
</MenubarTrigger>
<MenubarContent className="min-w-[12rem]">
{outputMenuContent}
</MenubarContent>
</MenubarMenu>
)}
{dataMenuContent != null && ( {dataMenuContent != null && (
<MenubarMenu> <MenubarMenu>
<MenubarTrigger className="px-1.5 py-0 text-xs"> <MenubarTrigger className="px-1.5 py-0 text-xs">

View File

@@ -27,7 +27,7 @@ import { NodeFooterEdgeIndicators } from '@/components/graph/NodeFooterEdgeIndic
import { NodeHeaderTitle } from '@/components/graph/NodeHeaderTitle' import { NodeHeaderTitle } from '@/components/graph/NodeHeaderTitle'
import { NodeMenubar } from '@/components/graph/NodeMenubar' import { NodeMenubar } from '@/components/graph/NodeMenubar'
import { NodeStatusIndicator } from '@/components/graph/NodeStatusIndicator' import { NodeStatusIndicator } from '@/components/graph/NodeStatusIndicator'
import { MenubarItem, MenubarSeparator, MenubarSub, MenubarSubContent, MenubarSubTrigger } from '@/components/ui/menubar' import { MenubarCheckboxItem, MenubarItem, MenubarSeparator, MenubarSub, MenubarSubContent, MenubarSubTrigger } from '@/components/ui/menubar'
import { Sparkles, ZoomIn, ZoomOut, RotateCcw, RotateCw, Copy, Play, ChevronDown } from 'lucide-react' import { Sparkles, ZoomIn, ZoomOut, RotateCcw, RotateCw, Copy, Play, ChevronDown } from 'lucide-react'
import { InputHandle } from '@/components/graph/NodeHandles' import { InputHandle } from '@/components/graph/NodeHandles'
import { TransformWrapper, TransformComponent } from 'react-zoom-pan-pinch' import { TransformWrapper, TransformComponent } from 'react-zoom-pan-pinch'
@@ -41,7 +41,6 @@ import {
DropdownMenuLabel, DropdownMenuLabel,
DropdownMenuTrigger, DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu' } from '@/components/ui/dropdown-menu'
import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group'
import { useTheme } from '@/lib/themeContext' import { useTheme } from '@/lib/themeContext'
import { toast } from 'sonner' import { toast } from 'sonner'
@@ -541,40 +540,6 @@ function RenderingNodeComponent({ id, data, width, height, selected }: Props) {
</DropdownMenuContent> </DropdownMenuContent>
</DropdownMenu> </DropdownMenu>
</ButtonGroup> </ButtonGroup>
<ToggleGroup
type="single"
value={viewMode}
onValueChange={(v) => {
if (v === 'preview' || v === 'raw') setViewMode(v)
}}
aria-label="View mode"
variant="outline"
size="sm"
className="gap-0 rounded-md p-0.5 [&>button]:rounded-none [&>button:first-child]:rounded-l-md [&>button:last-child]:rounded-r-md [&>button:not(:first-child)]:border-l-0"
>
<ToggleGroupItem
value="preview"
aria-label="Preview"
className="gap-1.5 px-2.5 h-7"
onClick={(e) => {
e.stopPropagation()
setViewMode('preview')
}}
>
Preview
</ToggleGroupItem>
<ToggleGroupItem
value="raw"
aria-label="Raw config"
className="gap-1.5 px-2.5 h-7"
onClick={(e) => {
e.stopPropagation()
setViewMode('raw')
}}
>
Raw
</ToggleGroupItem>
</ToggleGroup>
</div> </div>
) : undefined ) : undefined
} }
@@ -585,11 +550,26 @@ function RenderingNodeComponent({ id, data, width, height, selected }: Props) {
<NodeMenubar <NodeMenubar
nodeId={id} nodeId={id}
nodeType="render" nodeType="render"
nodeMenuExtraContent={ outputMenuContent={
<> <>
<MenubarCheckboxItem
className="text-xs"
checked={viewMode === 'preview'}
onCheckedChange={(checked) => checked && setViewMode('preview')}
>
Preview
</MenubarCheckboxItem>
<MenubarCheckboxItem
className="text-xs"
checked={viewMode === 'raw'}
onCheckedChange={(checked) => checked && setViewMode('raw')}
>
Raw
</MenubarCheckboxItem>
<MenubarSeparator />
{outputType === 'image' && ( {outputType === 'image' && (
<MenubarSub> <MenubarSub>
<MenubarSubTrigger className="text-xs">Viewport</MenubarSubTrigger> <MenubarSubTrigger className="text-xs">Viewport size</MenubarSubTrigger>
<MenubarSubContent className="min-w-[12rem] p-2"> <MenubarSubContent className="min-w-[12rem] p-2">
<div className="grid gap-2"> <div className="grid gap-2">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
@@ -631,10 +611,10 @@ function RenderingNodeComponent({ id, data, width, height, selected }: Props) {
</MenubarSubContent> </MenubarSubContent>
</MenubarSub> </MenubarSub>
)} )}
<MenubarSeparator />
<MenubarSub> <MenubarSub>
<MenubarSeparator />
<MenubarSubTrigger className="text-xs" disabled={!isSvgOutput}> <MenubarSubTrigger className="text-xs" disabled={!isSvgOutput}>
Export / Copy Export
</MenubarSubTrigger> </MenubarSubTrigger>
<MenubarSubContent className="min-w-[10rem]" aria-label="Export or copy diagram"> <MenubarSubContent className="min-w-[10rem]" aria-label="Export or copy diagram">
<MenubarItem className="text-xs" onClick={downloadSvg} disabled={!isSvgOutput}> <MenubarItem className="text-xs" onClick={downloadSvg} disabled={!isSvgOutput}>