Răsfoiți Sursa

fix(app): lift up project hover state to layout (#18732)

Brendan Allan 4 săptămâni în urmă
părinte
comite
0a7dfc03ee

+ 4 - 0
packages/app/src/pages/layout.tsx

@@ -1989,6 +1989,10 @@ export default function Layout(props: ParentProps) {
     onProjectMouseEnter: (worktree, event) => aim.enter(worktree, event),
     onProjectMouseLeave: (worktree) => aim.leave(worktree),
     onProjectFocus: (worktree) => aim.activate(worktree),
+    onHoverOpenChanged: (worktree, hoverOpen) => {
+      if (!hoverOpen && state.hoverProject && state.hoverProject !== worktree) return
+      setState("hoverProject", hoverOpen ? worktree : undefined)
+    },
     navigateToProject,
     openSidebar: () => layout.sidebar.open(),
     closeProject,

+ 8 - 21
packages/app/src/pages/layout/sidebar-project.tsx

@@ -23,6 +23,7 @@ export type ProjectSidebarContext = {
   onProjectMouseEnter: (worktree: string, event: MouseEvent) => void
   onProjectMouseLeave: (worktree: string) => void
   onProjectFocus: (worktree: string) => void
+  onHoverOpenChanged: (worktree: string, hovered: boolean) => void
   navigateToProject: (directory: string) => void
   openSidebar: () => void
   closeProject: (directory: string) => void
@@ -197,7 +198,6 @@ const ProjectPreviewPanel = (props: {
   projectChildren: Accessor<Map<string, string[]>>
   workspaceSessions: (directory: string) => ReturnType<typeof sortedRootSessions>
   workspaceChildren: (directory: string) => Map<string, string[]>
-  setOpen: (value: boolean) => void
   ctx: ProjectSidebarContext
   language: ReturnType<typeof useLanguage>
 }): JSX.Element => (
@@ -264,7 +264,7 @@ const ProjectPreviewPanel = (props: {
         class="flex w-full text-left justify-start text-text-base px-2 hover:bg-transparent active:bg-transparent"
         onClick={() => {
           props.ctx.openSidebar()
-          props.setOpen(false)
+          props.ctx.onHoverOpenChanged(props.project.worktree, false)
           if (props.selected()) return
           props.ctx.navigateToProject(props.project.worktree)
         }}
@@ -289,28 +289,16 @@ export const SortableProject = (props: {
   const workspaceEnabled = createMemo(() => props.ctx.workspacesEnabled(props.project))
   const dirs = createMemo(() => props.ctx.workspaceIds(props.project))
   const [state, setState] = createStore({
-    open: false,
     menu: false,
     suppressHover: false,
   })
 
+  const isHoverProject = () => props.ctx.hoverProject() === props.project.worktree
   const preview = createMemo(() => !props.mobile && props.ctx.sidebarOpened())
   const overlay = createMemo(() => !props.mobile && !props.ctx.sidebarOpened())
-  const active = createMemo(
-    () => state.menu || (preview() ? state.open : overlay() && props.ctx.hoverProject() === props.project.worktree),
-  )
+  const active = createMemo(() => state.menu || (preview() ? isHoverProject() : overlay() && isHoverProject()))
 
-  createEffect(() => {
-    if (preview()) return
-    if (!state.open) return
-    setState("open", false)
-  })
-
-  createEffect(() => {
-    if (!selected()) return
-    if (!state.open) return
-    setState("open", false)
-  })
+  const hoverOpen = () => isHoverProject() && preview() && !selected() && !state.menu
 
   const label = (directory: string) => {
     const [data] = globalSync.child(directory, { bootstrap: false })
@@ -351,7 +339,7 @@ export const SortableProject = (props: {
       workspacesEnabled={props.ctx.workspacesEnabled}
       closeProject={props.ctx.closeProject}
       setMenu={(value) => setState("menu", value)}
-      setOpen={(value) => setState("open", value)}
+      setOpen={(value) => props.ctx.onHoverOpenChanged(props.project.worktree, value)}
       setSuppressHover={(value) => setState("suppressHover", value)}
       language={language}
     />
@@ -362,7 +350,7 @@ export const SortableProject = (props: {
     <div use:sortable classList={{ "opacity-30": sortable.isActiveDraggable }}>
       <Show when={preview() && !selected()} fallback={tile()}>
         <HoverCard
-          open={!state.suppressHover && state.open && !state.menu}
+          open={!state.suppressHover && hoverOpen() && !state.menu}
           openDelay={0}
           closeDelay={0}
           placement="right-start"
@@ -371,7 +359,7 @@ export const SortableProject = (props: {
           onOpenChange={(value) => {
             if (state.menu) return
             if (value && state.suppressHover) return
-            setState("open", value)
+            props.ctx.onHoverOpenChanged(props.project.worktree, value)
             if (value) props.ctx.setHoverSession(undefined)
           }}
         >
@@ -386,7 +374,6 @@ export const SortableProject = (props: {
             projectChildren={projectChildren}
             workspaceSessions={workspaceSessions}
             workspaceChildren={workspaceChildren}
-            setOpen={(value) => setState("open", value)}
             ctx={props.ctx}
             language={language}
           />