feat: canvas options

This commit is contained in:
2026-03-11 14:17:12 +01:00
parent 581cfca506
commit 94da42f9fc
4 changed files with 49 additions and 19 deletions

View File

@@ -34,8 +34,6 @@ export type CanvasMenubarProps = {
canDuplicate?: boolean
canCopy?: boolean
onFitView?: () => void
showMinimap?: boolean
onToggleMinimap?: (visible: boolean) => void
}
const UNDO_KEYS = { key: 'z', shiftKey: false }
@@ -59,8 +57,6 @@ export function CanvasMenubar({
canDuplicate = false,
canCopy = false,
onFitView,
showMinimap = false,
onToggleMinimap,
}: CanvasMenubarProps) {
const { projectId } = useParams<{ projectId: string }>()
const { projects, renameProject } = usePlatform()
@@ -233,18 +229,6 @@ export function CanvasMenubar({
</span>
</MenubarItem>
)}
{onToggleMinimap != null && (
<>
<MenubarSeparator />
<MenubarCheckboxItem
checked={showMinimap}
onCheckedChange={(checked) => onToggleMinimap(checked)}
className="gap-2"
>
Minimap
</MenubarCheckboxItem>
</>
)}
</MenubarContent>
</MenubarMenu>
</Menubar>

View File

@@ -25,6 +25,7 @@ import {
import { AnimatedEdge } from '@/components/base/AnimatedEdge'
import FlowContext from '@/lib/flowContext'
import { useTheme } from '@/lib/themeContext'
import { usePlatform } from '@/app/platform/platformContext'
import { useGraphStateWithHistory } from '@/hooks/useGraphStateWithHistory'
import {
ContextMenu,
@@ -148,6 +149,7 @@ function getInitialGraph(projectId: string | undefined): { nodes: AppNode[]; edg
export function CanvasPage({ projectId }: CanvasPageProps) {
const { theme } = useTheme()
const { showMinimap } = usePlatform()
const initialGraph = useMemo(() => getInitialGraph(projectId), [projectId])
const {
nodes,
@@ -190,7 +192,6 @@ export function CanvasPage({ projectId }: CanvasPageProps) {
const [lastCreatedNodeId, setLastCreatedNodeId] = React.useState<string | null>(null)
const [isPanning, setIsPanning] = React.useState(false)
const [isSelecting, setIsSelecting] = React.useState(false)
const [showMinimap, setShowMinimap] = React.useState(false)
const [ariaAnnouncement, setAriaAnnouncement] = React.useState<string | null>(null)
const nodesRef = useRef(nodes)
nodesRef.current = nodes
@@ -570,8 +571,6 @@ export function CanvasPage({ projectId }: CanvasPageProps) {
canDuplicate={selectedNodes.length > 0}
canCopy={selectedNodes.length === 1}
onFitView={() => flowActionsRef.current?.fitView?.()}
showMinimap={showMinimap}
onToggleMinimap={setShowMinimap}
/>
{apiTodosCount !== null && (
<div className="shrink-0 px-3 py-1 text-xs text-muted-foreground border-b border-border/50">

View File

@@ -18,8 +18,10 @@ import {
SelectTrigger,
SelectValue,
} from '@/components/ui/select'
import { Switch } from '@/components/ui/switch'
import { useTheme } from '@/lib/themeContext'
import type { Theme } from '@/lib/themeContext'
import { usePlatform } from './platformContext'
import { Sun, Sparkles } from 'lucide-react'
type SettingsSection = 'appearance' | 'ai'
@@ -32,6 +34,7 @@ export function SettingsDialog({
const [open, setOpen] = useState(false)
const [section, setSection] = useState<SettingsSection>('appearance')
const { theme, setTheme } = useTheme()
const { showMinimap, setShowMinimap } = usePlatform()
return (
<Dialog open={open} onOpenChange={setOpen}>
@@ -88,6 +91,21 @@ export function SettingsDialog({
</SelectContent>
</Select>
</div>
<div className="space-y-3 pt-2 border-t">
<h4 className="text-xs font-medium text-muted-foreground uppercase tracking-wider">
Canvas
</h4>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-[minmax(0,1fr)_auto] sm:items-center">
<label htmlFor="settings-minimap" className="text-sm font-medium">
Minimap
</label>
<Switch
id="settings-minimap"
checked={showMinimap}
onCheckedChange={setShowMinimap}
/>
</div>
</div>
</div>
)}
{section === 'ai' && (

View File

@@ -11,8 +11,24 @@ import { PROJECT_VERSION } from './projectGraphStorage'
const STORAGE_KEY = 'zui_platform_projects'
const ORDER_STORAGE_KEY = 'zui_platform_project_order'
const RECENT_STORAGE_KEY = 'zui_platform_recent_project_ids'
const CANVAS_MINIMAP_KEY = 'zui_canvas_show_minimap'
const RECENT_MAX = 5
function loadShowMinimap(): boolean {
try {
const raw = localStorage.getItem(CANVAS_MINIMAP_KEY)
if (raw === 'true') return true
if (raw === 'false') return false
} catch {}
return false
}
function saveShowMinimap(value: boolean) {
try {
localStorage.setItem(CANVAS_MINIMAP_KEY, JSON.stringify(value))
} catch {}
}
function loadOrder(): string[] {
try {
const raw = localStorage.getItem(ORDER_STORAGE_KEY)
@@ -107,6 +123,9 @@ export type PlatformContextValue = {
updateLastEdited: (id: string) => void
reorderProjects: (orderedIds: string[]) => void
restoreProject: (project: Project, graphSnapshot: GraphSnapshot | null) => void
/** Canvas: show React Flow minimap (persisted) */
showMinimap: boolean
setShowMinimap: (value: boolean) => void
}
const PlatformContext = createContext<PlatformContextValue | null>(null)
@@ -115,6 +134,12 @@ export function PlatformProvider({ children }: { children: React.ReactNode }) {
const [projects, setProjects] = useState<Project[]>(loadProjects)
const [projectOrder, setProjectOrder] = useState<string[]>(loadOrder)
const [recentProjectIds, setRecentProjectIds] = useState<string[]>(loadRecentIds)
const [showMinimap, setShowMinimapState] = useState<boolean>(loadShowMinimap)
const setShowMinimap = useCallback((value: boolean) => {
setShowMinimapState(value)
saveShowMinimap(value)
}, [])
const persist = useCallback((next: Project[]) => {
setProjects(next)
@@ -220,6 +245,8 @@ export function PlatformProvider({ children }: { children: React.ReactNode }) {
updateLastEdited,
reorderProjects,
restoreProject,
showMinimap,
setShowMinimap,
}),
[
projects,
@@ -234,6 +261,8 @@ export function PlatformProvider({ children }: { children: React.ReactNode }) {
updateLastEdited,
reorderProjects,
restoreProject,
showMinimap,
setShowMinimap,
]
)