-
Notifications
You must be signed in to change notification settings - Fork 1.1k
feat(ui): make tool list panel resizable #2253
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Add draggable resize handle to tool list panel with min/max width constraints, visual feedback, and localStorage persistence. Fixes googleapis#1729
Summary of ChangesHello @bennymagid, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a significant user interface improvement by making the tool list panel dynamically resizable. Users can now adjust the width of this panel to their preference using a new draggable handle, with the chosen dimensions being saved locally for a consistent experience. This change enhances the flexibility and usability of the application's layout. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces a resizable tool list panel, a great usability improvement. The implementation correctly handles min/max width constraints and persists the user's preference using localStorage. My review focuses on improving the JavaScript event handling to prevent potential resource leaks and on minor code cleanup in both CSS and JavaScript for better maintainability. Overall, the changes are well-structured and effective.
internal/server/static/js/resize.js
Outdated
| let isResizing = false; | ||
| let startX = 0; | ||
| let startWidth = 0; | ||
|
|
||
| resizeHandle.addEventListener('mousedown', (e) => { | ||
| isResizing = true; | ||
| startX = e.clientX; | ||
| startWidth = secondNav.offsetWidth; | ||
| resizeHandle.classList.add('active'); | ||
| document.body.style.cursor = 'ew-resize'; | ||
| document.body.style.userSelect = 'none'; | ||
| e.preventDefault(); | ||
| }); | ||
|
|
||
| document.addEventListener('mousemove', (e) => { | ||
| if (!isResizing) { | ||
| return; | ||
| } | ||
|
|
||
| const deltaX = e.clientX - startX; | ||
| const newWidth = startWidth + deltaX; | ||
| const maxWidth = (window.innerWidth * MAX_WIDTH_PERCENT) / 100; | ||
|
|
||
| const clampedWidth = Math.max(MIN_WIDTH, Math.min(newWidth, maxWidth)); | ||
| setPanelWidth(secondNav, clampedWidth); | ||
| }); | ||
|
|
||
| document.addEventListener('mouseup', () => { | ||
| if (isResizing) { | ||
| isResizing = false; | ||
| resizeHandle.classList.remove('active'); | ||
| document.body.style.cursor = ''; | ||
| document.body.style.userSelect = ''; | ||
|
|
||
| // Save width to localStorage | ||
| localStorage.setItem(STORAGE_KEY, secondNav.offsetWidth.toString()); | ||
| } | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current implementation adds mousemove and mouseup event listeners to the global document object and never removes them. This can lead to unnecessary event processing and potential memory leaks over time. A more robust and efficient pattern is to add these listeners only during the drag operation (on mousedown) and remove them immediately after (on mouseup). This refactoring also simplifies the logic by eliminating the need for the isResizing flag.
let startX = 0;
let startWidth = 0;
const onMouseMove = (e) => {
const deltaX = e.clientX - startX;
const newWidth = startWidth + deltaX;
const maxWidth = (window.innerWidth * MAX_WIDTH_PERCENT) / 100;
const clampedWidth = Math.max(MIN_WIDTH, Math.min(newWidth, maxWidth));
setPanelWidth(secondNav, clampedWidth);
};
const onMouseUp = () => {
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
resizeHandle.classList.remove('active');
document.body.style.cursor = '';
document.body.style.userSelect = '';
// Save width to localStorage
localStorage.setItem(STORAGE_KEY, secondNav.offsetWidth.toString());
};
resizeHandle.addEventListener('mousedown', (e) => {
startX = e.clientX;
startWidth = secondNav.offsetWidth;
resizeHandle.classList.add('active');
document.body.style.cursor = 'ew-resize';
document.body.style.userSelect = 'none';
e.preventDefault();
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
});
internal/server/static/css/style.css
Outdated
| .resize-handle:hover { | ||
| background-color: var(--toolbox-blue); | ||
| } | ||
|
|
||
| .resize-handle.active { | ||
| background-color: var(--toolbox-blue); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The styles for :hover and .active states of the resize handle are identical. To reduce code duplication and improve maintainability, you can group these selectors.
| .resize-handle:hover { | |
| background-color: var(--toolbox-blue); | |
| } | |
| .resize-handle.active { | |
| background-color: var(--toolbox-blue); | |
| } | |
| .resize-handle:hover, | |
| .resize-handle.active { | |
| background-color: var(--toolbox-blue); | |
| } |
| function setPanelWidth(panel, width) { | ||
| panel.style.flex = `0 0 ${width}px`; | ||
| panel.style.width = `${width}px`; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When an element is a flex item, setting flex-basis (via the flex shorthand property) is sufficient to control its size along the main axis. The width property is redundant in this case because flex-basis will take precedence. You can simplify this function by removing the line that sets panel.style.width.
function setPanelWidth(panel, width) {
panel.style.flex = `0 0 ${width}px`;
}- Fix event listener memory leak by adding/removing listeners during drag - Remove redundant width property from setPanelWidth - Combine duplicate CSS selectors for hover and active states
Description
Add draggable resize handle to tool list panel with min/max width
constraints, visual feedback, and localStorage persistence.
PR Checklist
CONTRIBUTING.md
bug/issue
before writing your code! That way we can discuss the change, evaluate
designs, and agree on the general idea
!if this involve a breaking change🛠️ Fixes #1729