From d94e492584c4d914f4f61f92801cfe49d5f56817 Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Thu, 5 Mar 2026 12:43:33 +0100 Subject: [PATCH] Left Main: Hide tab shadow when no scroll (#6743) --- src/components/left/main/ChatFolders.tsx | 10 ++++++++++ src/components/left/main/ChatList.tsx | 3 +++ src/components/left/main/LeftMain.scss | 10 ++++++++-- src/hooks/useScrolledState.ts | 14 +++++++++++++- 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/components/left/main/ChatFolders.tsx b/src/components/left/main/ChatFolders.tsx index b0b8cbec5..1f479918b 100644 --- a/src/components/left/main/ChatFolders.tsx +++ b/src/components/left/main/ChatFolders.tsx @@ -22,6 +22,7 @@ import useFolderTabs from '../../../hooks/useFolderTabs'; import useHistoryBack from '../../../hooks/useHistoryBack'; import useLang from '../../../hooks/useLang'; import useLastCallback from '../../../hooks/useLastCallback'; +import useScrolledState from '../../../hooks/useScrolledState'; import useShowTransition from '../../../hooks/useShowTransition'; import StoryRibbon from '../../story/StoryRibbon'; @@ -86,10 +87,17 @@ const ChatFolders: FC = ({ const lang = useLang(); + const { isAtBeginning: isNotScrolled, handleScroll, updateScrollState } = useScrolledState(); + useEffect(() => { loadChatFolders(); }, []); + useEffect(() => { + const activeList = transitionRef.current?.querySelector('.chat-list.Transition_slide-active'); + updateScrollState(activeList ?? undefined); + }, [activeChatFolder, updateScrollState]); + const { ref, shouldRender: shouldRenderStoryRibbon, @@ -231,6 +239,7 @@ const ChatFolders: FC = ({ isFoldersSidebarShown={isFoldersSidebarShown} isStoryRibbonShown={isStoryRibbonShown} withTags + onScroll={handleScroll} /> ); } @@ -255,6 +264,7 @@ const ChatFolders: FC = ({ tabs={folderTabs} activeTab={activeChatFolder} onSwitchTab={handleSwitchTab} + className={!isNotScrolled ? 'scrolled' : undefined} /> ) : shouldRenderPlaceholder ? (
diff --git a/src/components/left/main/ChatList.tsx b/src/components/left/main/ChatList.tsx index d27247886..ec2381e03 100644 --- a/src/components/left/main/ChatList.tsx +++ b/src/components/left/main/ChatList.tsx @@ -48,6 +48,7 @@ type OwnProps = { isFoldersSidebarShown?: boolean; isStoryRibbonShown?: boolean; foldersDispatch?: FolderEditDispatch; + onScroll?: (e: React.UIEvent) => void; }; const INTERSECTION_THROTTLE = 200; @@ -66,6 +67,7 @@ const ChatList = ({ isFoldersSidebarShown, isStoryRibbonShown, foldersDispatch, + onScroll, }: OwnProps) => { const { openChat, @@ -227,6 +229,7 @@ const ChatList = ({ withAbsolutePositioning maxHeight={chatsHeight + archiveHeight + panesHeight} onLoadMore={getMore} + onScroll={onScroll} > {isAllFolder && } {shouldDisplayArchive && ( diff --git a/src/components/left/main/LeftMain.scss b/src/components/left/main/LeftMain.scss index 5962992e0..442e961b0 100644 --- a/src/components/left/main/LeftMain.scss +++ b/src/components/left/main/LeftMain.scss @@ -35,11 +35,17 @@ justify-content: flex-start; - border-bottom: 0; + border-bottom: 1px solid var(--color-borders); opacity: 1; + box-shadow: none; - transition: opacity var(--layer-transition); + transition: opacity var(--layer-transition), box-shadow 0.2s, border-color 0.2s; + + &.scrolled { + border-bottom-color: transparent; + box-shadow: 0 2px 2px var(--color-light-shadow); + } } &--tabs-hidden .TabList { diff --git a/src/hooks/useScrolledState.ts b/src/hooks/useScrolledState.ts index 6688dda96..3aa2d9af4 100644 --- a/src/hooks/useScrolledState.ts +++ b/src/hooks/useScrolledState.ts @@ -15,5 +15,17 @@ export default function useScrolledState(threshold = THRESHOLD) { setIsAtEnd(scrollHeight - scrollTop - clientHeight < threshold); }); - return { isAtBeginning, isAtEnd, handleScroll }; + const updateScrollState = useLastCallback((element: HTMLElement | undefined) => { + if (!element) { + setIsAtBeginning(true); + setIsAtEnd(true); + return; + } + + const { scrollHeight, scrollTop, clientHeight } = element; + setIsAtBeginning(scrollTop < threshold); + setIsAtEnd(scrollHeight - scrollTop - clientHeight < threshold); + }); + + return { isAtBeginning, isAtEnd, handleScroll, updateScrollState }; }