diff --git a/.changeset/fn-6143-workflow-prompt-fullscreen.md b/.changeset/fn-6143-workflow-prompt-fullscreen.md new file mode 100644 index 0000000000..df84d6ddb1 --- /dev/null +++ b/.changeset/fn-6143-workflow-prompt-fullscreen.md @@ -0,0 +1,5 @@ +--- +"@runfusion/fusion": patch +--- + +Add an expand/collapse control for the workflow prompt editor so long prompts can be edited in a fullscreen overlay. diff --git a/packages/dashboard/app/components/TaskCard.css b/packages/dashboard/app/components/TaskCard.css index 6060fb964e..671895bf40 100644 --- a/packages/dashboard/app/components/TaskCard.css +++ b/packages/dashboard/app/components/TaskCard.css @@ -1437,6 +1437,7 @@ } .card-promote-action.card-send-back-btn { + opacity: 1; margin-left: auto; } diff --git a/packages/dashboard/app/components/WorkflowNodeEditor.css b/packages/dashboard/app/components/WorkflowNodeEditor.css index ae67a08d71..91b5709e7b 100644 --- a/packages/dashboard/app/components/WorkflowNodeEditor.css +++ b/packages/dashboard/app/components/WorkflowNodeEditor.css @@ -665,6 +665,79 @@ box-shadow: var(--focus-ring); } +/* ── Prompt fullscreen editor ─────────────────────────────────── */ +.wf-prompt-editor { + position: relative; +} + +.wf-prompt-editor--fullscreen { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 10000; + background: var(--surface); + padding: max(var(--space-lg), env(safe-area-inset-top, 0)) + max(var(--space-lg), env(safe-area-inset-right, 0)) + max(var(--space-lg), env(safe-area-inset-bottom, 0)) + max(var(--space-lg), env(safe-area-inset-left, 0)); + display: flex; + flex-direction: column; +} + +.wf-prompt-editor--fullscreen .wf-field { + flex: 1; + display: flex; + flex-direction: column; +} + +.wf-prompt-editor--fullscreen textarea { + flex: 1; + min-height: unset; + resize: none; + border-radius: var(--radius-md); + font-size: 0.9375rem; + line-height: 1.6; +} + +.wf-prompt-fullscreen-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: var(--space-md); + font-size: 0.8125rem; + font-weight: 600; + color: var(--text-muted); +} + +.wf-prompt-expand-btn { + display: inline-flex; + align-items: center; + gap: var(--space-xs); +} + +.wf-prompt-expand-btn--inline { + position: absolute; + top: calc(var(--space-xs) + 1.2em + var(--space-xs)); + right: var(--space-xs); + z-index: 2; + color: var(--text-muted); + background: var(--bg-secondary); + border: 1px solid var(--border); + border-radius: var(--radius-sm); + padding: calc(var(--space-xs) / 2) var(--space-xs); +} + +.wf-prompt-expand-btn--inline:hover { + background: var(--bg-tertiary); + color: var(--text); +} + +.wf-prompt-editor:not(.wf-prompt-editor--fullscreen) textarea { + padding-right: calc(var(--space-xl) + var(--space-md)); +} + .wf-inspector-note { margin: 0; font-size: 0.78rem; @@ -1242,6 +1315,10 @@ } @media (max-width: 768px) { + .wf-prompt-editor--fullscreen { + padding: var(--space-sm); + } + .modal-overlay:has(.wf-editor-modal), .modal-overlay:has(.wf-create-modal) { padding-top: 0; diff --git a/packages/dashboard/app/components/WorkflowNodeEditor.tsx b/packages/dashboard/app/components/WorkflowNodeEditor.tsx index cb44b6c247..c975265a58 100644 --- a/packages/dashboard/app/components/WorkflowNodeEditor.tsx +++ b/packages/dashboard/app/components/WorkflowNodeEditor.tsx @@ -15,7 +15,7 @@ import { type Edge as FlowEdge, } from "@xyflow/react"; import { useTranslation } from "react-i18next"; -import { X, Plus, Trash2, Save, MessageSquare, Terminal, Shield, GitMerge, Loader2, HelpCircle, PauseCircle, Split, Merge, Repeat, ClipboardCheck, ListChecks, Code2, Bell, LayoutGrid, Workflow, Download, Upload, ChevronDown, ChevronRight, ChevronLeft, Library, Sparkles } from "lucide-react"; +import { X, Plus, Trash2, Save, MessageSquare, Terminal, Shield, GitMerge, Loader2, HelpCircle, PauseCircle, Split, Merge, Repeat, ClipboardCheck, ListChecks, Code2, Bell, LayoutGrid, Workflow, Download, Upload, ChevronDown, ChevronRight, ChevronLeft, Library, Sparkles, Maximize2, Minimize2 } from "lucide-react"; import type { WorkflowDefinition, WorkflowIrColumn, TraitViolation, WorkflowStepTemplate } from "@fusion/core"; import { getErrorMessage } from "@fusion/core"; import { @@ -1879,6 +1879,16 @@ function InnerEditor({ const selectedNode = nodes.find((n) => n.id === selectedNodeId) ?? null; const selectedEdge = edges.find((e) => e.id === selectedEdgeId) ?? null; + const [isPromptExpanded, setIsPromptExpanded] = useState(false); + const handleTogglePromptExpand = useCallback(() => { + setIsPromptExpanded((prev) => !prev); + }, []); + const handlePromptFullscreenKeyDown = useCallback((e: React.KeyboardEvent) => { + if (!isPromptExpanded || e.key !== "Escape") return; + e.preventDefault(); + e.stopPropagation(); + setIsPromptExpanded(false); + }, [isPromptExpanded]); const selectedNodePromptValue = selectedNode && (selectedNode.data.kind === "prompt" || selectedNode.data.kind === "gate") ? String( @@ -3134,14 +3144,44 @@ function InnerEditor({ {selectedNode.data.kind === "prompt" || selectedNode.data.kind === "gate" ? ( -