@patternfly/chatbot 6.3.0 → 6.4.0-prerelease.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +5 -1
  2. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +3 -3
  3. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +17 -0
  4. package/dist/cjs/FileDropZone/FileDropZone.d.ts +1 -2
  5. package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.js +1 -10
  6. package/dist/cjs/Message/Message.d.ts +4 -2
  7. package/dist/cjs/Message/Message.js +4 -4
  8. package/dist/cjs/Message/Message.test.js +26 -0
  9. package/dist/cjs/Message/MessageInput.d.ts +3 -1
  10. package/dist/cjs/Message/MessageInput.js +2 -2
  11. package/dist/cjs/MessageBar/AttachButton.d.ts +2 -2
  12. package/dist/cjs/MessageBar/MessageBar.d.ts +2 -2
  13. package/dist/cjs/MessageBox/MessageBox.js +1 -1
  14. package/dist/cjs/MessageDivider/MessageDivider.d.ts +9 -0
  15. package/dist/cjs/MessageDivider/MessageDivider.js +23 -0
  16. package/dist/cjs/MessageDivider/MessageDivider.test.d.ts +1 -0
  17. package/dist/cjs/MessageDivider/MessageDivider.test.js +29 -0
  18. package/dist/cjs/MessageDivider/index.d.ts +2 -0
  19. package/dist/cjs/MessageDivider/index.js +23 -0
  20. package/dist/cjs/ResponseActions/ResponseActions.d.ts +1 -0
  21. package/dist/cjs/ResponseActions/ResponseActions.js +4 -4
  22. package/dist/cjs/ResponseActions/ResponseActions.test.js +6 -1
  23. package/dist/cjs/index.d.ts +2 -0
  24. package/dist/cjs/index.js +4 -1
  25. package/dist/css/main.css +56 -55
  26. package/dist/css/main.css.map +1 -1
  27. package/dist/dynamic/MessageDivider/package.json +1 -0
  28. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +5 -1
  29. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +5 -5
  30. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +17 -0
  31. package/dist/esm/FileDropZone/FileDropZone.d.ts +1 -2
  32. package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.js +1 -7
  33. package/dist/esm/Message/Message.d.ts +4 -2
  34. package/dist/esm/Message/Message.js +4 -4
  35. package/dist/esm/Message/Message.test.js +26 -0
  36. package/dist/esm/Message/MessageInput.d.ts +3 -1
  37. package/dist/esm/Message/MessageInput.js +2 -2
  38. package/dist/esm/MessageBar/AttachButton.d.ts +2 -2
  39. package/dist/esm/MessageBar/MessageBar.d.ts +2 -2
  40. package/dist/esm/MessageBox/MessageBox.js +1 -1
  41. package/dist/esm/MessageDivider/MessageDivider.d.ts +9 -0
  42. package/dist/esm/MessageDivider/MessageDivider.js +21 -0
  43. package/dist/esm/MessageDivider/MessageDivider.test.d.ts +1 -0
  44. package/dist/esm/MessageDivider/MessageDivider.test.js +24 -0
  45. package/dist/esm/MessageDivider/index.d.ts +2 -0
  46. package/dist/esm/MessageDivider/index.js +2 -0
  47. package/dist/esm/ResponseActions/ResponseActions.d.ts +1 -0
  48. package/dist/esm/ResponseActions/ResponseActions.js +5 -5
  49. package/dist/esm/ResponseActions/ResponseActions.test.js +6 -1
  50. package/dist/esm/index.d.ts +2 -0
  51. package/dist/esm/index.js +2 -0
  52. package/dist/tsconfig.tsbuildinfo +1 -1
  53. package/package.json +5 -3
  54. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithDividers.tsx +24 -0
  55. package/patternfly-docs/content/extensions/chatbot/examples/Messages/Messages.md +15 -1
  56. package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessage.tsx +39 -7
  57. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawer.tsx +9 -0
  58. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawerWithPin.tsx +196 -0
  59. package/patternfly-docs/content/extensions/chatbot/examples/UI/UI.md +9 -1
  60. package/patternfly-docs/content/extensions/chatbot/examples/demos/Chatbot.md +33 -1
  61. package/patternfly-docs/content/extensions/chatbot/examples/demos/ChatbotDisplayMode.tsx +486 -0
  62. package/patternfly-docs/content/extensions/chatbot/examples/demos/ChatbotTranscripts.tsx +565 -0
  63. package/src/Chatbot/Chatbot.scss +1 -1
  64. package/src/ChatbotContent/ChatbotContent.scss +1 -1
  65. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.scss +14 -2
  66. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.tsx +58 -0
  67. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.tsx +29 -12
  68. package/src/ChatbotFooter/ChatbotFooter.scss +1 -1
  69. package/src/ChatbotHeader/ChatbotHeader.scss +3 -3
  70. package/src/ChatbotToggle/ChatbotToggle.scss +2 -2
  71. package/src/FileDropZone/FileDropZone.tsx +2 -2
  72. package/src/Message/CodeBlockMessage/CodeBlockMessage.tsx +3 -27
  73. package/src/Message/Message.scss +9 -7
  74. package/src/Message/Message.test.tsx +35 -0
  75. package/src/Message/Message.tsx +8 -4
  76. package/src/Message/MessageInput.tsx +5 -1
  77. package/src/MessageBar/AttachButton.tsx +2 -2
  78. package/src/MessageBar/MessageBar.tsx +2 -2
  79. package/src/MessageBar/SendButton.scss +3 -3
  80. package/src/MessageBox/JumpButton.scss +1 -1
  81. package/src/MessageBox/MessageBox.tsx +1 -1
  82. package/src/MessageDivider/MessageDivider.scss +45 -0
  83. package/src/MessageDivider/MessageDivider.test.tsx +24 -0
  84. package/src/MessageDivider/MessageDivider.tsx +35 -0
  85. package/src/MessageDivider/index.ts +3 -0
  86. package/src/ResponseActions/ResponseActions.test.tsx +6 -1
  87. package/src/ResponseActions/ResponseActions.tsx +24 -3
  88. package/src/index.ts +3 -0
  89. package/src/main.scss +1 -52
  90. package/dist/cjs/Message/CodeBlockMessage/ExpandableSectionForSyntaxHighlighter.d.ts +0 -62
  91. package/dist/cjs/Message/CodeBlockMessage/ExpandableSectionForSyntaxHighlighter.js +0 -139
  92. package/dist/esm/Message/CodeBlockMessage/ExpandableSectionForSyntaxHighlighter.d.ts +0 -62
  93. package/dist/esm/Message/CodeBlockMessage/ExpandableSectionForSyntaxHighlighter.js +0 -133
  94. package/src/Message/CodeBlockMessage/ExpandableSectionForSyntaxHighlighter.tsx +0 -223
@@ -0,0 +1,486 @@
1
+ import React, { FunctionComponent, MouseEvent, useEffect, useRef, useState } from 'react';
2
+
3
+ import {
4
+ Brand,
5
+ DropdownList,
6
+ DropdownItem,
7
+ Page,
8
+ Masthead,
9
+ MastheadMain,
10
+ MastheadBrand,
11
+ MastheadLogo,
12
+ PageSidebarBody,
13
+ PageSidebar,
14
+ MastheadToggle,
15
+ PageToggleButton,
16
+ SkipToContent,
17
+ Drawer,
18
+ DrawerContent,
19
+ DrawerContentBody,
20
+ DrawerPanelContent,
21
+ DropdownGroup
22
+ } from '@patternfly/react-core';
23
+
24
+ import ChatbotToggle from '@patternfly/chatbot/dist/dynamic/ChatbotToggle';
25
+ import Chatbot, { ChatbotDisplayMode } from '@patternfly/chatbot/dist/dynamic/Chatbot';
26
+ import ChatbotContent from '@patternfly/chatbot/dist/dynamic/ChatbotContent';
27
+ import ChatbotWelcomePrompt from '@patternfly/chatbot/dist/dynamic/ChatbotWelcomePrompt';
28
+ import ChatbotFooter, { ChatbotFootnote } from '@patternfly/chatbot/dist/dynamic/ChatbotFooter';
29
+ import MessageBar from '@patternfly/chatbot/dist/dynamic/MessageBar';
30
+ import MessageBox from '@patternfly/chatbot/dist/dynamic/MessageBox';
31
+ import Message, { MessageProps } from '@patternfly/chatbot/dist/dynamic/Message';
32
+ import ChatbotConversationHistoryNav, {
33
+ Conversation
34
+ } from '@patternfly/chatbot/dist/dynamic/ChatbotConversationHistoryNav';
35
+ import ChatbotHeader, {
36
+ ChatbotHeaderMenu,
37
+ ChatbotHeaderMain,
38
+ ChatbotHeaderTitle,
39
+ ChatbotHeaderActions,
40
+ ChatbotHeaderSelectorDropdown,
41
+ ChatbotHeaderOptionsDropdown,
42
+ ChatbotHeaderCloseButton
43
+ } from '@patternfly/chatbot/dist/dynamic/ChatbotHeader';
44
+ import PFIconLogoColor from '../UI/PF-IconLogo-Color.svg';
45
+ import PFIconLogoReverse from '../UI/PF-IconLogo-Reverse.svg';
46
+ import { BarsIcon } from '@patternfly/react-icons';
47
+ import ExpandIcon from '@patternfly/react-icons/dist/esm/icons/expand-icon';
48
+ import OpenDrawerRightIcon from '@patternfly/react-icons/dist/esm/icons/open-drawer-right-icon';
49
+ import OutlinedWindowRestoreIcon from '@patternfly/react-icons/dist/esm/icons/outlined-window-restore-icon';
50
+ import userAvatar from '../Messages/user_avatar.svg';
51
+ import patternflyAvatar from '../Messages/patternfly_avatar.jpg';
52
+ import '@patternfly/react-core/dist/styles/base.css';
53
+ import '@patternfly/chatbot/dist/css/main.css';
54
+
55
+ const footnoteProps = {
56
+ label: 'ChatBot uses AI. Check for mistakes.',
57
+ popover: {
58
+ title: 'Verify accuracy',
59
+ description: `While ChatBot strives for accuracy, there's always a possibility of errors. It's a good practice to verify critical information from reliable sources, especially if it's crucial for decision-making or actions.`,
60
+ bannerImage: {
61
+ src: 'https://cdn.dribbble.com/userupload/10651749/file/original-8a07b8e39d9e8bf002358c66fce1223e.gif',
62
+ alt: 'Example image for footnote popover'
63
+ },
64
+ cta: {
65
+ label: 'Got it',
66
+ onClick: () => {
67
+ alert('Do something!');
68
+ }
69
+ },
70
+ link: {
71
+ label: 'Learn more',
72
+ url: 'https://www.redhat.com/'
73
+ }
74
+ }
75
+ };
76
+
77
+ const markdown = `A paragraph with *emphasis* and **strong importance**.`;
78
+
79
+ const date = new Date();
80
+
81
+ const initialMessages: MessageProps[] = [
82
+ {
83
+ id: '1',
84
+ role: 'user',
85
+ content: 'Hello, can you give me an example of what you can do?',
86
+ name: 'User',
87
+ avatar: userAvatar,
88
+ timestamp: date.toLocaleString(),
89
+ avatarProps: { isBordered: true }
90
+ },
91
+ {
92
+ id: '2',
93
+ role: 'bot',
94
+ content: markdown,
95
+ name: 'Bot',
96
+ avatar: patternflyAvatar,
97
+ timestamp: date.toLocaleString(),
98
+ actions: {
99
+ // eslint-disable-next-line no-console
100
+ positive: { onClick: () => console.log('Good response') },
101
+ // eslint-disable-next-line no-console
102
+ negative: { onClick: () => console.log('Bad response') },
103
+ // eslint-disable-next-line no-console
104
+ copy: { onClick: () => console.log('Copy') },
105
+ // eslint-disable-next-line no-console
106
+ download: { onClick: () => console.log('Download') },
107
+ // eslint-disable-next-line no-console
108
+ listen: { onClick: () => console.log('Listen') }
109
+ }
110
+ }
111
+ ];
112
+
113
+ const welcomePrompts = [
114
+ {
115
+ title: 'Topic 1',
116
+ message: 'Helpful prompt for Topic 1'
117
+ },
118
+ {
119
+ title: 'Topic 2',
120
+ message: 'Helpful prompt for Topic 2'
121
+ }
122
+ ];
123
+
124
+ const initialConversations = {
125
+ Today: [{ id: '1', text: 'Hello, can you give me an example of what you can do?' }],
126
+ 'This month': [
127
+ {
128
+ id: '2',
129
+ text: 'Enterprise Linux installation and setup'
130
+ }
131
+ ]
132
+ };
133
+
134
+ export const ChatbotDisplayModeDemo: FunctionComponent = () => {
135
+ const [messages, setMessages] = useState<MessageProps[]>(initialMessages);
136
+ const [selectedModel, setSelectedModel] = useState('Granite 7B');
137
+ const [isSendButtonDisabled, setIsSendButtonDisabled] = useState(false);
138
+ const [isDrawerOpen, setIsDrawerOpen] = useState(false);
139
+ const [conversations, setConversations] = useState<Conversation[] | { [key: string]: Conversation[] }>(
140
+ initialConversations
141
+ );
142
+ const [isSidebarOpen, setIsSidebarOpen] = useState(false);
143
+ const [announcement, setAnnouncement] = useState<string>();
144
+ const scrollToBottomRef = useRef<HTMLDivElement>(null);
145
+ const historyRef = useRef<HTMLButtonElement>(null);
146
+ const drawerRef = useRef<HTMLDivElement>();
147
+ const [chatbotVisible, setChatbotVisible] = useState<boolean>(true);
148
+ const toggleRef = useRef<HTMLButtonElement>(null);
149
+ const chatbotRef = useRef<HTMLDivElement>(null);
150
+ const [shouldFocusOptions, setShouldFocusOptions] = useState(false);
151
+
152
+ const [displayMode, setDisplayMode] = useState<ChatbotDisplayMode>(ChatbotDisplayMode.default);
153
+
154
+ const isDrawerPanelExpanded = displayMode === ChatbotDisplayMode.drawer;
155
+
156
+ const onExpand = () => {
157
+ drawerRef.current && drawerRef.current.focus();
158
+ };
159
+
160
+ useEffect(() => {
161
+ if (messages.length > 2) {
162
+ scrollToBottomRef.current?.scrollIntoView({ behavior: 'smooth' });
163
+ }
164
+ }, [messages]);
165
+
166
+ // Focus options dropdown after display mode changes
167
+ useEffect(() => {
168
+ if (shouldFocusOptions) {
169
+ // Use a more reliable timeout to ensure DOM has updated
170
+ const timeoutId = setTimeout(() => {
171
+ // Find the options dropdown button via CSS selector since ref forwarding isn't supported
172
+ const optionsButton = document.querySelector('.pf-chatbot__button--toggle-options');
173
+ if (optionsButton instanceof HTMLElement) {
174
+ optionsButton.focus();
175
+ }
176
+ setShouldFocusOptions(false);
177
+ }, 100);
178
+
179
+ return () => clearTimeout(timeoutId);
180
+ }
181
+ }, [displayMode, shouldFocusOptions]);
182
+
183
+ const onSelectModel = (_event: MouseEvent<Element, MouseEvent> | undefined, value: string | number | undefined) => {
184
+ setSelectedModel(value as string);
185
+ };
186
+
187
+ const onSelectDisplayMode = (
188
+ _event: MouseEvent<Element, MouseEvent> | undefined,
189
+ value: string | number | undefined
190
+ ) => {
191
+ setDisplayMode(value as ChatbotDisplayMode);
192
+ // Flag to focus options dropdown after render
193
+ setShouldFocusOptions(true);
194
+ };
195
+
196
+ const generateId = () => {
197
+ const id = Date.now() + Math.random();
198
+ return id.toString();
199
+ };
200
+
201
+ const handleSend = (message: string) => {
202
+ setIsSendButtonDisabled(true);
203
+ const newMessages: MessageProps[] = [...messages];
204
+ const date = new Date();
205
+ newMessages.push({
206
+ id: generateId(),
207
+ role: 'user',
208
+ content: message,
209
+ name: 'User',
210
+ avatar: userAvatar,
211
+ timestamp: date.toLocaleString(),
212
+ avatarProps: { isBordered: true }
213
+ });
214
+ newMessages.push({
215
+ id: generateId(),
216
+ role: 'bot',
217
+ content: 'API response goes here',
218
+ name: 'Bot',
219
+ avatar: patternflyAvatar,
220
+ isLoading: true,
221
+ timestamp: date.toLocaleString()
222
+ });
223
+ setMessages(newMessages);
224
+ setAnnouncement(`Message from User: ${message}. Message from Bot is loading.`);
225
+
226
+ setTimeout(() => {
227
+ const loadedMessages: MessageProps[] = [...newMessages];
228
+ loadedMessages.pop();
229
+ loadedMessages.push({
230
+ id: generateId(),
231
+ role: 'bot',
232
+ content: 'API response goes here',
233
+ name: 'Bot',
234
+ avatar: patternflyAvatar,
235
+ isLoading: false,
236
+ actions: {
237
+ // eslint-disable-next-line no-console
238
+ positive: { onClick: () => console.log('Good response') },
239
+ // eslint-disable-next-line no-console
240
+ negative: { onClick: () => console.log('Bad response') },
241
+ // eslint-disable-next-line no-console
242
+ copy: { onClick: () => console.log('Copy') },
243
+ // eslint-disable-next-line no-console
244
+ download: { onClick: () => console.log('Download') },
245
+ // eslint-disable-next-line no-console
246
+ listen: { onClick: () => console.log('Listen') }
247
+ },
248
+ timestamp: date.toLocaleString()
249
+ });
250
+ setMessages(loadedMessages);
251
+ setAnnouncement(`Message from Bot: API response goes here`);
252
+ setIsSendButtonDisabled(false);
253
+ }, 2000);
254
+ };
255
+
256
+ const findMatchingItems = (targetValue: string) => {
257
+ let filteredConversations = Object.entries(initialConversations).reduce((acc, [key, items]) => {
258
+ const filteredItems = items.filter((item) => item.text.toLowerCase().includes(targetValue.toLowerCase()));
259
+ if (filteredItems.length > 0) {
260
+ acc[key] = filteredItems;
261
+ }
262
+ return acc;
263
+ }, {});
264
+
265
+ if (Object.keys(filteredConversations).length === 0) {
266
+ filteredConversations = [{ id: '13', noIcon: true, text: 'No results found' }];
267
+ }
268
+ return filteredConversations;
269
+ };
270
+
271
+ const iconLogo = (
272
+ <>
273
+ <Brand className="show-light" src={PFIconLogoColor} alt="PatternFly" />
274
+ <Brand className="show-dark" src={PFIconLogoReverse} alt="PatternFly" />
275
+ </>
276
+ );
277
+ const masthead = (
278
+ <Masthead>
279
+ <MastheadMain>
280
+ <MastheadToggle>
281
+ <PageToggleButton
282
+ variant="plain"
283
+ aria-label="Global navigation"
284
+ isSidebarOpen={isSidebarOpen}
285
+ onSidebarToggle={() => setIsSidebarOpen(!isSidebarOpen)}
286
+ id="fill-nav-toggle"
287
+ >
288
+ <BarsIcon />
289
+ </PageToggleButton>
290
+ </MastheadToggle>
291
+ <MastheadBrand>
292
+ <MastheadLogo href="https://patternfly.org" target="_blank">
293
+ Logo
294
+ </MastheadLogo>
295
+ </MastheadBrand>
296
+ </MastheadMain>
297
+ </Masthead>
298
+ );
299
+
300
+ const sidebar = (
301
+ <PageSidebar isSidebarOpen={isSidebarOpen} id="fill-sidebar">
302
+ <PageSidebarBody>Navigation</PageSidebarBody>
303
+ </PageSidebar>
304
+ );
305
+
306
+ const skipToChatbot = (e: MouseEvent) => {
307
+ e.preventDefault();
308
+ /* eslint-disable indent */
309
+ switch (displayMode) {
310
+ case ChatbotDisplayMode.default:
311
+ if (!chatbotVisible && toggleRef.current) {
312
+ toggleRef.current.focus();
313
+ }
314
+ if (chatbotVisible && chatbotRef.current) {
315
+ chatbotRef.current.focus();
316
+ }
317
+ break;
318
+ default:
319
+ if (historyRef.current) {
320
+ historyRef.current.focus();
321
+ }
322
+ break;
323
+ }
324
+ /* eslint-enable indent */
325
+ };
326
+
327
+ const skipToContent = (
328
+ <SkipToContent href="#" onClick={skipToChatbot}>
329
+ Skip to chatbot
330
+ </SkipToContent>
331
+ );
332
+
333
+ const handleChatbotVisibilityDrawer = () => {
334
+ setChatbotVisible(!chatbotVisible);
335
+ setDisplayMode(ChatbotDisplayMode.default);
336
+ };
337
+
338
+ const chatbotComponent = (
339
+ <Chatbot isVisible={chatbotVisible} displayMode={displayMode} ref={chatbotRef}>
340
+ <ChatbotConversationHistoryNav
341
+ displayMode={displayMode}
342
+ onDrawerToggle={() => {
343
+ setIsDrawerOpen(!isDrawerOpen);
344
+ setConversations(initialConversations);
345
+ }}
346
+ isDrawerOpen={isDrawerOpen}
347
+ setIsDrawerOpen={setIsDrawerOpen}
348
+ activeItemId="1"
349
+ conversations={conversations}
350
+ onNewChat={() => {
351
+ setIsDrawerOpen(!isDrawerOpen);
352
+ setMessages([]);
353
+ setConversations(initialConversations);
354
+ }}
355
+ handleTextInputChange={(value: string) => {
356
+ if (value === '') {
357
+ setConversations(initialConversations);
358
+ }
359
+ const newConversations: { [key: string]: Conversation[] } = findMatchingItems(value);
360
+ setConversations(newConversations);
361
+ }}
362
+ drawerContent={
363
+ <>
364
+ <ChatbotHeader>
365
+ <ChatbotHeaderMain>
366
+ <ChatbotHeaderMenu
367
+ ref={historyRef}
368
+ aria-expanded={isDrawerOpen}
369
+ onMenuToggle={() => setIsDrawerOpen(!isDrawerOpen)}
370
+ />
371
+ <ChatbotHeaderTitle>{iconLogo}</ChatbotHeaderTitle>
372
+ </ChatbotHeaderMain>
373
+ <ChatbotHeaderActions>
374
+ <ChatbotHeaderSelectorDropdown value={selectedModel} onSelect={onSelectModel}>
375
+ <DropdownList>
376
+ <DropdownItem value="Granite 7B" key="granite">
377
+ Granite 7B
378
+ </DropdownItem>
379
+ <DropdownItem value="Llama 3.0" key="llama">
380
+ Llama 3.0
381
+ </DropdownItem>
382
+ </DropdownList>
383
+ </ChatbotHeaderSelectorDropdown>
384
+ <ChatbotHeaderOptionsDropdown onSelect={onSelectDisplayMode}>
385
+ <DropdownGroup label="Display mode">
386
+ <DropdownList>
387
+ <DropdownItem
388
+ value={ChatbotDisplayMode.default}
389
+ key="switchDisplayOverlay"
390
+ icon={<OutlinedWindowRestoreIcon aria-hidden />}
391
+ isSelected={displayMode === ChatbotDisplayMode.default}
392
+ >
393
+ <span>Overlay</span>
394
+ </DropdownItem>
395
+ <DropdownItem
396
+ value={ChatbotDisplayMode.drawer}
397
+ key="switchDisplayDock"
398
+ icon={<OpenDrawerRightIcon aria-hidden />}
399
+ isSelected={displayMode === ChatbotDisplayMode.drawer}
400
+ >
401
+ <span>Drawer</span>
402
+ </DropdownItem>
403
+ <DropdownItem
404
+ value={ChatbotDisplayMode.fullscreen}
405
+ key="switchDisplayFullscreen"
406
+ icon={<ExpandIcon aria-hidden />}
407
+ isSelected={displayMode === ChatbotDisplayMode.fullscreen}
408
+ >
409
+ <span>Fullscreen</span>
410
+ </DropdownItem>
411
+ </DropdownList>
412
+ </DropdownGroup>
413
+ </ChatbotHeaderOptionsDropdown>
414
+ {(displayMode === ChatbotDisplayMode.drawer || displayMode === ChatbotDisplayMode.fullscreen) && (
415
+ <ChatbotHeaderCloseButton onClick={handleChatbotVisibilityDrawer} />
416
+ )}
417
+ </ChatbotHeaderActions>
418
+ </ChatbotHeader>
419
+ <ChatbotContent>
420
+ <MessageBox announcement={announcement}>
421
+ <ChatbotWelcomePrompt
422
+ title="Hello, Chatbot User"
423
+ description="How may I help you today?"
424
+ prompts={welcomePrompts}
425
+ />
426
+ {messages.map((message, index) => {
427
+ if (index === messages.length - 1) {
428
+ return (
429
+ <React.Fragment key={message.id}>
430
+ <div ref={scrollToBottomRef}></div>
431
+ <Message {...message} />
432
+ </React.Fragment>
433
+ );
434
+ }
435
+ return <Message key={message.id} {...message} />;
436
+ })}
437
+ </MessageBox>
438
+ </ChatbotContent>
439
+ <ChatbotFooter>
440
+ <MessageBar onSendMessage={handleSend} hasMicrophoneButton isSendButtonDisabled={isSendButtonDisabled} />
441
+ <ChatbotFootnote {...footnoteProps} />
442
+ </ChatbotFooter>
443
+ </>
444
+ }
445
+ />
446
+ </Chatbot>
447
+ );
448
+
449
+ const chatbotToggle =
450
+ displayMode === ChatbotDisplayMode.default ? (
451
+ <ChatbotToggle
452
+ tooltipLabel="Chatbot"
453
+ isChatbotVisible={chatbotVisible}
454
+ onToggleChatbot={() => {
455
+ setChatbotVisible(!chatbotVisible);
456
+ }}
457
+ id="chatbot-toggle"
458
+ ref={toggleRef}
459
+ />
460
+ ) : null;
461
+
462
+ const panelContent = <DrawerPanelContent>{chatbotComponent}</DrawerPanelContent>;
463
+
464
+ const pageContent = (
465
+ <Page skipToContent={skipToContent} masthead={masthead} sidebar={sidebar} isContentFilled>
466
+ {displayMode === ChatbotDisplayMode.default && chatbotToggle}
467
+ </Page>
468
+ );
469
+
470
+ if (displayMode === ChatbotDisplayMode.drawer) {
471
+ return (
472
+ <Drawer isExpanded={isDrawerPanelExpanded} isInline onExpand={onExpand}>
473
+ <DrawerContent panelContent={panelContent}>
474
+ <DrawerContentBody>{pageContent}</DrawerContentBody>
475
+ </DrawerContent>
476
+ </Drawer>
477
+ );
478
+ }
479
+
480
+ return (
481
+ <>
482
+ {pageContent}
483
+ {chatbotComponent}
484
+ </>
485
+ );
486
+ };