Files
twenty/packages/twenty-front/src/modules/ai/components/internal/AIChatSkeletonLoader.tsx
T
Lucas Bordeau 2a82df7073 AI tools to create a demo workspace (#18236)
This PR adds the necessary tool to create a demo workspace with :
relevant custom objects and fields, mock data and a real dashboard with
graph widgets.

It is still a bit under-optimized and slow but it works.

This PR also adds an AI tool that allows to see what happens in real
time, it navigates the app and waits when necessary.

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
2026-03-05 11:39:31 +01:00

66 lines
2.0 KiB
TypeScript

import { agentChatHasMessageComponentSelector } from '@/ai/states/agentChatHasMessageComponentSelector';
import { agentChatIsLoadingState } from '@/ai/states/agentChatIsLoadingState';
import { useAtomComponentSelectorValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentSelectorValue';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
import { styled } from '@linaria/react';
import { useContext } from 'react';
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
import { ThemeContext } from 'twenty-ui/theme';
import { themeCssVariables } from 'twenty-ui/theme-constants';
const StyledSkeletonContainer = styled.div`
display: flex;
flex: 1;
flex-direction: column;
gap: ${themeCssVariables.spacing[6]};
padding: ${themeCssVariables.spacing[3]};
`;
const StyledMessageBubble = styled.div`
align-items: center;
display: flex;
gap: ${themeCssVariables.spacing[3]};
`;
const StyledMessageSkeleton = styled.div`
width: 100%;
`;
const NUMBER_OF_SKELETONS = 6;
export const AIChatSkeletonLoader = () => {
const { theme } = useContext(ThemeContext);
const agentChatIsLoading = useAtomStateValue(agentChatIsLoadingState);
const hasMessages = useAtomComponentSelectorValue(
agentChatHasMessageComponentSelector,
);
const shouldRender = agentChatIsLoading && !hasMessages;
if (!shouldRender) {
return null;
}
return (
<SkeletonTheme
baseColor={theme.background.tertiary}
highlightColor={theme.background.transparent.lighter}
borderRadius={4}
>
<StyledSkeletonContainer>
{Array.from({ length: NUMBER_OF_SKELETONS }).map((_, index) => (
<StyledMessageBubble key={index}>
<Skeleton width={24} height={24} borderRadius={4} />
<StyledMessageSkeleton>
<Skeleton height={20} borderRadius={8} />
</StyledMessageSkeleton>
</StyledMessageBubble>
))}
</StyledSkeletonContainer>
</SkeletonTheme>
);
};