@@ -58,6 +58,7 @@ import { usePermission } from "@/context/permission"
5858import { Binary } from "@opencode-ai/util/binary"
5959import { retry } from "@opencode-ai/util/retry"
6060import { playSound , soundSrc } from "@/utils/sound"
61+ import { createAim } from "@/utils/aim"
6162import { Worktree as WorktreeState } from "@/utils/worktree"
6263import { agentColor } from "@/utils/agent"
6364
@@ -146,9 +147,20 @@ export default function Layout(props: ParentProps) {
146147
147148 const navLeave = { current : undefined as number | undefined }
148149
150+ const aim = createAim ( {
151+ enabled : ( ) => ! layout . sidebar . opened ( ) ,
152+ active : ( ) => state . hoverProject ,
153+ el : ( ) => state . nav ,
154+ onActivate : ( directory ) => {
155+ globalSync . child ( directory )
156+ setState ( "hoverProject" , directory )
157+ setState ( "hoverSession" , undefined )
158+ } ,
159+ } )
160+
149161 onCleanup ( ( ) => {
150- if ( navLeave . current === undefined ) return
151- clearTimeout ( navLeave . current )
162+ if ( navLeave . current !== undefined ) clearTimeout ( navLeave . current )
163+ aim . reset ( )
152164 } )
153165
154166 const sidebarHovering = createMemo ( ( ) => ! layout . sidebar . opened ( ) && state . hoverProject !== undefined )
@@ -162,15 +174,22 @@ export default function Layout(props: ParentProps) {
162174
163175 createEffect ( ( ) => {
164176 if ( ! layout . sidebar . opened ( ) ) return
177+ aim . reset ( )
165178 setState ( "hoverProject" , undefined )
166179 } )
167180
181+ createEffect ( ( ) => {
182+ if ( state . hoverProject !== undefined ) return
183+ aim . reset ( )
184+ } )
185+
168186 createEffect (
169187 on (
170188 ( ) => ( { dir : params . dir , id : params . id } ) ,
171189 ( ) => {
172190 if ( layout . sidebar . opened ( ) ) return
173191 if ( ! state . hoverProject ) return
192+ aim . reset ( )
174193 setState ( "hoverSession" , undefined )
175194 setState ( "hoverProject" , undefined )
176195 } ,
@@ -2311,17 +2330,17 @@ export default function Layout(props: ParentProps) {
23112330 ! selected ( ) && ! active ( ) ,
23122331 "bg-surface-base-hover border border-border-weak-base" : ! selected ( ) && active ( ) ,
23132332 } }
2314- onMouseEnter = { ( ) => {
2333+ onMouseEnter = { ( event : MouseEvent ) => {
2334+ if ( ! overlay ( ) ) return
2335+ aim . enter ( props . project . worktree , event )
2336+ } }
2337+ onMouseLeave = { ( ) => {
23152338 if ( ! overlay ( ) ) return
2316- globalSync . child ( props . project . worktree )
2317- setState ( "hoverProject" , props . project . worktree )
2318- setState ( "hoverSession" , undefined )
2339+ aim . leave ( props . project . worktree )
23192340 } }
23202341 onFocus = { ( ) => {
23212342 if ( ! overlay ( ) ) return
2322- globalSync . child ( props . project . worktree )
2323- setState ( "hoverProject" , props . project . worktree )
2324- setState ( "hoverSession" , undefined )
2343+ aim . activate ( props . project . worktree )
23252344 } }
23262345 onClick = { ( ) => navigateToProject ( props . project . worktree ) }
23272346 onBlur = { ( ) => setOpen ( false ) }
@@ -2806,7 +2825,7 @@ export default function Layout(props: ParentProps) {
28062825
28072826 return (
28082827 < div class = "flex h-full w-full overflow-hidden" >
2809- < div class = "w-16 shrink-0 bg-background-base flex flex-col items-center overflow-hidden" >
2828+ < div class = "w-16 shrink-0 bg-background-base flex flex-col items-center overflow-hidden" onMouseMove = { aim . move } >
28102829 < div class = "flex-1 min-h-0 w-full" >
28112830 < DragDropProvider
28122831 onDragStart = { handleDragStart }
@@ -2901,6 +2920,7 @@ export default function Layout(props: ParentProps) {
29012920 navLeave . current = undefined
29022921 } }
29032922 onMouseLeave = { ( ) => {
2923+ aim . reset ( )
29042924 if ( ! sidebarHovering ( ) ) return
29052925
29062926 if ( navLeave . current !== undefined ) clearTimeout ( navLeave . current )
@@ -2916,7 +2936,7 @@ export default function Layout(props: ParentProps) {
29162936 </ div >
29172937 < Show when = { ! layout . sidebar . opened ( ) ? hoverProjectData ( ) : undefined } keyed >
29182938 { ( project ) => (
2919- < div class = "absolute inset-y-0 left-16 z-50 flex" >
2939+ < div class = "absolute inset-y-0 left-16 z-50 flex" onMouseEnter = { aim . reset } >
29202940 < SidebarPanel project = { project } />
29212941 </ div >
29222942 ) }
0 commit comments