-
Notifications
You must be signed in to change notification settings - Fork 121
feat(system_logs): Fixed auto scroll #630
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
feat(system_logs): Fixed auto scroll #630
Conversation
WalkthroughThe changes add a button to the logs section that appears when the logs container is out of view. An Changes
Sequence Diagram(s)sequenceDiagram
participant U as User
participant SL as SystemLogs Component
participant IO as IntersectionObserver
participant LC as Logs Container
U->>SL: Load component with logs
IO-->>SL: Detect visibility of LC
alt LC out of view
SL->>U: Display scroll down button
U->>SL: Click scroll down button
SL->>LC: Trigger scrollDown (scroll into view)
else LC visible
SL->>U: Keep button hidden
end
Poem
✨ Finishing Touches
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? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
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.
Actionable comments posted: 1
🧹 Nitpick comments (2)
web-server/src/content/Service/SystemLogs.tsx (2)
92-113
: Scroll button implementation needs performance optimization.The button implementation works correctly, but there's a potential performance issue with reading DOM properties during render.
Reading
containerRef.current.clientWidth
during render (lines 105-107) can cause layout thrashing. Consider moving this calculation to a useEffect or a state variable:export const SystemLogs = ({ serviceName }: { serviceName?: ServiceNames }) => { const { services, loading, logs } = useSystemLogs({ serviceName }); const showScrollDownButton = useBoolState(false); const containerRef = useRef<HTMLDivElement>(null); + const [buttonMarginLeft, setButtonMarginLeft] = useState(0); const scrollDown = () => { containerRef.current.scrollIntoView({ behavior: 'smooth' }); }; + useEffect(() => { + if (containerRef.current) { + setButtonMarginLeft(containerRef.current.clientWidth / 2 - 67); + } + }, []); // Rest of component... return ( // Rest of JSX... {showScrollDownButton.value && ( <Button onClick={scrollDown} component={MotionBox} initial={{ opacity: 0, scale: 0.7 }} animate={{ opacity: 1, scale: 1 }} transition={{ ease: 'easeOut' }} bottom={20} sx={{ position: 'fixed', - marginLeft: `calc(${ - containerRef.current - ? containerRef.current.clientWidth / 2 - 67 - : 0 - }px)` + marginLeft: `${buttonMarginLeft}px` }} > <ExpandCircleDown fontSize="large" color="secondary" /> </Button> )} ); };Additionally, consider adding a resize observer to update the button position if the container width changes.
45-48
: Variable declaration can be optimized.There's a minor code duplication issue with
containerElement
.- const containerElement = containerRef.current; - if (containerRef.current) { - observer.observe(containerElement); + const containerElement = containerRef.current; + observer.observe(containerElement);This makes the variable scoped only where it's needed and avoids declaring it when it might be null.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
web-server/src/content/Service/SystemLogs.tsx
(3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: All file linting
🔇 Additional comments (3)
web-server/src/content/Service/SystemLogs.tsx (3)
1-2
: Import additions look good.The necessary imports have been added for the new scroll button functionality including MUI components, animation components, and state management hooks.
Also applies to: 13-13, 17-18
21-21
: State and scroll function implementation is clean.Good use of the
useBoolState
hook for managing button visibility, and thescrollDown
function is implemented correctly with smooth scrolling behavior.Also applies to: 24-26
57-61
: Auto-scroll effect implementation is robust.This effect correctly handles automatic scrolling when:
- New logs are added (
logs
dependency)- The scroll button is not visible (user hasn't manually scrolled up)
This satisfies the requirement to disable auto-scroll when the user has manually scrolled away from the bottom.
useEffect(() => { | ||
const observer = new IntersectionObserver( | ||
(entries) => { | ||
entries.forEach((entry) => { | ||
if (entry.isIntersecting) { | ||
showScrollDownButton.false(); | ||
} else { | ||
showScrollDownButton.true(); | ||
} | ||
}); | ||
}, | ||
{ | ||
threshold: 0 | ||
} | ||
); | ||
|
||
const containerElement = containerRef.current; | ||
|
||
if (containerRef.current) { | ||
containerRef.current.scrollIntoView({ behavior: 'smooth' }); | ||
observer.observe(containerElement); | ||
} | ||
}, [logs]); | ||
|
||
return () => { | ||
if (containerElement) { | ||
observer.unobserve(containerElement); | ||
} | ||
}; | ||
}, [showScrollDownButton]); |
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.
🛠️ Refactor suggestion
IntersectionObserver implementation needs dependency fix.
The implementation correctly observes when the logs container is in/out of view, but there's an issue with the effect dependency array.
The dependency array includes showScrollDownButton
which is an object (the state handler), not a primitive. This could cause unnecessary re-renders and observer recreation. Change it to use the primitive value:
- }, [showScrollDownButton]);
+ }, []);
The effect doesn't need any dependencies since it's only setting up and cleaning up the observer, and the state updaters (showScrollDownButton.true()
and showScrollDownButton.false()
) are stable references that won't change.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
useEffect(() => { | |
const observer = new IntersectionObserver( | |
(entries) => { | |
entries.forEach((entry) => { | |
if (entry.isIntersecting) { | |
showScrollDownButton.false(); | |
} else { | |
showScrollDownButton.true(); | |
} | |
}); | |
}, | |
{ | |
threshold: 0 | |
} | |
); | |
const containerElement = containerRef.current; | |
if (containerRef.current) { | |
containerRef.current.scrollIntoView({ behavior: 'smooth' }); | |
observer.observe(containerElement); | |
} | |
}, [logs]); | |
return () => { | |
if (containerElement) { | |
observer.unobserve(containerElement); | |
} | |
}; | |
}, [showScrollDownButton]); | |
useEffect(() => { | |
const observer = new IntersectionObserver( | |
(entries) => { | |
entries.forEach((entry) => { | |
if (entry.isIntersecting) { | |
showScrollDownButton.false(); | |
} else { | |
showScrollDownButton.true(); | |
} | |
}); | |
}, | |
{ | |
threshold: 0 | |
} | |
); | |
const containerElement = containerRef.current; | |
if (containerRef.current) { | |
observer.observe(containerElement); | |
} | |
return () => { | |
if (containerElement) { | |
observer.unobserve(containerElement); | |
} | |
}; | |
}, []); |
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.
Thanks @Kamlesh72
Linked Issue(s)
Closes #607
Acceptance Criteria fulfillment
Proposed changes (including videos or screenshots)
Screen.Recording.2025-03-03.at.1.32.29.AM.mov
Summary by CodeRabbit