@patternfly/chatbot 6.4.0-prerelease.2 → 6.4.0-prerelease.20

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 (186) hide show
  1. package/dist/cjs/Chatbot/Chatbot.js +1 -7
  2. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.d.ts +2 -0
  3. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.js +2 -2
  4. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +22 -2
  5. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +15 -9
  6. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +40 -2
  7. package/dist/cjs/ChatbotHeader/ChatbotHeaderMenu.js +1 -1
  8. package/dist/cjs/ChatbotHeader/ChatbotHeaderMenu.test.js +1 -1
  9. package/dist/cjs/ChatbotHeader/ChatbotHeaderNewChatButton.d.ts +18 -0
  10. package/dist/cjs/ChatbotHeader/ChatbotHeaderNewChatButton.js +25 -0
  11. package/dist/cjs/ChatbotHeader/ChatbotHeaderNewChatButton.test.d.ts +1 -0
  12. package/dist/cjs/ChatbotHeader/ChatbotHeaderNewChatButton.test.js +22 -0
  13. package/dist/cjs/ChatbotHeader/index.d.ts +1 -0
  14. package/dist/cjs/ChatbotHeader/index.js +1 -0
  15. package/dist/cjs/DeepThinking/DeepThinking.d.ts +18 -0
  16. package/dist/cjs/DeepThinking/DeepThinking.js +18 -0
  17. package/dist/cjs/DeepThinking/DeepThinking.test.d.ts +1 -0
  18. package/dist/cjs/DeepThinking/DeepThinking.test.js +48 -0
  19. package/dist/cjs/DeepThinking/index.d.ts +2 -0
  20. package/dist/cjs/DeepThinking/index.js +23 -0
  21. package/dist/cjs/FilePreview/FilePreview.d.ts +26 -0
  22. package/dist/cjs/FilePreview/FilePreview.js +26 -0
  23. package/dist/cjs/FilePreview/FilePreview.test.d.ts +1 -0
  24. package/dist/cjs/FilePreview/FilePreview.test.js +97 -0
  25. package/dist/cjs/FilePreview/index.d.ts +2 -0
  26. package/dist/cjs/FilePreview/index.js +23 -0
  27. package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.js +3 -3
  28. package/dist/cjs/Message/LinkMessage/LinkMessage.d.ts +2 -1
  29. package/dist/cjs/Message/LinkMessage/LinkMessage.js +7 -3
  30. package/dist/cjs/Message/ListMessage/ListItemMessage.d.ts +1 -1
  31. package/dist/cjs/Message/ListMessage/ListItemMessage.js +16 -1
  32. package/dist/cjs/Message/Message.d.ts +15 -0
  33. package/dist/cjs/Message/Message.js +129 -32
  34. package/dist/cjs/Message/Message.test.js +71 -0
  35. package/dist/cjs/Message/SuperscriptMessage/SuperscriptMessage.d.ts +3 -0
  36. package/dist/cjs/Message/SuperscriptMessage/SuperscriptMessage.js +5 -0
  37. package/dist/cjs/Message/UserFeedback/UserFeedback.d.ts +15 -1
  38. package/dist/cjs/Message/UserFeedback/UserFeedback.js +4 -4
  39. package/dist/cjs/Message/UserFeedback/UserFeedback.test.js +44 -0
  40. package/dist/cjs/MessageBar/MessageBar.js +19 -4
  41. package/dist/cjs/MessageBox/JumpButton.d.ts +5 -0
  42. package/dist/cjs/MessageBox/JumpButton.js +1 -1
  43. package/dist/cjs/MessageBox/JumpButton.test.js +4 -4
  44. package/dist/cjs/MessageBox/MessageBox.d.ts +9 -0
  45. package/dist/cjs/MessageBox/MessageBox.js +2 -2
  46. package/dist/cjs/MessageBox/MessageBox.test.js +2 -2
  47. package/dist/cjs/SourcesCard/SourcesCard.d.ts +13 -1
  48. package/dist/cjs/SourcesCard/SourcesCard.js +6 -6
  49. package/dist/cjs/SourcesCard/SourcesCard.test.js +49 -0
  50. package/dist/cjs/ToolResponse/ToolResponse.d.ts +30 -0
  51. package/dist/cjs/ToolResponse/ToolResponse.js +18 -0
  52. package/dist/cjs/ToolResponse/ToolResponse.test.d.ts +1 -0
  53. package/dist/cjs/ToolResponse/ToolResponse.test.js +60 -0
  54. package/dist/cjs/ToolResponse/index.d.ts +2 -0
  55. package/dist/cjs/ToolResponse/index.js +23 -0
  56. package/dist/cjs/index.d.ts +6 -0
  57. package/dist/cjs/index.js +10 -1
  58. package/dist/css/main.css +273 -17
  59. package/dist/css/main.css.map +1 -1
  60. package/dist/dynamic/DeepThinking/package.json +1 -0
  61. package/dist/dynamic/FilePreview/package.json +1 -0
  62. package/dist/dynamic/ToolResponse/package.json +1 -0
  63. package/dist/esm/Chatbot/Chatbot.js +1 -7
  64. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.d.ts +2 -0
  65. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.js +2 -2
  66. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +22 -2
  67. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +17 -11
  68. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +41 -3
  69. package/dist/esm/ChatbotHeader/ChatbotHeaderMenu.js +1 -1
  70. package/dist/esm/ChatbotHeader/ChatbotHeaderMenu.test.js +1 -1
  71. package/dist/esm/ChatbotHeader/ChatbotHeaderNewChatButton.d.ts +18 -0
  72. package/dist/esm/ChatbotHeader/ChatbotHeaderNewChatButton.js +22 -0
  73. package/dist/esm/ChatbotHeader/ChatbotHeaderNewChatButton.test.d.ts +1 -0
  74. package/dist/esm/ChatbotHeader/ChatbotHeaderNewChatButton.test.js +20 -0
  75. package/dist/esm/ChatbotHeader/index.d.ts +1 -0
  76. package/dist/esm/ChatbotHeader/index.js +1 -0
  77. package/dist/esm/DeepThinking/DeepThinking.d.ts +18 -0
  78. package/dist/esm/DeepThinking/DeepThinking.js +14 -0
  79. package/dist/esm/DeepThinking/DeepThinking.test.d.ts +1 -0
  80. package/dist/esm/DeepThinking/DeepThinking.test.js +43 -0
  81. package/dist/esm/DeepThinking/index.d.ts +2 -0
  82. package/dist/esm/DeepThinking/index.js +2 -0
  83. package/dist/esm/FilePreview/FilePreview.d.ts +26 -0
  84. package/dist/esm/FilePreview/FilePreview.js +21 -0
  85. package/dist/esm/FilePreview/FilePreview.test.d.ts +1 -0
  86. package/dist/esm/FilePreview/FilePreview.test.js +92 -0
  87. package/dist/esm/FilePreview/index.d.ts +2 -0
  88. package/dist/esm/FilePreview/index.js +2 -0
  89. package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.js +5 -5
  90. package/dist/esm/Message/LinkMessage/LinkMessage.d.ts +2 -1
  91. package/dist/esm/Message/LinkMessage/LinkMessage.js +7 -3
  92. package/dist/esm/Message/ListMessage/ListItemMessage.d.ts +1 -1
  93. package/dist/esm/Message/ListMessage/ListItemMessage.js +16 -1
  94. package/dist/esm/Message/Message.d.ts +15 -0
  95. package/dist/esm/Message/Message.js +129 -32
  96. package/dist/esm/Message/Message.test.js +71 -0
  97. package/dist/esm/Message/SuperscriptMessage/SuperscriptMessage.d.ts +3 -0
  98. package/dist/esm/Message/SuperscriptMessage/SuperscriptMessage.js +3 -0
  99. package/dist/esm/Message/UserFeedback/UserFeedback.d.ts +15 -1
  100. package/dist/esm/Message/UserFeedback/UserFeedback.js +4 -4
  101. package/dist/esm/Message/UserFeedback/UserFeedback.test.js +45 -1
  102. package/dist/esm/MessageBar/MessageBar.js +19 -4
  103. package/dist/esm/MessageBox/JumpButton.d.ts +5 -0
  104. package/dist/esm/MessageBox/JumpButton.js +1 -1
  105. package/dist/esm/MessageBox/JumpButton.test.js +4 -4
  106. package/dist/esm/MessageBox/MessageBox.d.ts +9 -0
  107. package/dist/esm/MessageBox/MessageBox.js +2 -2
  108. package/dist/esm/MessageBox/MessageBox.test.js +2 -2
  109. package/dist/esm/SourcesCard/SourcesCard.d.ts +13 -1
  110. package/dist/esm/SourcesCard/SourcesCard.js +6 -6
  111. package/dist/esm/SourcesCard/SourcesCard.test.js +50 -1
  112. package/dist/esm/ToolResponse/ToolResponse.d.ts +30 -0
  113. package/dist/esm/ToolResponse/ToolResponse.js +14 -0
  114. package/dist/esm/ToolResponse/ToolResponse.test.d.ts +1 -0
  115. package/dist/esm/ToolResponse/ToolResponse.test.js +55 -0
  116. package/dist/esm/ToolResponse/index.d.ts +2 -0
  117. package/dist/esm/ToolResponse/index.js +2 -0
  118. package/dist/esm/index.d.ts +6 -0
  119. package/dist/esm/index.js +6 -0
  120. package/dist/tsconfig.tsbuildinfo +1 -1
  121. package/package.json +7 -6
  122. package/patternfly-docs/content/extensions/chatbot/examples/Messages/BotMessage.tsx +101 -3
  123. package/patternfly-docs/content/extensions/chatbot/examples/Messages/FilePreview.tsx +33 -0
  124. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithDeepThinking.tsx +17 -0
  125. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithFeedback.tsx +111 -85
  126. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithSources.tsx +70 -0
  127. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithToolResponse.tsx +135 -0
  128. package/patternfly-docs/content/extensions/chatbot/examples/Messages/Messages.md +28 -4
  129. package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessage.tsx +107 -2
  130. package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessageWithExtraContent.tsx +616 -3
  131. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotConversationEditing.tsx +202 -0
  132. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderBasic.tsx +17 -3
  133. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawer.tsx +36 -5
  134. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawerWithPin.tsx +12 -2
  135. package/patternfly-docs/content/extensions/chatbot/examples/UI/UI.md +22 -3
  136. package/patternfly-docs/content/extensions/chatbot/examples/demos/Chatbot.md +1 -1
  137. package/patternfly-docs/patternfly-docs.config.js +1 -1
  138. package/src/Chatbot/Chatbot.scss +9 -2
  139. package/src/Chatbot/Chatbot.tsx +18 -31
  140. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.tsx +5 -1
  141. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.scss +28 -10
  142. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.tsx +132 -3
  143. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.tsx +80 -33
  144. package/src/ChatbotHeader/ChatbotHeaderMenu.test.tsx +1 -1
  145. package/src/ChatbotHeader/ChatbotHeaderMenu.tsx +2 -2
  146. package/src/ChatbotHeader/ChatbotHeaderNewChatButton.test.tsx +25 -0
  147. package/src/ChatbotHeader/ChatbotHeaderNewChatButton.tsx +64 -0
  148. package/src/ChatbotHeader/index.ts +1 -0
  149. package/src/ChatbotModal/ChatbotModal.scss +1 -1
  150. package/src/DeepThinking/DeepThinking.scss +24 -0
  151. package/src/DeepThinking/DeepThinking.test.tsx +61 -0
  152. package/src/DeepThinking/DeepThinking.tsx +68 -0
  153. package/src/DeepThinking/index.ts +3 -0
  154. package/src/FileDetails/__snapshots__/FileDetails.test.tsx.snap +6 -9
  155. package/src/FileDetailsLabel/__snapshots__/FileDetailsLabel.test.tsx.snap +6 -9
  156. package/src/FilePreview/FilePreview.scss +22 -0
  157. package/src/FilePreview/FilePreview.test.tsx +112 -0
  158. package/src/FilePreview/FilePreview.tsx +58 -0
  159. package/src/FilePreview/index.ts +3 -0
  160. package/src/Message/CodeBlockMessage/CodeBlockMessage.scss +2 -1
  161. package/src/Message/CodeBlockMessage/CodeBlockMessage.tsx +6 -5
  162. package/src/Message/LinkMessage/LinkMessage.tsx +6 -2
  163. package/src/Message/ListMessage/ListItemMessage.tsx +5 -1
  164. package/src/Message/ListMessage/ListMessage.scss +17 -0
  165. package/src/Message/Message.scss +44 -0
  166. package/src/Message/Message.test.tsx +90 -0
  167. package/src/Message/Message.tsx +171 -46
  168. package/src/Message/SuperscriptMessage/SuperscriptMessage.scss +8 -0
  169. package/src/Message/SuperscriptMessage/SuperscriptMessage.tsx +13 -0
  170. package/src/Message/TextMessage/TextMessage.scss +46 -5
  171. package/src/Message/UserFeedback/UserFeedback.test.tsx +107 -0
  172. package/src/Message/UserFeedback/UserFeedback.tsx +41 -6
  173. package/src/MessageBar/MessageBar.tsx +23 -3
  174. package/src/MessageBox/JumpButton.test.tsx +4 -4
  175. package/src/MessageBox/JumpButton.tsx +20 -4
  176. package/src/MessageBox/MessageBox.test.tsx +2 -2
  177. package/src/MessageBox/MessageBox.tsx +22 -1
  178. package/src/SourcesCard/SourcesCard.scss +17 -0
  179. package/src/SourcesCard/SourcesCard.test.tsx +93 -0
  180. package/src/SourcesCard/SourcesCard.tsx +116 -80
  181. package/src/ToolResponse/ToolResponse.scss +36 -0
  182. package/src/ToolResponse/ToolResponse.test.tsx +78 -0
  183. package/src/ToolResponse/ToolResponse.tsx +95 -0
  184. package/src/ToolResponse/index.ts +3 -0
  185. package/src/index.ts +9 -0
  186. package/src/main.scss +3 -0
@@ -1,8 +1,46 @@
1
- import { Fragment, FunctionComponent } from 'react';
2
-
1
+ import { Fragment, FunctionComponent, useState, useEffect } from 'react';
3
2
  import Message from '@patternfly/chatbot/dist/dynamic/Message';
4
3
  import userAvatar from './user_avatar.svg';
5
- import { Alert, Badge, Button, Card, CardBody, CardFooter, CardTitle } from '@patternfly/react-core';
4
+ import patternflyAvatar from '../Messages/patternfly_avatar.jpg';
5
+ import {
6
+ Accordion,
7
+ AccordionContent,
8
+ AccordionItem,
9
+ AccordionToggle,
10
+ Alert,
11
+ Badge,
12
+ Button,
13
+ ButtonVariant,
14
+ Card,
15
+ CardBody,
16
+ CardExpandableContent,
17
+ CardFooter,
18
+ CardHeader,
19
+ CardTitle,
20
+ CodeBlock,
21
+ CodeBlockCode,
22
+ Content,
23
+ ContentVariants,
24
+ DescriptionList,
25
+ DescriptionListDescription,
26
+ DescriptionListGroup,
27
+ DescriptionListTerm,
28
+ Flex,
29
+ FlexItem,
30
+ HelperText,
31
+ HelperTextItem,
32
+ Icon,
33
+ Progress,
34
+ ProgressMeasureLocation,
35
+ ExpandableSection,
36
+ ExpandableSectionToggle,
37
+ Label,
38
+ Tab,
39
+ Tabs,
40
+ TabTitleText,
41
+ Spinner
42
+ } from '@patternfly/react-core';
43
+ import { ArrowCircleDownIcon, ArrowRightIcon, CheckCircleIcon, CubeIcon, CubesIcon } from '@patternfly/react-icons';
6
44
 
7
45
  const UserActionEndContent = () => {
8
46
  // eslint-disable-next-line no-console
@@ -36,6 +74,552 @@ const BeforeMainContent = () => (
36
74
  </div>
37
75
  );
38
76
 
77
+ interface Stage {
78
+ id: string;
79
+ name: string;
80
+ startProgress: number;
81
+ endProgress: number;
82
+ }
83
+
84
+ const LiveProgressSummaryCard = () => {
85
+ const [isCardExpanded, setIsCardExpanded] = useState(false);
86
+ const [isAccordionExpanded, setIsAccordionExpanded] = useState('installing-toggle');
87
+ const [progress, setProgress] = useState(15);
88
+ const [isSimulationRunning, setIsSimulationRunning] = useState(false);
89
+ const [userManuallyExpandedAccordion, setUserManuallyExpandedAccordion] = useState(false);
90
+
91
+ const stages: Stage[] = [
92
+ {
93
+ id: 'installing-toggle',
94
+ name: 'Installing cluster bootstrap',
95
+ startProgress: 0,
96
+ endProgress: 25
97
+ },
98
+ {
99
+ id: 'setup-toggle',
100
+ name: 'Control plane setup',
101
+ startProgress: 25,
102
+ endProgress: 45
103
+ },
104
+ {
105
+ id: 'deploying-toggle',
106
+ name: 'Deploying cluster operators',
107
+ startProgress: 45,
108
+ endProgress: 85
109
+ },
110
+ {
111
+ id: 'finalizing-toggle',
112
+ name: 'Finalizing installation',
113
+ startProgress: 85,
114
+ endProgress: 100
115
+ }
116
+ ];
117
+
118
+ const getCurrentStage = () =>
119
+ stages.find((stage) => progress >= stage.startProgress && progress < stage.endProgress) ||
120
+ stages[stages.length - 1];
121
+
122
+ const getTimeRemaining = () => {
123
+ const remainingProgress = 100 - progress;
124
+ const estimatedMinutes = Math.max(1, Math.round((remainingProgress / 100) * 30)); // 30 minutes total simulation
125
+ return `About ${estimatedMinutes} minute${estimatedMinutes !== 1 ? 's' : ''} remaining`;
126
+ };
127
+
128
+ const getCurrentStageName = () => {
129
+ const currentStage = getCurrentStage();
130
+ return currentStage.name;
131
+ };
132
+
133
+ const getStageStatus = (stage: Stage) => {
134
+ if (progress >= stage.endProgress) {
135
+ return 'completed';
136
+ }
137
+ if (progress >= stage.startProgress) {
138
+ return 'in-progress';
139
+ }
140
+ return 'pending';
141
+ };
142
+
143
+ const renderStageIcon = (stage: Stage) => {
144
+ const status = getStageStatus(stage);
145
+
146
+ if (status === 'completed') {
147
+ return <CheckCircleIcon color="green" aria-label="Complete" />;
148
+ } else if (status === 'in-progress') {
149
+ return <Spinner size="sm" aria-valuetext="In progress" />;
150
+ } else {
151
+ return <div style={{ width: 'var(--pf-t--global--spacer--md)' }}>{/* Empty space for pending stages */}</div>;
152
+ }
153
+ };
154
+
155
+ // Auto-increment progress when simulation is running
156
+ useEffect(() => {
157
+ let interval;
158
+
159
+ if (isSimulationRunning && progress < 100) {
160
+ interval = setInterval(() => {
161
+ setProgress((prev) => {
162
+ const increment = Math.random() * 2 + 0.5; // Random increment between 0.5-2.5%
163
+ const newProgress = Math.min(prev + increment, 100);
164
+
165
+ // Stop simulation when complete
166
+ if (newProgress >= 100) {
167
+ setIsSimulationRunning(false);
168
+ setUserManuallyExpandedAccordion(false); // Reset manual override when simulation completes
169
+ }
170
+
171
+ return newProgress;
172
+ });
173
+ }, 800);
174
+ }
175
+
176
+ return () => {
177
+ if (interval) {
178
+ clearInterval(interval);
179
+ }
180
+ };
181
+ }, [isSimulationRunning, progress]);
182
+
183
+ // Auto-expand accordion to show current stage (only if user hasn't manually overridden)
184
+ useEffect(() => {
185
+ if (isSimulationRunning && !userManuallyExpandedAccordion) {
186
+ setIsAccordionExpanded(getCurrentStage().id);
187
+ }
188
+ }, [progress, isSimulationRunning, userManuallyExpandedAccordion]);
189
+
190
+ const onExpandCard = (_event: React.MouseEvent) => {
191
+ setIsCardExpanded(!isCardExpanded);
192
+ };
193
+
194
+ const onExpandAccordion = (id: string) => {
195
+ setUserManuallyExpandedAccordion(true);
196
+
197
+ if (id === isAccordionExpanded) {
198
+ setIsAccordionExpanded('');
199
+ } else {
200
+ setIsAccordionExpanded(id);
201
+ }
202
+ };
203
+
204
+ const getStageContent = (stage: Stage) => {
205
+ const status = getStageStatus(stage);
206
+
207
+ if (status === 'in-progress') {
208
+ switch (stage.id) {
209
+ case 'installing-toggle':
210
+ return `Installing bootstrap node...
211
+ Installing etcd cluster...
212
+ Installing control plane...`;
213
+ case 'setup-toggle':
214
+ return `Configuring cluster networking...
215
+ Setting up OpenShift API server...
216
+ Configuring authentication...
217
+ Setting up cluster operators...`;
218
+ case 'deploying-toggle':
219
+ return `Deploying openshift-apiserver operator...
220
+ Deploying openshift-sdn operator...
221
+ Deploying openshift-ingress operator...
222
+ `;
223
+ case 'finalizing-toggle':
224
+ return `Finalizing cluster configuration...
225
+ Running post-installation tasks...
226
+ Setting up cluster console...`;
227
+ }
228
+ }
229
+ if (status === 'pending') {
230
+ return 'Processing...';
231
+ }
232
+ return 'Complete!';
233
+ };
234
+
235
+ const renderCodeBlock = (stage: Stage) => (
236
+ <CodeBlock
237
+ style={
238
+ {
239
+ '--pf-v6-c-code-block--BackgroundColor': 'var(--pf-t--color--gray--95)',
240
+ '--pf-v6-c-code-block--BorderRadius': 'var(--pf-t--global--border--radius--small)'
241
+ } as React.CSSProperties
242
+ }
243
+ >
244
+ <CodeBlockCode>{getStageContent(stage)}</CodeBlockCode>
245
+ </CodeBlock>
246
+ );
247
+
248
+ return (
249
+ <>
250
+ <Flex className="pf-v6-u-mt-lg" spaceItems={{ default: 'spaceItemsSm' }}>
251
+ <FlexItem>
252
+ <Button
253
+ variant="primary"
254
+ size="sm"
255
+ onClick={() => {
256
+ setProgress(15);
257
+ setIsSimulationRunning(true);
258
+ setUserManuallyExpandedAccordion(false);
259
+ }}
260
+ isDisabled={isSimulationRunning}
261
+ >
262
+ {isSimulationRunning ? 'Simulation running...' : 'Start simulation of cluster installation progress'}
263
+ </Button>
264
+ </FlexItem>
265
+ <FlexItem>
266
+ <Button
267
+ variant="secondary"
268
+ size="sm"
269
+ onClick={() => {
270
+ setIsSimulationRunning(false);
271
+ setProgress(15);
272
+ setIsAccordionExpanded('installing-toggle');
273
+ setUserManuallyExpandedAccordion(false);
274
+ }}
275
+ >
276
+ Reset
277
+ </Button>
278
+ </FlexItem>
279
+ </Flex>
280
+ <Card ouiaId="LiveProgressSummaryCard" isExpanded={isCardExpanded}>
281
+ <CardHeader
282
+ onExpand={onExpandCard}
283
+ isToggleRightAligned
284
+ toggleButtonProps={{
285
+ id: 'toggle-button1',
286
+ 'aria-label': 'Details',
287
+ 'aria-labelledby': 'expandable-card-title toggle-button1',
288
+ 'aria-expanded': isCardExpanded
289
+ }}
290
+ >
291
+ <DescriptionList>
292
+ <DescriptionListGroup
293
+ style={
294
+ {
295
+ '--pf-v6-c-description-list__group--RowGap': 'var(--pf-t--global--spacer--md)'
296
+ } as React.CSSProperties
297
+ }
298
+ >
299
+ <DescriptionListTerm id="title-outside-progress-example-label">
300
+ OpenShift cluster installation
301
+ </DescriptionListTerm>
302
+ <DescriptionListDescription>
303
+ <Progress
304
+ aria-labelledby="title-outside-progress-example-label"
305
+ value={progress}
306
+ measureLocation={ProgressMeasureLocation.outside}
307
+ style={{ '--pf-v6-c-progress--GridGap': 'var(--pf-t--global--spacer--sm' } as React.CSSProperties}
308
+ helperText={
309
+ <Flex justifyContent={{ default: 'justifyContentSpaceBetween' }}>
310
+ <FlexItem>
311
+ <HelperText>
312
+ <HelperTextItem>
313
+ {progress >= 100 ? 'Installation complete!' : getCurrentStageName()}
314
+ </HelperTextItem>
315
+ </HelperText>
316
+ </FlexItem>
317
+ <FlexItem>
318
+ <HelperText>
319
+ {/* Progress was getting announced on VoiceOver constantly - this helps avoid that */}
320
+ <HelperTextItem aria-live="off">
321
+ {progress >= 100 ? 'Completed' : getTimeRemaining()}
322
+ </HelperTextItem>
323
+ </HelperText>
324
+ </FlexItem>
325
+ </Flex>
326
+ }
327
+ />
328
+ </DescriptionListDescription>
329
+ </DescriptionListGroup>
330
+ </DescriptionList>
331
+ </CardHeader>
332
+ <CardExpandableContent>
333
+ <CardBody>
334
+ <hr
335
+ style={
336
+ {
337
+ border: 'none',
338
+ height: 'var(--pf-t--global--border--width--divider--default)',
339
+ backgroundColor: 'var(--pf-t--global--border--color--control--read-only)'
340
+ } as React.CSSProperties
341
+ }
342
+ className="pf-v6-u-mb-md"
343
+ />
344
+ <Accordion
345
+ style={
346
+ {
347
+ '--pf-v6-c-accordion__expandable-content-body--PaddingBlockStart': 'var(--pf-t--global--spacer--md)',
348
+ '--pf-v6-c-accordion__expandable-content-body--PaddingBlockEnd': '0',
349
+ '--pf-v6-c-accordion__expandable-content-body--PaddingInlineStart': '0',
350
+ '--pf-v6-c-accordion__expandable-content-body--PaddingInlineEnd': '0',
351
+ '--pf-v6-c-accordion__expandable-content--BackgroundColor': 'initial',
352
+ '--pf-v6-c-accordion__expandable-content--Color': '#fff'
353
+ } as React.CSSProperties
354
+ }
355
+ >
356
+ {stages.map((stage) => (
357
+ <AccordionItem key={stage.id} isExpanded={isAccordionExpanded === stage.id}>
358
+ <AccordionToggle
359
+ onClick={() => {
360
+ onExpandAccordion(stage.id);
361
+ }}
362
+ id={stage.id}
363
+ >
364
+ <Flex spaceItems={{ default: 'spaceItemsSm' }} alignItems={{ default: 'alignItemsCenter' }}>
365
+ <FlexItem>{renderStageIcon(stage)}</FlexItem>
366
+ <FlexItem>{stage.name}</FlexItem>
367
+ </Flex>
368
+ </AccordionToggle>
369
+ <AccordionContent id={stage.id.replace('-toggle', '')}>{renderCodeBlock(stage)}</AccordionContent>
370
+ </AccordionItem>
371
+ ))}
372
+ </Accordion>
373
+ </CardBody>
374
+ </CardExpandableContent>
375
+ <CardFooter>
376
+ <Button isBlock variant="tertiary" icon={<ArrowRightIcon />} iconPosition="end">
377
+ Open in console
378
+ </Button>
379
+ </CardFooter>
380
+ </Card>
381
+ </>
382
+ );
383
+ };
384
+
385
+ const VersionSelectorCard = () => {
386
+ const [activeTabKey, setActiveTabKey] = useState<string | number>(0);
387
+ const [isCardSelected, setIsCardSelected] = useState('');
388
+ const [isExpanded, setIsExpanded] = useState(false);
389
+ const id1 = '4.20';
390
+ const id2 = '4.19';
391
+ const id3 = '4.18';
392
+ const id4 = '4.17';
393
+
394
+ const onChange = (event: React.FormEvent<HTMLInputElement>) => {
395
+ setIsCardSelected(event.currentTarget.id);
396
+ };
397
+
398
+ const onToggleExpandableSection = (isExpanded: boolean) => {
399
+ setIsExpanded(isExpanded);
400
+ };
401
+
402
+ const handleTabClick = (_event: any, tabIndex: string | number) => {
403
+ setActiveTabKey(tabIndex);
404
+ };
405
+
406
+ const contentId = 'detached-expandable-section-content';
407
+ const toggleId = 'detached-expandable-section-toggle';
408
+
409
+ const generateTabContent = (title: string, subtitle: string) => (
410
+ <Flex direction={{ default: 'column' }} alignItems={{ default: 'alignItemsCenter' }} gap={{ default: 'gapMd' }}>
411
+ <FlexItem alignSelf={{ default: 'alignSelfCenter' }} className="pf-v6-u-mt-md pf-v6-u-text-align-center">
412
+ <div className="pf-v6-u-font-weight-bold">{title}</div>
413
+ <div>{subtitle}</div>
414
+ </FlexItem>
415
+ <FlexItem alignSelf={{ default: 'alignSelfStretch' }}>
416
+ <Card id="4.20-card" isSelectable isSelected={isCardSelected === id1}>
417
+ <CardHeader
418
+ selectableActions={{
419
+ selectableActionId: id1,
420
+ selectableActionAriaLabelledby: '4.20-card',
421
+ name: 'version',
422
+ variant: 'single',
423
+ onChange,
424
+ isHidden: true
425
+ }}
426
+ >
427
+ <CardTitle>
428
+ <Flex spaceItems={{ default: 'spaceItemsSm' }}>
429
+ <FlexItem>4.20.0-ec.3</FlexItem>
430
+ <FlexItem>
431
+ <Label isCompact color={isCardSelected === id1 ? 'blue' : undefined}>
432
+ Preview
433
+ </Label>
434
+ </FlexItem>
435
+ </Flex>
436
+ </CardTitle>
437
+ </CardHeader>
438
+ <CardBody>Developer preview • Not for production</CardBody>
439
+ </Card>
440
+ </FlexItem>
441
+ <FlexItem alignSelf={{ default: 'alignSelfStretch' }}>
442
+ <Card id="4.19-card" isSelectable isSelected={isCardSelected === id2}>
443
+ <CardHeader
444
+ selectableActions={{
445
+ selectableActionId: id2,
446
+ selectableActionAriaLabelledby: '4.19-card',
447
+ name: 'version',
448
+ variant: 'single',
449
+ onChange,
450
+ isHidden: true
451
+ }}
452
+ >
453
+ <CardTitle>
454
+ <Flex spaceItems={{ default: 'spaceItemsSm' }}>
455
+ <FlexItem>4.19.2</FlexItem>
456
+ <FlexItem>
457
+ <Label isCompact color={isCardSelected === id2 ? 'blue' : undefined}>
458
+ Latest
459
+ </Label>
460
+ </FlexItem>
461
+ </Flex>
462
+ </CardTitle>
463
+ </CardHeader>
464
+ <CardBody>Newest features • 18-month support • Recommended</CardBody>
465
+ </Card>
466
+ </FlexItem>
467
+ <FlexItem alignSelf={{ default: 'alignSelfStretch' }}>
468
+ <Card id="4.18-card" isSelectable isSelected={isCardSelected === id3}>
469
+ <CardHeader
470
+ selectableActions={{
471
+ selectableActionId: id3,
472
+ selectableActionAriaLabelledby: '4.18-card',
473
+ name: 'version',
474
+ variant: 'single',
475
+ onChange,
476
+ isHidden: true
477
+ }}
478
+ >
479
+ <CardTitle>4.18.19</CardTitle>
480
+ </CardHeader>
481
+ <CardBody>Previous stable • Full support</CardBody>
482
+ </Card>
483
+ <ExpandableSection isExpanded={isExpanded} isDetached toggleId={toggleId} contentId={contentId}>
484
+ <Flex
485
+ direction={{ default: 'column' }}
486
+ alignItems={{ default: 'alignItemsCenter' }}
487
+ gap={{ default: 'gapMd' }}
488
+ >
489
+ <FlexItem alignSelf={{ default: 'alignSelfStretch' }}>
490
+ <Card className="pf-v6-u-mt-md" id="4.17-card" isSelectable isSelected={isCardSelected === id4}>
491
+ <CardHeader
492
+ selectableActions={{
493
+ selectableActionId: id4,
494
+ selectableActionAriaLabelledby: '4.17-card',
495
+ name: 'version',
496
+ variant: 'single',
497
+ onChange,
498
+ isHidden: true
499
+ }}
500
+ >
501
+ <CardTitle>
502
+ <Flex spaceItems={{ default: 'spaceItemsSm' }}>
503
+ <FlexItem>4.17.34</FlexItem>
504
+ <FlexItem>
505
+ <Label isCompact color={isCardSelected === id4 ? 'blue' : undefined}>
506
+ Maintenance
507
+ </Label>
508
+ </FlexItem>
509
+ </Flex>
510
+ </CardTitle>
511
+ </CardHeader>
512
+ <CardBody>Maintenance support phase</CardBody>
513
+ </Card>
514
+ </FlexItem>
515
+ </Flex>
516
+ </ExpandableSection>
517
+ </FlexItem>
518
+ <FlexItem>
519
+ <ExpandableSectionToggle
520
+ isExpanded={isExpanded}
521
+ onToggle={onToggleExpandableSection}
522
+ toggleId={toggleId}
523
+ contentId={contentId}
524
+ direction="up"
525
+ >
526
+ {isExpanded ? 'Hide older versions' : 'Show older versions'}
527
+ </ExpandableSectionToggle>
528
+ </FlexItem>
529
+ </Flex>
530
+ );
531
+
532
+ return (
533
+ <Card ouiaId="VersionSelectorCard">
534
+ <CardBody
535
+ style={{ '--pf-v6-c-card--child--PaddingBlockEnd': 'var(--pf-t--global--spacer--md)' } as React.CSSProperties}
536
+ >
537
+ <Tabs activeKey={activeTabKey} onSelect={handleTabClick} aria-label="Architecture" role="region" isFilled>
538
+ <Tab
539
+ eventKey={0}
540
+ title={
541
+ <TabTitleText>
542
+ <Flex spaceItems={{ default: 'spaceItemsXs' }}>
543
+ <FlexItem>
544
+ <CubeIcon />
545
+ </FlexItem>
546
+ <FlexItem>Single arch</FlexItem>
547
+ </Flex>
548
+ </TabTitleText>
549
+ }
550
+ >
551
+ {generateTabContent('x86_64 Intel/AMD only', 'Standard deployments • Most common choice')}
552
+ </Tab>
553
+ <Tab
554
+ eventKey={1}
555
+ title={
556
+ <TabTitleText>
557
+ <Flex spaceItems={{ default: 'spaceItemsXs' }}>
558
+ <FlexItem>
559
+ <CubesIcon />
560
+ </FlexItem>
561
+ <FlexItem>Multi arch</FlexItem>
562
+ </Flex>
563
+ </TabTitleText>
564
+ }
565
+ >
566
+ {generateTabContent('Multi arch', 'Standard deployments')}
567
+ </Tab>
568
+ </Tabs>
569
+ </CardBody>
570
+ <CardFooter>
571
+ <Button isBlock isDisabled={isCardSelected === ''}>
572
+ Continue with selections
573
+ </Button>
574
+ </CardFooter>
575
+ </Card>
576
+ );
577
+ };
578
+
579
+ const DownloadCard = () => (
580
+ <Card>
581
+ <CardHeader isToggleRightAligned>
582
+ <CardTitle>
583
+ <Flex spaceItems={{ default: 'spaceItemsSm' }}>
584
+ <FlexItem>
585
+ <Icon size="lg" status="success">
586
+ <CheckCircleIcon />
587
+ </Icon>
588
+ </FlexItem>
589
+ <FlexItem>Your discovery ISO is ready</FlexItem>
590
+ </Flex>
591
+ </CardTitle>
592
+ </CardHeader>
593
+ <CardBody>
594
+ <Flex direction={{ default: 'column' }} spaceItems={{ default: 'spaceItemsLg' }}>
595
+ <FlexItem>
596
+ <Content component={ContentVariants.p}>
597
+ To begin adding hosts to your bare metal cluster, you first need to boot them with the generated Discovery
598
+ ISO. This allows the installation program to see and manage your hardware.
599
+ </Content>
600
+ </FlexItem>
601
+
602
+ <Flex direction={{ default: 'column' }} spaceItems={{ default: 'spaceItemsSm' }}>
603
+ <FlexItem>
604
+ <Button variant={ButtonVariant.primary} icon={<ArrowCircleDownIcon />} isBlock>
605
+ Download Discovery ISO
606
+ </Button>
607
+ </FlexItem>
608
+
609
+ <FlexItem alignSelf={{ default: 'alignSelfCenter' }}>
610
+ <Content component={ContentVariants.small}>1.2 GB • Expires in 24 hours</Content>
611
+ </FlexItem>
612
+ </Flex>
613
+ </Flex>
614
+ </CardBody>
615
+ <CardFooter>
616
+ <Content component={ContentVariants.small}>
617
+ <strong>Next step:</strong> After downloading, boot your bare metal hosts from this ISO image.
618
+ </Content>
619
+ </CardFooter>
620
+ </Card>
621
+ );
622
+
39
623
  export const UserMessageWithExtraContent: FunctionComponent = () => (
40
624
  <>
41
625
  <Message
@@ -50,5 +634,34 @@ export const UserMessageWithExtraContent: FunctionComponent = () => (
50
634
  endContent: <UserActionEndContent />
51
635
  }}
52
636
  />
637
+ <Message
638
+ avatar={patternflyAvatar}
639
+ name="Bot"
640
+ role="bot"
641
+ content="This is a message with a live progress summmary card."
642
+ timestamp="1 hour ago"
643
+ extraContent={{
644
+ afterMainContent: <LiveProgressSummaryCard />
645
+ }}
646
+ />
647
+ <Message
648
+ avatar={patternflyAvatar}
649
+ name="Bot"
650
+ role="bot"
651
+ content="This is a message with a version selector card."
652
+ timestamp="1 hour ago"
653
+ extraContent={{
654
+ afterMainContent: <VersionSelectorCard />
655
+ }}
656
+ />
657
+ <Message
658
+ avatar={patternflyAvatar}
659
+ name="Bot"
660
+ role="bot"
661
+ content="All set! I've finished building the Discovery ISO. The next step is to download it and boot your hosts, which you can do using the summary card I've prepared for you:"
662
+ extraContent={{
663
+ endContent: <DownloadCard />
664
+ }}
665
+ />
53
666
  </>
54
667
  );