[AI] Navigation panel scroll refactor + Non chat placeholder (#18999)
<img width="374" height="1319" alt="CleanShot 2026-03-26 at 16 19 34" src="https://github.com/user-attachments/assets/bebc7f67-3e9d-47c2-8e13-b57dab83d923" /> <img width="438" height="1320" alt="CleanShot 2026-03-26 at 16 19 20" src="https://github.com/user-attachments/assets/e48ae2d2-066e-402f-a04b-aba7bae776bb" /> https://github.com/user-attachments/assets/64a8ad9b-0030-414c-a67d-3817ac3dd6b0
This commit is contained in:
+52
-22
@@ -1,4 +1,6 @@
|
||||
import { styled } from '@linaria/react';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
import { AIChatSkeletonLoader } from '@/ai/components/internal/AIChatSkeletonLoader';
|
||||
import { NavigationDrawerAIChatThreadDateSection } from '@/ai/components/NavigationDrawerAIChatThreadDateSection';
|
||||
@@ -10,25 +12,39 @@ import { DATE_GROUP_KEYS } from '@/ai/utils/dateGroupKeys';
|
||||
import { getDateGroupTitle } from '@/ai/utils/getDateGroupTitle';
|
||||
import { groupThreadsByDate } from '@/ai/utils/groupThreadsByDate';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
const StyledScrollableList = styled.div`
|
||||
const StyledContainer = styled.div`
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
`;
|
||||
|
||||
const StyledThreadList = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: ${themeCssVariables.spacing[2]} ${themeCssVariables.spacing[0]};
|
||||
width: calc(100% - ${themeCssVariables.spacing[2]});
|
||||
`;
|
||||
|
||||
const StyledEmptyState = styled.div`
|
||||
align-items: center;
|
||||
color: ${themeCssVariables.font.color.light};
|
||||
display: flex;
|
||||
flex: 1;
|
||||
font-size: ${themeCssVariables.font.size.md};
|
||||
justify-content: center;
|
||||
`;
|
||||
|
||||
const StyledFetchMoreTrigger = styled.div`
|
||||
height: 1px;
|
||||
min-height: 1px;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
export const NavigationDrawerAIChatThreadsList = () => {
|
||||
export const NavigationDrawerAIChatContent = () => {
|
||||
const { t } = useLingui();
|
||||
|
||||
const currentAIChatThread = useAtomStateValue(currentAIChatThreadState);
|
||||
const { handleThreadClick } = useAIChatThreadClick({
|
||||
resetNavigationStack: true,
|
||||
@@ -39,26 +55,40 @@ export const NavigationDrawerAIChatThreadsList = () => {
|
||||
const groupedThreads = groupThreadsByDate(threads);
|
||||
|
||||
if (loading && threads.length === 0) {
|
||||
return <AIChatSkeletonLoader />;
|
||||
return (
|
||||
<StyledContainer>
|
||||
<AIChatSkeletonLoader />
|
||||
</StyledContainer>
|
||||
);
|
||||
}
|
||||
|
||||
if (threads.length === 0) {
|
||||
return (
|
||||
<StyledContainer>
|
||||
<StyledEmptyState>{t`No chat`}</StyledEmptyState>
|
||||
</StyledContainer>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<StyledScrollableList>
|
||||
{DATE_GROUP_KEYS.map((key: DateGroupKey) => {
|
||||
const threadsInGroup = groupedThreads[key];
|
||||
if (threadsInGroup.length === 0) return null;
|
||||
<StyledContainer>
|
||||
<StyledThreadList>
|
||||
{DATE_GROUP_KEYS.map((key: DateGroupKey) => {
|
||||
const threadsInGroup = groupedThreads[key];
|
||||
if (threadsInGroup.length === 0) return null;
|
||||
|
||||
return (
|
||||
<NavigationDrawerAIChatThreadDateSection
|
||||
key={key}
|
||||
title={getDateGroupTitle(key)}
|
||||
threads={threadsInGroup}
|
||||
currentThreadId={currentAIChatThread}
|
||||
onThreadClick={handleThreadClick}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
{hasNextPage ? <StyledFetchMoreTrigger ref={fetchMoreRef} /> : null}
|
||||
</StyledScrollableList>
|
||||
return (
|
||||
<NavigationDrawerAIChatThreadDateSection
|
||||
key={key}
|
||||
title={getDateGroupTitle(key)}
|
||||
threads={threadsInGroup}
|
||||
currentThreadId={currentAIChatThread}
|
||||
onThreadClick={handleThreadClick}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
{hasNextPage ? <StyledFetchMoreTrigger ref={fetchMoreRef} /> : null}
|
||||
</StyledThreadList>
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
@@ -1,5 +1,5 @@
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { MainNavigationDrawerAIChatContent } from '@/navigation/components/MainNavigationDrawerAIChatContent';
|
||||
import { NavigationDrawerAIChatContent } from '@/ai/components/NavigationDrawerAIChatContent';
|
||||
import { MainNavigationDrawerNavigationContent } from '@/navigation/components/MainNavigationDrawerNavigationContent';
|
||||
import { MainNavigationDrawerTabsRow } from '@/navigation/components/MainNavigationDrawerTabsRow';
|
||||
import { NavigationDrawer } from '@/ui/navigation/navigation-drawer/components/NavigationDrawer';
|
||||
@@ -27,7 +27,7 @@ export const MainNavigationDrawer = ({ className }: { className?: string }) => {
|
||||
<NavigationDrawerScrollableContent>
|
||||
{navigationDrawerActiveTab ===
|
||||
NAVIGATION_DRAWER_TABS.AI_CHAT_HISTORY ? (
|
||||
<MainNavigationDrawerAIChatContent />
|
||||
<NavigationDrawerAIChatContent />
|
||||
) : (
|
||||
<MainNavigationDrawerNavigationContent />
|
||||
)}
|
||||
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
import { styled } from '@linaria/react';
|
||||
|
||||
import { NavigationDrawerAIChatThreadsList } from '@/ai/components/NavigationDrawerAIChatThreadsList';
|
||||
|
||||
const StyledAIChatThreadsListWrapper = styled.div`
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
`;
|
||||
|
||||
export const MainNavigationDrawerAIChatContent = () => {
|
||||
return (
|
||||
<StyledAIChatThreadsListWrapper>
|
||||
<NavigationDrawerAIChatThreadsList />
|
||||
</StyledAIChatThreadsListWrapper>
|
||||
);
|
||||
};
|
||||
+1
-3
@@ -7,10 +7,8 @@ import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
const StyledItemsContainer = styled.div`
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
margin-bottom: auto;
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
`;
|
||||
|
||||
const StyledScrollableInnerContainer = styled.div<{ isMobile?: boolean }>`
|
||||
|
||||
Reference in New Issue
Block a user