@patternfly/chatbot 2.2.0-prerelease.1 → 2.2.0-prerelease.11

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 (187) hide show
  1. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +19 -1
  2. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +11 -11
  3. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +39 -3
  4. package/dist/cjs/ChatbotHeader/ChatbotHeaderCloseButton.d.ts +17 -0
  5. package/dist/cjs/ChatbotHeader/ChatbotHeaderCloseButton.js +14 -0
  6. package/dist/cjs/ChatbotHeader/ChatbotHeaderMenu.d.ts +2 -0
  7. package/dist/cjs/ChatbotHeader/ChatbotHeaderMenu.js +2 -2
  8. package/dist/cjs/ChatbotHeader/index.d.ts +1 -0
  9. package/dist/cjs/ChatbotHeader/index.js +1 -0
  10. package/dist/cjs/CodeModal/CodeModal.js +2 -12
  11. package/dist/cjs/Compare/Compare.d.ts +17 -0
  12. package/dist/cjs/Compare/Compare.js +50 -0
  13. package/dist/cjs/Compare/Compare.test.d.ts +1 -0
  14. package/dist/cjs/Compare/Compare.test.js +20 -0
  15. package/dist/cjs/Compare/index.d.ts +2 -0
  16. package/dist/cjs/Compare/index.js +23 -0
  17. package/dist/cjs/Message/ListMessage/OrderedListMessage.d.ts +1 -1
  18. package/dist/cjs/Message/ListMessage/OrderedListMessage.js +2 -2
  19. package/dist/cjs/Message/Message.d.ts +16 -6
  20. package/dist/cjs/Message/Message.js +6 -6
  21. package/dist/cjs/Message/Message.test.js +51 -0
  22. package/dist/cjs/Message/QuickResponse/QuickResponse.d.ts +15 -0
  23. package/dist/cjs/Message/QuickResponse/QuickResponse.js +33 -0
  24. package/dist/cjs/Message/QuickStarts/FallbackImg.d.ts +13 -0
  25. package/dist/cjs/Message/QuickStarts/FallbackImg.js +34 -0
  26. package/dist/cjs/Message/QuickStarts/QuickStartTile.d.ts +27 -0
  27. package/dist/cjs/Message/QuickStarts/QuickStartTile.js +82 -0
  28. package/dist/cjs/Message/QuickStarts/QuickStartTileDescription.d.ts +23 -0
  29. package/dist/cjs/Message/QuickStarts/QuickStartTileDescription.js +64 -0
  30. package/dist/cjs/Message/QuickStarts/QuickStartTileDescription.test.d.ts +1 -0
  31. package/dist/cjs/Message/QuickStarts/QuickStartTileDescription.test.js +76 -0
  32. package/dist/cjs/Message/QuickStarts/QuickStartTileHeader.d.ts +11 -0
  33. package/dist/cjs/Message/QuickStarts/QuickStartTileHeader.js +30 -0
  34. package/dist/cjs/Message/QuickStarts/monitor-sampleapp-quickstart-with-image.d.ts +30 -0
  35. package/dist/cjs/Message/QuickStarts/monitor-sampleapp-quickstart-with-image.js +77 -0
  36. package/dist/cjs/Message/QuickStarts/monitor-sampleapp-quickstart.d.ts +30 -0
  37. package/dist/cjs/Message/QuickStarts/monitor-sampleapp-quickstart.js +77 -0
  38. package/dist/cjs/Message/QuickStarts/types.d.ts +132 -0
  39. package/dist/cjs/Message/QuickStarts/types.js +17 -0
  40. package/dist/cjs/ResponseActions/ResponseActionButton.d.ts +6 -0
  41. package/dist/cjs/ResponseActions/ResponseActionButton.js +10 -2
  42. package/dist/cjs/ResponseActions/ResponseActionButton.test.d.ts +1 -0
  43. package/dist/cjs/ResponseActions/ResponseActionButton.test.js +54 -0
  44. package/dist/cjs/ResponseActions/ResponseActions.d.ts +4 -0
  45. package/dist/cjs/ResponseActions/ResponseActions.js +26 -9
  46. package/dist/cjs/ResponseActions/ResponseActions.test.js +79 -5
  47. package/dist/cjs/Settings/SettingsForm.d.ts +13 -0
  48. package/dist/cjs/Settings/SettingsForm.js +27 -0
  49. package/dist/cjs/Settings/index.d.ts +2 -0
  50. package/dist/cjs/Settings/index.js +23 -0
  51. package/dist/cjs/TermsOfUse/TermsOfUse.d.ts +34 -0
  52. package/dist/cjs/TermsOfUse/TermsOfUse.js +49 -0
  53. package/dist/cjs/TermsOfUse/TermsOfUse.test.d.ts +1 -0
  54. package/dist/cjs/TermsOfUse/TermsOfUse.test.js +79 -0
  55. package/dist/cjs/TermsOfUse/index.d.ts +2 -0
  56. package/dist/cjs/TermsOfUse/index.js +23 -0
  57. package/dist/cjs/index.d.ts +6 -0
  58. package/dist/cjs/index.js +10 -1
  59. package/dist/css/main.css +244 -18
  60. package/dist/css/main.css.map +1 -1
  61. package/dist/dynamic/Compare/package.json +1 -0
  62. package/dist/dynamic/Settings/package.json +1 -0
  63. package/dist/dynamic/TermsOfUse/package.json +1 -0
  64. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +19 -1
  65. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +11 -11
  66. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +39 -3
  67. package/dist/esm/ChatbotHeader/ChatbotHeaderCloseButton.d.ts +17 -0
  68. package/dist/esm/ChatbotHeader/ChatbotHeaderCloseButton.js +8 -0
  69. package/dist/esm/ChatbotHeader/ChatbotHeaderMenu.d.ts +2 -0
  70. package/dist/esm/ChatbotHeader/ChatbotHeaderMenu.js +2 -2
  71. package/dist/esm/ChatbotHeader/index.d.ts +1 -0
  72. package/dist/esm/ChatbotHeader/index.js +1 -0
  73. package/dist/esm/CodeModal/CodeModal.js +2 -12
  74. package/dist/esm/Compare/Compare.d.ts +17 -0
  75. package/dist/esm/Compare/Compare.js +43 -0
  76. package/dist/esm/Compare/Compare.test.d.ts +1 -0
  77. package/dist/esm/Compare/Compare.test.js +15 -0
  78. package/dist/esm/Compare/index.d.ts +2 -0
  79. package/dist/esm/Compare/index.js +2 -0
  80. package/dist/esm/Message/ListMessage/OrderedListMessage.d.ts +1 -1
  81. package/dist/esm/Message/ListMessage/OrderedListMessage.js +2 -2
  82. package/dist/esm/Message/Message.d.ts +16 -6
  83. package/dist/esm/Message/Message.js +7 -7
  84. package/dist/esm/Message/Message.test.js +51 -0
  85. package/dist/esm/Message/QuickResponse/QuickResponse.d.ts +15 -0
  86. package/dist/esm/Message/QuickResponse/QuickResponse.js +26 -0
  87. package/dist/esm/Message/QuickStarts/FallbackImg.d.ts +13 -0
  88. package/dist/esm/Message/QuickStarts/FallbackImg.js +9 -0
  89. package/dist/esm/Message/QuickStarts/QuickStartTile.d.ts +27 -0
  90. package/dist/esm/Message/QuickStarts/QuickStartTile.js +52 -0
  91. package/dist/esm/Message/QuickStarts/QuickStartTileDescription.d.ts +23 -0
  92. package/dist/esm/Message/QuickStarts/QuickStartTileDescription.js +35 -0
  93. package/dist/esm/Message/QuickStarts/QuickStartTileDescription.test.d.ts +1 -0
  94. package/dist/esm/Message/QuickStarts/QuickStartTileDescription.test.js +48 -0
  95. package/dist/esm/Message/QuickStarts/QuickStartTileHeader.d.ts +11 -0
  96. package/dist/esm/Message/QuickStarts/QuickStartTileHeader.js +5 -0
  97. package/dist/esm/Message/QuickStarts/monitor-sampleapp-quickstart-with-image.d.ts +30 -0
  98. package/dist/esm/Message/QuickStarts/monitor-sampleapp-quickstart-with-image.js +74 -0
  99. package/dist/esm/Message/QuickStarts/monitor-sampleapp-quickstart.d.ts +30 -0
  100. package/dist/esm/Message/QuickStarts/monitor-sampleapp-quickstart.js +74 -0
  101. package/dist/esm/Message/QuickStarts/types.d.ts +132 -0
  102. package/dist/esm/Message/QuickStarts/types.js +14 -0
  103. package/dist/esm/ResponseActions/ResponseActionButton.d.ts +6 -0
  104. package/dist/esm/ResponseActions/ResponseActionButton.js +10 -2
  105. package/dist/esm/ResponseActions/ResponseActionButton.test.d.ts +1 -0
  106. package/dist/esm/ResponseActions/ResponseActionButton.test.js +49 -0
  107. package/dist/esm/ResponseActions/ResponseActions.d.ts +4 -0
  108. package/dist/esm/ResponseActions/ResponseActions.js +26 -9
  109. package/dist/esm/ResponseActions/ResponseActions.test.js +79 -5
  110. package/dist/esm/Settings/SettingsForm.d.ts +13 -0
  111. package/dist/esm/Settings/SettingsForm.js +20 -0
  112. package/dist/esm/Settings/index.d.ts +2 -0
  113. package/dist/esm/Settings/index.js +2 -0
  114. package/dist/esm/TermsOfUse/TermsOfUse.d.ts +34 -0
  115. package/dist/esm/TermsOfUse/TermsOfUse.js +42 -0
  116. package/dist/esm/TermsOfUse/TermsOfUse.test.d.ts +1 -0
  117. package/dist/esm/TermsOfUse/TermsOfUse.test.js +74 -0
  118. package/dist/esm/TermsOfUse/index.d.ts +2 -0
  119. package/dist/esm/TermsOfUse/index.js +2 -0
  120. package/dist/esm/index.d.ts +6 -0
  121. package/dist/esm/index.js +6 -0
  122. package/dist/tsconfig.tsbuildinfo +1 -1
  123. package/package.json +7 -13
  124. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithCustomResponseActions.tsx +4 -0
  125. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithQuickStart.tsx +31 -0
  126. package/patternfly-docs/content/extensions/chatbot/examples/Messages/Messages.md +26 -4
  127. package/patternfly-docs/content/extensions/chatbot/examples/Messages/explore-pipeline-quickstart.ts +65 -0
  128. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotFooter.tsx +1 -1
  129. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotFootnote.tsx +2 -2
  130. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawer.tsx +2 -2
  131. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawerNavigation.tsx +67 -0
  132. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawerResizable.tsx +94 -0
  133. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawerWithSelection.tsx +78 -0
  134. package/patternfly-docs/content/extensions/chatbot/examples/UI/PF-TermsAndConditionsHeader.svg +148 -0
  135. package/patternfly-docs/content/extensions/chatbot/examples/UI/Settings.tsx +289 -0
  136. package/patternfly-docs/content/extensions/chatbot/examples/UI/SquareChatbotToggle.tsx +1 -1
  137. package/patternfly-docs/content/extensions/chatbot/examples/UI/TermsOfUse.tsx +147 -0
  138. package/patternfly-docs/content/extensions/chatbot/examples/UI/UI.md +54 -0
  139. package/patternfly-docs/content/extensions/chatbot/examples/demos/Chatbot.md +26 -3
  140. package/patternfly-docs/content/extensions/chatbot/examples/demos/Chatbot.tsx +2 -2
  141. package/patternfly-docs/content/extensions/chatbot/examples/demos/ChatbotAttachment.tsx +20 -19
  142. package/patternfly-docs/content/extensions/chatbot/examples/demos/ChatbotAttachmentMenu.tsx +1 -1
  143. package/patternfly-docs/content/extensions/chatbot/examples/demos/EmbeddedChatbot.tsx +2 -2
  144. package/patternfly-docs/content/extensions/chatbot/examples/demos/EmbeddedComparisonChatbot.tsx +206 -0
  145. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.scss +14 -0
  146. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.tsx +112 -3
  147. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.tsx +46 -9
  148. package/src/ChatbotFooter/ChatbotFooter.scss +2 -1
  149. package/src/ChatbotHeader/ChatbotHeaderCloseButton.tsx +51 -0
  150. package/src/ChatbotHeader/ChatbotHeaderMenu.tsx +5 -2
  151. package/src/ChatbotHeader/index.ts +1 -0
  152. package/src/CodeModal/CodeModal.scss +8 -0
  153. package/src/CodeModal/CodeModal.tsx +2 -13
  154. package/src/Compare/Compare.scss +72 -0
  155. package/src/Compare/Compare.test.tsx +31 -0
  156. package/src/Compare/Compare.tsx +98 -0
  157. package/src/Compare/index.ts +2 -0
  158. package/src/FileDropZone/__snapshots__/FileDropZone.test.tsx.snap +1 -1
  159. package/src/Message/ListMessage/OrderedListMessage.tsx +2 -2
  160. package/src/Message/Message.scss +0 -14
  161. package/src/Message/Message.test.tsx +76 -0
  162. package/src/Message/Message.tsx +35 -26
  163. package/src/Message/QuickResponse/QuickResponse.scss +33 -0
  164. package/src/Message/QuickResponse/QuickResponse.tsx +50 -0
  165. package/src/Message/QuickStarts/FallbackImg.tsx +24 -0
  166. package/src/Message/QuickStarts/QuickStartTile.scss +25 -0
  167. package/src/Message/QuickStarts/QuickStartTile.tsx +147 -0
  168. package/src/Message/QuickStarts/QuickStartTileDescription.test.tsx +57 -0
  169. package/src/Message/QuickStarts/QuickStartTileDescription.tsx +81 -0
  170. package/src/Message/QuickStarts/QuickStartTileHeader.tsx +21 -0
  171. package/src/Message/QuickStarts/monitor-sampleapp-quickstart-with-image.ts +75 -0
  172. package/src/Message/QuickStarts/monitor-sampleapp-quickstart.ts +75 -0
  173. package/src/Message/QuickStarts/types.ts +154 -0
  174. package/src/ResponseActions/ResponseActionButton.test.tsx +52 -0
  175. package/src/ResponseActions/ResponseActionButton.tsx +46 -27
  176. package/src/ResponseActions/ResponseActions.scss +10 -8
  177. package/src/ResponseActions/ResponseActions.test.tsx +103 -5
  178. package/src/ResponseActions/ResponseActions.tsx +54 -7
  179. package/src/Settings/Settings.scss +34 -0
  180. package/src/Settings/SettingsForm.tsx +25 -0
  181. package/src/Settings/index.ts +3 -0
  182. package/src/TermsOfUse/TermsOfUse.scss +66 -0
  183. package/src/TermsOfUse/TermsOfUse.test.tsx +138 -0
  184. package/src/TermsOfUse/TermsOfUse.tsx +117 -0
  185. package/src/TermsOfUse/index.ts +3 -0
  186. package/src/index.ts +9 -0
  187. package/src/main.scss +5 -0
@@ -42,10 +42,10 @@ import userAvatar from '../Messages/user_avatar.svg';
42
42
  import patternflyAvatar from '../Messages/patternfly_avatar.jpg';
43
43
 
44
44
  const footnoteProps = {
45
- label: 'Lightspeed uses AI. Check for mistakes.',
45
+ label: 'ChatBot uses AI. Check for mistakes.',
46
46
  popover: {
47
47
  title: 'Verify accuracy',
48
- description: `While Lightspeed 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.`,
48
+ 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.`,
49
49
  bannerImage: {
50
50
  src: 'https://cdn.dribbble.com/userupload/10651749/file/original-8a07b8e39d9e8bf002358c66fce1223e.gif',
51
51
  alt: 'Example image for footnote popover'
@@ -0,0 +1,206 @@
1
+ import React from 'react';
2
+
3
+ import {
4
+ Page,
5
+ Masthead,
6
+ MastheadMain,
7
+ MastheadBrand,
8
+ MastheadLogo,
9
+ PageSidebarBody,
10
+ PageSidebar,
11
+ MastheadToggle,
12
+ PageToggleButton
13
+ } from '@patternfly/react-core';
14
+ import Chatbot, { ChatbotDisplayMode } from '@patternfly/chatbot/dist/dynamic/Chatbot';
15
+ import ChatbotContent from '@patternfly/chatbot/dist/dynamic/ChatbotContent';
16
+ import ChatbotWelcomePrompt from '@patternfly/chatbot/dist/dynamic/ChatbotWelcomePrompt';
17
+ import ChatbotFooter from '@patternfly/chatbot/dist/dynamic/ChatbotFooter';
18
+ import MessageBar from '@patternfly/chatbot/dist/dynamic/MessageBar';
19
+ import MessageBox from '@patternfly/chatbot/dist/dynamic/MessageBox';
20
+ import Message, { MessageProps } from '@patternfly/chatbot/dist/dynamic/Message';
21
+ import ChatbotHeader, { ChatbotHeaderMain } from '@patternfly/chatbot/dist/dynamic/ChatbotHeader';
22
+ import Compare from '@patternfly/chatbot/dist/dynamic/Compare';
23
+ import { BarsIcon } from '@patternfly/react-icons';
24
+ import userAvatar from '../Messages/user_avatar.svg';
25
+ import patternflyAvatar from '../Messages/patternfly_avatar.jpg';
26
+
27
+ export const CompareChild = ({ name, input, hasNewInput, setIsSendButtonDisabled }) => {
28
+ const [messages, setMessages] = React.useState<MessageProps[]>([]);
29
+ const [announcement, setAnnouncement] = React.useState<string>();
30
+ const scrollToBottomRef = React.useRef<HTMLDivElement>(null);
31
+ const displayMode = ChatbotDisplayMode.embedded;
32
+
33
+ // you will likely want to come up with your own unique id function; this is for demo purposes only
34
+ const generateId = () => {
35
+ const id = Date.now() + Math.random();
36
+ return id.toString();
37
+ };
38
+
39
+ const handleSend = (input: string) => {
40
+ const date = new Date();
41
+ const newMessages: MessageProps[] = [];
42
+ messages.forEach((message) => newMessages.push(message));
43
+ newMessages.push({
44
+ avatar: userAvatar,
45
+ avatarProps: { isBordered: true },
46
+ id: generateId(),
47
+ name: 'You',
48
+ role: 'user',
49
+ content: input,
50
+ timestamp: `${date?.toLocaleDateString()} ${date?.toLocaleTimeString()}`
51
+ });
52
+ newMessages.push({
53
+ avatar: patternflyAvatar,
54
+ id: generateId(),
55
+ name,
56
+ role: 'bot',
57
+ timestamp: `${date?.toLocaleDateString()} ${date?.toLocaleTimeString()}`,
58
+ isLoading: true
59
+ });
60
+ setMessages(newMessages);
61
+ // make announcement to assistive devices that new messages have been added
62
+ setAnnouncement(`Message from You: ${input}. Message from ${name} is loading.`);
63
+
64
+ // this is for demo purposes only; in a real situation, there would be an API response we would wait for
65
+ setTimeout(() => {
66
+ const loadedMessages: MessageProps[] = [];
67
+ // we can't use structuredClone since messages contains functions, but we can't mutate
68
+ // items that are going into state or the UI won't update correctly
69
+ newMessages.forEach((message) => loadedMessages.push(message));
70
+ loadedMessages.pop();
71
+ loadedMessages.push({
72
+ id: generateId(),
73
+ role: 'bot',
74
+ content: `API response from ${name} goes here`,
75
+ name,
76
+ avatar: patternflyAvatar,
77
+ isLoading: false,
78
+ actions: {
79
+ // eslint-disable-next-line no-console
80
+ positive: { onClick: () => console.log('Good response') },
81
+ // eslint-disable-next-line no-console
82
+ negative: { onClick: () => console.log('Bad response') },
83
+ // eslint-disable-next-line no-console
84
+ copy: { onClick: () => console.log('Copy') },
85
+ // eslint-disable-next-line no-console
86
+ share: { onClick: () => console.log('Share') },
87
+ // eslint-disable-next-line no-console
88
+ listen: { onClick: () => console.log('Listen') }
89
+ },
90
+ timestamp: date.toLocaleString()
91
+ });
92
+ setMessages(loadedMessages);
93
+ // make announcement to assistive devices that new message has loaded
94
+ setAnnouncement(`Message from ${name}: API response goes here`);
95
+ setIsSendButtonDisabled(false);
96
+ }, 5000);
97
+ };
98
+
99
+ React.useEffect(() => {
100
+ if (input) {
101
+ handleSend(input);
102
+ }
103
+ }, [hasNewInput]);
104
+
105
+ // Auto-scrolls to the latest message
106
+ React.useEffect(() => {
107
+ // don't scroll the first load, but scroll if there's a current stream or a new source has popped up
108
+ if (messages.length > 0) {
109
+ scrollToBottomRef.current?.scrollIntoView();
110
+ }
111
+ }, [messages]);
112
+
113
+ return (
114
+ <Chatbot displayMode={displayMode}>
115
+ <ChatbotHeader>
116
+ <ChatbotHeaderMain>{name}</ChatbotHeaderMain>
117
+ </ChatbotHeader>
118
+ <ChatbotContent>
119
+ <MessageBox ariaLabel={`Scrollable message log for ${name}`} announcement={announcement}>
120
+ <ChatbotWelcomePrompt title="Hello, Chatbot User" description="How may I help you today?" />
121
+ {messages.map((message) => (
122
+ <Message key={message.id} {...message} />
123
+ ))}
124
+ <div ref={scrollToBottomRef}></div>
125
+ </MessageBox>
126
+ </ChatbotContent>
127
+ </Chatbot>
128
+ );
129
+ };
130
+
131
+ export const EmbeddedComparisonChatbotDemo: React.FunctionComponent = () => {
132
+ const [input, setInput] = React.useState<string>();
133
+ const [hasNewInput, setHasNewInput] = React.useState(false);
134
+ const [isSidebarOpen, setIsSidebarOpen] = React.useState(false);
135
+ const [isSendButtonDisabled, setIsSendButtonDisabled] = React.useState(false);
136
+
137
+ const handleSend = (value: string) => {
138
+ setInput(value);
139
+ setHasNewInput(!hasNewInput);
140
+ setIsSendButtonDisabled(true);
141
+ };
142
+
143
+ const masthead = (
144
+ <Masthead>
145
+ <MastheadMain>
146
+ <MastheadToggle>
147
+ <PageToggleButton
148
+ variant="plain"
149
+ aria-label="Global navigation"
150
+ isSidebarOpen={isSidebarOpen}
151
+ onSidebarToggle={() => setIsSidebarOpen(!isSidebarOpen)}
152
+ id="fill-nav-toggle"
153
+ >
154
+ <BarsIcon />
155
+ </PageToggleButton>
156
+ </MastheadToggle>
157
+ <MastheadBrand>
158
+ <MastheadLogo href="https://patternfly.org" target="_blank">
159
+ Logo
160
+ </MastheadLogo>
161
+ </MastheadBrand>
162
+ </MastheadMain>
163
+ </Masthead>
164
+ );
165
+
166
+ const sidebar = (
167
+ <PageSidebar isSidebarOpen={isSidebarOpen} id="fill-sidebar">
168
+ <PageSidebarBody>Navigation</PageSidebarBody>
169
+ </PageSidebar>
170
+ );
171
+
172
+ return (
173
+ <Page masthead={masthead} sidebar={sidebar} isContentFilled>
174
+ <div className="pf-chatbot__compare-container">
175
+ <Compare
176
+ firstChild={
177
+ <CompareChild
178
+ input={input}
179
+ hasNewInput={hasNewInput}
180
+ name="ChatBot 1"
181
+ setIsSendButtonDisabled={setIsSendButtonDisabled}
182
+ />
183
+ }
184
+ secondChild={
185
+ <CompareChild
186
+ input={input}
187
+ hasNewInput={hasNewInput}
188
+ name="ChatBot 2"
189
+ setIsSendButtonDisabled={setIsSendButtonDisabled}
190
+ />
191
+ }
192
+ firstChildDisplayName="ChatBot 1"
193
+ secondChildDisplayName="ChatBot 2"
194
+ />
195
+ <ChatbotFooter>
196
+ <MessageBar
197
+ onSendMessage={handleSend}
198
+ hasAttachButton={false}
199
+ alwayShowSendButton
200
+ isSendButtonDisabled={isSendButtonDisabled}
201
+ />
202
+ </ChatbotFooter>
203
+ </div>
204
+ </Page>
205
+ );
206
+ };
@@ -44,10 +44,23 @@
44
44
  color: var(--pf-t--global--text--color--regular);
45
45
  font-size: var(--pf-t--global--font--size--body--lg);
46
46
  font-weight: var(--pf-t--global--font--weight--body--default);
47
+ border-radius: var(--pf-t--global--border--radius--small);
48
+ }
49
+ // allows focus state to have border radius
50
+ .pf-v6-c-menu__list-item.pf-chatbot__menu-item {
51
+ overflow: hidden;
47
52
  }
48
53
  .pf-chatbot__history-actions {
49
54
  transform: rotate(90deg);
50
55
  }
56
+
57
+ .pf-chatbot__menu-item--active {
58
+ background-color: var(--pf-t--global--background--color--action--plain--clicked);
59
+ }
60
+
61
+ button.pf-chatbot__menu-item--active {
62
+ background-color: initial;
63
+ }
51
64
  }
52
65
 
53
66
  // Chatbot Header - Drawer
@@ -105,6 +118,7 @@
105
118
  border-radius: var(--pf-t--global--border--radius--pill);
106
119
  justify-content: center;
107
120
  align-items: center;
121
+ border-radius: var(--pf-t--global--border--radius--small);
108
122
  }
109
123
  }
110
124
 
@@ -11,7 +11,7 @@ describe('ChatbotConversationHistoryNav', () => {
11
11
  const initialConversations: Conversation[] = [
12
12
  {
13
13
  id: '1',
14
- text: 'Lightspeed documentation'
14
+ text: 'ChatBot documentation'
15
15
  }
16
16
  ];
17
17
 
@@ -25,7 +25,7 @@ describe('ChatbotConversationHistoryNav', () => {
25
25
  conversations={initialConversations}
26
26
  />
27
27
  );
28
- expect(screen.queryByText('Lightspeed documentation')).toBeInTheDocument();
28
+ expect(screen.queryByText('ChatBot documentation')).toBeInTheDocument();
29
29
  });
30
30
 
31
31
  it('should display the conversations for grouped conversations', () => {
@@ -120,7 +120,116 @@ describe('ChatbotConversationHistoryNav', () => {
120
120
  });
121
121
 
122
122
  waitFor(() => {
123
- expect(screen.queryByText('Lightspeed documentation')).not.toBeInTheDocument();
123
+ expect(screen.queryByText('ChatBot documentation')).not.toBeInTheDocument();
124
124
  });
125
125
  });
126
+
127
+ it('should be resizable', () => {
128
+ render(
129
+ <ChatbotConversationHistoryNav
130
+ onDrawerToggle={onDrawerToggle}
131
+ isDrawerOpen={true}
132
+ displayMode={ChatbotDisplayMode.fullscreen}
133
+ setIsDrawerOpen={jest.fn()}
134
+ conversations={initialConversations}
135
+ drawerPanelContentProps={{ isResizable: true, minSize: '200px' }}
136
+ />
137
+ );
138
+ expect(screen.getByRole('dialog', { name: /Resize/i })).toBeTruthy();
139
+ expect(screen.getByRole('separator', { name: /Resize/i })).toBeTruthy();
140
+ expect(screen.getByRole('dialog', { name: /Resize/i })).toHaveAttribute(
141
+ 'style',
142
+ '--pf-v6-c-drawer__panel--md--FlexBasis: 384px; --pf-v6-c-drawer__panel--md--FlexBasis--min: 200px;'
143
+ );
144
+ });
145
+
146
+ it('should accept drawerContentProps', () => {
147
+ const { container } = render(
148
+ <ChatbotConversationHistoryNav
149
+ onDrawerToggle={onDrawerToggle}
150
+ isDrawerOpen={true}
151
+ displayMode={ChatbotDisplayMode.fullscreen}
152
+ setIsDrawerOpen={jest.fn()}
153
+ conversations={initialConversations}
154
+ drawerContentProps={{ className: 'test' }}
155
+ />
156
+ );
157
+ const element = container.querySelector('.test');
158
+ expect(element).toBeInTheDocument();
159
+ });
160
+
161
+ it('should accept drawerContentBodyProps', () => {
162
+ const { container } = render(
163
+ <ChatbotConversationHistoryNav
164
+ onDrawerToggle={onDrawerToggle}
165
+ isDrawerOpen={true}
166
+ displayMode={ChatbotDisplayMode.fullscreen}
167
+ setIsDrawerOpen={jest.fn()}
168
+ conversations={initialConversations}
169
+ drawerContentBodyProps={{ className: 'test' }}
170
+ />
171
+ );
172
+ const element = container.querySelector('.test');
173
+ expect(element).toBeInTheDocument();
174
+ });
175
+
176
+ it('should accept drawerHeadProps', () => {
177
+ const { container } = render(
178
+ <ChatbotConversationHistoryNav
179
+ onDrawerToggle={onDrawerToggle}
180
+ isDrawerOpen={true}
181
+ displayMode={ChatbotDisplayMode.fullscreen}
182
+ setIsDrawerOpen={jest.fn()}
183
+ conversations={initialConversations}
184
+ drawerHeadProps={{ className: 'test' }}
185
+ />
186
+ );
187
+ const element = container.querySelector('.test');
188
+ expect(element).toBeInTheDocument();
189
+ });
190
+
191
+ it('should accept drawerActionsProps', () => {
192
+ const { container } = render(
193
+ <ChatbotConversationHistoryNav
194
+ onDrawerToggle={onDrawerToggle}
195
+ isDrawerOpen={true}
196
+ displayMode={ChatbotDisplayMode.fullscreen}
197
+ setIsDrawerOpen={jest.fn()}
198
+ conversations={initialConversations}
199
+ drawerActionsProps={{ className: 'test' }}
200
+ />
201
+ );
202
+ const element = container.querySelector('.test');
203
+ expect(element).toBeInTheDocument();
204
+ });
205
+
206
+ it('should accept drawerCloseButtonProps', () => {
207
+ const { container } = render(
208
+ <ChatbotConversationHistoryNav
209
+ onDrawerToggle={onDrawerToggle}
210
+ isDrawerOpen={true}
211
+ displayMode={ChatbotDisplayMode.fullscreen}
212
+ setIsDrawerOpen={jest.fn()}
213
+ conversations={initialConversations}
214
+ drawerCloseButtonProps={{ className: 'test' }}
215
+ />
216
+ );
217
+ const element = container.querySelector('.test');
218
+ expect(element).toBeInTheDocument();
219
+ });
220
+
221
+ it('should accept drawerPanelBodyProps', () => {
222
+ const { container } = render(
223
+ <ChatbotConversationHistoryNav
224
+ onDrawerToggle={onDrawerToggle}
225
+ isDrawerOpen={true}
226
+ displayMode={ChatbotDisplayMode.fullscreen}
227
+ setIsDrawerOpen={jest.fn()}
228
+ conversations={initialConversations}
229
+ drawerPanelBodyProps={{ className: 'test' }}
230
+ />
231
+ );
232
+ const element = container.querySelector('.test');
233
+ expect(element).toBeInTheDocument();
234
+ });
126
235
  });
@@ -20,7 +20,16 @@ import {
20
20
  MenuList,
21
21
  MenuGroup,
22
22
  MenuItem,
23
- MenuContent
23
+ MenuContent,
24
+ MenuItemProps,
25
+ MenuProps,
26
+ DrawerPanelContentProps,
27
+ DrawerContentProps,
28
+ DrawerContentBodyProps,
29
+ DrawerHeadProps,
30
+ DrawerActionsProps,
31
+ DrawerCloseButtonProps,
32
+ DrawerPanelBodyProps
24
33
  } from '@patternfly/react-core';
25
34
 
26
35
  import { OutlinedCommentAltIcon } from '@patternfly/react-icons';
@@ -44,6 +53,8 @@ export interface Conversation {
44
53
  label?: string;
45
54
  /** Callback for when user selects item. */
46
55
  onSelect?: (event?: React.MouseEvent, value?: string | number) => void;
56
+ /** Additional props passed to conversation menu item */
57
+ additionalProps?: MenuItemProps;
47
58
  }
48
59
  export interface ChatbotConversationHistoryNavProps extends DrawerProps {
49
60
  /** Function called to toggle drawer */
@@ -76,6 +87,22 @@ export interface ChatbotConversationHistoryNavProps extends DrawerProps {
76
87
  reverseButtonOrder?: boolean;
77
88
  /** Custom test id for the drawer actions */
78
89
  drawerActionsTestId?: string;
90
+ /** Additional props applied to menu */
91
+ menuProps?: MenuProps;
92
+ /** Additional props applied to panel */
93
+ drawerPanelContentProps?: DrawerPanelContentProps;
94
+ /** Additional props applied to drawer content */
95
+ drawerContentProps?: Omit<DrawerContentProps, 'panelContent'>;
96
+ /** Additional props applied to drawer content body */
97
+ drawerContentBodyProps?: DrawerContentBodyProps;
98
+ /** Additional props applied to drawer head */
99
+ drawerHeadProps?: DrawerHeadProps;
100
+ /** Additional props applied to drawer actions */
101
+ drawerActionsProps?: DrawerActionsProps;
102
+ /** Additional props applied to drawer close button */
103
+ drawerCloseButtonProps?: DrawerCloseButtonProps;
104
+ /** Additional props appleid to drawer panel body */
105
+ drawerPanelBodyProps?: DrawerPanelBodyProps;
79
106
  }
80
107
 
81
108
  export const ChatbotConversationHistoryNav: React.FunctionComponent<ChatbotConversationHistoryNavProps> = ({
@@ -94,6 +121,14 @@ export const ChatbotConversationHistoryNav: React.FunctionComponent<ChatbotConve
94
121
  displayMode,
95
122
  reverseButtonOrder = false,
96
123
  drawerActionsTestId = 'chatbot-nav-drawer-actions',
124
+ menuProps,
125
+ drawerPanelContentProps,
126
+ drawerContentProps,
127
+ drawerContentBodyProps,
128
+ drawerHeadProps,
129
+ drawerActionsProps,
130
+ drawerCloseButtonProps,
131
+ drawerPanelBodyProps,
97
132
  ...props
98
133
  }: ChatbotConversationHistoryNavProps) => {
99
134
  const drawerRef = React.useRef<HTMLDivElement>(null);
@@ -104,7 +139,7 @@ export const ChatbotConversationHistoryNav: React.FunctionComponent<ChatbotConve
104
139
 
105
140
  const getNavItem = (conversation: Conversation) => (
106
141
  <MenuItem
107
- className="pf-chatbot__menu-item"
142
+ className={`pf-chatbot__menu-item ${activeItemId && activeItemId === conversation.id ? 'pf-chatbot__menu-item--active' : ''}`}
108
143
  itemId={conversation.id}
109
144
  key={conversation.id}
110
145
  {...(conversation.noIcon ? {} : { icon: conversation.icon ?? <OutlinedCommentAltIcon /> })}
@@ -121,6 +156,7 @@ export const ChatbotConversationHistoryNav: React.FunctionComponent<ChatbotConve
121
156
  )
122
157
  }
123
158
  : {})}
159
+ {...conversation.additionalProps}
124
160
  /* eslint-enable indent */
125
161
  >
126
162
  {conversation.text}
@@ -159,19 +195,20 @@ export const ChatbotConversationHistoryNav: React.FunctionComponent<ChatbotConve
159
195
  // - Consumers should pass an array to <Chatbot> of the list of conversations
160
196
  // - Groups could be optional, but items need to be ordered by date
161
197
  const menuContent = (
162
- <Menu isPlain onSelect={onSelectActiveItem} activeItemId={activeItemId}>
198
+ <Menu isPlain onSelect={onSelectActiveItem} activeItemId={activeItemId} {...menuProps}>
163
199
  <MenuContent>{buildMenu()}</MenuContent>
164
200
  </Menu>
165
201
  );
166
202
 
167
203
  const panelContent = (
168
- <DrawerPanelContent focusTrap={{ enabled: true }} minSize="384px" maxSize="384px">
169
- <DrawerHead>
204
+ <DrawerPanelContent focusTrap={{ enabled: true }} defaultSize="384px" {...drawerPanelContentProps}>
205
+ <DrawerHead {...drawerHeadProps}>
170
206
  <DrawerActions
171
207
  data-testid={drawerActionsTestId}
172
208
  className={reverseButtonOrder ? 'pf-v6-c-drawer__actions--reversed' : ''}
209
+ {...drawerActionsProps}
173
210
  >
174
- <DrawerCloseButton onClick={onDrawerToggle} />
211
+ <DrawerCloseButton onClick={onDrawerToggle} {...drawerCloseButtonProps} />
175
212
  {onNewChat && <Button onClick={onNewChat}>{newChatButtonText}</Button>}
176
213
  </DrawerActions>
177
214
  </DrawerHead>
@@ -184,7 +221,7 @@ export const ChatbotConversationHistoryNav: React.FunctionComponent<ChatbotConve
184
221
  />
185
222
  </div>
186
223
  )}
187
- <DrawerPanelBody>{menuContent}</DrawerPanelBody>
224
+ <DrawerPanelBody {...drawerPanelBodyProps}>{menuContent}</DrawerPanelBody>
188
225
  </DrawerPanelContent>
189
226
  );
190
227
 
@@ -209,8 +246,8 @@ export const ChatbotConversationHistoryNav: React.FunctionComponent<ChatbotConve
209
246
  isInline={displayMode === ChatbotDisplayMode.fullscreen || displayMode === ChatbotDisplayMode.embedded}
210
247
  {...props}
211
248
  >
212
- <DrawerContent panelContent={panelContent}>
213
- <DrawerContentBody>
249
+ <DrawerContent panelContent={panelContent} {...drawerContentProps}>
250
+ <DrawerContentBody {...drawerContentBodyProps}>
214
251
  <>
215
252
  <div
216
253
  className={`${isDrawerOpen && (displayMode === ChatbotDisplayMode.default || displayMode === ChatbotDisplayMode.docked) ? 'pf-v6-c-backdrop pf-chatbot__drawer-backdrop' : undefined} `}
@@ -33,7 +33,8 @@
33
33
  }
34
34
  }
35
35
  .pf-chatbot__footer-container {
36
- width: 60rem;
36
+ width: 90%;
37
+ max-width: 60rem;
37
38
  padding: var(--pf-t--global--spacer--sm) 0;
38
39
  }
39
40
  }
@@ -0,0 +1,51 @@
1
+ import React from 'react';
2
+
3
+ import { Button, Icon, Tooltip, TooltipProps } from '@patternfly/react-core';
4
+ import { CloseIcon } from '@patternfly/react-icons';
5
+
6
+ export interface ChatbotHeaderCloseButtonProps {
7
+ /** Callback function for when button is clicked */
8
+ onClick: () => void;
9
+ /** Custom classname for the header component */
10
+ className?: string;
11
+ /** Props spread to the PF Tooltip component wrapping the display mode dropdown */
12
+ tooltipProps?: TooltipProps;
13
+ /** Aria label for menu */
14
+ menuAriaLabel?: string;
15
+ /** Ref applied to menu */
16
+ innerRef?: React.Ref<HTMLButtonElement>;
17
+ /** Content used in tooltip */
18
+ tooltipContent?: string;
19
+ }
20
+
21
+ const ChatbotHeaderCloseButtonBase: React.FunctionComponent<ChatbotHeaderCloseButtonProps> = ({
22
+ className,
23
+ onClick,
24
+ tooltipProps,
25
+ menuAriaLabel = 'Close',
26
+ innerRef,
27
+ tooltipContent = 'Close'
28
+ }: ChatbotHeaderCloseButtonProps) => (
29
+ <div className={`pf-chatbot__menu ${className}`}>
30
+ <Tooltip content={tooltipContent} position="bottom" {...tooltipProps}>
31
+ <Button
32
+ className="pf-chatbot__button--toggle-menu"
33
+ variant="plain"
34
+ onClick={onClick}
35
+ aria-label={menuAriaLabel}
36
+ ref={innerRef}
37
+ icon={
38
+ <Icon size="xl" isInline>
39
+ <CloseIcon />
40
+ </Icon>
41
+ }
42
+ />
43
+ </Tooltip>
44
+ </div>
45
+ );
46
+
47
+ export const ChatbotHeaderCloseButton = React.forwardRef(
48
+ (props: ChatbotHeaderCloseButtonProps, ref: React.Ref<HTMLButtonElement>) => (
49
+ <ChatbotHeaderCloseButtonBase innerRef={ref} {...props} />
50
+ )
51
+ );
@@ -14,6 +14,8 @@ export interface ChatbotHeaderMenuProps {
14
14
  menuAriaLabel?: string;
15
15
  /** Ref applied to menu */
16
16
  innerRef?: React.Ref<HTMLButtonElement>;
17
+ /** Content used in tooltip */
18
+ tooltipContent?: string;
17
19
  }
18
20
 
19
21
  const ChatbotHeaderMenuBase: React.FunctionComponent<ChatbotHeaderMenuProps> = ({
@@ -21,10 +23,11 @@ const ChatbotHeaderMenuBase: React.FunctionComponent<ChatbotHeaderMenuProps> = (
21
23
  onMenuToggle,
22
24
  tooltipProps,
23
25
  menuAriaLabel = 'Toggle menu',
24
- innerRef
26
+ innerRef,
27
+ tooltipContent = 'Menu'
25
28
  }: ChatbotHeaderMenuProps) => (
26
29
  <div className={`pf-chatbot__menu ${className}`}>
27
- <Tooltip content="Menu" position="bottom" {...tooltipProps}>
30
+ <Tooltip content={tooltipContent} position="bottom" {...tooltipProps}>
28
31
  <Button
29
32
  className="pf-chatbot__button--toggle-menu"
30
33
  variant="plain"
@@ -7,3 +7,4 @@ export * from './ChatbotHeaderMenu';
7
7
  export * from './ChatbotHeaderTitle';
8
8
  export * from './ChatbotHeaderOptionsDropdown';
9
9
  export * from './ChatbotHeaderSelectorDropdown';
10
+ export * from './ChatbotHeaderCloseButton';
@@ -74,3 +74,11 @@
74
74
  }
75
75
  }
76
76
  }
77
+
78
+ .pf-chatbot__code-modal-body {
79
+ flex: 1;
80
+ }
81
+
82
+ .pf-chatbot__code-modal--fullscreen {
83
+ height: inherit; // override shared modal so code editor works in full screen
84
+ }
@@ -87,17 +87,6 @@ export const CodeModal: React.FunctionComponent<CodeModalProps> = ({
87
87
  }
88
88
  };
89
89
 
90
- /* eslint-disable indent */
91
- const getHeight = (displayMode: ChatbotDisplayMode) => {
92
- switch (displayMode) {
93
- case ChatbotDisplayMode.docked:
94
- return '100vh';
95
- default:
96
- return '45vh';
97
- }
98
- };
99
- /* eslint-enable indent */
100
-
101
90
  const modal = (
102
91
  <ChatbotModal
103
92
  isOpen={isModalOpen}
@@ -114,7 +103,7 @@ export const CodeModal: React.FunctionComponent<CodeModalProps> = ({
114
103
  <StackItem className="pf-chatbot__code-modal-file-details">
115
104
  <FileDetails fileName={fileName} />
116
105
  </StackItem>
117
- <StackItem>
106
+ <StackItem className="pf-chatbot__code-modal-body">
118
107
  <CodeEditor
119
108
  isDarkTheme
120
109
  isLineNumbersVisible={isLineNumbersVisible}
@@ -126,7 +115,7 @@ export const CodeModal: React.FunctionComponent<CodeModalProps> = ({
126
115
  onEditorDidMount={onEditorDidMount}
127
116
  onCodeChange={onCodeChange}
128
117
  className={codeEditorClassName}
129
- height={getHeight(displayMode)}
118
+ isFullHeight
130
119
  options={{
131
120
  glyphMargin: false,
132
121
  folding: false