+
} onClick={onOpenSearch} aria-label="搜索画布节点" title="搜索画布节点" />
- } aria-label="导入第三方画布" title="导入第三方画布">
+ } aria-label="导入第三方画布" title="导入第三方画布">
导入第三方画布
@@ -222,13 +209,13 @@ export function CanvasTopBar({
],
}}
>
-
} aria-label="媒体性能模式" title="媒体性能模式" />
+
} aria-label="媒体性能模式" title="媒体性能模式" />
{compactAgentStatus ?
: null}
{user && creditsEnabled ? (
@@ -239,7 +226,7 @@ export function CanvasTopBar({
}
onClick={onEnterFocusMode}
@@ -250,24 +237,26 @@ export function CanvasTopBar({
}
onClick={handleShortDramaGuideToggle}
aria-label="短剧流程"
+ aria-pressed={!shortDramaGuide.collapsed}
>
{shortDramaGuide.progress.completedCount}/5
) : null}
- } onClick={onShare} aria-label="分享画布" title="分享画布" />
+ } onClick={onShare} aria-label="分享画布" title="分享画布" />
}
onClick={onToggleAgent}
+ aria-pressed={agentOpen}
>
Agent
@@ -301,19 +290,20 @@ export function CanvasTopBar({
);
}
-function CanvasWorkspaceModeSwitch({ mode, onChange, open, onOpenChange }: { mode: CanvasWorkspaceMode; onChange: (mode: CanvasWorkspaceMode) => void; open: boolean; onOpenChange: (open: boolean) => void }) {
+export function CanvasWorkspaceModeSwitch({ mode, onChange }: { mode: CanvasWorkspaceMode; onChange: (mode: CanvasWorkspaceMode) => void }) {
const theme = canvasThemes[useThemeStore((state) => state.theme)];
const reducedMotion = useReducedMotion();
const simple = mode === "simple";
const rootRef = useRef(null);
+ const [open, setOpen] = useState(false);
useEffect(() => {
if (!open) return;
const closeOnOutsidePress = (event: PointerEvent) => {
- if (event.target instanceof Node && !rootRef.current?.contains(event.target)) onOpenChange(false);
+ if (event.target instanceof Node && !rootRef.current?.contains(event.target)) setOpen(false);
};
const closeOnEscape = (event: KeyboardEvent) => {
- if (event.key === "Escape") onOpenChange(false);
+ if (event.key === "Escape") setOpen(false);
};
document.addEventListener("pointerdown", closeOnOutsidePress);
document.addEventListener("keydown", closeOnEscape);
@@ -321,26 +311,26 @@ function CanvasWorkspaceModeSwitch({ mode, onChange, open, onOpenChange }: { mod
document.removeEventListener("pointerdown", closeOnOutsidePress);
document.removeEventListener("keydown", closeOnEscape);
};
- }, [open, onOpenChange]);
+ }, [open]);
const selectMode = (nextMode: CanvasWorkspaceMode) => {
if (nextMode !== mode) onChange(nextMode);
- onOpenChange(false);
+ setOpen(false);
};
return (
-
+
onOpenChange(!open)}
+ onClick={() => setOpen((value) => !value)}
>
{simple ? : }
@@ -351,18 +341,18 @@ function CanvasWorkspaceModeSwitch({ mode, onChange, open, onOpenChange }: { mod
-
+
{open ? (
} title="简洁模式" description="保留核心创作路径,降低参数密度" theme={theme} onClick={() => selectMode("simple")} />
} title="专业模式" description="显示完整节点、导演台与生成控制" theme={theme} onClick={() => selectMode("professional")} />
@@ -384,7 +374,7 @@ function ModeOption({ active, motionEnabled, icon, title, description, theme, on
aria-selected={active}
whileTap={motionEnabled ? { scale: 0.98 } : undefined}
transition={aceternityMotion.spring.dock}
- className="group flex min-h-14 w-full items-center gap-3 rounded-[var(--r-md)] px-3 py-2 text-left outline-none transition-colors hover:bg-black/5 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-0 dark:hover:bg-white/8"
+ className="canvas-mode-switch-option group flex min-h-14 w-full items-center gap-3 rounded-[var(--r-md)] px-3 py-2 text-left outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-0"
style={{ background: active ? theme.accent.primarySoft : "transparent", color: theme.node.text, outlineColor: theme.accent.primary }}
onClick={onClick}
>
@@ -414,7 +404,7 @@ function CompactAgentStatus({ status, onClick }: { status: { connected: boolean;
const label = status.connected ? "已连接到本地 Codex" : status.enabled ? status.activity || "连接中" : "正在连接本地 Codex";
const dotColor = status.connected ? "#22c55e" : status.enabled ? "#f59e0b" : theme.node.muted;
return (
-