@patternfly/chatbot 6.5.0-prerelease.27 → 6.5.0-prerelease.29
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.
- package/dist/cjs/MarkdownContent/MarkdownContent.d.ts +7 -2
- package/dist/cjs/Message/ErrorMessage/ErrorMessage.d.ts +15 -1
- package/dist/cjs/Message/ErrorMessage/ErrorMessage.js +5 -3
- package/dist/cjs/Message/ErrorMessage/ErrorMessage.test.d.ts +1 -0
- package/dist/cjs/Message/ErrorMessage/ErrorMessage.test.js +30 -0
- package/dist/cjs/Message/Message.d.ts +2 -0
- package/dist/cjs/Message/Message.js +5 -5
- package/dist/cjs/Message/MessageAndActions/MessageAndActions.d.ts +14 -0
- package/dist/cjs/Message/MessageAndActions/MessageAndActions.js +22 -0
- package/dist/cjs/Message/MessageAndActions/MessageAndActions.test.d.ts +1 -0
- package/dist/cjs/Message/MessageAndActions/MessageAndActions.test.js +25 -0
- package/dist/cjs/Message/MessageAndActions/index.d.ts +1 -0
- package/dist/cjs/Message/MessageAndActions/index.js +17 -0
- package/dist/cjs/Message/MessageAttachments/MessageAttachmentItem.d.ts +13 -0
- package/dist/cjs/Message/MessageAttachments/MessageAttachmentItem.js +22 -0
- package/dist/cjs/Message/MessageAttachments/MessageAttachmentItem.test.d.ts +1 -0
- package/dist/cjs/Message/MessageAttachments/MessageAttachmentItem.test.js +25 -0
- package/dist/cjs/Message/MessageAttachments/MessageAttachmentsContainer.d.ts +13 -0
- package/dist/cjs/Message/MessageAttachments/MessageAttachmentsContainer.js +22 -0
- package/dist/cjs/Message/MessageAttachments/MessageAttachmentsContainer.test.d.ts +1 -0
- package/dist/cjs/Message/MessageAttachments/MessageAttachmentsContainer.test.js +25 -0
- package/dist/cjs/Message/MessageAttachments/index.d.ts +2 -0
- package/dist/cjs/Message/MessageAttachments/index.js +18 -0
- package/dist/cjs/Message/MessageInput.d.ts +1 -1
- package/dist/cjs/Message/MessageInput.js +3 -1
- package/dist/cjs/Message/MessageLoading.d.ts +13 -4
- package/dist/cjs/Message/MessageLoading.js +19 -5
- package/dist/cjs/Message/MessageLoading.test.d.ts +1 -0
- package/dist/cjs/Message/MessageLoading.test.js +25 -0
- package/dist/cjs/Message/QuickResponse/QuickResponse.js +3 -2
- package/dist/cjs/Message/QuickResponse/QuickResponse.test.d.ts +1 -0
- package/dist/cjs/Message/QuickResponse/QuickResponse.test.js +109 -0
- package/dist/cjs/Message/QuickResponse/index.d.ts +1 -0
- package/dist/cjs/Message/QuickResponse/index.js +17 -0
- package/dist/cjs/Message/QuickStarts/QuickStartTile.d.ts +1 -1
- package/dist/cjs/Message/QuickStarts/QuickStartTile.js +3 -2
- package/dist/cjs/Message/QuickStarts/index.d.ts +2 -0
- package/dist/cjs/Message/QuickStarts/index.js +18 -0
- package/dist/cjs/Message/UserFeedback/UserFeedback.d.ts +1 -1
- package/dist/cjs/Message/UserFeedback/UserFeedback.js +3 -1
- package/dist/cjs/Message/UserFeedback/UserFeedbackComplete.d.ts +1 -1
- package/dist/cjs/Message/UserFeedback/UserFeedbackComplete.js +3 -2
- package/dist/cjs/Message/UserFeedback/index.d.ts +2 -0
- package/dist/cjs/Message/UserFeedback/index.js +18 -0
- package/dist/cjs/Message/index.d.ts +8 -0
- package/dist/cjs/Message/index.js +8 -0
- package/dist/cjs/MessageBar/MessageBar.d.ts +6 -0
- package/dist/cjs/MessageBar/MessageBar.js +24 -12
- package/dist/cjs/MessageBar/MessageBar.test.js +12 -0
- package/dist/cjs/ResponseActions/ResponseActions.d.ts +4 -0
- package/dist/cjs/ResponseActions/ResponseActionsGroups.d.ts +13 -0
- package/dist/cjs/ResponseActions/ResponseActionsGroups.js +22 -0
- package/dist/cjs/ResponseActions/ResponseActionsGroups.test.d.ts +1 -0
- package/dist/cjs/ResponseActions/ResponseActionsGroups.test.js +25 -0
- package/dist/cjs/ResponseActions/index.d.ts +1 -0
- package/dist/cjs/ResponseActions/index.js +1 -0
- package/dist/css/main.css +13 -1
- package/dist/css/main.css.map +1 -1
- package/dist/esm/MarkdownContent/MarkdownContent.d.ts +7 -2
- package/dist/esm/Message/ErrorMessage/ErrorMessage.d.ts +15 -1
- package/dist/esm/Message/ErrorMessage/ErrorMessage.js +3 -3
- package/dist/esm/Message/ErrorMessage/ErrorMessage.test.d.ts +1 -0
- package/dist/esm/Message/ErrorMessage/ErrorMessage.test.js +25 -0
- package/dist/esm/Message/Message.d.ts +2 -0
- package/dist/esm/Message/Message.js +5 -5
- package/dist/esm/Message/MessageAndActions/MessageAndActions.d.ts +14 -0
- package/dist/esm/Message/MessageAndActions/MessageAndActions.js +18 -0
- package/dist/esm/Message/MessageAndActions/MessageAndActions.test.d.ts +1 -0
- package/dist/esm/Message/MessageAndActions/MessageAndActions.test.js +20 -0
- package/dist/esm/Message/MessageAndActions/index.d.ts +1 -0
- package/dist/esm/Message/MessageAndActions/index.js +1 -0
- package/dist/esm/Message/MessageAttachments/MessageAttachmentItem.d.ts +13 -0
- package/dist/esm/Message/MessageAttachments/MessageAttachmentItem.js +18 -0
- package/dist/esm/Message/MessageAttachments/MessageAttachmentItem.test.d.ts +1 -0
- package/dist/esm/Message/MessageAttachments/MessageAttachmentItem.test.js +20 -0
- package/dist/esm/Message/MessageAttachments/MessageAttachmentsContainer.d.ts +13 -0
- package/dist/esm/Message/MessageAttachments/MessageAttachmentsContainer.js +18 -0
- package/dist/esm/Message/MessageAttachments/MessageAttachmentsContainer.test.d.ts +1 -0
- package/dist/esm/Message/MessageAttachments/MessageAttachmentsContainer.test.js +20 -0
- package/dist/esm/Message/MessageAttachments/index.d.ts +2 -0
- package/dist/esm/Message/MessageAttachments/index.js +2 -0
- package/dist/esm/Message/MessageInput.d.ts +1 -1
- package/dist/esm/Message/MessageInput.js +1 -1
- package/dist/esm/Message/MessageLoading.d.ts +13 -4
- package/dist/esm/Message/MessageLoading.js +16 -4
- package/dist/esm/Message/MessageLoading.test.d.ts +1 -0
- package/dist/esm/Message/MessageLoading.test.js +20 -0
- package/dist/esm/Message/QuickResponse/QuickResponse.js +3 -2
- package/dist/esm/Message/QuickResponse/QuickResponse.test.d.ts +1 -0
- package/dist/esm/Message/QuickResponse/QuickResponse.test.js +104 -0
- package/dist/esm/Message/QuickResponse/index.d.ts +1 -0
- package/dist/esm/Message/QuickResponse/index.js +1 -0
- package/dist/esm/Message/QuickStarts/QuickStartTile.d.ts +1 -1
- package/dist/esm/Message/QuickStarts/QuickStartTile.js +1 -1
- package/dist/esm/Message/QuickStarts/index.d.ts +2 -0
- package/dist/esm/Message/QuickStarts/index.js +2 -0
- package/dist/esm/Message/UserFeedback/UserFeedback.d.ts +1 -1
- package/dist/esm/Message/UserFeedback/UserFeedback.js +1 -1
- package/dist/esm/Message/UserFeedback/UserFeedbackComplete.d.ts +1 -1
- package/dist/esm/Message/UserFeedback/UserFeedbackComplete.js +1 -2
- package/dist/esm/Message/UserFeedback/index.d.ts +2 -0
- package/dist/esm/Message/UserFeedback/index.js +2 -0
- package/dist/esm/Message/index.d.ts +8 -0
- package/dist/esm/Message/index.js +8 -0
- package/dist/esm/MessageBar/MessageBar.d.ts +6 -0
- package/dist/esm/MessageBar/MessageBar.js +24 -12
- package/dist/esm/MessageBar/MessageBar.test.js +12 -0
- package/dist/esm/ResponseActions/ResponseActions.d.ts +4 -0
- package/dist/esm/ResponseActions/ResponseActionsGroups.d.ts +13 -0
- package/dist/esm/ResponseActions/ResponseActionsGroups.js +18 -0
- package/dist/esm/ResponseActions/ResponseActionsGroups.test.d.ts +1 -0
- package/dist/esm/ResponseActions/ResponseActionsGroups.test.js +20 -0
- package/dist/esm/ResponseActions/index.d.ts +1 -0
- package/dist/esm/ResponseActions/index.js +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithCustomStructure.tsx +102 -0
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/Messages.md +55 -10
- package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotMessageBarCustomActions.tsx +190 -0
- package/patternfly-docs/content/extensions/chatbot/examples/UI/UI.md +15 -2
- package/src/MarkdownContent/MarkdownContent.tsx +7 -2
- package/src/Message/ErrorMessage/ErrorMessage.test.tsx +38 -0
- package/src/Message/ErrorMessage/ErrorMessage.tsx +17 -2
- package/src/Message/Message.tsx +75 -64
- package/src/Message/MessageAndActions/MessageAndActions.test.tsx +23 -0
- package/src/Message/MessageAndActions/MessageAndActions.tsx +22 -0
- package/src/Message/MessageAndActions/index.ts +1 -0
- package/src/Message/MessageAttachments/MessageAttachmentItem.test.tsx +23 -0
- package/src/Message/MessageAttachments/MessageAttachmentItem.tsx +25 -0
- package/src/Message/MessageAttachments/MessageAttachmentsContainer.test.tsx +23 -0
- package/src/Message/MessageAttachments/MessageAttachmentsContainer.tsx +25 -0
- package/src/Message/MessageAttachments/index.ts +2 -0
- package/src/Message/MessageInput.tsx +1 -1
- package/src/Message/MessageLoading.test.tsx +23 -0
- package/src/Message/MessageLoading.tsx +17 -2
- package/src/Message/QuickResponse/QuickResponse.test.tsx +131 -0
- package/src/Message/QuickResponse/QuickResponse.tsx +3 -2
- package/src/Message/QuickResponse/index.ts +1 -0
- package/src/Message/QuickStarts/QuickStartTile.tsx +1 -1
- package/src/Message/QuickStarts/index.ts +2 -0
- package/src/Message/UserFeedback/UserFeedback.tsx +1 -1
- package/src/Message/UserFeedback/UserFeedbackComplete.tsx +1 -4
- package/src/Message/UserFeedback/index.ts +2 -0
- package/src/Message/index.ts +8 -0
- package/src/MessageBar/MessageBar.scss +15 -1
- package/src/MessageBar/MessageBar.test.tsx +27 -0
- package/src/MessageBar/MessageBar.tsx +86 -50
- package/src/ResponseActions/ResponseActions.tsx +6 -0
- package/src/ResponseActions/ResponseActionsGroups.test.tsx +23 -0
- package/src/ResponseActions/ResponseActionsGroups.tsx +28 -0
- package/src/ResponseActions/index.ts +1 -0
package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithCustomStructure.tsx
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { FunctionComponent } from 'react';
|
|
2
|
+
import Message, {
|
|
3
|
+
ErrorMessage,
|
|
4
|
+
MessageAndActions,
|
|
5
|
+
MessageAttachmentItem,
|
|
6
|
+
MessageAttachmentsContainer,
|
|
7
|
+
MessageLoading
|
|
8
|
+
} from '@patternfly/chatbot/dist/dynamic/Message';
|
|
9
|
+
import MarkdownContent from '@patternfly/chatbot/dist/dynamic/MarkdownContent';
|
|
10
|
+
import ToolCall from '@patternfly/chatbot/dist/dynamic/ToolCall';
|
|
11
|
+
import ToolResponse from '@patternfly/chatbot/dist/dynamic/ToolResponse';
|
|
12
|
+
import FileDetailsLabel from '@patternfly/chatbot/dist/dynamic/FileDetailsLabel';
|
|
13
|
+
import ResponseActions, { ResponseActionsGroups } from '@patternfly/chatbot/dist/dynamic/ResponseActions';
|
|
14
|
+
import patternflyAvatar from './patternfly_avatar.jpg';
|
|
15
|
+
import userAvatar from './user_avatar.svg';
|
|
16
|
+
|
|
17
|
+
const handlePositiveResponse = () => {
|
|
18
|
+
// Handle positive response
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const handleNegativeResponse = () => {
|
|
22
|
+
// Handle negative response
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const handleCopy = () => {
|
|
26
|
+
// Handle copy action
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const handleDownload = () => {
|
|
30
|
+
// Handle download action
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const handleListen = () => {
|
|
34
|
+
// Handle listen action
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const MessageWithCustomStructure: FunctionComponent = () => (
|
|
38
|
+
<>
|
|
39
|
+
<Message name="Bot" role="bot" avatar={patternflyAvatar}>
|
|
40
|
+
<MessageAndActions>
|
|
41
|
+
<MarkdownContent
|
|
42
|
+
content={`This is a basic message with a more custom, fine-tuned structure. You can pass markdown to the MarkdownContent component, such as **bold content with double asterisks** or _italic content with single underscores_.`}
|
|
43
|
+
/>
|
|
44
|
+
<ToolCall titleText="Calling 'awesome_tool'" loadingText="Loading 'awesome_tool'" isLoading={true} />
|
|
45
|
+
<ToolResponse
|
|
46
|
+
toggleContent="Tool response: fetch_user_data"
|
|
47
|
+
subheading="Executed in 0.3 seconds"
|
|
48
|
+
body="Successfully retrieved user data from the database."
|
|
49
|
+
cardTitle="User Data Response"
|
|
50
|
+
cardBody="The tool returned 150 user records matching the specified criteria."
|
|
51
|
+
/>
|
|
52
|
+
<ErrorMessage title="An issue placed within this custom structure." />
|
|
53
|
+
<MarkdownContent
|
|
54
|
+
isMarkdownDisabled
|
|
55
|
+
textComponent={`You can also pass plain text without markdown to the MarkdownContent component by passing the isMarkdownDisabled prop. Optionally, you can also use the textComponent prop instead of content.`}
|
|
56
|
+
/>
|
|
57
|
+
<ToolCall titleText="Calling 'more_awesome_tool'" loadingText="Loading 'more_awesome_tool'" isLoading={true} />
|
|
58
|
+
<ToolCall titleText="Calling 'even_more_awesome_tool'" loadingText="Loading 'even_more_awesome_tool'" />
|
|
59
|
+
<MarkdownContent content={`You can even place a message loading state in the middle of a message:`} />
|
|
60
|
+
<MessageLoading loadingWord="Loading something in the middle of a custom structured message" />
|
|
61
|
+
<ResponseActionsGroups>
|
|
62
|
+
<ResponseActions
|
|
63
|
+
actions={{
|
|
64
|
+
positive: { onClick: handlePositiveResponse, ariaLabel: 'Good response' },
|
|
65
|
+
negative: { onClick: handleNegativeResponse, ariaLabel: 'Bad response' }
|
|
66
|
+
}}
|
|
67
|
+
persistActionSelection={true}
|
|
68
|
+
/>
|
|
69
|
+
<ResponseActions
|
|
70
|
+
actions={{
|
|
71
|
+
copy: { onClick: handleCopy, ariaLabel: 'Copy' },
|
|
72
|
+
download: { onClick: handleDownload, ariaLabel: 'Download' }
|
|
73
|
+
}}
|
|
74
|
+
persistActionSelection={false}
|
|
75
|
+
/>
|
|
76
|
+
<ResponseActions
|
|
77
|
+
actions={{
|
|
78
|
+
listen: { onClick: handleListen, ariaLabel: 'Listen' }
|
|
79
|
+
}}
|
|
80
|
+
persistActionSelection={true}
|
|
81
|
+
/>
|
|
82
|
+
</ResponseActionsGroups>
|
|
83
|
+
</MessageAndActions>
|
|
84
|
+
</Message>
|
|
85
|
+
<Message name="User" role="user" avatar={userAvatar}>
|
|
86
|
+
<MessageAndActions>
|
|
87
|
+
<MarkdownContent content="This message is in the MessageAndActions container, and the file attachments below are in their own separate MessageAttachmentsContainer!" />
|
|
88
|
+
</MessageAndActions>
|
|
89
|
+
<MessageAttachmentsContainer>
|
|
90
|
+
<MessageAttachmentItem>
|
|
91
|
+
<FileDetailsLabel fileName="project-report.pdf" />
|
|
92
|
+
</MessageAttachmentItem>
|
|
93
|
+
<MessageAttachmentItem>
|
|
94
|
+
<FileDetailsLabel fileName="data-analysis.csv" />
|
|
95
|
+
</MessageAttachmentItem>
|
|
96
|
+
<MessageAttachmentItem>
|
|
97
|
+
<FileDetailsLabel fileName="presentation-slides.pptx" />
|
|
98
|
+
</MessageAttachmentItem>
|
|
99
|
+
</MessageAttachmentsContainer>
|
|
100
|
+
</Message>
|
|
101
|
+
</>
|
|
102
|
+
);
|
|
@@ -14,24 +14,40 @@ propComponents:
|
|
|
14
14
|
[
|
|
15
15
|
'AttachMenu',
|
|
16
16
|
'AttachmentEdit',
|
|
17
|
-
'FileDetailsProps',
|
|
18
|
-
'FileDetailsLabelProps',
|
|
19
17
|
'FileDropZone',
|
|
20
|
-
'PreviewAttachment',
|
|
21
18
|
'Message',
|
|
22
|
-
'
|
|
23
|
-
'
|
|
19
|
+
'ErrorMessage',
|
|
20
|
+
'MessageLoadingProps',
|
|
21
|
+
'MessageInputProps',
|
|
22
|
+
'MessageAndActionsProps',
|
|
23
|
+
'MarkdownContent',
|
|
24
|
+
'QuickResponseProps',
|
|
25
|
+
'QuickStartTileProps',
|
|
26
|
+
'UserFeedback',
|
|
27
|
+
'UserFeedbackComplete',
|
|
28
|
+
'DeepThinking',
|
|
29
|
+
'ToolCall',
|
|
30
|
+
'ToolResponse',
|
|
31
|
+
'SourcesCard',
|
|
32
|
+
'ResponseActionsGroupsProps',
|
|
33
|
+
'ResponseActionProps',
|
|
24
34
|
'ActionProps',
|
|
25
|
-
'
|
|
26
|
-
'
|
|
27
|
-
'
|
|
28
|
-
'
|
|
35
|
+
'MessageAttachmentsContainerProps',
|
|
36
|
+
'MessageAttachmentItemProps',
|
|
37
|
+
'FileDetailsProps',
|
|
38
|
+
'FileDetailsLabelProps',
|
|
39
|
+
'MessageExtraContent',
|
|
40
|
+
'PreviewAttachment'
|
|
29
41
|
]
|
|
30
42
|
sortValue: 3
|
|
31
43
|
---
|
|
32
44
|
|
|
33
|
-
import Message from '@patternfly/chatbot/dist/dynamic/Message';
|
|
45
|
+
import Message, { ErrorMessage, MessageAndActions, MessageLoading, MessageAttachmentItem, MessageAttachmentsContainer } from '@patternfly/chatbot/dist/dynamic/Message';
|
|
46
|
+
import MarkdownContent from '@patternfly/chatbot/dist/dynamic/MarkdownContent';
|
|
34
47
|
import MessageDivider from '@patternfly/chatbot/dist/dynamic/MessageDivider';
|
|
48
|
+
import ToolCall from '@patternfly/chatbot/dist/dynamic/ToolCall';
|
|
49
|
+
import ResponseActions, { ResponseActionsGroups } from '@patternfly/chatbot/dist/dynamic/ResponseActions';
|
|
50
|
+
import ToolResponse from '@patternfly/chatbot/dist/dynamic/ToolResponse';
|
|
35
51
|
import { rehypeCodeBlockToggle } from '@patternfly/chatbot/dist/esm/Message/Plugins/rehypeCodeBlockToggle';
|
|
36
52
|
import SourcesCard from '@patternfly/chatbot/dist/dynamic/SourcesCard';
|
|
37
53
|
import { ArrowCircleDownIcon, ArrowRightIcon, CheckCircleIcon, CopyIcon, CubeIcon, CubesIcon, DownloadIcon, InfoCircleIcon, OutlinedQuestionCircleIcon, RedoIcon, RobotIcon, WrenchIcon } from '@patternfly/react-icons';
|
|
@@ -271,6 +287,35 @@ You can add custom content to specific parts of a `<Message>` via the `extraCont
|
|
|
271
287
|
|
|
272
288
|
```
|
|
273
289
|
|
|
290
|
+
### Custom message structure
|
|
291
|
+
|
|
292
|
+
For more advanced use cases, you can build completely custom message structures by passing children directly to `<Message>`. This approach is useful when you need to customize the order or structure of message elements beyond what the standard props allow.
|
|
293
|
+
|
|
294
|
+
When creating custom message structures, you must follow an intended composable structure.
|
|
295
|
+
|
|
296
|
+
1. **Message content and actions:** Wrap in `<MessageAndActions>`. This includes, but is not limited to:
|
|
297
|
+
|
|
298
|
+
- `<MarkdownContent>`: For rendering markdown or plain text content
|
|
299
|
+
- `<ErrorMessage>`
|
|
300
|
+
- `<MessageLoading>`
|
|
301
|
+
- `<MessageInput>`
|
|
302
|
+
- `<ToolCall>`
|
|
303
|
+
- `<ToolResponse>`
|
|
304
|
+
- `<DeepThinking>`
|
|
305
|
+
- `<QuickResponse>`
|
|
306
|
+
- `<QuickStartTile>`
|
|
307
|
+
- `<UserFeedback>` and `<UserFeedbackComplete>`
|
|
308
|
+
- `<SourcesCard>`
|
|
309
|
+
- `<ResponseActionsGroups>` and `<ResponseActions>`
|
|
310
|
+
|
|
311
|
+
2. **File attachments:** Placed outside `<MessageAndActions>` and wrapped in attachment containers:
|
|
312
|
+
- `<MessageAttachmentsContainer>`: Container for all attachments
|
|
313
|
+
- `<MessageAttachmentItem>`: Individual attachment wrapper (contains `<FileDetailsLabel>` or other attachment components)
|
|
314
|
+
|
|
315
|
+
```ts file="./MessageWithCustomStructure.tsx"
|
|
316
|
+
|
|
317
|
+
```
|
|
318
|
+
|
|
274
319
|
## File attachments
|
|
275
320
|
|
|
276
321
|
### Messages with attachments
|
package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotMessageBarCustomActions.tsx
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { useState, FunctionComponent, ReactNode } from 'react';
|
|
2
|
+
import { MessageBar } from '@patternfly/chatbot/dist/dynamic/MessageBar';
|
|
3
|
+
import {
|
|
4
|
+
Divider,
|
|
5
|
+
DropdownItem,
|
|
6
|
+
DropdownList,
|
|
7
|
+
Label,
|
|
8
|
+
MenuToggle,
|
|
9
|
+
Select,
|
|
10
|
+
SelectList,
|
|
11
|
+
SelectOption
|
|
12
|
+
} from '@patternfly/react-core';
|
|
13
|
+
import { PlusIcon, ClipboardIcon, CodeIcon, UploadIcon } from '@patternfly/react-icons';
|
|
14
|
+
import { useDropzone } from 'react-dropzone';
|
|
15
|
+
|
|
16
|
+
export const ChatbotMessageBarCustomActionsExample: FunctionComponent = () => {
|
|
17
|
+
const [isFirstMenuOpen, setIsFirstMenuOpen] = useState<boolean>(false);
|
|
18
|
+
const [isSecondMenuOpen, setIsSecondMenuOpen] = useState<boolean>(false);
|
|
19
|
+
const [isModelSelectOpen, setIsModelSelectOpen] = useState<boolean>(false);
|
|
20
|
+
const [selectedModel, setSelectedModel] = useState<string>('GPT-4');
|
|
21
|
+
const [showCanvasLabel, setShowCanvasLabel] = useState<boolean>(true);
|
|
22
|
+
|
|
23
|
+
const handleSend = (message: string | number) => alert(message);
|
|
24
|
+
|
|
25
|
+
const { open, getInputProps } = useDropzone({
|
|
26
|
+
multiple: true,
|
|
27
|
+
// eslint-disable-next-line no-console
|
|
28
|
+
onDropAccepted: () => console.log('fileUploaded')
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const onFirstMenuToggle = () => {
|
|
32
|
+
setIsFirstMenuOpen(!isFirstMenuOpen);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const onSecondMenuToggle = () => {
|
|
36
|
+
setIsSecondMenuOpen(!isSecondMenuOpen);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const onModelSelect = (
|
|
40
|
+
_event: React.MouseEvent<Element, MouseEvent> | undefined,
|
|
41
|
+
value: string | number | undefined
|
|
42
|
+
) => {
|
|
43
|
+
setSelectedModel(value as string);
|
|
44
|
+
setIsModelSelectOpen(false);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const firstMenuItems: ReactNode = (
|
|
48
|
+
<DropdownList>
|
|
49
|
+
<DropdownItem value="Logs" id="logs" icon={<ClipboardIcon />}>
|
|
50
|
+
Logs
|
|
51
|
+
</DropdownItem>
|
|
52
|
+
<DropdownItem value="YAML - Status" id="yaml-status" icon={<CodeIcon />}>
|
|
53
|
+
YAML - Status
|
|
54
|
+
</DropdownItem>
|
|
55
|
+
<DropdownItem value="YAML - All contents" id="yaml-all" icon={<CodeIcon />}>
|
|
56
|
+
YAML - All contents
|
|
57
|
+
</DropdownItem>
|
|
58
|
+
<Divider key="divider" />
|
|
59
|
+
<DropdownItem value="Upload from computer" id="upload" icon={<UploadIcon />} onClick={open}>
|
|
60
|
+
Upload from computer
|
|
61
|
+
</DropdownItem>
|
|
62
|
+
</DropdownList>
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
const secondMenuItems: ReactNode = (
|
|
66
|
+
<DropdownList>
|
|
67
|
+
<DropdownItem value="canvas" id="canvas">
|
|
68
|
+
{showCanvasLabel ? 'Disable' : 'Enable'} Canvas
|
|
69
|
+
</DropdownItem>
|
|
70
|
+
<Divider key="divider-1" />
|
|
71
|
+
<DropdownItem value="Logs" id="logs" icon={<ClipboardIcon />}>
|
|
72
|
+
Logs
|
|
73
|
+
</DropdownItem>
|
|
74
|
+
<DropdownItem value="YAML - Status" id="yaml-status" icon={<CodeIcon />}>
|
|
75
|
+
YAML - Status
|
|
76
|
+
</DropdownItem>
|
|
77
|
+
<DropdownItem value="YAML - All contents" id="yaml-all" icon={<CodeIcon />}>
|
|
78
|
+
YAML - All contents
|
|
79
|
+
</DropdownItem>
|
|
80
|
+
<Divider key="divider-2" />
|
|
81
|
+
<DropdownItem value="Upload from computer" id="upload" icon={<UploadIcon />} onClick={open}>
|
|
82
|
+
Upload from computer
|
|
83
|
+
</DropdownItem>
|
|
84
|
+
</DropdownList>
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
const modelOptions = ['GPT-4', 'GPT-3.5', 'Claude', 'Llama 2'];
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<>
|
|
91
|
+
{/* This is required for react-dropzone to work in Safari and Firefox */}
|
|
92
|
+
<input {...getInputProps()} hidden />
|
|
93
|
+
<div style={{ marginBottom: '1rem' }}>
|
|
94
|
+
<h4 style={{ marginBottom: '0.5rem' }}>Custom attach menu with a PlusIcon at the start</h4>
|
|
95
|
+
<MessageBar
|
|
96
|
+
onSendMessage={handleSend}
|
|
97
|
+
attachButtonPosition="start"
|
|
98
|
+
attachMenuProps={{
|
|
99
|
+
isAttachMenuOpen: isFirstMenuOpen,
|
|
100
|
+
setIsAttachMenuOpen: setIsFirstMenuOpen,
|
|
101
|
+
attachMenuItems: firstMenuItems,
|
|
102
|
+
onAttachMenuSelect: (_ev, value) => {
|
|
103
|
+
// eslint-disable-next-line no-console
|
|
104
|
+
console.log('selected', value);
|
|
105
|
+
setIsFirstMenuOpen(false);
|
|
106
|
+
},
|
|
107
|
+
attachMenuInputPlaceholder: 'Search options...',
|
|
108
|
+
onAttachMenuToggleClick: onFirstMenuToggle,
|
|
109
|
+
onAttachMenuOnOpenChangeKeys: ['Escape', 'Tab']
|
|
110
|
+
}}
|
|
111
|
+
buttonProps={{
|
|
112
|
+
attach: {
|
|
113
|
+
icon: <PlusIcon />,
|
|
114
|
+
tooltipContent: 'Message actions',
|
|
115
|
+
'aria-label': 'Message actions'
|
|
116
|
+
}
|
|
117
|
+
}}
|
|
118
|
+
/>
|
|
119
|
+
</div>
|
|
120
|
+
|
|
121
|
+
<div>
|
|
122
|
+
<h4 style={{ marginBottom: '0.5rem' }}>Custom attach menu with additional actions</h4>
|
|
123
|
+
<MessageBar
|
|
124
|
+
onSendMessage={handleSend}
|
|
125
|
+
attachButtonPosition="start"
|
|
126
|
+
attachMenuProps={{
|
|
127
|
+
isAttachMenuOpen: isSecondMenuOpen,
|
|
128
|
+
setIsAttachMenuOpen: setIsSecondMenuOpen,
|
|
129
|
+
attachMenuItems: secondMenuItems,
|
|
130
|
+
onAttachMenuOnOpenChangeKeys: ['Escape', 'Tab'],
|
|
131
|
+
onAttachMenuSelect: (_ev, value) => {
|
|
132
|
+
// eslint-disable-next-line no-console
|
|
133
|
+
console.log('selected', value);
|
|
134
|
+
if (value === 'canvas') {
|
|
135
|
+
setShowCanvasLabel(!showCanvasLabel);
|
|
136
|
+
}
|
|
137
|
+
setIsSecondMenuOpen(false);
|
|
138
|
+
},
|
|
139
|
+
onAttachMenuToggleClick: onSecondMenuToggle
|
|
140
|
+
}}
|
|
141
|
+
buttonProps={{
|
|
142
|
+
attach: {
|
|
143
|
+
icon: <PlusIcon />,
|
|
144
|
+
tooltipContent: 'Message actions',
|
|
145
|
+
'aria-label': 'Message actions'
|
|
146
|
+
}
|
|
147
|
+
}}
|
|
148
|
+
additionalActions={
|
|
149
|
+
<>
|
|
150
|
+
<Select
|
|
151
|
+
isOpen={isModelSelectOpen}
|
|
152
|
+
selected={selectedModel}
|
|
153
|
+
shouldFocusToggleOnSelect
|
|
154
|
+
onSelect={onModelSelect}
|
|
155
|
+
onOpenChange={(isOpen) => setIsModelSelectOpen(isOpen)}
|
|
156
|
+
toggle={(toggleRef) => (
|
|
157
|
+
<MenuToggle
|
|
158
|
+
ref={toggleRef}
|
|
159
|
+
variant="plainText"
|
|
160
|
+
onClick={() => setIsModelSelectOpen(!isModelSelectOpen)}
|
|
161
|
+
isExpanded={isModelSelectOpen}
|
|
162
|
+
aria-label={`${selectedModel}, Select a model`}
|
|
163
|
+
style={{
|
|
164
|
+
minWidth: '120px'
|
|
165
|
+
}}
|
|
166
|
+
>
|
|
167
|
+
{selectedModel}
|
|
168
|
+
</MenuToggle>
|
|
169
|
+
)}
|
|
170
|
+
>
|
|
171
|
+
<SelectList>
|
|
172
|
+
{modelOptions.map((option) => (
|
|
173
|
+
<SelectOption key={option} value={option}>
|
|
174
|
+
{option}
|
|
175
|
+
</SelectOption>
|
|
176
|
+
))}
|
|
177
|
+
</SelectList>
|
|
178
|
+
</Select>
|
|
179
|
+
{showCanvasLabel && (
|
|
180
|
+
<Label closeBtnAriaLabel="Remove Canvas mode" onClose={() => setShowCanvasLabel(false)}>
|
|
181
|
+
Canvas
|
|
182
|
+
</Label>
|
|
183
|
+
)}
|
|
184
|
+
</>
|
|
185
|
+
}
|
|
186
|
+
/>
|
|
187
|
+
</div>
|
|
188
|
+
</>
|
|
189
|
+
);
|
|
190
|
+
};
|
|
@@ -70,11 +70,11 @@ import { MessageBar } from '@patternfly/chatbot/dist/dynamic/MessageBar';
|
|
|
70
70
|
import SourceDetailsMenuItem from '@patternfly/chatbot/dist/dynamic/SourceDetailsMenuItem';
|
|
71
71
|
import { ChatbotModal } from '@patternfly/chatbot/dist/dynamic/ChatbotModal';
|
|
72
72
|
import SettingsForm from '@patternfly/chatbot/dist/dynamic/Settings';
|
|
73
|
-
import { BellIcon, CalendarAltIcon, ClipboardIcon, CodeIcon, ThumbtackIcon, UploadIcon } from '@patternfly/react-icons';
|
|
73
|
+
import { BellIcon, CalendarAltIcon, ClipboardIcon, CodeIcon, PlusIcon, ThumbtackIcon, UploadIcon } from '@patternfly/react-icons';
|
|
74
74
|
import { useDropzone } from 'react-dropzone';
|
|
75
75
|
|
|
76
76
|
import ChatbotConversationHistoryNav from '@patternfly/chatbot/dist/dynamic/ChatbotConversationHistoryNav';
|
|
77
|
-
import { Button, DropdownItem, DropdownList, Checkbox, MenuToggle, Select, SelectList, SelectOption } from '@patternfly/react-core';
|
|
77
|
+
import { Button, Label, DropdownItem, DropdownList, Checkbox, MenuToggle, Select, SelectList, SelectOption } from '@patternfly/react-core';
|
|
78
78
|
|
|
79
79
|
import OutlinedWindowRestoreIcon from '@patternfly/react-icons/dist/esm/icons/outlined-window-restore-icon';
|
|
80
80
|
import ExpandIcon from '@patternfly/react-icons/dist/esm/icons/expand-icon';
|
|
@@ -291,6 +291,19 @@ Attachments can also be added to the ChatBot via [drag and drop.](/extensions/ch
|
|
|
291
291
|
|
|
292
292
|
```
|
|
293
293
|
|
|
294
|
+
### Message bar with custom attach menu and additional actions
|
|
295
|
+
|
|
296
|
+
You can move the attach button to the start of the message bar and customize it with a different icon. To include additional actions in the message bar you can also use the `additionalActions` prop.
|
|
297
|
+
|
|
298
|
+
This example shows two message bar variations:
|
|
299
|
+
|
|
300
|
+
1. A message bar with a custom attach menu where a `PlusIcon` is positioned at the start
|
|
301
|
+
2. The same custom attach menu with additional actions, including a model selector menu and a dismissable "Canvas" label
|
|
302
|
+
|
|
303
|
+
```js file="./ChatbotMessageBarCustomActions.tsx"
|
|
304
|
+
|
|
305
|
+
```
|
|
306
|
+
|
|
294
307
|
### Footer with message bar and footnote
|
|
295
308
|
|
|
296
309
|
A simple footer with a message bar and footnote would have this code structure:
|
|
@@ -30,10 +30,15 @@ import SuperscriptMessage from '../Message/SuperscriptMessage/SuperscriptMessage
|
|
|
30
30
|
import { ButtonProps } from '@patternfly/react-core';
|
|
31
31
|
import { css } from '@patternfly/react-styles';
|
|
32
32
|
|
|
33
|
+
/**
|
|
34
|
+
* MarkdownContent renders content either as plain text or with content with markdown support.
|
|
35
|
+
*
|
|
36
|
+
* Use this component when passing children to Message to customize its structure.
|
|
37
|
+
*/
|
|
33
38
|
export interface MarkdownContentProps {
|
|
34
|
-
/** The
|
|
39
|
+
/** The content to render. Supports markdown formatting by default, or plain text when isMarkdownDisabled is true. */
|
|
35
40
|
content?: string;
|
|
36
|
-
/** Disables markdown parsing, allowing only text input */
|
|
41
|
+
/** Disables markdown parsing, allowing only plain text input */
|
|
37
42
|
isMarkdownDisabled?: boolean;
|
|
38
43
|
/** Props for code blocks */
|
|
39
44
|
codeBlockProps?: CodeBlockMessageProps;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { render, screen } from '@testing-library/react';
|
|
2
|
+
import '@testing-library/jest-dom';
|
|
3
|
+
import ErrorMessage from './ErrorMessage';
|
|
4
|
+
|
|
5
|
+
test('Renders with title', () => {
|
|
6
|
+
render(<ErrorMessage title="Error occurred" />);
|
|
7
|
+
|
|
8
|
+
expect(screen.getByText('Error occurred')).toBeVisible();
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test('Renders with children', () => {
|
|
12
|
+
render(<ErrorMessage title="Error occurred">This is the error message body</ErrorMessage>);
|
|
13
|
+
|
|
14
|
+
expect(screen.getByText('This is the error message body')).toBeVisible();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test('Renders with action links', () => {
|
|
18
|
+
const actionLinks = (
|
|
19
|
+
<a href="#retry" data-testid="retry-link">
|
|
20
|
+
Retry action link
|
|
21
|
+
</a>
|
|
22
|
+
);
|
|
23
|
+
render(<ErrorMessage title="Error occurred" actionLinks={actionLinks} />);
|
|
24
|
+
|
|
25
|
+
expect(screen.getByText('Retry action link')).toBeVisible();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('Renders with custom className', () => {
|
|
29
|
+
render(<ErrorMessage title="Error occurred" className="custom-error-class" />);
|
|
30
|
+
|
|
31
|
+
expect(screen.getByText('Error occurred').parentElement).toHaveClass('custom-error-class');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('Renders with spread props', () => {
|
|
35
|
+
render(<ErrorMessage title="Error occurred" id="test-error-id" />);
|
|
36
|
+
|
|
37
|
+
expect(screen.getByText('Error occurred').parentElement).toHaveAttribute('id', 'test-error-id');
|
|
38
|
+
});
|
|
@@ -4,8 +4,23 @@
|
|
|
4
4
|
|
|
5
5
|
import { Alert, AlertProps } from '@patternfly/react-core';
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
/**
|
|
8
|
+
* ErrorMessage displays an inline danger alert for error states in messages.
|
|
9
|
+
* Use this component when passing children to Message to display error information.
|
|
10
|
+
*/
|
|
11
|
+
export interface ErrorMessageProps extends Partial<AlertProps> {
|
|
12
|
+
/** Content to display in the error alert body */
|
|
13
|
+
children?: React.ReactNode;
|
|
14
|
+
/** Additional classes for the error alert */
|
|
15
|
+
className?: string;
|
|
16
|
+
/** Title of the error alert */
|
|
17
|
+
title?: React.ReactNode;
|
|
18
|
+
/** Action links to display in the alert footer */
|
|
19
|
+
actionLinks?: React.ReactNode;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const ErrorMessage = ({ title, actionLinks, children, className, ...props }: ErrorMessageProps) => (
|
|
23
|
+
<Alert isInline variant="danger" title={title} actionLinks={actionLinks} className={className} {...props}>
|
|
9
24
|
{children}
|
|
10
25
|
</Alert>
|
|
11
26
|
);
|
package/src/Message/Message.tsx
CHANGED
|
@@ -67,6 +67,8 @@ export interface MessageExtraContent {
|
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
export interface MessageProps extends Omit<HTMLProps<HTMLDivElement>, 'role'> {
|
|
70
|
+
/** Children to render instead of the default message structure, allowing more fine-tuned message control. When provided, this will override the default rendering of content, toolResponse, deepThinking, toolCall, sources, quickStarts, actions, etc. */
|
|
71
|
+
children?: ReactNode;
|
|
70
72
|
/** Unique id for message */
|
|
71
73
|
id?: string;
|
|
72
74
|
/** Role of the user sending the message */
|
|
@@ -193,6 +195,7 @@ export interface MessageProps extends Omit<HTMLProps<HTMLDivElement>, 'role'> {
|
|
|
193
195
|
}
|
|
194
196
|
|
|
195
197
|
export const MessageBase: FunctionComponent<MessageProps> = ({
|
|
198
|
+
children,
|
|
196
199
|
role,
|
|
197
200
|
content,
|
|
198
201
|
extraContent,
|
|
@@ -341,74 +344,82 @@ export const MessageBase: FunctionComponent<MessageProps> = ({
|
|
|
341
344
|
<Timestamp date={date}>{timestamp}</Timestamp>
|
|
342
345
|
</div>
|
|
343
346
|
<div className="pf-chatbot__message-response">
|
|
344
|
-
|
|
345
|
-
{
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
347
|
+
{children ? (
|
|
348
|
+
<>{children}</>
|
|
349
|
+
) : (
|
|
350
|
+
<>
|
|
351
|
+
<div className="pf-chatbot__message-and-actions">
|
|
352
|
+
{renderMessage()}
|
|
353
|
+
{afterMainContent && <>{afterMainContent}</>}
|
|
354
|
+
{toolResponse && <ToolResponse {...toolResponse} />}
|
|
355
|
+
{deepThinking && <DeepThinking {...deepThinking} />}
|
|
356
|
+
{toolCall && <ToolCall {...toolCall} />}
|
|
357
|
+
{!isLoading && sources && <SourcesCard {...sources} isCompact={isCompact} />}
|
|
358
|
+
{quickStarts && quickStarts.quickStart && (
|
|
359
|
+
<QuickStartTile
|
|
360
|
+
quickStart={quickStarts.quickStart}
|
|
361
|
+
onSelectQuickStart={quickStarts.onSelectQuickStart}
|
|
362
|
+
minuteWord={quickStarts.minuteWord}
|
|
363
|
+
minuteWordPlural={quickStarts.minuteWordPlural}
|
|
364
|
+
prerequisiteWord={quickStarts.prerequisiteWord}
|
|
365
|
+
prerequisiteWordPlural={quickStarts.prerequisiteWordPlural}
|
|
366
|
+
quickStartButtonAriaLabel={quickStarts.quickStartButtonAriaLabel}
|
|
367
|
+
isCompact={isCompact}
|
|
368
|
+
/>
|
|
369
|
+
)}
|
|
370
|
+
{!isLoading && !isEditable && actions && (
|
|
371
|
+
<>
|
|
372
|
+
{Array.isArray(actions) ? (
|
|
373
|
+
<div className="pf-chatbot__response-actions-groups">
|
|
374
|
+
{actions.map((actionGroup, index) => (
|
|
375
|
+
<ResponseActions
|
|
376
|
+
key={index}
|
|
377
|
+
actions={actionGroup.actions || actionGroup}
|
|
378
|
+
persistActionSelection={persistActionSelection || actionGroup.persistActionSelection}
|
|
379
|
+
/>
|
|
380
|
+
))}
|
|
381
|
+
</div>
|
|
382
|
+
) : (
|
|
383
|
+
<ResponseActions actions={actions} persistActionSelection={persistActionSelection} />
|
|
384
|
+
)}
|
|
385
|
+
</>
|
|
386
|
+
)}
|
|
387
|
+
{userFeedbackForm && (
|
|
388
|
+
<UserFeedback {...userFeedbackForm} timestamp={dateString} isCompact={isCompact} />
|
|
377
389
|
)}
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
quickResponses={quickResponses}
|
|
387
|
-
quickResponseContainerProps={quickResponseContainerProps}
|
|
388
|
-
isCompact={isCompact}
|
|
389
|
-
/>
|
|
390
|
-
)}
|
|
391
|
-
</div>
|
|
392
|
-
{attachments && (
|
|
393
|
-
<div className="pf-chatbot__message-attachments-container">
|
|
394
|
-
{attachments.map((attachment) => (
|
|
395
|
-
<div key={attachment.id ?? attachment.name} className="pf-chatbot__message-attachment">
|
|
396
|
-
<FileDetailsLabel
|
|
397
|
-
fileName={attachment.name}
|
|
398
|
-
fileId={attachment.id}
|
|
399
|
-
onClose={attachment.onClose}
|
|
400
|
-
onClick={attachment.onClick}
|
|
401
|
-
isLoading={attachment.isLoading}
|
|
402
|
-
closeButtonAriaLabel={attachment.closeButtonAriaLabel}
|
|
403
|
-
languageTestId={attachment.languageTestId}
|
|
404
|
-
spinnerTestId={attachment.spinnerTestId}
|
|
405
|
-
variant={isPrimary ? 'outline' : undefined}
|
|
390
|
+
{userFeedbackComplete && (
|
|
391
|
+
<UserFeedbackComplete {...userFeedbackComplete} timestamp={dateString} isCompact={isCompact} />
|
|
392
|
+
)}
|
|
393
|
+
{!isLoading && quickResponses && (
|
|
394
|
+
<QuickResponse
|
|
395
|
+
quickResponses={quickResponses}
|
|
396
|
+
quickResponseContainerProps={quickResponseContainerProps}
|
|
397
|
+
isCompact={isCompact}
|
|
406
398
|
/>
|
|
399
|
+
)}
|
|
400
|
+
</div>
|
|
401
|
+
{attachments && (
|
|
402
|
+
<div className="pf-chatbot__message-attachments-container">
|
|
403
|
+
{attachments.map((attachment) => (
|
|
404
|
+
<div key={attachment.id ?? attachment.name} className="pf-chatbot__message-attachment">
|
|
405
|
+
<FileDetailsLabel
|
|
406
|
+
fileName={attachment.name}
|
|
407
|
+
fileId={attachment.id}
|
|
408
|
+
onClose={attachment.onClose}
|
|
409
|
+
onClick={attachment.onClick}
|
|
410
|
+
isLoading={attachment.isLoading}
|
|
411
|
+
closeButtonAriaLabel={attachment.closeButtonAriaLabel}
|
|
412
|
+
languageTestId={attachment.languageTestId}
|
|
413
|
+
spinnerTestId={attachment.spinnerTestId}
|
|
414
|
+
variant={isPrimary ? 'outline' : undefined}
|
|
415
|
+
/>
|
|
416
|
+
</div>
|
|
417
|
+
))}
|
|
407
418
|
</div>
|
|
408
|
-
)
|
|
409
|
-
|
|
419
|
+
)}
|
|
420
|
+
{!isLoading && endContent && <>{endContent}</>}
|
|
421
|
+
</>
|
|
410
422
|
)}
|
|
411
|
-
{!isLoading && endContent && <>{endContent}</>}
|
|
412
423
|
</div>
|
|
413
424
|
</div>
|
|
414
425
|
</section>
|