diff --git a/canvas/src/components/CreateWorkspaceDialog.tsx b/canvas/src/components/CreateWorkspaceDialog.tsx index 37e1231d..09975a03 100644 --- a/canvas/src/components/CreateWorkspaceDialog.tsx +++ b/canvas/src/components/CreateWorkspaceDialog.tsx @@ -166,7 +166,6 @@ export function CreateWorkspaceButton() { Create Workspace diff --git a/canvas/src/components/DeleteCascadeConfirmDialog.tsx b/canvas/src/components/DeleteCascadeConfirmDialog.tsx index e31114b7..b51eef60 100644 --- a/canvas/src/components/DeleteCascadeConfirmDialog.tsx +++ b/canvas/src/components/DeleteCascadeConfirmDialog.tsx @@ -101,7 +101,7 @@ export function DeleteCascadeConfirmDialog({ {/* Warning */}
- + diff --git a/canvas/src/components/MissingKeysModal.tsx b/canvas/src/components/MissingKeysModal.tsx index 31f3bb2d..8444b7c9 100644 --- a/canvas/src/components/MissingKeysModal.tsx +++ b/canvas/src/components/MissingKeysModal.tsx @@ -1,6 +1,6 @@ "use client"; -import { useState, useEffect, useCallback } from "react"; +import { useState, useEffect, useCallback, useRef } from "react"; import { api } from "@/lib/api"; import { getKeyLabel } from "@/lib/deploy-preflight"; @@ -38,6 +38,7 @@ export function MissingKeysModal({ }: Props) { const [entries, setEntries] = useState([]); const [globalError, setGlobalError] = useState(null); + const firstInputRef = useRef(null); // Initialize entries when modal opens or missingKeys change useEffect(() => { @@ -55,7 +56,14 @@ export function MissingKeysModal({ setGlobalError(null); }, [open, missingKeys]); - // Keyboard handler + // Focus first input when modal opens + useEffect(() => { + if (!open) return; + const raf = requestAnimationFrame(() => { + firstInputRef.current?.focus(); + }); + return () => cancelAnimationFrame(raf); + }, [open]); useEffect(() => { if (!open) return; const handler = (e: KeyboardEvent) => { @@ -134,7 +142,12 @@ export function MissingKeysModal({ /> {/* Dialog */} -
+
{/* Header */}
@@ -150,7 +163,7 @@ export function MissingKeysModal({
-

+

Missing API Keys

@@ -193,7 +206,7 @@ export function MissingKeysModal({ onChange={(e) => updateEntry(index, { value: e.target.value.trimStart() })} placeholder={entry.key.includes("API_KEY") ? "sk-..." : "Enter value"} type="password" - autoFocus={index === 0} + ref={index === 0 ? firstInputRef : undefined} onKeyDown={(e) => { if (e.key === "Enter" && entry.value.trim()) { handleSaveKey(index); diff --git a/canvas/src/components/Toolbar.tsx b/canvas/src/components/Toolbar.tsx index 63684204..f994c75b 100644 --- a/canvas/src/components/Toolbar.tsx +++ b/canvas/src/components/Toolbar.tsx @@ -159,7 +159,7 @@ export function Toolbar() { title={`Stop all running tasks (${counts.activeTasks} active)`} aria-label={stopping ? "Stopping all running tasks" : `Stop all running tasks (${counts.activeTasks} active)`} > - + @@ -177,7 +177,7 @@ export function Toolbar() { title={`Restart ${needsRestartNodes.length} workspace${needsRestartNodes.length === 1 ? "" : "s"} that need to pick up config or secret changes`} aria-label={restartingAll ? "Restarting workspaces" : `Restart ${needsRestartNodes.length} workspace${needsRestartNodes.length === 1 ? "" : "s"} pending config or secret changes`} > - + @@ -253,7 +253,7 @@ export function Toolbar() { onClick={() => useCanvasStore.getState().setSearchOpen(true)} className="flex items-center gap-1.5 px-2.5 py-1 bg-zinc-800/50 hover:bg-zinc-700/50 border border-zinc-700/40 rounded-lg transition-colors" > - + @@ -269,7 +269,7 @@ export function Toolbar() { aria-expanded={helpOpen} aria-label="Open quick help" > - +