ghost scroll is back

This commit is contained in:
Nate Kelley 2025-04-17 00:57:19 -06:00
parent 5bfba6d082
commit 85eb0557f4
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
10 changed files with 50 additions and 15 deletions

View File

@ -257,8 +257,6 @@ export const useAddDashboardToCollection = () => {
const mutationFn = useMemoizedFn( const mutationFn = useMemoizedFn(
async (variables: { dashboardIds: string[]; collectionIds: string[] }) => { async (variables: { dashboardIds: string[]; collectionIds: string[] }) => {
const { dashboardIds, collectionIds } = variables; const { dashboardIds, collectionIds } = variables;
console.log('dashboardIds', dashboardIds);
console.log('collectionIds', collectionIds);
return await Promise.all( return await Promise.all(
collectionIds.map((collectionId) => collectionIds.map((collectionId) =>
addAssetToCollection({ addAssetToCollection({

View File

@ -64,8 +64,8 @@ export const NewDatasetGroupModal: React.FC<NewDatasetGroupModalProps> = React.m
return ( return (
<AppModal open={isOpen} onClose={onClose} header={header} footer={footer}> <AppModal open={isOpen} onClose={onClose} header={header} footer={footer}>
<div className="flex flex-col gap-2.5"> <div className="flex flex-col gap-2.5">
<Input ref={inputRef} autoFocus placeholder="Name of dataset group" />
<SelectedDatasetInput onSetDatasetId={onSetDatasetId} /> <SelectedDatasetInput onSetDatasetId={onSetDatasetId} />
<Input ref={inputRef} placeholder="Name of dataset group" />
</div> </div>
</AppModal> </AppModal>
); );

View File

@ -59,12 +59,13 @@ export const NewPermissionGroupModal: React.FC<NewPermissionGroupModalProps> = R
return ( return (
<AppModal open={isOpen} onClose={onClose} header={header} footer={footer}> <AppModal open={isOpen} onClose={onClose} header={header} footer={footer}>
<div className="flex flex-col gap-2.5"> <div className="flex flex-col gap-2.5">
<SelectedDatasetInput onSetDatasetId={setDatasetsIdsToAssign} />
<Input <Input
ref={inputRef} ref={inputRef}
autoFocus
placeholder="Name of permission group" placeholder="Name of permission group"
onPressEnter={onCreateNewPermissionGroup} onPressEnter={onCreateNewPermissionGroup}
/> />
<SelectedDatasetInput onSetDatasetId={setDatasetsIdsToAssign} />
</div> </div>
</AppModal> </AppModal>
); );

View File

@ -67,3 +67,34 @@ export const LongContent: Story = {
) )
} }
}; };
/*
<AppPageLayout
contentContainerId={CHAT_CONTENT_CONTAINER_ID}
header={<ChatHeader />}
headerBorderVariant="ghost"
scrollable
className="flex h-full w-full min-w-[295px] flex-col">
<ChatContent />
</AppPageLayout>
*/
export const LongContentGhostHeader: Story = {
args: {
contentContainerId: 'chat-container-content',
header: <div className="">Header Content</div>,
scrollable: true,
// className: 'flex h-full w-full min-w-[295px] flex-col',
headerBorderVariant: 'ghost',
children: (
<div className="">
{Array.from({ length: 100 }, (_, i) => (
<p key={i} className="mb-4">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua.
</p>
))}
</div>
)
}
};

View File

@ -272,14 +272,14 @@ export const AppSplitter = React.memo(
className="left-pane flex h-full flex-col" className="left-pane flex h-full flex-col"
minSize={leftPanelMinSize} minSize={leftPanelMinSize}
maxSize={leftPanelMaxSize}> maxSize={leftPanelMaxSize}>
{leftHidden || size?.width === 0 ? null : leftChildren} {leftHidden || size?.width === 0 || size?.width === undefined ? null : leftChildren}
</Pane> </Pane>
<Pane <Pane
className="right-pane flex h-full flex-col" className="right-pane flex h-full flex-col"
style={memoizedRightPaneStyle} style={memoizedRightPaneStyle}
minSize={rightPanelMinSize} minSize={rightPanelMinSize}
maxSize={rightPanelMaxSize}> maxSize={rightPanelMaxSize}>
{rightHidden || size?.width === 0 ? null : rightChildren} {rightHidden || size?.width === 0 || size?.width === undefined ? null : rightChildren}
</Pane> </Pane>
</SplitPane> </SplitPane>
</div> </div>

View File

@ -18,7 +18,7 @@ const ScrollArea = React.forwardRef<
{...props}> {...props}>
<ScrollAreaPrimitive.Viewport <ScrollAreaPrimitive.Viewport
ref={viewportRef} ref={viewportRef}
className="h-full w-full rounded-[inherit] [&>div]:!block" className="scroll-area-viewport h-full w-full rounded-[inherit] [&>div]:!block"
id={id}> id={id}>
{children} {children}
</ScrollAreaPrimitive.Viewport> </ScrollAreaPrimitive.Viewport>

View File

@ -323,3 +323,10 @@ The goal is to build a comprehensive dashboard on product sales YTD. The dashboa
This plan should provide a clear and comprehensive dashboard covering overall sales trends, key players in both sales and buying, and categorical breakdown for the top and bottom 10 products.` This plan should provide a clear and comprehensive dashboard covering overall sales trends, key players in both sales and buying, and categorical breakdown for the top and bottom 10 products.`
} }
}; };
export const WithHiddenNewlines: Story = {
args: {
markdown: 'This is line one.\nThis is line two.\nThis is line three.',
className: 'whitespace-pre-wrap'
}
};

View File

@ -3,16 +3,13 @@ import { ChatHeader } from './ChatHeader';
import { ChatContent } from './ChatContent'; import { ChatContent } from './ChatContent';
import { AppPageLayout } from '@/components/ui/layouts'; import { AppPageLayout } from '@/components/ui/layouts';
export const CHAT_CONTENT_CONTAINER_ID = 'chat-container-content'; export const ChatContainer = React.memo(({ mounted }: { mounted?: boolean }) => {
export const ChatContainer = React.memo(() => {
return ( return (
<AppPageLayout <AppPageLayout
contentContainerId={CHAT_CONTENT_CONTAINER_ID}
header={<ChatHeader />} header={<ChatHeader />}
headerBorderVariant="ghost" headerBorderVariant="ghost"
scrollable scrollable
className="flex h-full w-full min-w-[295px] flex-col"> className="chat-container-content flex h-full w-full min-w-[295px] flex-col">
<ChatContent /> <ChatContent />
</AppPageLayout> </AppPageLayout>
); );

View File

@ -5,7 +5,6 @@ import { useChatIndividualContextSelector } from '../../ChatContext';
import { ChatMessageBlock } from './ChatMessageBlock'; import { ChatMessageBlock } from './ChatMessageBlock';
import { ChatInput } from './ChatInput'; import { ChatInput } from './ChatInput';
import { useAutoScroll } from '@/hooks/useAutoScroll'; import { useAutoScroll } from '@/hooks/useAutoScroll';
import { CHAT_CONTENT_CONTAINER_ID } from '../ChatContainer';
import { ChatScrollToBottom } from './ChatScrollToBottom'; import { ChatScrollToBottom } from './ChatScrollToBottom';
const autoClass = 'mx-auto max-w-[600px] w-full'; const autoClass = 'mx-auto max-w-[600px] w-full';
@ -21,7 +20,9 @@ export const ChatContent: React.FC<{}> = React.memo(() => {
}); });
useEffect(() => { useEffect(() => {
const container = document.getElementById(CHAT_CONTENT_CONTAINER_ID); const container = document.querySelector(
'.chat-container-content .scroll-area-viewport'
) as HTMLElement;
if (!container) return; if (!container) return;
containerRef.current = container; containerRef.current = container;
enableAutoScroll(); enableAutoScroll();

View File

@ -35,7 +35,7 @@ export const ChatLayout: React.FC<ChatSplitterProps> = ({ children }) => {
<ChatContextProvider> <ChatContextProvider>
<AppSplitter <AppSplitter
ref={appSplitterRef} ref={appSplitterRef}
leftChildren={useMemo(() => mounted && <ChatContainer />, [mounted])} leftChildren={useMemo(() => mounted && <ChatContainer mounted={mounted} />, [mounted])}
rightChildren={useMemo( rightChildren={useMemo(
() => mounted && <FileContainer>{children}</FileContainer>, () => mounted && <FileContainer>{children}</FileContainer>,
[children, mounted] [children, mounted]