Skip to content

new-log-viewer: Resize panel width when the browser window resizes. #94

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

Merged
merged 12 commits into from
Oct 22, 2024

Conversation

junhaoliao
Copy link
Member

@junhaoliao junhaoliao commented Oct 15, 2024

References

new-log-viewer series: #45 #46 #48 #51 #52 #53 #54 #55 #56 #59 #60 #61 #62 #63 #66 #67 #68 #69 #70 #71 #72 #73 #74 #76 #77 #78 #79 #80 #81 #82 #83 #84 #89 #91 #93

Description

  1. Refactor panel width setter / getters to use document.documentElement.
  2. Call getComputedStyle(document.documentElement) instead of accessing document.documentElement.style directly.
  3. Enforce a min width on the editor in place of the previous max panel width ratio approach.
  4. Add window resize event handler to resize panel width when necessary.

Validation performed

  1. Started debug server as specified in Add support for loading files, decoding them as JSONL, and formatting them using a Logback-like format string. #46.
  2. Launch the app in a maximized browser window (Zoom: 100%) on a display larger than 1920x1080 (Scale: 1). Observed the panel was expanded by default.
  3. Used the resize handle to adjust the width of the panel by dragging the handle towards the right of the window. Observed that the resizes were successful and that the panel cannot be further expanded when the editor's width becomes too small.
  4. "Restore"d the browser window so it was no longer maximized. Reduced the window's width by dragging the resize handle towards the left and observed that as the panel reduced its width at the same time, while the editor remained visible with a fixed width. As the window becomes too small, the viewport could no longer hold both the editor and the panel, and the panel's width stopped reducing as the window's width reduced. Kept dragging the handle towards the left and the editor eventually became invisible.

Summary by CodeRabbit

  • New Features

    • Enhanced sidebar resizing logic to maintain a minimum width for the editor.
    • Dynamic adjustment of sidebar width during window resizing for improved user experience.
  • Bug Fixes

    • Resolved issues with sidebar width calculations that could lead to improper display.

…width ratio approach; Add window resize event handler to resize panel width when necessary.
…utedStyle instead of getPropertyValue from the element's `style` object directly.
Copy link

coderabbitai bot commented Oct 15, 2024

Walkthrough

The pull request modifies the Sidebar component in the index.tsx file. Key changes include updating the PANEL_CLIP_THRESHOLD_IN_PIXELS constant from 250 to 360 pixels and introducing a new constant, EDITOR_MIN_WIDTH_IN_PIXELS, set to 250 pixels. The getPanelWidth and setPanelWidth functions now interact with document.documentElement instead of document.body. The handleResize function's logic has been revised to account for the minimum editor width during resizing, and a new useEffect hook has been added to manage window resize events.

Changes

File Path Change Summary
new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx Updated PANEL_CLIP_THRESHOLD_IN_PIXELS, added EDITOR_MIN_WIDTH_IN_PIXELS, modified getPanelWidth and setPanelWidth to use document.documentElement, revised handleResize logic, and added a useEffect hook for window resize handling.

Possibly related PRs

  • new-log-viewer: Persist active tab across sessions. #93: The changes in the Sidebar component regarding the handleActiveTabNameChange function and the introduction of useEffect hooks are directly related to the modifications made in the same file in this PR, which also updates the logic for managing the active tab state.

Suggested reviewers

  • davemarco
  • Henry8192

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (1)
new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx (1)

17-17: Make EDITOR_MIN_WIDTH_IN_PIXELS configurable

The hardcoded value of 250 pixels for EDITOR_MIN_WIDTH_IN_PIXELS may not accommodate all screen sizes or user preferences. Consider making this value configurable or responsive to enhance flexibility and usability across different devices.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between ae24669 and 337e013.

📒 Files selected for processing (1)
  • new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx (4 hunks)
🧰 Additional context used
📓 Learnings (1)
new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx (2)
Learnt from: junhaoliao
PR: y-scope/yscope-log-viewer#74
File: new-log-viewer/src/components/CentralContainer/Sidebar/ResizeHandle.tsx:77-82
Timestamp: 2024-09-28T02:32:08.882Z
Learning: Accessibility improvements, such as adding ARIA attributes to components like `ResizeHandle`, require broader discussion and are considered out of scope for small PRs.
Learnt from: junhaoliao
PR: y-scope/yscope-log-viewer#74
File: new-log-viewer/src/components/CentralContainer/Sidebar/ResizeHandle.tsx:77-82
Timestamp: 2024-10-08T15:52:50.753Z
Learning: Accessibility improvements, such as adding ARIA attributes to components like `ResizeHandle`, require broader discussion and are considered out of scope for small PRs.
🔇 Additional comments (1)
new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx (1)

25-25: Verify the change from document.body to document.documentElement

Switching from document.body to document.documentElement when accessing and setting the --ylv-panel-width CSS variable may have broader implications. Ensure that all styles and components relying on this variable continue to function correctly after this change.

Run the following script to search for all occurrences of --ylv-panel-width in the codebase to confirm consistent usage:

Also applies to: 35-35

✅ Verification successful

Verification Completed: Consistent Usage of --ylv-panel-width Confirmed

All instances of --ylv-panel-width have been reviewed and are consistently used within CSS files. The change from document.body to document.documentElement does not impact other parts of the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all instances of '--ylv-panel-width' in CSS and JavaScript files.

rg '--ylv-panel-width'

Length of output: 442


Script:

#!/bin/bash
# Description: Corrected script to find all instances of '--ylv-panel-width' in CSS and JavaScript files.

rg -e '--ylv-panel-width' --type-add 'js:*.js' --type-add 'css:*.css' --js --css

Length of output: 509


Script:

#!/bin/bash
# Description: Corrected script to find all instances of '--ylv-panel-width' in CSS and JavaScript files.

rg -e '--ylv-panel-width' -tjs -tcss

Length of output: 268

Comment on lines 99 to 118
// On initialization, register window resize event handler to resize panel width when necessary.
useEffect(() => {
const handleWindowResize = () => {
const availableWidth = window.innerWidth - EDITOR_MIN_WIDTH_IN_PIXELS;
if (
getPanelWidth() > availableWidth &&
tabListRef.current &&
tabListRef.current.clientWidth + PANEL_CLIP_THRESHOLD_IN_PIXELS < availableWidth
) {
setPanelWidth(availableWidth);
}
};

window.addEventListener("resize", handleWindowResize);

return () => {
window.removeEventListener("resize", handleWindowResize);
};
}, []);

Copy link

@coderabbitai coderabbitai bot Oct 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Confirm dependencies in useEffect are correctly specified

The useEffect hook currently has an empty dependency array. Ensure that all variables and functions used within the effect, such as getPanelWidth, tabListRef.current, and PANEL_CLIP_THRESHOLD_IN_PIXELS, do not need to be included in the dependency array to prevent potential bugs due to stale closures.

Consider adding necessary dependencies to the dependency array or refactoring the handleWindowResize function using useCallback if appropriate.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getPanelWidth is declared outside of the functional component and does not have any dependency on React states;
tabListRef is a ref which I believe does not need to be included in the dependency array.
PANEL_CLIP_THRESHOLD_IN_PIXELS is a const declared outside of the functional component, which does not change at all as well.

Do you think the dependency array is correctly specified now?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@junhaoliao, you're right. Since getPanelWidth and PANEL_CLIP_THRESHOLD_IN_PIXELS are constants declared outside the functional component, and tabListRef is a ref object that remains consistent throughout the component's lifecycle, the dependency array is correctly specified as is. Thank you for the clarification.

(・⊝・)


✏️ Learnings added
Learnt from: junhaoliao
PR: y-scope/yscope-log-viewer#94
File: new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx:99-118
Timestamp: 2024-10-19T03:33:29.285Z
Learning: In `new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx`, when using `useEffect` to register window resize event handlers, it's acceptable to have an empty dependency array because the variables and functions used within the effect (`getPanelWidth`, `PANEL_CLIP_THRESHOLD_IN_PIXELS`, and `tabListRef`) are constants or refs declared outside the functional component and do not change.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@davemarco
Copy link
Contributor

If you click on the tab when the editor is small, the tab appears to "jump" to smaller length. I didn't investigate, but I feel it has something do to with this line const availableWidth = window.innerWidth - EDITOR_MIN_WIDTH_IN_PIXELS

Screen.Recording.2024-10-20.at.12.37.42.PM.mov

Copy link
Contributor

@davemarco davemarco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see earlier comment

…PIXELS to 140 to enhance layout consistency.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (1)
new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx (1)

99-118: LGTM: Effective window resize handling implemented.

The new useEffect hook successfully implements the PR objective of adjusting the panel width when the browser window resizes. The cleanup function properly removes the event listener, which is good practice to prevent memory leaks.

To further improve performance, consider debouncing the handleWindowResize function. This would reduce the frequency of recalculations during rapid window resizing, potentially improving the user experience on less powerful devices.

Example implementation using a custom debounce hook:

import { useCallback, useEffect } from 'react';

function useDebounce(callback: () => void, delay: number) {
  useEffect(() => {
    const handler = setTimeout(() => callback(), delay);
    return () => clearTimeout(handler);
  }, [callback, delay]);
}

// In your component:
const debouncedHandleWindowResize = useCallback(() => {
  // Your existing handleWindowResize logic here
}, [/* dependencies */]);

useDebounce(debouncedHandleWindowResize, 250); // 250ms delay

useEffect(() => {
  window.addEventListener('resize', debouncedHandleWindowResize);
  return () => window.removeEventListener('resize', debouncedHandleWindowResize);
}, [debouncedHandleWindowResize]);

This approach would maintain responsiveness while reducing unnecessary calculations.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 337e013 and 740080e.

📒 Files selected for processing (1)
  • new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx (4 hunks)
🧰 Additional context used
📓 Learnings (1)
new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx (3)
Learnt from: junhaoliao
PR: y-scope/yscope-log-viewer#94
File: new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx:99-118
Timestamp: 2024-10-19T03:33:29.578Z
Learning: In `new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx`, when using `useEffect` to register window resize event handlers, it's acceptable to have an empty dependency array because the variables and functions used within the effect (`getPanelWidth`, `PANEL_CLIP_THRESHOLD_IN_PIXELS`, and `tabListRef`) are constants or refs declared outside the functional component and do not change.
Learnt from: junhaoliao
PR: y-scope/yscope-log-viewer#74
File: new-log-viewer/src/components/CentralContainer/Sidebar/ResizeHandle.tsx:77-82
Timestamp: 2024-09-28T02:32:08.882Z
Learning: Accessibility improvements, such as adding ARIA attributes to components like `ResizeHandle`, require broader discussion and are considered out of scope for small PRs.
Learnt from: junhaoliao
PR: y-scope/yscope-log-viewer#74
File: new-log-viewer/src/components/CentralContainer/Sidebar/ResizeHandle.tsx:77-82
Timestamp: 2024-10-08T15:52:50.753Z
Learning: Accessibility improvements, such as adding ARIA attributes to components like `ResizeHandle`, require broader discussion and are considered out of scope for small PRs.
🔇 Additional comments (4)
new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx (4)

3-3: LGTM: Import of useEffect is appropriate.

The addition of useEffect to the import statement is consistent with its usage in the new window resize event handling logic introduced later in the component.


16-17: LGTM: New constants introduced for panel and editor dimensions.

The introduction of PANEL_CLIP_THRESHOLD_IN_PIXELS and EDITOR_MIN_WIDTH_IN_PIXELS is appropriate for the new resizing logic. However, could you please provide some context on how these specific values (360 and 140) were determined? This would help in understanding the design decisions behind these constants.


25-25: LGTM: Improved DOM interaction for panel width.

The change from document.body to document.documentElement in both getPanelWidth and setPanelWidth functions is a good improvement. Using document.documentElement is more standard and reliable across different browsers for accessing and setting CSS custom properties. This change ensures more consistent behaviour of the panel width calculations and adjustments.

Also applies to: 35-35


86-95: LGTM: Improved resize handling with minimum editor width consideration.

The new resize logic effectively implements a responsive panel width while ensuring the editor maintains a minimum width. This change aligns well with the PR objectives.

However, I notice that the availableWidth calculation is duplicated in both handleResize and the useEffect hook for window resize. To improve maintainability, consider refactoring this calculation into a separate function.

# Conflicts:
#	new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (3)
new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx (3)

22-23: Approve changes and suggest documentation for constants

The updates to PANEL_CLIP_THRESHOLD_IN_PIXELS and the introduction of EDITOR_MIN_WIDTH_IN_PIXELS align well with the PR objectives. These changes should improve the resizing behaviour of the sidebar and editor.

Consider adding brief comments to explain the purpose and impact of these constants, especially EDITOR_MIN_WIDTH_IN_PIXELS, as it's a new addition.


93-102: Approve resize logic and suggest refactoring

The updated handleResize function now properly considers the minimum editor width, which is a significant improvement. This change ensures better usability by maintaining a minimum editor size during resizing.

To reduce code duplication, consider extracting the availableWidth calculation into a separate function:

const calculateAvailableWidth = () => window.innerWidth - EDITOR_MIN_WIDTH_IN_PIXELS;

// Then use it in handleResize and handleWindowResize:
const availableWidth = calculateAvailableWidth();

This refactoring will improve maintainability and reduce the risk of inconsistencies.


106-125: Approve window resize handling and suggest optimization

The addition of the useEffect hook for handling window resize events is a great improvement. It ensures that the sidebar remains responsive to window size changes while respecting the minimum editor width.

Consider using the useCallback hook for the handleWindowResize function to optimize performance:

const handleWindowResize = useCallback(() => {
  // ... existing logic ...
}, []);

useEffect(() => {
  window.addEventListener("resize", handleWindowResize);
  return () => window.removeEventListener("resize", handleWindowResize);
}, [handleWindowResize]);

This change can help prevent unnecessary re-renders and improve overall performance.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 740080e and 9101e31.

📒 Files selected for processing (1)
  • new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx (3 hunks)
🧰 Additional context used
📓 Learnings (1)
new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx (3)
Learnt from: junhaoliao
PR: y-scope/yscope-log-viewer#94
File: new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx:99-118
Timestamp: 2024-10-19T03:33:29.578Z
Learning: In `new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx`, when using `useEffect` to register window resize event handlers, it's acceptable to have an empty dependency array because the variables and functions used within the effect (`getPanelWidth`, `PANEL_CLIP_THRESHOLD_IN_PIXELS`, and `tabListRef`) are constants or refs declared outside the functional component and do not change.
Learnt from: junhaoliao
PR: y-scope/yscope-log-viewer#74
File: new-log-viewer/src/components/CentralContainer/Sidebar/ResizeHandle.tsx:77-82
Timestamp: 2024-09-28T02:32:08.882Z
Learning: Accessibility improvements, such as adding ARIA attributes to components like `ResizeHandle`, require broader discussion and are considered out of scope for small PRs.
Learnt from: junhaoliao
PR: y-scope/yscope-log-viewer#74
File: new-log-viewer/src/components/CentralContainer/Sidebar/ResizeHandle.tsx:77-82
Timestamp: 2024-10-08T15:52:50.753Z
Learning: Accessibility improvements, such as adding ARIA attributes to components like `ResizeHandle`, require broader discussion and are considered out of scope for small PRs.
🔇 Additional comments (2)
new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx (2)

31-31: Approve consistent use of document.documentElement

The change to use document.documentElement in both getPanelWidth and setPanelWidth functions is a good improvement. It ensures consistency and reliability across different HTML structures.

Also applies to: 41-41


Line range hint 1-155: Summary of changes and their impact

The modifications to the Sidebar component effectively address the PR objectives:

  1. The panel width calculation and setting now use document.documentElement, ensuring consistency.
  2. The introduction of EDITOR_MIN_WIDTH_IN_PIXELS and the updated resize logic maintain a minimum editor width during resizing.
  3. The new window resize event handler ensures the sidebar remains responsive to window size changes.

These changes collectively improve the user experience by providing a more robust and responsive sidebar resizing functionality.

@junhaoliao
Copy link
Member Author

If you click on the tab when the editor is small, the tab appears to "jump" to smaller length. I didn't investigate, but I feel it has something do to with this line const availableWidth = window.innerWidth - EDITOR_MIN_WIDTH_IN_PIXELS

Screen.Recording.2024-10-20.at.12.37.42.PM.mov

Should be now addressed with the tweaks in PANEL_CLIP_THRESHOLD_IN_PIXELS and EDITOR_MIN_WIDTH_IN_PIXELS.

@Henry8192
Copy link
Collaborator

Henry8192 commented Oct 21, 2024

If you click on the tab when the editor is small, the tab appears to "jump" to smaller length. I didn't investigate, but I feel it has something do to with this line const availableWidth = window.innerWidth - EDITOR_MIN_WIDTH_IN_PIXELS

Screen.Recording.2024-10-20.at.12.37.42.PM.mov

@junhaoliao I think I found the root cause: We need to also need to address sidebar-tab-list-spacing when we do the calculation. Though it is currently using flex-grow, I found the default value to be 48px for most of the case, so a hard code solution is to deduct 48 whenever you do the caluculation.

For example,

if (
    tabListRef.current.clientWidth + PANEL_CLIP_THRESHOLD_IN_PIXELS - 48 >
    resizeHandlePosition
) {
    // If the resize handle is positioned to the right of the <TabList/>'s right edge
    // with a clipping threshold accounted, close the panel.
    setPanelWidth(tabListRef.current.clientWidth);
}

@junhaoliao
Copy link
Member Author

If you click on the tab when the editor is small, the tab appears to "jump" to smaller length. I didn't investigate, but I feel it has something do to with this line const availableWidth = window.innerWidth - EDITOR_MIN_WIDTH_IN_PIXELS
Screen.Recording.2024-10-20.at.12.37.42.PM.mov

@junhaoliao I think I found the root cause: We need to also need to address sidebar-tab-list-spacing when we do the calculation. Though it is currently using flex-grow, I found the default value to be 48px for most of the case, so a hard code solution is to deduct 48 whenever you do the caluculation.

For example,

if (
    tabListRef.current.clientWidth + PANEL_CLIP_THRESHOLD_IN_PIXELS - 48 >
    resizeHandlePosition
) {
    // If the resize handle is positioned to the right of the <TabList/>'s right edge
    // with a clipping threshold accounted, close the panel.
    setPanelWidth(tabListRef.current.clientWidth);
}

I think your analysis is correct on that we did not account the sidebar width when doing the calculations. (We can confirm by double checking whether tabListRef.current.clientWidth is 48.)
Essentially, I believe we should not include tabListRef.current.clientWidth when comparing the resizeHandlePosition with the panel threshold. i.e., we can simply write:

        if (PANEL_CLIP_THRESHOLD_IN_PIXELS > resizeHandlePosition) {
            // If the resize handle is positioned to the right of the <TabList/>'s right edge
            // with a clipping threshold accounted, close the panel.
            setPanelWidth(tabListRef.current.clientWidth);
        }
...

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (3)
new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx (3)

22-23: LGTM! Consider adding documentation for the new constant.

The changes to PANEL_CLIP_THRESHOLD_IN_PIXELS and the addition of EDITOR_MIN_WIDTH_IN_PIXELS align well with the PR objectives. These updates should improve the resizing behaviour of the sidebar.

Consider adding a brief comment explaining the purpose of EDITOR_MIN_WIDTH_IN_PIXELS for better code maintainability.


86-99: LGTM! Improved resizing logic.

The updated handleResize function successfully implements a more robust resizing behaviour, addressing the PR objectives. The new logic ensures that the editor maintains a minimum width while allowing the panel to resize appropriately.

For improved readability, consider extracting the calculation of availableWidth into a separate constant at the beginning of the function:

const availableWidth = window.innerWidth - EDITOR_MIN_WIDTH_IN_PIXELS;

This would eliminate the need to repeat this calculation and make the code slightly more DRY.


103-121: LGTM! Effective implementation of window resize handling.

The new useEffect hook successfully implements responsive panel width adjustment, addressing the PR objective. The logic for adjusting the panel width is consistent with the handleResize function, ensuring a cohesive resizing behaviour.

For consistency with the handleResize function, consider extracting the availableWidth calculation into a constant at the beginning of the handleWindowResize function:

const handleWindowResize = () => {
    const availableWidth = window.innerWidth - EDITOR_MIN_WIDTH_IN_PIXELS;
    // ... rest of the function
};

This would make the code more consistent and easier to maintain.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 9101e31 and 3caf68e.

📒 Files selected for processing (1)
  • new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx (3 hunks)
🧰 Additional context used
📓 Learnings (1)
new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx (3)
Learnt from: junhaoliao
PR: y-scope/yscope-log-viewer#94
File: new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx:99-118
Timestamp: 2024-10-19T03:33:29.578Z
Learning: In `new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx`, when using `useEffect` to register window resize event handlers, it's acceptable to have an empty dependency array because the variables and functions used within the effect (`getPanelWidth`, `PANEL_CLIP_THRESHOLD_IN_PIXELS`, and `tabListRef`) are constants or refs declared outside the functional component and do not change.
Learnt from: junhaoliao
PR: y-scope/yscope-log-viewer#74
File: new-log-viewer/src/components/CentralContainer/Sidebar/ResizeHandle.tsx:77-82
Timestamp: 2024-09-28T02:32:08.882Z
Learning: Accessibility improvements, such as adding ARIA attributes to components like `ResizeHandle`, require broader discussion and are considered out of scope for small PRs.
Learnt from: junhaoliao
PR: y-scope/yscope-log-viewer#74
File: new-log-viewer/src/components/CentralContainer/Sidebar/ResizeHandle.tsx:77-82
Timestamp: 2024-10-08T15:52:50.753Z
Learning: Accessibility improvements, such as adding ARIA attributes to components like `ResizeHandle`, require broader discussion and are considered out of scope for small PRs.
🔇 Additional comments (2)
new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx (2)

31-31: LGTM! Improved consistency in DOM element usage.

The change from document.body to document.documentElement enhances code consistency. This modification aligns the getPanelWidth function with other parts of the codebase that might be using document.documentElement.


41-41: LGTM! Consistent use of document.documentElement.

The change to use document.documentElement in setPanelWidth is consistent with the modification made to getPanelWidth. This ensures that both getter and setter functions operate on the same DOM element, maintaining consistency throughout the codebase.

…HOLD_IN_PIXELS and EDITOR_MIN_WIDTH_IN_PIXELS back to 250.
Copy link
Contributor

@davemarco davemarco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I played around with current version, and found another bug. Here is my suggestions to fix issue. I think it works... Basically the idea is that you never let the window resize callback to resize smaller than the default panel. I also removed issue where resize handle was trying to set panel to a weird "available width"(when the window is very small)

Comment on lines 44 to 57
/**
* Adjusts and sets the width of the panel based on the desired width and available width for the
* panel.
*
* @param desiredWidth
*/
const adjustAndSetPanelWidth = (desiredWidth: number) => {
const availableWidth = window.innerWidth - EDITOR_MIN_WIDTH_IN_PIXELS;
setPanelWidth(
desiredWidth < availableWidth ?
desiredWidth :
availableWidth
);
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing this since new methodology

Suggested change
/**
* Adjusts and sets the width of the panel based on the desired width and available width for the
* panel.
*
* @param desiredWidth
*/
const adjustAndSetPanelWidth = (desiredWidth: number) => {
const availableWidth = window.innerWidth - EDITOR_MIN_WIDTH_IN_PIXELS;
setPanelWidth(
desiredWidth < availableWidth ?
desiredWidth :
availableWidth
);
};

tabListRef.current.clientWidth + PANEL_CLIP_THRESHOLD_IN_PIXELS >
resizeHandlePosition
) {
if (PANEL_CLIP_THRESHOLD_IN_PIXELS > resizeHandlePosition) {
Copy link
Contributor

@davemarco davemarco Oct 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See suggestion below since can't suggest

    const handleResize = useCallback((resizeHandlePosition: number) => {
        if (null === tabListRef.current) {
            console.error("Unexpected null tabListRef.current");

            return;
        }
        const maxHandleXPos = Math.max(window.innerWidth - EDITOR_MIN_WIDTH_IN_PIXELS, PANEL_DEFAULT_WIDTH_IN_PIXELS);
        if (resizeHandlePosition < PANEL_CLIP_THRESHOLD_IN_PIXELS) {
            // If the resize handle is positioned to the right of the <TabList/>'s right edge
            // with a clipping threshold accounted, close the panel.
            setPanelWidth(tabListRef.current.clientWidth);
        } else if (resizeHandlePosition < maxHandleXPos) {
            // Update the panel width with the distance between the mouse pointer and the window's
            // left edge.
            setPanelWidth(resizeHandlePosition);
        }
    }, []);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to the one in handleActiveTabNameChange, I feel we want to use Math.min(newPanelWidth, window.innerWidth - EDITOR_MIN_WIDTH_IN_PIXELS)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like that line in handleActiveTabNameChange is dangerous, as can set below the clipping width. The max here is meant to solve issues where window.innerWidth - EDITOR_MIN_WIDTH_IN_PIXELS calculation is flawed. When the window.innerwidth is small, the actual editor width is smaller than EDITOR_MIN_WIDTH_IN_PIXELS. This can give very small values nonsensical values for maxHandleXPos/available width. Say the innerwidth is 400, the editor min width is 360. Then the maxHandleXPos/avaialble is 40. However, in reality. the editor is probably only taking up 40px, and the available width should be 360.

However, im sure my calc is flawed in other ways... but for now it seems to work.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still think we should come up with a better fix for this later, and just approve something that works for now

Copy link
Member Author

@junhaoliao junhaoliao Oct 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that line in handleActiveTabNameChange is dangerous, as can set below the clipping width

I agree. Let's fix it at least in a way that mobile users can read the content in the panel; we can optimize the experience in a later PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I havn't tested on mobile... if my comment was unclear i basically just want to keep the max

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right, we kept the max and also added a min:

        clamp(
            window.innerWidth - EDITOR_MIN_WIDTH_IN_PIXELS,
            PANEL_CLIP_THRESHOLD_IN_PIXELS,
            PANEL_DEFAULT_WIDTH_IN_PIXELS
        )

FYR

/**
 * Clamps a number to the given range. E.g. If the number is greater than the range's upper bound,
 * the range's upper bound is returned.
 *
 * @param num The number to be clamped.
 * @param min The lower boundary of the output range.
 * @param max The upper boundary of the output range.
 * @return The clamped number.
 */
const clamp = (num: number, min: number, max: number) => Math.min(Math.max(num, min), max);

Comment on lines 111 to 126
// On initialization, register window resize event handler to resize panel width when necessary.
useEffect(() => {
const handleWindowResize = () => {
const availableWidth = window.innerWidth - EDITOR_MIN_WIDTH_IN_PIXELS;
if (getPanelWidth() > availableWidth) {
adjustAndSetPanelWidth(PANEL_CLIP_THRESHOLD_IN_PIXELS);
}
};

window.addEventListener("resize", handleWindowResize);

return () => {
window.removeEventListener("resize", handleWindowResize);
};
}, []);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// On initialization, register window resize event handler to resize panel width when necessary.
useEffect(() => {
const handleWindowResize = () => {
const availableWidth = window.innerWidth - EDITOR_MIN_WIDTH_IN_PIXELS;
if (getPanelWidth() > availableWidth) {
adjustAndSetPanelWidth(PANEL_CLIP_THRESHOLD_IN_PIXELS);
}
};
window.addEventListener("resize", handleWindowResize);
return () => {
window.removeEventListener("resize", handleWindowResize);
};
}, []);
// On initialization, register window resize event handler to resize panel width when necessary.
useEffect(() => {
const handleWindowResize = () => {
const maxHandleXPos = Math.max(window.innerWidth - EDITOR_MIN_WIDTH_IN_PIXELS, PANEL_DEFAULT_WIDTH_IN_PIXELS);
if (getPanelWidth() > maxHandleXPos) {
setPanelWidth(maxHandleXPos);
}
};
window.addEventListener("resize", handleWindowResize);
return () => {
window.removeEventListener("resize", handleWindowResize);
};
}, []);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for making a typo during refactoring, here's the intended logic. What do you think?

        const handleWindowResize = () => {
            const availableWidth = Math.max(
                window.innerWidth - EDITOR_MIN_WIDTH_IN_PIXELS,
                PANEL_CLIP_THRESHOLD_IN_PIXELS
            );

            if (getPanelWidth() > availableWidth) {
                setPanelWidth(availableWidth);
            }
        };

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm okay with this

@davemarco
Copy link
Contributor

Here is video of issue with previous push. Window jumps to clip size.

Screen.Recording.2024-10-21.at.7.35.24.PM.mov

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (3)
new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx (3)

64-79: Approve refactored handleActiveTabNameChange with suggestion

The refactored handleActiveTabNameChange function improves user experience by allowing panel closure on repeated tab clicks and ensures the panel width stays within acceptable bounds. Good use of the clamp function to manage panel width.

Consider adding a brief comment explaining the parameters of the clamp function for better code readability:

const newPanelWidth = clamp(
    window.innerWidth - EDITOR_MIN_WIDTH_IN_PIXELS, // maximum width
    PANEL_CLIP_THRESHOLD_IN_PIXELS, // minimum width
    PANEL_DEFAULT_WIDTH_IN_PIXELS // default width
);

95-104: Approve handleResize changes with suggestion

The modifications to handleResize function improve the panel resizing logic by ensuring it respects both the minimum threshold for closure and the available space. Good use of Math.min to prevent the panel from expanding beyond the available width.

Consider adding a brief comment explaining the Math.min usage for better code readability:

setPanelWidth(
    Math.min(
        resizeHandlePosition,
        window.innerWidth - EDITOR_MIN_WIDTH_IN_PIXELS // Ensure editor maintains minimum width
    )
);

108-126: Approve new useEffect for window resize with suggestion

The addition of the useEffect hook for handling window resize events is a good improvement. It ensures the panel width remains appropriate when the window is resized, and the cleanup is properly implemented.

Consider debouncing the handleWindowResize function to improve performance, especially on lower-end devices. This can prevent excessive recalculations during rapid resize events. Here's an example implementation:

import { debounce } from 'lodash'; // Or implement your own debounce function

useEffect(() => {
    const handleWindowResize = debounce(() => {
        // ... existing logic ...
    }, 100); // Adjust the delay as needed

    window.addEventListener("resize", handleWindowResize);

    return () => {
        window.removeEventListener("resize", handleWindowResize);
        handleWindowResize.cancel(); // Cancel any pending debounced calls
    };
}, []);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 9dcabbc and 7d23a26.

📒 Files selected for processing (1)
  • new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx (5 hunks)
🧰 Additional context used
📓 Learnings (1)
new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx (1)
Learnt from: junhaoliao
PR: y-scope/yscope-log-viewer#94
File: new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx:99-118
Timestamp: 2024-10-19T03:33:29.578Z
Learning: In `new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx`, when using `useEffect` to register window resize event handlers, it's acceptable to have an empty dependency array because the variables and functions used within the effect (`getPanelWidth`, `PANEL_CLIP_THRESHOLD_IN_PIXELS`, and `tabListRef`) are constants or refs declared outside the functional component and do not change.
🔇 Additional comments (4)
new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx (4)

15-15: Verify the usage of the imported clamp function

The addition of the clamp function import is appropriate. Ensure that it's used correctly throughout the component to constrain values within desired ranges.


24-24: Verify the usage of EDITOR_MIN_WIDTH_IN_PIXELS

The addition of the EDITOR_MIN_WIDTH_IN_PIXELS constant is appropriate for maintaining a minimum editor width. Ensure it's used consistently throughout the component to prevent the editor from becoming too narrow.


32-32: Approve the use of document.documentElement

The change from document.body to document.documentElement in both getPanelWidth and setPanelWidth functions is appropriate. It ensures consistency with the root element of the document.

Please verify that this change doesn't affect other parts of the application that might have been relying on the panel width being set on document.body.

Also applies to: 42-42


Line range hint 1-155: Overall improvements to Sidebar component

The changes made to the Sidebar component significantly enhance its responsiveness and usability. The introduction of new constants, utility functions, and refined event handling for resizing and tab changes collectively improve the component's behaviour and user experience.

To ensure the changes work as intended across various scenarios, please conduct comprehensive testing, including:

  1. Resizing the window to extreme dimensions (very small and very large).
  2. Rapidly resizing the window to check for any performance issues.
  3. Testing on different devices and browsers to ensure consistent behaviour.
  4. Verifying that the editor maintains its minimum width under all circumstances.
  5. Checking that tab switching and panel closure work correctly after window resizes.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (4)
new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx (4)

24-24: LGTM: Addition of EDITOR_MIN_WIDTH_IN_PIXELS constant

The introduction of this constant is a good practice for maintaining a consistent minimum editor width. It enhances code readability and makes it easier to adjust this value if needed in the future.

Consider adding a brief comment explaining the purpose of this constant, such as:

// Minimum width in pixels for the editor to ensure usability across different screen sizes
const EDITOR_MIN_WIDTH_IN_PIXELS = 250;

64-80: LGTM: Improved handleActiveTabNameChange logic

The refactored function enhances the handling of tab changes and panel resizing. The use of the clamp function ensures that the panel width remains within acceptable bounds, which is a good practice.

Consider renaming the clamp function's first argument to improve clarity:

clamp(
    availableWidth,
    PANEL_CLIP_THRESHOLD_IN_PIXELS,
    PANEL_DEFAULT_WIDTH_IN_PIXELS
)

Where availableWidth = window.innerWidth - EDITOR_MIN_WIDTH_IN_PIXELS.

This change would make the purpose of each argument in the clamp function more evident.


95-108: LGTM: Simplified handleResize function

The refactored handleResize function improves readability and consistency with the handleActiveTabNameChange function. The use of the clamp function ensures that the panel width remains within acceptable bounds.

Consider extracting the clamp logic into a separate function to reduce duplication:

const calculatePanelWidth = (width: number) => clamp(
    window.innerWidth - EDITOR_MIN_WIDTH_IN_PIXELS,
    PANEL_CLIP_THRESHOLD_IN_PIXELS,
    width
);

// Then use it in both handleResize and handleActiveTabNameChange
setPanelWidth(calculatePanelWidth(resizeHandlePosition));

This change would improve code reusability and maintain consistency across both functions.


112-130: LGTM: Addition of window resize handler

The new useEffect hook for handling window resize events is well-implemented. It correctly adds and removes the event listener, which prevents potential memory leaks. The resize logic ensures that the panel width remains appropriate as the window size changes.

Consider extracting the handleWindowResize function outside of the useEffect hook for better readability:

const handleWindowResize = useCallback(() => {
    const availableWidth = Math.max(
        window.innerWidth - EDITOR_MIN_WIDTH_IN_PIXELS,
        PANEL_CLIP_THRESHOLD_IN_PIXELS
    );

    if (getPanelWidth() > availableWidth) {
        setPanelWidth(availableWidth);
    }
}, []);

useEffect(() => {
    window.addEventListener("resize", handleWindowResize);
    return () => {
        window.removeEventListener("resize", handleWindowResize);
    };
}, [handleWindowResize]);

This change would improve code organization and potentially allow for easier testing of the handleWindowResize function.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 7d23a26 and a1c812d.

📒 Files selected for processing (1)
  • new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx (5 hunks)
🧰 Additional context used
📓 Learnings (1)
new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx (1)
Learnt from: junhaoliao
PR: y-scope/yscope-log-viewer#94
File: new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx:99-118
Timestamp: 2024-10-19T03:33:29.578Z
Learning: In `new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx`, when using `useEffect` to register window resize event handlers, it's acceptable to have an empty dependency array because the variables and functions used within the effect (`getPanelWidth`, `PANEL_CLIP_THRESHOLD_IN_PIXELS`, and `tabListRef`) are constants or refs declared outside the functional component and do not change.
🔇 Additional comments (2)
new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx (2)

15-15: LGTM: Importing the clamp function

The addition of the clamp function import is appropriate and aligns with good coding practices. This utility function will be useful for constraining values within specified ranges in the modified functions.


131-131: LGTM: Added blank line for improved readability

The addition of this blank line enhances code readability by clearly separating the new useEffect hook from the existing one. This is a good practice for maintaining clean and organized code.

@junhaoliao
Copy link
Member Author

Copy link
Contributor

@davemarco davemarco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I conditionally approve code. Functionality works as expected. Logic is not intuitive, but it works for now. We will have to redesign widths at a later date

@junhaoliao junhaoliao merged commit d5a32e0 into y-scope:main Oct 22, 2024
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants