Skip to content

Commit 8e4c94a

Browse files
committed
First test
1 parent 854c448 commit 8e4c94a

File tree

5 files changed

+81
-22
lines changed

5 files changed

+81
-22
lines changed

packages/gitbook/src/components/AI/useAIChat.tsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ export type AIChatMessage = {
2323
query?: string;
2424
};
2525

26+
export type AIChatSize = 'default' | 'large';
27+
2628
export type AIChatPendingTool = {
2729
icon?: IconName;
2830
label: string;
@@ -85,6 +87,11 @@ export type AIChatState = {
8587
* display an error alert. Clearing the conversation will reset this flag.
8688
*/
8789
error: boolean;
90+
91+
/**
92+
* The size of the chat window.
93+
*/
94+
size: AIChatSize;
8895
};
8996

9097
export type AIChatController = {
@@ -96,12 +103,14 @@ export type AIChatController = {
96103
postMessage: (input: { message: string }) => void;
97104
/** Clear the conversation */
98105
clear: () => void;
106+
/** Toggle the size of the chat window */
107+
setSize: (size: AIChatSize) => void;
99108
};
100109

101110
const AIChatControllerContext = React.createContext<AIChatController | null>(null);
102111

103112
// Global state store for AI chat
104-
const globalState = zustand.create<AIChatState>(() => {
113+
export const globalState = zustand.create<AIChatState>(() => {
105114
return {
106115
opened: false,
107116
responseId: null,
@@ -112,6 +121,7 @@ const globalState = zustand.create<AIChatState>(() => {
112121
loading: false,
113122
error: false,
114123
initialQuery: null,
124+
size: 'default',
115125
};
116126
});
117127

@@ -438,14 +448,19 @@ export function AIChatProvider(props: {
438448
}));
439449
}, [setSearchState]);
440450

451+
const onSetSize = React.useCallback((size: AIChatSize) => {
452+
globalState.setState((state) => ({ ...state, size }));
453+
}, []);
454+
441455
const controller = React.useMemo(() => {
442456
return {
443457
open: onOpen,
444458
close: onClose,
445459
clear: onClear,
446460
postMessage: onPostMessage,
461+
setSize: onSetSize,
447462
};
448-
}, [onOpen, onClose, onClear, onPostMessage]);
463+
}, [onOpen, onClose, onClear, onPostMessage, onSetSize]);
449464

450465
return (
451466
<AIChatControllerContext.Provider value={controller}>

packages/gitbook/src/components/AIChat/AIChat.tsx

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import { t, tString, useLanguage } from '@/intl/client';
44
import type { TranslationLanguage } from '@/intl/translations';
5+
import { tcls } from '@/lib/tailwind';
56
import { Icon } from '@gitbook/icons';
67
import React from 'react';
78
import { useHotkeys } from 'react-hotkeys-hook';
@@ -64,7 +65,10 @@ export function AIChat(props: { trademark: boolean }) {
6465
return (
6566
<div
6667
data-testid="ai-chat"
67-
className="ai-chat inset-y-0 right-0 z-40 mx-auto flex max-w-3xl animate-present scroll-mt-36 px-4 py-4 transition-all duration-300 sm:px-6 lg:fixed lg:w-80 lg:animate-enter-from-right lg:pr-4 lg:pl-0 xl:w-96"
68+
className={tcls(
69+
'ai-chat z-40 mx-auto flex max-h-full w-full max-w-3xl animate-present scroll-mt-36 p-4 transition-all duration-300 max-md:inset-x-0 max-md:bottom-0 lg:fixed lg:inset-y-0 lg:right-0 lg:animate-enter-from-right',
70+
chat.size === 'large' ? 'lg:w-104 xl:w-156' : 'lg:w-80 xl:w-96'
71+
)}
6872
>
6973
<EmbeddableFrame
7074
className="relative circular-corners:rounded-3xl rounded-corners:rounded-md depth-subtle:shadow-lg shadow-tint ring-1 ring-tint-subtle"
@@ -92,6 +96,23 @@ export function AIChat(props: { trademark: boolean }) {
9296
/>
9397
}
9498
>
99+
<DropdownMenuItem
100+
onClick={() => {
101+
chatController.setSize(
102+
chat.size === 'default' ? 'large' : 'default'
103+
);
104+
}}
105+
>
106+
<Icon
107+
icon={
108+
chat.size === 'default'
109+
? 'arrow-up-right-and-arrow-down-left-from-center'
110+
: 'arrow-down-left-and-arrow-up-right-to-center'
111+
}
112+
className="size-3 shrink-0 text-tint-subtle"
113+
/>
114+
{chat.size === 'default' ? 'Maximize' : 'Minimize'}
115+
</DropdownMenuItem>
95116
<DropdownMenuItem
96117
onClick={() => {
97118
chatController.clear();
@@ -223,27 +244,32 @@ export function AIChatBody(props: {
223244
<>
224245
<div
225246
ref={scrollContainerRef}
226-
className="flex grow scroll-pt-4 flex-col gap-4 overflow-y-auto p-4"
247+
className={tcls(
248+
'flex grow scroll-pt-4 flex-col gap-4 overflow-y-auto p-4 transition-all',
249+
chat.size === 'large' ? 'text-base' : 'text-sm'
250+
)}
227251
style={{
228252
paddingBottom: `${inputHeight}px`,
229253
}}
230254
>
231255
{isEmpty ? (
232256
<div className="flex min-h-full w-full shrink-0 flex-col items-center justify-center gap-6 py-4">
233-
<div className="flex size-32 animate-fade-in-slow items-center justify-center rounded-full bg-tint-subtle">
234-
<AIChatIcon
235-
state="intro"
236-
trademark={trademark}
237-
className="size-16 animate-[present_500ms_200ms_both]"
238-
/>
239-
</div>
240-
<div className="animate-[fadeIn_500ms_400ms_both]">
241-
<h5 className=" text-center font-bold text-lg text-tint-strong">
242-
{timeGreeting}
243-
</h5>
244-
<p className="text-center text-tint">
245-
{t(language, 'ai_chat_assistant_description')}
246-
</p>
257+
<div className="flex items-center gap-4 lg:flex-col">
258+
<div className="flex animate-fade-in-slow items-center justify-center rounded-full bg-tint-subtle p-4 lg:p-8">
259+
<AIChatIcon
260+
state="intro"
261+
trademark={trademark}
262+
className="size-8 animate-[present_500ms_200ms_both] lg:size-16"
263+
/>
264+
</div>
265+
<div className="animate-[fadeIn_500ms_400ms_both]">
266+
<h5 className="font-bold text-lg text-tint-strong lg:text-center">
267+
{timeGreeting}
268+
</h5>
269+
<p className="text-tint lg:text-center">
270+
{t(language, 'ai_chat_assistant_description')}
271+
</p>
272+
</div>
247273
</div>
248274
{!chat.error ? (
249275
<AIChatSuggestedQuestions chatController={chatController} />

packages/gitbook/src/components/AIChat/AIChatInput.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ export function AIChatInput(props: {
140140
<span className="leading-none">
141141
{t(language, 'ai_chat_context_title')}
142142
</span>
143-
<Icon icon="question-circle" className="size-3" />
143+
<Icon icon="question-circle" className="size-3 shrink-0" />
144144
</div>
145145
</HoverCardTrigger>
146146
</HoverCardRoot>

packages/gitbook/src/components/AIChat/AIChatSuggestedQuestions.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ export default function AIChatSuggestedQuestions(props: { chatController: AIChat
1313
];
1414

1515
return (
16-
<div className="flex flex-col items-center gap-2">
16+
<div className="flex items-center gap-2 lg:flex-col">
1717
{DEFAULT_SUGGESTED_QUESTIONS.map((question, index) => (
1818
<Button
1919
key={question}
2020
variant="secondary"
2121
size="medium"
22-
className="max-w-full animate-[present_500ms_both] whitespace-normal"
22+
className="shrink grow animate-[present_500ms_both] whitespace-normal"
2323
style={{
2424
animationDelay: `${800 + index * 100}ms`,
2525
}}

packages/gitbook/src/components/Integrations/LoadIntegrations.tsx

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import type {
99
GitBookIntegrationEventCallback,
1010
GitBookIntegrationTool,
1111
} from '@gitbook/browser-types';
12-
import type { Assistant } from '../AI';
12+
import { type Assistant, globalState } from '../AI';
1313

1414
const events = new Map<GitBookIntegrationEvent, GitBookIntegrationEventCallback[]>();
1515

@@ -67,6 +67,24 @@ if (typeof window !== 'undefined') {
6767
},
6868
};
6969
window.GitBook = gitbookGlobal;
70+
71+
window.GitBook?.registerTool({
72+
name: 'ExpandChatSize',
73+
description:
74+
'FREE TO USE: Expand the chat to a larger size. Use this tool before you start writing your final answer if you need to show a lot of content, like step-by-step instructions or codeblocks. You do not need to preface this tool with feedback to the user, just call it and the chat will expand.',
75+
execute: async () => {
76+
globalState.setState((state) => ({ ...state, size: 'large' }));
77+
return {
78+
output: {
79+
expanded: true,
80+
},
81+
summary: {
82+
icon: 'arrow-up-right-and-arrow-down-left-from-center',
83+
text: 'Chat size expanded',
84+
},
85+
};
86+
},
87+
});
7088
}
7189

7290
/**

0 commit comments

Comments
 (0)