Conversation
There was a problem hiding this comment.
Pull request overview
This PR implements window management functionality including minimize and resize capabilities for window components. The changes enhance the window wrapper HOC with interactive resize handles, update the state management to track minimized state and dimensions, and refactor the Terminal component's structure with improved CSS organization.
Key changes:
- Added window minimize and resize functionality with state management
- Implemented interactive resize handles with mouse event handlers
- Refactored Terminal component structure with semantic CSS class names
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| src/hoc/WindowWrapper.jsx | Adds resize functionality with mouse event handlers and state for window dimensions; updates draggable trigger to use window header |
| src/store/window.js | Adds minimizeWindow and resizeWindow actions; updates openWindow/closeWindow to manage isMinimized, width, and height state |
| src/constants/index.js | Extends window configuration objects to include isMinimized, width, and height properties |
| src/components/WindowControls.jsx | Connects minimize button to minimizeWindow action |
| src/components/Dock.jsx | Implements window restore logic for minimized windows and adds visual indicator dot for open windows |
| src/windows/Terminal.jsx | Restructures component with nested divs and more semantic class names for better styling control |
| src/index.css | Adds terminal content/body styles, resize handle styles, and nav z-index for proper layering |
Comments suppressed due to low confidence (1)
src/hoc/WindowWrapper.jsx:26
- Unused variable isResizing.
const [isResizing, setIsResizing] = useState(false);
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/hoc/WindowWrapper.jsx
Outdated
| newWidth = Math.max(300, startWidth + (e.clientX - startX)); | ||
| } | ||
| if (edge.includes('left')) { | ||
| const delta = e.clientX - startX; | ||
| newWidth = Math.max(300, startWidth - delta); | ||
| if (newWidth > 300) newLeft = startLeft + delta; | ||
| } | ||
| if (edge.includes('bottom')) { | ||
| newHeight = Math.max(200, startHeight + (e.clientY - startY)); | ||
| } | ||
| if (edge.includes('top')) { | ||
| const delta = e.clientY - startY; | ||
| newHeight = Math.max(200, startHeight - delta); | ||
| if (newHeight > 200) newTop = startTop + delta; |
There was a problem hiding this comment.
The minimum width and height values (300 and 200) are hardcoded in multiple places. These magic numbers should be extracted into named constants at the top of the file or imported from a configuration file to improve maintainability and make it easier to adjust these values consistently.
There was a problem hiding this comment.
@copilot open a new pull request to apply changes based on this feedback
src/hoc/WindowWrapper.jsx
Outdated
| const { focusWindow, windows, resizeWindow } = useWindowStore(); | ||
| const { isOpen, zIndex, isMinimized, width, height } = windows[windowKey]; | ||
| const ref = useRef(null); | ||
| const [isResizing, setIsResizing] = useState(false); |
There was a problem hiding this comment.
The isResizing state variable is set but never used anywhere in the component. This is unused state that adds unnecessary overhead. Consider removing it or implementing the intended functionality.
src/hoc/WindowWrapper.jsx
Outdated
| newHeight = Math.max(200, startHeight - delta); | ||
| if (newHeight > 200) newTop = startTop + delta; |
There was a problem hiding this comment.
When resizing from the top edge, the position update logic has a bug. The condition checks if newHeight is greater than 200, but it should check if the calculated height before clamping would have been greater than 200. This causes the window position to not update correctly when the height is at the minimum constraint, resulting in jerky resize behavior at the minimum height boundary.
| newHeight = Math.max(200, startHeight - delta); | |
| if (newHeight > 200) newTop = startTop + delta; | |
| const rawHeight = startHeight - delta; | |
| newHeight = Math.max(200, rawHeight); | |
| if (rawHeight > 200) newTop = startTop + delta; |
| {windows[id]?.isOpen && ( | ||
| <div className="absolute -bottom-1 w-1 h-1 bg-white rounded-full" /> | ||
| )} |
There was a problem hiding this comment.
The indicator dot is shown when isOpen is true, but it should also consider the isMinimized state. According to typical window management UX patterns, the indicator should remain visible for minimized windows. However, verify if this matches the intended behavior - if minimized windows should not show the indicator, then the condition should be isOpen && !isMinimized.
|
@christopher-ling I've opened a new pull request, #6, to work on those changes. Once the pull request is ready, I'll request review from you. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (1)
src/hoc/WindowWrapper.jsx:26
- Unused variable isResizing.
const [isResizing, setIsResizing] = useState(false);
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/hoc/WindowWrapper.jsx
Outdated
| newWidth = Math.max(300, startWidth + (e.clientX - startX)); | ||
| } | ||
| if (edge.includes('left')) { | ||
| const delta = e.clientX - startX; | ||
| const proposedWidth = startWidth - delta; | ||
| newWidth = Math.max(300, proposedWidth); | ||
| if (proposedWidth > 300) newLeft = startLeft + delta; | ||
| } | ||
| if (edge.includes('bottom')) { | ||
| newHeight = Math.max(200, startHeight + (e.clientY - startY)); | ||
| } | ||
| if (edge.includes('top')) { | ||
| const delta = e.clientY - startY; | ||
| const proposedHeight = startHeight - delta; | ||
| newHeight = Math.max(200, proposedHeight); | ||
| if (proposedHeight > 200) newTop = startTop + delta; | ||
| } |
There was a problem hiding this comment.
The minimum width (300) and minimum height (200) are magic numbers that appear multiple times in the resize logic. Consider extracting these as named constants at the top of the file or component for better maintainability and consistency.
| const [instance] = Draggable.create(el, { | ||
| trigger: el.querySelector("#window-header"), |
There was a problem hiding this comment.
The Draggable trigger queries for '#window-header' on mount, but if the Component is not yet rendered or doesn't contain this element, the querySelector will return null and dragging may not work. Consider adding error handling or validation to ensure the trigger element exists before creating the Draggable instance.
| const [instance] = Draggable.create(el, { | |
| trigger: el.querySelector("#window-header"), | |
| const headerEl = el.querySelector("#window-header"); | |
| if (!headerEl) return; | |
| const [instance] = Draggable.create(el, { | |
| trigger: headerEl, |
fe42c09 to
63767c2
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.
Comments suppressed due to low confidence (1)
src/hoc/WindowWrapper.jsx:26
- Unused variable isResizing.
const [isResizing, setIsResizing] = useState(false);
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/hoc/WindowWrapper.jsx
Outdated
| <div className="resize-right" /> | ||
| <div className="resize-left" /> | ||
| <div className="resize-bottom" /> | ||
| <div className="resize-top" /> | ||
| <div className="resize-corner-br" /> | ||
| <div className="resize-corner-bl" /> | ||
| <div className="resize-corner-tr" /> | ||
| <div className="resize-corner-tl" /> |
There was a problem hiding this comment.
The resize handles are not accessible via keyboard navigation. Users who rely on keyboard-only navigation cannot resize windows. Consider adding tabindex, role, aria-label attributes, and keyboard event handlers (e.g., arrow keys) to make these handles accessible.
src/components/WindowControls.jsx
Outdated
| <div className="close" onClick={() => closeWindow(target)}/> | ||
| <div className="minimize" /> | ||
| <div className="minimize" onClick={() => minimizeWindow(target)}/> | ||
| <div className="maximize" /> |
There was a problem hiding this comment.
The window control buttons (close, minimize, maximize) lack accessibility attributes. They should have aria-label or title attributes to describe their function for screen reader users, and should use semantic button elements instead of divs with onClick handlers.
src/hoc/WindowWrapper.jsx
Outdated
| edges.forEach(({ selector, edge }) => { | ||
| const handle = el.querySelector(selector); | ||
| if (handle) { | ||
| handle.addEventListener('mousedown', (e) => handleMouseDown(e, edge)); | ||
| } | ||
| }); |
There was a problem hiding this comment.
The event listeners added to resize handles are never removed, causing a memory leak. Each time the component re-renders and the useLayoutEffect runs (when dependencies change), new event listeners are added without cleaning up the previous ones. A cleanup function should be returned that removes all added event listeners.
There was a problem hiding this comment.
@copilot open a new pull request to apply changes based on this feedback
|
|
||
| nav { | ||
| @apply flex justify-between items-center bg-white/50 backdrop-blur-3xl p-2 px-5 select-none; | ||
| @apply flex justify-between items-center bg-white/50 backdrop-blur-3xl p-2 px-5 select-none relative z-40; |
There was a problem hiding this comment.
The z-index value of 40 for the nav is hardcoded here, but window z-indexes start at INITIAL_Z_INDEX (1000) and increment from there. This could cause windows to appear above the navigation bar. Consider using a z-index value higher than the maximum possible window z-index, or defining navigation z-index as a constant.
| @apply flex justify-between items-center bg-white/50 backdrop-blur-3xl p-2 px-5 select-none relative z-40; | |
| @apply flex justify-between items-center bg-white/50 backdrop-blur-3xl p-2 px-5 select-none relative z-[9999]; |
- Implement minimize window feature with white dot indicator in dock - Add maximize functionality triggered by green button or drag-to-top - Add navbar highlight effect when dragging window to top - Make only window header draggable (not entire window) - Maximized windows cover dock and fill screen below navbar - Windows reset to original size when closed - Fix minimize restore behavior in dock click handler
|
@christopher-ling I've opened a new pull request, #7, to work on those changes. Once the pull request is ready, I'll request review from you. |
No description provided.