feat: [US-019] - Editor toolbar
Add toolbar component with buttons for adding nodes (Dialogue, Choice, Variable) and managing projects (Save, Export, Import). Buttons are styled with TailwindCSS and wired to placeholder handlers. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
e530606cef
commit
9aa2aa48f0
|
|
@ -13,6 +13,7 @@ import ReactFlow, {
|
||||||
Edge,
|
Edge,
|
||||||
} from 'reactflow'
|
} from 'reactflow'
|
||||||
import 'reactflow/dist/style.css'
|
import 'reactflow/dist/style.css'
|
||||||
|
import Toolbar from '@/components/editor/Toolbar'
|
||||||
import type { FlowchartData, FlowchartNode, FlowchartEdge } from '@/types/flowchart'
|
import type { FlowchartData, FlowchartNode, FlowchartEdge } from '@/types/flowchart'
|
||||||
|
|
||||||
type FlowchartEditorProps = {
|
type FlowchartEditorProps = {
|
||||||
|
|
@ -57,19 +58,54 @@ export default function FlowchartEditor({
|
||||||
[setEdges]
|
[setEdges]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Placeholder handlers - functionality will be added in future stories
|
||||||
|
const handleAddDialogue = useCallback(() => {
|
||||||
|
// TODO: Implement in US-021
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const handleAddChoice = useCallback(() => {
|
||||||
|
// TODO: Implement in US-023
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const handleAddVariable = useCallback(() => {
|
||||||
|
// TODO: Implement in US-026
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const handleSave = useCallback(() => {
|
||||||
|
// TODO: Implement in US-034
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const handleExport = useCallback(() => {
|
||||||
|
// TODO: Implement in US-035
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const handleImport = useCallback(() => {
|
||||||
|
// TODO: Implement in US-036
|
||||||
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-full w-full">
|
<div className="flex h-full w-full flex-col">
|
||||||
<ReactFlow
|
<Toolbar
|
||||||
nodes={nodes}
|
onAddDialogue={handleAddDialogue}
|
||||||
edges={edges}
|
onAddChoice={handleAddChoice}
|
||||||
onNodesChange={onNodesChange}
|
onAddVariable={handleAddVariable}
|
||||||
onEdgesChange={onEdgesChange}
|
onSave={handleSave}
|
||||||
onConnect={onConnect}
|
onExport={handleExport}
|
||||||
fitView
|
onImport={handleImport}
|
||||||
>
|
/>
|
||||||
<Background variant={BackgroundVariant.Dots} gap={16} size={1} />
|
<div className="flex-1">
|
||||||
<Controls position="bottom-right" />
|
<ReactFlow
|
||||||
</ReactFlow>
|
nodes={nodes}
|
||||||
|
edges={edges}
|
||||||
|
onNodesChange={onNodesChange}
|
||||||
|
onEdgesChange={onEdgesChange}
|
||||||
|
onConnect={onConnect}
|
||||||
|
fitView
|
||||||
|
>
|
||||||
|
<Background variant={BackgroundVariant.Dots} gap={16} size={1} />
|
||||||
|
<Controls position="bottom-right" />
|
||||||
|
</ReactFlow>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
'use client'
|
||||||
|
|
||||||
|
type ToolbarProps = {
|
||||||
|
onAddDialogue: () => void
|
||||||
|
onAddChoice: () => void
|
||||||
|
onAddVariable: () => void
|
||||||
|
onSave: () => void
|
||||||
|
onExport: () => void
|
||||||
|
onImport: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Toolbar({
|
||||||
|
onAddDialogue,
|
||||||
|
onAddChoice,
|
||||||
|
onAddVariable,
|
||||||
|
onSave,
|
||||||
|
onExport,
|
||||||
|
onImport,
|
||||||
|
}: ToolbarProps) {
|
||||||
|
return (
|
||||||
|
<div className="flex items-center justify-between border-b border-zinc-200 bg-zinc-50 px-4 py-2 dark:border-zinc-700 dark:bg-zinc-800">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<span className="mr-2 text-sm font-medium text-zinc-500 dark:text-zinc-400">
|
||||||
|
Add Node:
|
||||||
|
</span>
|
||||||
|
<button
|
||||||
|
onClick={onAddDialogue}
|
||||||
|
className="rounded bg-blue-500 px-3 py-1.5 text-sm font-medium text-white hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:focus:ring-offset-zinc-800"
|
||||||
|
>
|
||||||
|
Dialogue
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={onAddChoice}
|
||||||
|
className="rounded bg-green-500 px-3 py-1.5 text-sm font-medium text-white hover:bg-green-600 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2 dark:focus:ring-offset-zinc-800"
|
||||||
|
>
|
||||||
|
Choice
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={onAddVariable}
|
||||||
|
className="rounded bg-orange-500 px-3 py-1.5 text-sm font-medium text-white hover:bg-orange-600 focus:outline-none focus:ring-2 focus:ring-orange-500 focus:ring-offset-2 dark:focus:ring-offset-zinc-800"
|
||||||
|
>
|
||||||
|
Variable
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<button
|
||||||
|
onClick={onSave}
|
||||||
|
className="rounded border border-zinc-300 bg-white px-3 py-1.5 text-sm font-medium text-zinc-700 hover:bg-zinc-50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:border-zinc-600 dark:bg-zinc-700 dark:text-zinc-200 dark:hover:bg-zinc-600 dark:focus:ring-offset-zinc-800"
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={onExport}
|
||||||
|
className="rounded border border-zinc-300 bg-white px-3 py-1.5 text-sm font-medium text-zinc-700 hover:bg-zinc-50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:border-zinc-600 dark:bg-zinc-700 dark:text-zinc-200 dark:hover:bg-zinc-600 dark:focus:ring-offset-zinc-800"
|
||||||
|
>
|
||||||
|
Export
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={onImport}
|
||||||
|
className="rounded border border-zinc-300 bg-white px-3 py-1.5 text-sm font-medium text-zinc-700 hover:bg-zinc-50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:border-zinc-600 dark:bg-zinc-700 dark:text-zinc-200 dark:hover:bg-zinc-600 dark:focus:ring-offset-zinc-800"
|
||||||
|
>
|
||||||
|
Import
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue