feat(desktop/studio): Tier1 编排画布主题化 + 节点精修(产品灵魂打磨)
react-flow 此前 colorMode 写死 dark、背景/连线/控件全用库默认,换肤下不协调。改为: - colorMode 绑定当前主题 → 控件/连线/手柄/选区自动随亮暗切换。 - Background 点阵色、MiniMap 遮罩随主题;隐藏库水印(proOptions.hideAttribution,更干净)。 - index.css 精修 react-flow:控件(细边/圆角/themed hover)、连线(中性描边+选中紫)、迷你图边框,对齐设计系统。 - TypedNode:卡面落到表面色(ink-850)、选中环用 brand 令牌(替硬编码紫)、加 hover 描边、手柄themed。 - 工具栏/调色板/检查器已用新 Button + 令牌类,自动一致。 tsc + 生产构建通过;桌面端已 HMR。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -89,3 +89,34 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 输入控件随主题(color-scheme 由 :root/.dark 设定,控件自动继承) */
|
/* 输入控件随主题(color-scheme 由 :root/.dark 设定,控件自动继承) */
|
||||||
|
|
||||||
|
/* react-flow 画布主题化:控件/连线/迷你图与设计系统对齐(colorMode 已处理大半,此处精修) */
|
||||||
|
.react-flow__controls {
|
||||||
|
box-shadow: none;
|
||||||
|
border: 1px solid rgb(var(--line));
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.react-flow__controls-button {
|
||||||
|
background: rgb(var(--ink-900));
|
||||||
|
border-bottom: 1px solid rgb(var(--line));
|
||||||
|
color: rgb(var(--slate-400));
|
||||||
|
}
|
||||||
|
.react-flow__controls-button:hover {
|
||||||
|
background: rgb(var(--ink-800));
|
||||||
|
}
|
||||||
|
.react-flow__controls-button svg {
|
||||||
|
fill: currentColor;
|
||||||
|
}
|
||||||
|
.react-flow__edge-path {
|
||||||
|
stroke: rgb(var(--slate-600));
|
||||||
|
stroke-width: 1.5;
|
||||||
|
}
|
||||||
|
.react-flow__edge.selected .react-flow__edge-path,
|
||||||
|
.react-flow__edge:focus .react-flow__edge-path {
|
||||||
|
stroke: #8b5cf6;
|
||||||
|
}
|
||||||
|
.react-flow__minimap {
|
||||||
|
border: 1px solid rgb(var(--line));
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import { NODE_KINDS, NODE_ORDER } from "./nodeCatalog";
|
|||||||
import { exportDsl, validate, type Issue, type TaskDsl } from "../lib/dsl";
|
import { exportDsl, validate, type Issue, type TaskDsl } from "../lib/dsl";
|
||||||
import type { RunPhase } from "../lib/run";
|
import type { RunPhase } from "../lib/run";
|
||||||
import { listKb, listChatModels, listAgents, saveAgent, deleteAgent, type Identity, type AgentInfo } from "../lib/api";
|
import { listKb, listChatModels, listAgents, saveAgent, deleteAgent, type Identity, type AgentInfo } from "../lib/api";
|
||||||
|
import { useTheme } from "../lib/theme";
|
||||||
import { Button, Input, cn, useToast } from "../ui";
|
import { Button, Input, cn, useToast } from "../ui";
|
||||||
|
|
||||||
let seq = 0;
|
let seq = 0;
|
||||||
@@ -50,6 +51,7 @@ function buildExample(): { nodes: Node[]; edges: Edge[] } {
|
|||||||
// 编排 Studio:左(节点面板 + 我的编排) · 中画布 · 右检查器 · 顶工具栏。
|
// 编排 Studio:左(节点面板 + 我的编排) · 中画布 · 右检查器 · 顶工具栏。
|
||||||
export function StudioView({ onRun, phase, identity }: { onRun: (dsl: TaskDsl) => void; phase: RunPhase; identity: Identity }) {
|
export function StudioView({ onRun, phase, identity }: { onRun: (dsl: TaskDsl) => void; phase: RunPhase; identity: Identity }) {
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
|
const { theme } = useTheme();
|
||||||
const [nodes, setNodes, onNodesChange] = useNodesState<Node>([]);
|
const [nodes, setNodes, onNodesChange] = useNodesState<Node>([]);
|
||||||
const [edges, setEdges, onEdgesChange] = useEdgesState<Edge>([]);
|
const [edges, setEdges, onEdgesChange] = useEdgesState<Edge>([]);
|
||||||
const [selId, setSelId] = useState<string | null>(null);
|
const [selId, setSelId] = useState<string | null>(null);
|
||||||
@@ -263,7 +265,8 @@ export function StudioView({ onRun, phase, identity }: { onRun: (dsl: TaskDsl) =
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ReactFlow
|
<ReactFlow
|
||||||
colorMode="dark"
|
colorMode={theme}
|
||||||
|
proOptions={{ hideAttribution: true }}
|
||||||
nodes={nodes}
|
nodes={nodes}
|
||||||
edges={edges}
|
edges={edges}
|
||||||
nodeTypes={nodeTypes}
|
nodeTypes={nodeTypes}
|
||||||
@@ -275,9 +278,9 @@ export function StudioView({ onRun, phase, identity }: { onRun: (dsl: TaskDsl) =
|
|||||||
deleteKeyCode={["Backspace", "Delete"]}
|
deleteKeyCode={["Backspace", "Delete"]}
|
||||||
fitView
|
fitView
|
||||||
>
|
>
|
||||||
<Background color="#242b3c" gap={18} />
|
<Background color={theme === "dark" ? "#27272a" : "#e4e4e7"} gap={18} />
|
||||||
<Controls />
|
<Controls />
|
||||||
<MiniMap zoomable pannable className="!bg-ink-850" />
|
<MiniMap zoomable pannable maskColor={theme === "dark" ? "rgba(0,0,0,0.55)" : "rgba(0,0,0,0.08)"} className="!bg-ink-850" />
|
||||||
</ReactFlow>
|
</ReactFlow>
|
||||||
|
|
||||||
{issues && issues.length > 0 && (
|
{issues && issues.length > 0 && (
|
||||||
|
|||||||
@@ -19,11 +19,11 @@ export function TypedNode({ data, selected }: NodeProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`relative min-w-[170px] rounded-lg border border-l-[3px] bg-ink-800 shadow-card ${k.accent} ${
|
className={`relative min-w-[180px] rounded-lg border border-l-[3px] bg-ink-850 shadow-card transition ${k.accent} ${
|
||||||
selected ? "ring-2 ring-violet-500/70" : "border-line"
|
selected ? "ring-2 ring-brand/60 border-line" : "border-line hover:border-ink-600"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<Handle type="target" position={Position.Left} className="!h-2 !w-2 !border-0 !bg-slate-500" />
|
<Handle type="target" position={Position.Left} className="!h-2 !w-2 !border-0 !bg-slate-400" />
|
||||||
<div className="flex items-center justify-between gap-2 px-3 py-2">
|
<div className="flex items-center justify-between gap-2 px-3 py-2">
|
||||||
<span className={`rounded px-1.5 py-0.5 text-[10px] font-medium ${k.badge}`}>{k.label}</span>
|
<span className={`rounded px-1.5 py-0.5 text-[10px] font-medium ${k.badge}`}>{k.label}</span>
|
||||||
<span className={`h-2 w-2 rounded-full ${dot}`} />
|
<span className={`h-2 w-2 rounded-full ${dot}`} />
|
||||||
@@ -41,7 +41,7 @@ export function TypedNode({ data, selected }: NodeProps) {
|
|||||||
<span className="pointer-events-none absolute right-3 top-[66%] text-[9px] font-medium text-rose-400">假</span>
|
<span className="pointer-events-none absolute right-3 top-[66%] text-[9px] font-medium text-rose-400">假</span>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<Handle type="source" position={Position.Right} className="!h-2 !w-2 !border-0 !bg-slate-500" />
|
<Handle type="source" position={Position.Right} className="!h-2 !w-2 !border-0 !bg-slate-400" />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user