3,200+ hardcoded color values replaced with CSS variable-backed Tailwind classes (bg-card, text-foreground, border-border, etc.). Enables light mode via CSS variable swap. Only syntax highlighting colors and intentional one-offs remain hardcoded (~15 values). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
70 lines
2.9 KiB
TypeScript
70 lines
2.9 KiB
TypeScript
import { memo, useState } from 'react'
|
|
import { Handle, Position, type NodeProps } from '@xyflow/react'
|
|
import { HelpCircle, Zap, CheckCircle } from 'lucide-react'
|
|
import { cn } from '@/lib/utils'
|
|
import type { TreeStructure } from '@/types'
|
|
|
|
export interface FlowCanvasAnswerNodeData {
|
|
node: TreeStructure
|
|
onSelectType: (nodeId: string, type: 'decision' | 'action' | 'solution') => void
|
|
}
|
|
|
|
function FlowCanvasAnswerNodeComponent({ data, selected }: NodeProps) {
|
|
const { node, onSelectType } = data as unknown as FlowCanvasAnswerNodeData
|
|
const [picking, setPicking] = useState(false)
|
|
const label = node.title || 'Answer'
|
|
|
|
return (
|
|
<>
|
|
<Handle type="target" position={Position.Top} className="bg-border! w-2! h-2! border-0!" />
|
|
|
|
<div
|
|
className={cn(
|
|
'w-[280px] rounded-xl border-2 border-dashed border-border bg-card/50 transition-all',
|
|
!picking && 'cursor-pointer hover:border-primary/40 hover:bg-accent/30',
|
|
selected && 'ring-1 ring-primary'
|
|
)}
|
|
onClick={() => !picking && setPicking(true)}
|
|
>
|
|
<div className="px-3 pt-2.5 pb-1 text-sm font-heading font-medium text-foreground text-center">
|
|
{label}
|
|
</div>
|
|
|
|
{!picking ? (
|
|
<div className="pb-2.5 text-center text-[10px] text-muted-foreground font-sans text-xs">
|
|
+ Choose Type
|
|
</div>
|
|
) : (
|
|
<div className="flex items-center justify-center gap-1.5 pb-2.5 px-2">
|
|
<button
|
|
type="button"
|
|
onClick={(e) => { e.stopPropagation(); onSelectType(node.id, 'decision') }}
|
|
className="flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-sans text-xs border border-blue-500/30 bg-blue-500/10 text-blue-400 hover:bg-blue-500/20"
|
|
>
|
|
<HelpCircle className="h-2.5 w-2.5" /> Decision
|
|
</button>
|
|
<button
|
|
type="button"
|
|
onClick={(e) => { e.stopPropagation(); onSelectType(node.id, 'action') }}
|
|
className="flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-sans text-xs border border-yellow-500/30 bg-yellow-500/10 text-yellow-400 hover:bg-yellow-500/20"
|
|
>
|
|
<Zap className="h-2.5 w-2.5" /> Action
|
|
</button>
|
|
<button
|
|
type="button"
|
|
onClick={(e) => { e.stopPropagation(); onSelectType(node.id, 'solution') }}
|
|
className="flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-sans text-xs border border-green-500/30 bg-green-500/10 text-green-400 hover:bg-green-500/20"
|
|
>
|
|
<CheckCircle className="h-2.5 w-2.5" /> Solution
|
|
</button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<Handle type="source" position={Position.Bottom} className="bg-border! w-2! h-2! border-0!" />
|
|
</>
|
|
)
|
|
}
|
|
|
|
export const FlowCanvasAnswerNode = memo(FlowCanvasAnswerNodeComponent)
|