refactor: remove unused MessageSquare icon from sidebar content

This commit is contained in:
tusharmagar 2026-02-04 14:43:52 +05:30
parent 10f94ce67e
commit 23a1544a17
2 changed files with 99 additions and 4 deletions

View file

@ -4,7 +4,7 @@ import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import { ArrowDownIcon } from "lucide-react";
import type { ComponentProps } from "react";
import { useCallback } from "react";
import { useCallback, useEffect, useRef } from "react";
import { StickToBottom, useStickToBottomContext } from "use-stick-to-bottom";
export type ConversationProps = ComponentProps<typeof StickToBottom>;
@ -13,11 +13,109 @@ export const Conversation = ({ className, ...props }: ConversationProps) => (
<StickToBottom
className={cn("relative flex-1 overflow-y-hidden", className)}
initial="smooth"
resize="smooth"
role="log"
{...props}
/>
);
// Threshold in pixels - if user scrolls more than this from bottom, they're considered "engaged"
const SCROLL_ENGAGEMENT_THRESHOLD = 100;
/**
* Component that preserves scroll position when user has scrolled away from bottom.
* Place this inside a StickToBottom context to prevent unwanted scroll jumps.
*/
export const ScrollPositionPreserver = () => {
const { isAtBottom } = useStickToBottomContext();
const scrollContainerRef = useRef<HTMLElement | null>(null);
const isUserEngagedRef = useRef(false);
const savedScrollTopRef = useRef<number | null>(null);
const lastContentHeightRef = useRef<number>(0);
useEffect(() => {
// Find the scroll container (StickToBottom creates a scrollable element)
const findScrollContainer = () => {
// The scroll container is the element with overflow-y-auto/scroll
const containers = document.querySelectorAll('[data-stick-to-bottom-scroll-container]');
if (containers.length > 0) {
return containers[0] as HTMLElement;
}
// Fallback: find by class pattern from the library
const fallback = document.querySelector('.use-stick-to-bottom-scroll-container');
return fallback as HTMLElement | null;
};
// Try to find it, the library creates it dynamically
const container = findScrollContainer();
if (container) {
scrollContainerRef.current = container;
}
}, []);
// Track when user scrolls away from bottom
useEffect(() => {
if (!isAtBottom) {
// User is not at bottom - they've scrolled up
isUserEngagedRef.current = true;
// Save their current position
if (scrollContainerRef.current) {
savedScrollTopRef.current = scrollContainerRef.current.scrollTop;
lastContentHeightRef.current = scrollContainerRef.current.scrollHeight;
}
}
}, [isAtBottom]);
// When user reaches bottom again, reset engagement
useEffect(() => {
if (isAtBottom && isUserEngagedRef.current) {
isUserEngagedRef.current = false;
savedScrollTopRef.current = null;
}
}, [isAtBottom]);
// Use MutationObserver to detect content changes and restore position if needed
useEffect(() => {
const container = scrollContainerRef.current;
if (!container) return;
const observer = new MutationObserver(() => {
// If user was engaged (scrolled away) and we have a saved position
if (isUserEngagedRef.current && savedScrollTopRef.current !== null) {
const currentHeight = container.scrollHeight;
const previousHeight = lastContentHeightRef.current;
// If content height changed significantly and user was scrolled away
if (Math.abs(currentHeight - previousHeight) > 10) {
// Calculate how far from bottom they were
const distanceFromBottom = previousHeight - savedScrollTopRef.current - container.clientHeight;
// Restore position relative to where they were
// If they were reading something in the middle, keep them there
if (distanceFromBottom > SCROLL_ENGAGEMENT_THRESHOLD) {
// Keep them at the same scroll position (reading older content)
container.scrollTop = savedScrollTopRef.current;
}
// Update saved values
lastContentHeightRef.current = currentHeight;
}
}
});
observer.observe(container, {
childList: true,
subtree: true,
characterData: true,
});
return () => observer.disconnect();
}, []);
return null;
};
export type ConversationContentProps = ComponentProps<
typeof StickToBottom.Content
>;

View file

@ -11,7 +11,6 @@ import {
FilePlus,
Folder,
FolderPlus,
MessageSquare,
Mic,
Network,
Pencil,
@ -689,9 +688,7 @@ function TasksSection({
<SidebarMenuButton
isActive={currentRunId === run.id}
onClick={() => actions?.onSelectRun(run.id)}
className="gap-2"
>
<MessageSquare className="size-4 shrink-0" />
<span className="truncate text-sm">{run.title || '(Untitled chat)'}</span>
</SidebarMenuButton>
</SidebarMenuItem>