diff --git a/apps/array/src/renderer/App.tsx b/apps/array/src/renderer/App.tsx index 18141560..bce9236d 100644 --- a/apps/array/src/renderer/App.tsx +++ b/apps/array/src/renderer/App.tsx @@ -1,4 +1,3 @@ -import { CursorGlow } from "@components/CursorGlow"; import { LoginTransition } from "@components/LoginTransition"; import { MainLayout } from "@components/MainLayout"; import { AuthScreen } from "@features/auth/components/AuthScreen"; @@ -67,7 +66,6 @@ function App() { return ( <> - {!isAuthenticated ? ( ; +} + +export function TorchGlow({ containerRef }: TorchGlowProps) { + const isDarkMode = useThemeStore((state) => state.isDarkMode); + const [mousePos, setMousePos] = useState<{ x: number; y: number } | null>( + null, + ); + const [isHovering, setIsHovering] = useState(false); + + useEffect(() => { + const container = containerRef.current; + if (!container) return; + + const handleMouseMove = (e: MouseEvent) => { + const rect = container.getBoundingClientRect(); + setMousePos({ + x: e.clientX - rect.left, + y: e.clientY - rect.top, + }); + }; + + const handleMouseEnter = () => setIsHovering(true); + const handleMouseLeave = () => { + setIsHovering(false); + setMousePos(null); + }; + + container.addEventListener("mousemove", handleMouseMove); + container.addEventListener("mouseenter", handleMouseEnter); + container.addEventListener("mouseleave", handleMouseLeave); + + return () => { + container.removeEventListener("mousemove", handleMouseMove); + container.removeEventListener("mouseenter", handleMouseEnter); + container.removeEventListener("mouseleave", handleMouseLeave); + }; + }, [containerRef]); + + // Only show in dark mode when hovering + if (!isDarkMode || !isHovering || !mousePos) return null; + + return ( + <> + {/* SVG filter for grainy torch light texture */} + + + {/* Base layer - outer glow */} +
+ + {/* Middle layer - offset for irregular shape */} +
+ + {/* Inner layer - pulsing flame core */} +
+ + ); +} diff --git a/apps/array/src/renderer/features/task-detail/components/TaskInput.tsx b/apps/array/src/renderer/features/task-detail/components/TaskInput.tsx index 407261a6..3414cd38 100644 --- a/apps/array/src/renderer/features/task-detail/components/TaskInput.tsx +++ b/apps/array/src/renderer/features/task-detail/components/TaskInput.tsx @@ -1,3 +1,4 @@ +import { TorchGlow } from "@components/TorchGlow"; import { FolderPicker } from "@features/folder-picker/components/FolderPicker"; import type { MessageEditorHandle } from "@features/message-editor/components/MessageEditor"; import type { ExecutionMode } from "@features/sessions/stores/sessionStore"; @@ -35,6 +36,7 @@ export function TaskInput() { const { lastUsedLocalWorkspaceMode } = useSettingsStore(); const editorRef = useRef(null); + const containerRef = useRef(null); const [selectedDirectory, setSelectedDirectory] = useState( lastUsedDirectory || "", @@ -81,89 +83,100 @@ export function TaskInput() { }); return ( - - + - - - {selectedDirectory && ( - - +
); } diff --git a/apps/array/src/renderer/styles/globals.css b/apps/array/src/renderer/styles/globals.css index 2d8a3b1e..9a15b72d 100644 --- a/apps/array/src/renderer/styles/globals.css +++ b/apps/array/src/renderer/styles/globals.css @@ -113,6 +113,21 @@ animation: campfire-pulse 1s ease-in-out infinite; } +/* Torch glow pulse animation for cursor flame effect */ +@keyframes torch-pulse { + 0%, + 100% { + opacity: 1; + } + 50% { + opacity: 0.3; + } +} + +.torch-glow-pulse { + animation: torch-pulse 1.5s ease-in-out infinite; +} + .radix-themes { /* Font families */ --default-font-family: