feat(layout): allow to minimize chat (#35)

This commit is contained in:
Dominic Elm
2024-08-14 11:08:52 +02:00
committed by GitHub
parent 8fd9d4477e
commit d5a29c2427
18 changed files with 262 additions and 114 deletions

View File

@@ -0,0 +1,19 @@
.BaseChat {
&[data-chat-visible='false'] {
--workbench-inner-width: 100%;
--workbench-left: 0;
.Chat {
--at-apply: bolt-ease-cubic-bezier;
transition-property: transform, opacity;
transition-duration: 0.3s;
will-change: transform, opacity;
transform: translateX(-50%);
opacity: 0;
}
}
}
.Chat {
opacity: 1;
}

View File

@@ -8,10 +8,13 @@ import { classNames } from '~/utils/classNames';
import { Messages } from './Messages.client';
import { SendButton } from './SendButton.client';
import styles from './BaseChat.module.scss';
interface BaseChatProps {
textareaRef?: React.RefObject<HTMLTextAreaElement> | undefined;
messageRef?: RefCallback<HTMLDivElement> | undefined;
scrollRef?: RefCallback<HTMLDivElement> | undefined;
showChat?: boolean;
chatStarted?: boolean;
isStreaming?: boolean;
messages?: Message[];
@@ -40,6 +43,7 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
textareaRef,
messageRef,
scrollRef,
showChat = true,
chatStarted = false,
isStreaming = false,
enhancingPrompt = false,
@@ -56,12 +60,19 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
const TEXTAREA_MAX_HEIGHT = chatStarted ? 400 : 200;
return (
<div ref={ref} className="relative flex h-full w-full overflow-hidden bg-bolt-elements-background-depth-1">
<div
ref={ref}
className={classNames(
styles.BaseChat,
'relative flex h-full w-full overflow-hidden bg-bolt-elements-background-depth-1',
)}
data-chat-visible={showChat}
>
<ClientOnly>{() => <Menu />}</ClientOnly>
<div ref={scrollRef} className="flex overflow-scroll w-full h-full">
<div className="flex flex-col w-full h-full px-6">
<div className={classNames(styles.Chat, 'flex flex-col flex-grow min-w-[var(--chat-min-width)] h-full')}>
{!chatStarted && (
<div id="intro" className="mt-[26vh] max-w-2xl mx-auto">
<div id="intro" className="mt-[26vh] max-w-chat mx-auto">
<h1 className="text-5xl text-center font-bold text-bolt-elements-textPrimary mb-2">
Where ideas begin
</h1>
@@ -71,7 +82,7 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
</div>
)}
<div
className={classNames('pt-6', {
className={classNames('pt-6 px-6', {
'h-full flex flex-col': chatStarted,
})}
>
@@ -80,7 +91,7 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
return chatStarted ? (
<Messages
ref={messageRef}
className="flex flex-col w-full flex-1 max-w-2xl px-4 pb-6 mx-auto z-1"
className="flex flex-col w-full flex-1 max-w-chat px-4 pb-6 mx-auto z-1"
messages={messages}
isStreaming={isStreaming}
/>
@@ -88,7 +99,7 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
}}
</ClientOnly>
<div
className={classNames('relative w-full max-w-2xl md:mx-auto z-2', {
className={classNames('relative w-full max-w-chat mx-auto z-prompt', {
'sticky bottom-0': chatStarted,
})}
>
@@ -174,7 +185,7 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
</div>
</div>
{!chatStarted && (
<div id="examples" className="relative w-full max-w-2xl mx-auto mt-8 flex justify-center">
<div id="examples" className="relative w-full max-w-xl mx-auto mt-8 flex justify-center">
<div className="flex flex-col space-y-2 [mask-image:linear-gradient(to_bottom,black_0%,transparent_180%)] hover:[mask-image:none]">
{EXAMPLE_PROMPTS.map((examplePrompt, index) => {
return (

View File

@@ -1,8 +1,10 @@
import { useStore } from '@nanostores/react';
import type { Message } from 'ai';
import { useChat } from 'ai/react';
import { useAnimate } from 'framer-motion';
import { memo, useEffect, useRef, useState } from 'react';
import { cssTransition, toast, ToastContainer } from 'react-toastify';
import { AnalyticsAction, AnalyticsTrackEvent, sendAnalyticsEvent } from '~/lib/analytics';
import { useMessageParser, usePromptEnhancer, useShortcuts, useSnapScroll } from '~/lib/hooks';
import { useChatHistory } from '~/lib/persistence';
import { chatStore } from '~/lib/stores/chat';
@@ -11,7 +13,6 @@ import { fileModificationsToHTML } from '~/utils/diff';
import { cubicEasingFn } from '~/utils/easings';
import { createScopedLogger, renderLogger } from '~/utils/logger';
import { BaseChat } from './BaseChat';
import { sendAnalyticsEvent, AnalyticsTrackEvent, AnalyticsAction } from '~/lib/analytics';
const toastAnimation = cssTransition({
enter: 'animated fadeInRight',
@@ -71,6 +72,8 @@ export const ChatImpl = memo(({ initialMessages, storeMessageHistory }: ChatProp
const [chatStarted, setChatStarted] = useState(initialMessages.length > 0);
const { showChat } = useStore(chatStore);
const [animationScope, animate] = useAnimate();
const { messages, isLoading, input, handleInputChange, setInput, stop, append } = useChat({
@@ -213,6 +216,7 @@ export const ChatImpl = memo(({ initialMessages, storeMessageHistory }: ChatProp
ref={animationScope}
textareaRef={textareaRef}
input={input}
showChat={showChat}
chatStarted={chatStarted}
isStreaming={isLoading}
enhancingPrompt={enhancingPrompt}