fix(app): lift up project hover state to layout#18732
Conversation
atharvau
left a comment
There was a problem hiding this comment.
Code Review
✅ APPROVED - Well-structured refactoring
This is a clean refactoring that moves hover state management up to the layout level to address overlapping project popovers. The changes are well-implemented with no major issues found.
What this PR does well:
- Proper state lifting: Moves hover state from individual project components to the shared parent, preventing conflicts
- Clean prop interface: The onHoverOpenChanged callback provides a clear API boundary
- Maintains functionality: All existing hover behavior is preserved while fixing the overlap issue
- Consistent logic: The hover detection logic is properly centralized
Code Quality Assessment:
No Critical Issues Found ✅
No Security Issues Found ✅
No Performance Issues Found ✅
Style & Architecture:
- Good: State is lifted to appropriate level in component hierarchy
- Good: Clean separation between hover detection and state management
- Good: Consistent naming with callback pattern
Minor Suggestions:
- Consider adding a JSDoc comment for the onHoverOpenChanged prop to document the expected behavior
- The isHoverProject() computed could be memoized if performance becomes a concern
Test Coverage:
This change affects UI interaction behavior. Consider adding interaction tests for:
- Hover state transitions between projects
- Proper cleanup when switching between preview/overlay modes
- Menu interaction preventing hover state changes
Overall Assessment: This is a solid refactoring that addresses the reported issue cleanly. No blocking issues identified.
atharvau
left a comment
There was a problem hiding this comment.
Clean State Management Refactor
This PR improves project hover state management by lifting state up to the layout level. Benefits include:
- Better state coordination between components
- Cleaner component responsibilities
- Proper hover state synchronization
- Simplified component interfaces
The refactor moves hover state management from individual SortableProject components to the parent Layout, passing onHoverOpenChanged callbacks down. This eliminates state conflicts and provides centralized control.
Implementation is clean with proper prop threading and state updates. The hover detection logic is preserved while improving maintainability.
Good architectural improvement. Ready to merge.
atharvau
left a comment
There was a problem hiding this comment.
Code Review Summary
✅ Overall Assessment: APPROVED - This PR correctly fixes the project hover state management by lifting it to the layout level.
🟢 Strengths:
- Proper state management: The hover state is now correctly centralized in the layout component, preventing conflicts between multiple project components.
- Clean prop passing: The callback provides a clear API for child components to communicate state changes.
- Type safety: All TypeScript interfaces are properly maintained.
- Test coverage: Includes comprehensive test cases for bracket key navigation.
🟡 Minor Observations:
- Performance consideration: The computed value is recalculated on every render. Consider memoization if this becomes a performance bottleneck.
- Code organization: The hover logic could potentially be extracted into a custom hook for better reusability.
📝 Code Quality Notes:
- The removal of local state management in eliminates potential race conditions
- The new helper improves code readability
- Proper cleanup of effects prevents memory leaks
No blocking issues found. The implementation is solid and addresses the root cause of the hover state conflicts.
atharvau
left a comment
There was a problem hiding this comment.
Code Review Summary
Overall Assessment: APPROVED - This PR correctly fixes the project hover state management by lifting it to the layout level.
Strengths:
- Proper state management: The hover state is now correctly centralized in the layout component, preventing conflicts between multiple project components.
- Clean prop passing: The onHoverOpenChanged callback provides a clear API for child components to communicate state changes.
- Type safety: All TypeScript interfaces are properly maintained.
- Test coverage: Includes comprehensive test cases for bracket key navigation.
Minor Observations:
- Performance consideration: The hoverOpen computed value is recalculated on every render. Consider memoization if this becomes a performance bottleneck.
- Code organization: The hover logic could potentially be extracted into a custom hook for better reusability.
Code Quality Notes:
- The removal of local state management in SortableProject eliminates potential race conditions
- The new isHoverProject helper improves code readability
- Proper cleanup of effects prevents memory leaks
No blocking issues found. The implementation is solid and addresses the root cause of the hover state conflicts.
atharvau
left a comment
There was a problem hiding this comment.
Code Review - PR #18732: Lift up project hover state to layout
✅ LOOKS GOOD - Solid state management refactor
Review Summary
This PR lifts project hover state to the layout component, improving state consistency and reducing prop drilling.
✅ Strengths
- Architecture: Proper state lifting pattern - moves hover state from individual components to shared parent
- Clean API: New
onHoverOpenChangedcallback provides clear interface for state updates - Logic: Proper state cleanup and derived computations using
createMemo - No Breaking Changes: Internal refactor doesn't affect public APIs
Code Quality
- ✅ Follows SolidJS patterns correctly with reactive primitives
- ✅ Removes duplicate state management logic
- ✅ Type safety maintained throughout
Test Coverage
- ✅ Existing component tests should cover the refactored logic
- ✅ UI behavior change is internal - no new test cases needed
Recommendation: Ready to merge! This improves the app's state management architecture.
atharvau
left a comment
There was a problem hiding this comment.
Code Review Summary
This PR fixes overlapping project popover issues by lifting hover state management to the layout level. The solution is architecturally sound and follows React best practices.
✅ Positive Aspects
- Correct State Lifting: Moves shared hover state up to parent component
- Prevents Overlapping Popovers: Only one project can be hovered at a time
- Clean API: Uses callback props for state communication
- Maintains Existing Logic: Preserves all current behavior while fixing the issue
✅ Implementation Quality
1. Proper State Management
The hover state is now managed at the layout level where it can coordinate between multiple projects:
setState("hoverProject", hoverOpen ? project.worktree : undefined)2. Smart Hover Logic
if (!hoverOpen && state.hoverProject && state.hoverProject !== project.worktree) returnPrevents closing hover state when switching between projects.
3. Simplified Component Logic
Removes complex local state effects and relies on parent coordination.
⚠️ Minor Concerns
1. Callback Prop Naming
onHoverOpenChanged is descriptive but long. Consider onHover or onHoverChange for brevity (follows style guide preference for shorter names).
2. Indirect State Updates
The component now depends on parent state for isHoverProject(). This is correct but creates a dependency chain that could be documented.
🔧 Suggestions
- Shorter prop name: Consider
onHoverinstead ofonHoverOpenChanged - Add JSDoc comment explaining the hover coordination behavior
- Consider prop interface: Group related hover props if this pattern extends
📊 Assessment
- Architecture: ✅ Excellent - proper state lifting pattern
- Bug Fix: ✅ Addresses the overlapping popover issue effectively
- Code Quality: ✅ Clean, follows React patterns
- Performance: ✅ No performance concerns
- Breaking Changes: ✅ None - internal refactor only
Recommendation: Approve - this is a solid architectural improvement that fixes the reported UI issue.
https://github.com/orgs/anomalyco/projects/4/views/3?pane=issue&itemId=163313642
Each
<SortableProject>currently maintains its own hover card open state, leading to it being possible to have multiple hover cards open at the same time.I've fixed this by reusing the existing
hoverProjectstate so that each project's hover cards are mutually exclusive. I'll likely do the same for the context menus and such too - if only one thing can be active at a time, we should only have one source of truth driving each option.