@@ -36,6 +36,23 @@ export type { WorkspaceSelection } from "./WorkspaceListItem";
3636// Draggable project item moved to module scope to avoid remounting on every parent render.
3737// Defining components inside another component causes a new function identity each render,
3838// which forces React to unmount/remount the subtree. That led to hover flicker and high CPU.
39+
40+ const PROJECT_ITEM_BASE_CLASS =
41+ "py-2 px-3 flex items-center border-l-transparent bg-sidebar transition-colors duration-150" ;
42+
43+ function getProjectItemClassName ( opts : {
44+ isDragging : boolean ;
45+ isOver : boolean ;
46+ selected : boolean ;
47+ } ) : string {
48+ return cn (
49+ PROJECT_ITEM_BASE_CLASS ,
50+ opts . isDragging ? "cursor-grabbing opacity-35 [&_*]:!cursor-grabbing" : "cursor-grab" ,
51+ opts . isOver && "bg-accent/[0.08]" ,
52+ opts . selected && "bg-hover border-l-accent" ,
53+ "hover:[&_button]:opacity-100 hover:[&_[data-drag-handle]]:opacity-100"
54+ ) ;
55+ }
3956type DraggableProjectItemProps = React . PropsWithChildren < {
4057 projectPath : string ;
4158 onReorder : ( draggedPath : string , targetPath : string ) => void ;
@@ -87,13 +104,11 @@ const DraggableProjectItemBase: React.FC<DraggableProjectItemProps> = ({
87104 return (
88105 < div
89106 ref = { ( node ) => drag ( drop ( node ) ) }
90- className = { cn (
91- "py-2 px-3 flex items-center border-l-transparent transition-all duration-150 bg-sidebar" ,
92- isDragging ? "cursor-grabbing opacity-40 [&_*]:!cursor-grabbing" : "cursor-grab" ,
93- isOver && "bg-accent/[0.08]" ,
94- selected && "bg-hover border-l-accent" ,
95- "hover:[&_button]:opacity-100 hover:[&_[data-drag-handle]]:opacity-100"
96- ) }
107+ className = { getProjectItemClassName ( {
108+ isDragging,
109+ isOver,
110+ selected : ! ! selected ,
111+ } ) }
97112 { ...rest }
98113 >
99114 { children }
@@ -141,18 +156,17 @@ const ProjectDragLayer: React.FC = () => {
141156 if ( ! isDragging || ! currentOffset || ! item ?. projectPath ) return null ;
142157
143158 const abbrevPath = PlatformPaths . abbreviate ( item . projectPath ) ;
144- const { dirPath , basename } = PlatformPaths . splitAbbreviated ( abbrevPath ) ;
159+ const { basename } = PlatformPaths . splitAbbreviated ( abbrevPath ) ;
145160
146161 return (
147162 < div className = "pointer-events-none fixed inset-0 z-[9999] cursor-grabbing" >
148163 < div style = { { transform : `translate(${ currentOffset . x + 10 } px, ${ currentOffset . y + 10 } px)` } } >
149- < div className = "bg-hover/95 text-foreground border-l-accent flex w-fit max-w-72 min-w-44 items-center rounded border-l-[3px] px-3 py-1.5 shadow-[0_6px_24px_rgba(0,0,0,0.4)]" >
150- < span className = "text-muted mr-2 text-xs" > ▶</ span >
151- < div className = "min-w-0 flex-1" >
152- < div className = "text-muted-dark font-monospace truncate text-sm leading-tight" >
153- < span > { dirPath } </ span >
154- < span className = "text-foreground font-medium" > { basename } </ span >
155- </ div >
164+ < div className = { cn ( PROJECT_ITEM_BASE_CLASS , "w-fit max-w-64 rounded-sm shadow-lg" ) } >
165+ < span className = "text-secondary mr-2 flex h-5 w-5 shrink-0 items-center justify-center" >
166+ < ChevronRight size = { 12 } />
167+ </ span >
168+ < div className = "flex min-w-0 flex-1 items-center pr-2" >
169+ < span className = "text-foreground truncate text-sm font-medium" > { basename } </ span >
156170 </ div >
157171 </ div >
158172 </ div >
0 commit comments