diff --git a/apps/rowboat/app/projects/[projectId]/copilot/app.tsx b/apps/rowboat/app/projects/[projectId]/copilot/app.tsx index cd50a10e..743f6a55 100644 --- a/apps/rowboat/app/projects/[projectId]/copilot/app.tsx +++ b/apps/rowboat/app/projects/[projectId]/copilot/app.tsx @@ -7,11 +7,11 @@ import { CopilotMessage } from "../../../lib/types/copilot_types"; import { Workflow } from "@/app/lib/types/workflow_types"; import { DataSource } from "@/app/lib/types/datasource_types"; import { z } from "zod"; -import { Action as WorkflowDispatch } from "../workflow/workflow_editor"; +import { Action as WorkflowDispatch } from "@/app/projects/[projectId]/workflow/workflow_editor"; import { Panel } from "@/components/common/panel-common"; import { ComposeBoxCopilot } from "@/components/common/compose-box-copilot"; import { Messages } from "./components/messages"; -import { CopyIcon, CheckIcon, PlusIcon, XIcon, InfoIcon } from "lucide-react"; +import { CopyIcon, CheckIcon, PlusIcon, XIcon, InfoIcon, Sparkles } from "lucide-react"; import { useCopilot } from "./use-copilot"; import { BillingUpgradeModal } from "@/components/common/billing-upgrade-modal"; import { WithStringId } from "@/app/lib/types/types"; @@ -225,7 +225,7 @@ const App = forwardRef<{ handleCopyChat: () => void; handleUserMessage: (message )} -
+
{responseError && (

{responseError}

@@ -322,16 +322,11 @@ export const Copilot = forwardRef<{ handleUserMessage: (message: string) => void variant="copilot" tourTarget="copilot" showWelcome={messages.length === 0} - title={ -
-
-
- Skipper -
- - - -
+ icon={} + title="Skipper" + subtitle="Build your assistant" + rightActions={ +
-
- } - rightActions={ -
- ); - // Utility to filter out divider/empty markdown blocks function isNonDividerMarkdown(content: string) { const trimmed = content.trim(); @@ -435,9 +374,6 @@ function AssistantMessage({ ); } - // Restore panelOpen state if missing - const [panelOpen, setPanelOpen] = useState(false); // collapsed by default - // At the end of the render, call onStatusBarChange with the current status bar props // Track the latest status bar info const latestStatusBar = useRef(null); diff --git a/apps/rowboat/app/projects/[projectId]/playground/app.tsx b/apps/rowboat/app/projects/[projectId]/playground/app.tsx index 5366555b..c9b5978f 100644 --- a/apps/rowboat/app/projects/[projectId]/playground/app.tsx +++ b/apps/rowboat/app/projects/[projectId]/playground/app.tsx @@ -7,7 +7,7 @@ import { Chat } from "./components/chat"; import { Panel } from "@/components/common/panel-common"; import { Button } from "@/components/ui/button"; import { Tooltip } from "@heroui/react"; -import { CheckIcon, CopyIcon, PlusIcon, InfoIcon, BugIcon, BugOffIcon } from "lucide-react"; +import { CheckIcon, CopyIcon, PlusIcon, InfoIcon, BugIcon, BugOffIcon, MessageCircle } from "lucide-react"; export function App({ hidden = false, @@ -56,16 +56,11 @@ export function App({ className={`${hidden ? 'hidden' : 'block'}`} variant="playground" tourTarget="playground" - title={ -
-
-
- Playground -
- - - -
+ icon={} + title="Playground" + subtitle="Chat with your assistant" + rightActions={ +
-
- } - rightActions={ -
+ +
+
+ {showCopySuccess &&
+
Copied to clipboard
+
} +
+ {isLive &&
+
+ + This version is locked. Changes applied will not be reflected. +
+
} + + {!isLive && <> + + + } + + {/* Deploy CTA - always visible */} +
+ + + + + + + } + onPress={onSettingsModalOpen} + > + API & SDK settings + + } + onPress={onTriggersModalOpen} + > + Manage triggers + + {!isLive ? ( + <> + } + onPress={() => onChangeMode('live')} + > + View live version + + } + onPress={onRevertToLive} + className="text-red-600 dark:text-red-400" + > + Reset to live version + + + ) : null} + + +
+ + {isLive &&
+ +
} + + {!isLive && } +
+
+
+ ); +} diff --git a/apps/rowboat/app/projects/[projectId]/workflow/workflow_editor.tsx b/apps/rowboat/app/projects/[projectId]/workflow/workflow_editor.tsx index b51a6a68..9e8bdf6a 100644 --- a/apps/rowboat/app/projects/[projectId]/workflow/workflow_editor.tsx +++ b/apps/rowboat/app/projects/[projectId]/workflow/workflow_editor.tsx @@ -38,6 +38,7 @@ import { InputField } from "@/app/lib/components/input-field"; import { VoiceSection } from "../config/components/voice"; import { ChatWidgetSection } from "../config/components/project"; import { TriggersModal } from "./components/TriggersModal"; +import { TopBar } from "./components/TopBar"; enablePatches(); @@ -1221,161 +1222,31 @@ export function WorkflowEditor({ onSelectTool: handleSelectTool, onSelectPrompt: handleSelectPrompt, }}> -
-
-
- {/* Project Name Editor */} -
- -
- -
- -
- {state.present.publishing && } - {isLive &&
- - Live workflow -
} - {!isLive &&
- - Draft workflow -
} - - {/* Download JSON icon button, with tooltip, to the left of the menu */} - - - -
-
- {showCopySuccess &&
-
Copied to clipboard
-
} -
- {isLive &&
-
- - This version is locked. Changes applied will not be reflected. -
-
} - - {!isLive && <> - - - } - - {/* Deploy CTA - always visible */} -
- - - - - - - } - onPress={onSettingsModalOpen} - > - API & SDK settings - - } - onPress={onTriggersModalOpen} - > - Manage triggers - - {!isLive ? ( - <> - } - onPress={() => onChangeMode('live')} - > - View live version - - } - onPress={handleRevertToLive} - className="text-red-600 dark:text-red-400" - > - Reset to live version - - - ) : null} - - -
- - {isLive &&
- -
} - - {!isLive && } -
-
- +
+ {/* Top Bar - Isolated like sidebar */} + 0} + canRedo={state.currentIndex < state.patches.length} + showCopilot={showCopilot} + onUndo={() => dispatch({ type: "undo" })} + onRedo={() => dispatch({ type: "redo" })} + onDownloadJSON={handleDownloadJSON} + onPublishWorkflow={handlePublishWorkflow} + onChangeMode={onChangeMode} + onRevertToLive={handleRevertToLive} + onToggleCopilot={() => setShowCopilot(!showCopilot)} + onSettingsModalOpen={onSettingsModalOpen} + onTriggersModalOpen={onTriggersModalOpen} + /> + + {/* Content Area */} +
{/* Sidebar with improved shadow and blur */} -
+
{/* Main content area */} -
- {billingPastDue &&
+
+ {billingPastDue &&
Your subscription is past due. Please update your payment information to avoid losing access to your projects.
} -
- {children} -
+ {children}
); diff --git a/apps/rowboat/components/common/compose-box-copilot.tsx b/apps/rowboat/components/common/compose-box-copilot.tsx index eb6c6f5e..31e49563 100644 --- a/apps/rowboat/components/common/compose-box-copilot.tsx +++ b/apps/rowboat/components/common/compose-box-copilot.tsx @@ -100,13 +100,12 @@ export function ComposeBoxCopilot({ disabled={loading} placeholder="Type a message..." autoResize={true} - maxHeight={120} + maxHeight={200} className={` - min-h-0! + min-h-6 border-0! shadow-none! ring-0! bg-transparent resize-none - overflow-y-auto [&::-webkit-scrollbar]:w-1 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:bg-gray-300 @@ -294,7 +293,7 @@ function CopilotStatusBar({ ); }; return ( -
+
{/* Left: context + status/ticker, flex-1, truncate as needed */}
{renderContext()} diff --git a/apps/rowboat/components/common/panel-common.tsx b/apps/rowboat/components/common/panel-common.tsx index 435bb5e3..87228150 100644 --- a/apps/rowboat/components/common/panel-common.tsx +++ b/apps/rowboat/components/common/panel-common.tsx @@ -33,6 +33,8 @@ export function ActionButton({ interface PanelProps { title: React.ReactNode; + subtitle?: string; + icon?: React.ReactNode; rightActions?: React.ReactNode; actions?: React.ReactNode; children: React.ReactNode; @@ -47,6 +49,8 @@ interface PanelProps { export function Panel({ title, + subtitle, + icon, rightActions, actions, children, @@ -65,8 +69,8 @@ export function Panel({ "flex flex-col rounded-xl border relative w-full", // Only apply overflow-hidden if no custom overflow is set (for backward compatibility) overflow ? undefined : "overflow-hidden", - variant === 'copilot' ? "border-blue-200 dark:border-blue-800" : "border-zinc-200 dark:border-zinc-800", - "bg-white dark:bg-zinc-900", + variant === 'copilot' ? "border-transparent" : "border-zinc-200 dark:border-zinc-800", + variant === 'copilot' ? "bg-zinc-50 dark:bg-zinc-900" : "bg-white dark:bg-zinc-900", maxHeight ? "max-h-(--panel-height)" : "h-full", className )} @@ -93,7 +97,8 @@ export function Panel({ )}
- {title} + {icon && icon} +
+
+ {title} +
+ {subtitle && ( +
+ {subtitle} +
+ )} +
+
+ {rightActions} + + ) : variant === 'playground' ? ( + <> +
+ {icon && icon} +
+
+ {title} +
+ {subtitle && ( +
+ {subtitle} +
+ )} +
{rightActions} diff --git a/apps/rowboat/components/ui/textarea.tsx b/apps/rowboat/components/ui/textarea.tsx index 83df5fea..e3ac1390 100644 --- a/apps/rowboat/components/ui/textarea.tsx +++ b/apps/rowboat/components/ui/textarea.tsx @@ -47,7 +47,6 @@ export const Textarea = forwardRef(({ } }, [propValue, isEditing]); - /* useEffect(() => { if (!autoResize) return; @@ -69,7 +68,6 @@ export const Textarea = forwardRef(({ window.addEventListener('resize', adjustHeight); return () => window.removeEventListener('resize', adjustHeight); }, [localValue, autoResize, maxHeight, textareaRef]); - */ const validateAndUpdate = (value: string) => { if (validate) {