Loading...
Loading...
Compare original and translation side by side
npx create-next-app@latest ai-workflow && cd ai-workflownpx create-next-app@latest ai-workflow && cd ai-workflownpx ai-elements@latestnpx ai-elements@latestnpm i @xyflow/reactnpm i @xyflow/reactnpx ai-elements@latest add canvas
npx ai-elements@latest add node
npx ai-elements@latest add edge
npx ai-elements@latest add connection
npx ai-elements@latest add controls
npx ai-elements@latest add panel
npx ai-elements@latest add toolbarnpx ai-elements@latest add canvas
npx ai-elements@latest add node
npx ai-elements@latest add edge
npx ai-elements@latest add connection
npx ai-elements@latest add controls
npx ai-elements@latest add panel
npx ai-elements@latest add toolbar'use client';
import { Canvas } from '@/components/ai-elements/canvas';
import { Connection } from '@/components/ai-elements/connection';
import { Controls } from '@/components/ai-elements/controls';
import { Edge } from '@/components/ai-elements/edge';
import {
Node,
NodeContent,
NodeDescription,
NodeFooter,
NodeHeader,
NodeTitle,
} from '@/components/ai-elements/node';
import { Panel } from '@/components/ai-elements/panel';
import { Toolbar } from '@/components/ai-elements/toolbar';
import { Button } from '@/components/ui/button';'use client';
import { Canvas } from '@/components/ai-elements/canvas';
import { Connection } from '@/components/ai-elements/connection';
import { Controls } from '@/components/ai-elements/controls';
import { Edge } from '@/components/ai-elements/edge';
import {
Node,
NodeContent,
NodeDescription,
NodeFooter,
NodeHeader,
NodeTitle,
} from '@/components/ai-elements/node';
import { Panel } from '@/components/ai-elements/panel';
import { Toolbar } from '@/components/ai-elements/toolbar';
import { Button } from '@/components/ui/button';const nodeIds = {
start: 'start',
process1: 'process1',
decision: 'decision',
output1: 'output1',
output2: 'output2',
complete: 'complete',
};const nodeIds = {
start: 'start',
process1: 'process1',
decision: 'decision',
output1: 'output1',
output2: 'output2',
complete: 'complete',
};const nodes = [
{
id: nodeIds.start,
type: 'workflow',
position: { x: 0, y: 0 },
data: {
label: 'Start',
description: 'Initialize workflow',
handles: { target: false, source: true },
content: 'Triggered by user action',
footer: 'Status: Ready',
},
},
// Add more nodes...
];const nodes = [
{
id: nodeIds.start,
type: 'workflow',
position: { x: 0, y: 0 },
data: {
label: 'Start',
description: 'Initialize workflow',
handles: { target: false, source: true },
content: 'Triggered by user action',
footer: 'Status: Ready',
},
},
// 添加更多节点...
];animatedtemporaryconst edges = [
{
id: 'edge1',
source: nodeIds.start,
target: nodeIds.process1,
type: 'animated',
},
{
id: 'edge2',
source: nodeIds.decision,
target: nodeIds.output2,
type: 'temporary', // For error/conditional paths
},
];animatedtemporaryconst edges = [
{
id: 'edge1',
source: nodeIds.start,
target: nodeIds.process1,
type: 'animated',
},
{
id: 'edge2',
source: nodeIds.decision,
target: nodeIds.output2,
type: 'temporary', // 用于错误/条件路径
},
];const nodeTypes = {
workflow: ({
data,
}: {
data: {
label: string;
description: string;
handles: { target: boolean; source: boolean };
content: string;
footer: string;
};
}) => (
<Node handles={data.handles}>
<NodeHeader>
<NodeTitle>{data.label}</NodeTitle>
<NodeDescription>{data.description}</NodeDescription>
</NodeHeader>
<NodeContent>
<p className="text-sm">{data.content}</p>
</NodeContent>
<NodeFooter>
<p className="text-muted-foreground text-xs">{data.footer}</p>
</NodeFooter>
<Toolbar>
<Button size="sm" variant="ghost">Edit</Button>
<Button size="sm" variant="ghost">Delete</Button>
</Toolbar>
</Node>
),
};const nodeTypes = {
workflow: ({
data,
}: {
data: {
label: string;
description: string;
handles: { target: boolean; source: boolean };
content: string;
footer: string;
};
}) => (
<Node handles={data.handles}>
<NodeHeader>
<NodeTitle>{data.label}</NodeTitle>
<NodeDescription>{data.description}</NodeDescription>
</NodeHeader>
<NodeContent>
<p className="text-sm">{data.content}</p>
</NodeContent>
<NodeFooter>
<p className="text-muted-foreground text-xs">{data.footer}</p>
</NodeFooter>
<Toolbar>
<Button size="sm" variant="ghost">Edit</Button>
<Button size="sm" variant="ghost">Delete</Button>
</Toolbar>
</Node>
),
};const edgeTypes = {
animated: Edge.Animated,
temporary: Edge.Temporary,
};const edgeTypes = {
animated: Edge.Animated,
temporary: Edge.Temporary,
};const App = () => (
<Canvas
edges={edges}
edgeTypes={edgeTypes}
fitView
nodes={nodes}
nodeTypes={nodeTypes}
connectionLineComponent={Connection}
>
<Controls />
<Panel position="top-left">
<Button size="sm" variant="secondary">Export</Button>
</Panel>
</Canvas>
);
export default App;const App = () => (
<Canvas
edges={edges}
edgeTypes={edgeTypes}
fitView
nodes={nodes}
nodeTypes={nodeTypes}
connectionLineComponent={Connection}
>
<Controls />
<Panel position="top-left">
<Button size="sm" variant="secondary">Export</Button>
</Panel>
</Canvas>
);
export default App;| Feature | Description |
|---|---|
| Custom Node Components | Use NodeHeader, NodeTitle, NodeDescription, NodeContent, NodeFooter for structured layouts |
| Node Toolbars | Attach contextual actions to nodes via Toolbar component |
| Handle Configuration | Control connections with |
| Edge Types | |
| Connection Lines | Styled bezier curves when dragging new connections |
| Controls | Zoom in/out and fit view buttons |
| Panels | Position custom UI anywhere on the canvas |
| 特性 | 描述 |
|---|---|
| 自定义节点组件 | 使用NodeHeader、NodeTitle、NodeDescription、NodeContent、NodeFooter构建结构化布局 |
| 节点工具栏 | 通过Toolbar组件为节点添加上下文操作 |
| 连接点配置 | 通过 |
| 连线类型 | |
| 连线样式 | 拖拽新连接时显示风格化的贝塞尔曲线 |
| 控制组件 | 提供放大/缩小和适配视图的按钮 |
| 面板组件 | 可在画布任意位置放置自定义UI |
references/components.mdreferences/components.md