@patternfly/chatbot 6.5.0-prerelease.22 → 6.5.0-prerelease.24

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 (110) hide show
  1. package/dist/cjs/DeepThinking/DeepThinking.d.ts +11 -0
  2. package/dist/cjs/DeepThinking/DeepThinking.js +30 -2
  3. package/dist/cjs/DeepThinking/DeepThinking.test.js +39 -0
  4. package/dist/cjs/MarkdownContent/MarkdownContent.d.ts +39 -0
  5. package/dist/cjs/MarkdownContent/MarkdownContent.js +181 -0
  6. package/dist/cjs/MarkdownContent/MarkdownContent.test.d.ts +1 -0
  7. package/dist/cjs/MarkdownContent/MarkdownContent.test.js +192 -0
  8. package/dist/cjs/MarkdownContent/index.d.ts +2 -0
  9. package/dist/cjs/MarkdownContent/index.js +23 -0
  10. package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.d.ts +3 -1
  11. package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.js +3 -2
  12. package/dist/cjs/Message/LinkMessage/LinkMessage.d.ts +5 -1
  13. package/dist/cjs/Message/LinkMessage/LinkMessage.js +4 -3
  14. package/dist/cjs/Message/ListMessage/OrderedListMessage.d.ts +9 -1
  15. package/dist/cjs/Message/ListMessage/OrderedListMessage.js +2 -1
  16. package/dist/cjs/Message/ListMessage/UnorderedListMessage.d.ts +7 -1
  17. package/dist/cjs/Message/ListMessage/UnorderedListMessage.js +2 -1
  18. package/dist/cjs/Message/Message.js +2 -155
  19. package/dist/cjs/Message/TableMessage/TableMessage.d.ts +6 -1
  20. package/dist/cjs/Message/TableMessage/TableMessage.js +3 -2
  21. package/dist/cjs/Message/TextMessage/TextMessage.d.ts +8 -1
  22. package/dist/cjs/Message/TextMessage/TextMessage.js +3 -2
  23. package/dist/cjs/Message/UserFeedback/UserFeedback.d.ts +2 -0
  24. package/dist/cjs/Message/UserFeedback/UserFeedback.js +5 -5
  25. package/dist/cjs/MessageBar/MessageBar.js +18 -4
  26. package/dist/cjs/ToolCall/ToolCall.d.ts +9 -0
  27. package/dist/cjs/ToolCall/ToolCall.js +19 -3
  28. package/dist/cjs/ToolCall/ToolCall.test.js +31 -0
  29. package/dist/cjs/ToolResponse/ToolResponse.d.ts +15 -0
  30. package/dist/cjs/ToolResponse/ToolResponse.js +48 -2
  31. package/dist/cjs/ToolResponse/ToolResponse.test.js +60 -0
  32. package/dist/cjs/index.d.ts +2 -0
  33. package/dist/cjs/index.js +4 -1
  34. package/dist/css/main.css +82 -9
  35. package/dist/css/main.css.map +1 -1
  36. package/dist/dynamic/MarkdownContent/package.json +1 -0
  37. package/dist/esm/DeepThinking/DeepThinking.d.ts +11 -0
  38. package/dist/esm/DeepThinking/DeepThinking.js +27 -2
  39. package/dist/esm/DeepThinking/DeepThinking.test.js +39 -0
  40. package/dist/esm/MarkdownContent/MarkdownContent.d.ts +39 -0
  41. package/dist/esm/MarkdownContent/MarkdownContent.js +174 -0
  42. package/dist/esm/MarkdownContent/MarkdownContent.test.d.ts +1 -0
  43. package/dist/esm/MarkdownContent/MarkdownContent.test.js +187 -0
  44. package/dist/esm/MarkdownContent/index.d.ts +2 -0
  45. package/dist/esm/MarkdownContent/index.js +2 -0
  46. package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.d.ts +3 -1
  47. package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.js +3 -2
  48. package/dist/esm/Message/LinkMessage/LinkMessage.d.ts +5 -1
  49. package/dist/esm/Message/LinkMessage/LinkMessage.js +4 -3
  50. package/dist/esm/Message/ListMessage/OrderedListMessage.d.ts +9 -1
  51. package/dist/esm/Message/ListMessage/OrderedListMessage.js +2 -1
  52. package/dist/esm/Message/ListMessage/UnorderedListMessage.d.ts +7 -1
  53. package/dist/esm/Message/ListMessage/UnorderedListMessage.js +2 -1
  54. package/dist/esm/Message/Message.js +3 -156
  55. package/dist/esm/Message/TableMessage/TableMessage.d.ts +6 -1
  56. package/dist/esm/Message/TableMessage/TableMessage.js +3 -2
  57. package/dist/esm/Message/TextMessage/TextMessage.d.ts +8 -1
  58. package/dist/esm/Message/TextMessage/TextMessage.js +3 -2
  59. package/dist/esm/Message/UserFeedback/UserFeedback.d.ts +2 -0
  60. package/dist/esm/Message/UserFeedback/UserFeedback.js +6 -6
  61. package/dist/esm/MessageBar/MessageBar.js +18 -4
  62. package/dist/esm/ToolCall/ToolCall.d.ts +9 -0
  63. package/dist/esm/ToolCall/ToolCall.js +16 -3
  64. package/dist/esm/ToolCall/ToolCall.test.js +31 -0
  65. package/dist/esm/ToolResponse/ToolResponse.d.ts +15 -0
  66. package/dist/esm/ToolResponse/ToolResponse.js +45 -2
  67. package/dist/esm/ToolResponse/ToolResponse.test.js +60 -0
  68. package/dist/esm/index.d.ts +2 -0
  69. package/dist/esm/index.js +2 -0
  70. package/dist/tsconfig.tsbuildinfo +1 -1
  71. package/package.json +1 -1
  72. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithFeedback.tsx +14 -1
  73. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithMarkdownDeepThinking.tsx +26 -0
  74. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithMarkdownToolCall.tsx +29 -0
  75. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithMarkdownToolResponse.tsx +200 -0
  76. package/patternfly-docs/content/extensions/chatbot/examples/Messages/Messages.md +32 -0
  77. package/patternfly-docs/content/extensions/chatbot/examples/demos/Chatbot.md +15 -1
  78. package/src/DeepThinking/DeepThinking.test.tsx +48 -0
  79. package/src/DeepThinking/DeepThinking.tsx +50 -4
  80. package/src/MarkdownContent/MarkdownContent.test.tsx +207 -0
  81. package/src/MarkdownContent/MarkdownContent.tsx +264 -0
  82. package/src/MarkdownContent/index.ts +2 -0
  83. package/src/Message/CodeBlockMessage/CodeBlockMessage.scss +4 -0
  84. package/src/Message/CodeBlockMessage/CodeBlockMessage.tsx +5 -1
  85. package/src/Message/LinkMessage/LinkMessage.scss +5 -0
  86. package/src/Message/LinkMessage/LinkMessage.tsx +24 -2
  87. package/src/Message/ListMessage/ListMessage.scss +8 -0
  88. package/src/Message/ListMessage/OrderedListMessage.tsx +16 -2
  89. package/src/Message/ListMessage/UnorderedListMessage.tsx +12 -2
  90. package/src/Message/Message.tsx +21 -181
  91. package/src/Message/QuickResponse/QuickResponse.scss +3 -1
  92. package/src/Message/TableMessage/TableMessage.scss +11 -0
  93. package/src/Message/TableMessage/TableMessage.tsx +18 -2
  94. package/src/Message/TextMessage/TextMessage.scss +8 -0
  95. package/src/Message/TextMessage/TextMessage.tsx +29 -2
  96. package/src/Message/UserFeedback/UserFeedback.scss +28 -1
  97. package/src/Message/UserFeedback/UserFeedback.tsx +22 -12
  98. package/src/MessageBar/AttachButton.scss +0 -1
  99. package/src/MessageBar/MessageBar.scss +11 -2
  100. package/src/MessageBar/MessageBar.tsx +22 -3
  101. package/src/MessageBar/MicrophoneButton.scss +0 -1
  102. package/src/MessageBar/SendButton.scss +0 -1
  103. package/src/MessageBar/StopButton.scss +0 -1
  104. package/src/ToolCall/ToolCall.test.tsx +40 -0
  105. package/src/ToolCall/ToolCall.tsx +37 -3
  106. package/src/ToolResponse/ToolResponse.scss +10 -0
  107. package/src/ToolResponse/ToolResponse.test.tsx +75 -0
  108. package/src/ToolResponse/ToolResponse.tsx +78 -6
  109. package/src/index.ts +3 -0
  110. package/src/main.scss +1 -0
@@ -41,6 +41,5 @@
41
41
  .pf-v6-c-button.pf-chatbot__button--stop.pf-m-compact {
42
42
  width: 1.5rem;
43
43
  height: 1.5rem;
44
- padding: var(--pf-t--global--spacer--sm);
45
44
  align-items: center;
46
45
  }
@@ -232,4 +232,44 @@ describe('ToolCall', () => {
232
232
  expect(toggleButton).toHaveAttribute('aria-expanded', 'false');
233
233
  expect(screen.queryByText('Expandable Content')).not.toBeVisible();
234
234
  });
235
+
236
+ it('should render titleText as markdown when isTitleMarkdown is true', () => {
237
+ const titleText = '**Bold title**';
238
+ const { container } = render(<ToolCall titleText={titleText} isTitleMarkdown />);
239
+ expect(container.querySelector('strong')).toBeTruthy();
240
+ expect(screen.getByText('Bold title')).toBeTruthy();
241
+ });
242
+
243
+ it('should not render titleText as markdown when isTitleMarkdown is false', () => {
244
+ const titleText = '**Bold title**';
245
+ render(<ToolCall titleText={titleText} />);
246
+ expect(screen.getByText('**Bold title**')).toBeTruthy();
247
+ });
248
+
249
+ it('should render expandableContent as markdown when isExpandableContentMarkdown is true', async () => {
250
+ const user = userEvent.setup();
251
+ const expandableContent = '**Bold expandable content**';
252
+ const { container } = render(
253
+ <ToolCall {...defaultProps} expandableContent={expandableContent} isExpandableContentMarkdown />
254
+ );
255
+ await user.click(screen.getByRole('button', { name: defaultProps.titleText }));
256
+ expect(container.querySelector('strong')).toBeTruthy();
257
+ expect(screen.getByText('Bold expandable content')).toBeTruthy();
258
+ });
259
+
260
+ it('should not render expandableContent as markdown when isExpandableContentMarkdown is false', async () => {
261
+ const user = userEvent.setup();
262
+ const expandableContent = '**Bold expandable content**';
263
+ render(<ToolCall {...defaultProps} expandableContent={expandableContent} />);
264
+ await user.click(screen.getByRole('button', { name: defaultProps.titleText }));
265
+ expect(screen.getByText('**Bold expandable content**')).toBeTruthy();
266
+ });
267
+
268
+ it('should pass markdownContentProps to MarkdownContent component', () => {
269
+ const titleText = '**Bold title**';
270
+ const { container } = render(
271
+ <ToolCall titleText={titleText} isTitleMarkdown markdownContentProps={{ isPrimary: true }} />
272
+ );
273
+ expect(container.querySelector('.pf-m-primary')).toBeTruthy();
274
+ });
235
275
  });
@@ -19,6 +19,8 @@ import {
19
19
  Spinner,
20
20
  SpinnerProps
21
21
  } from '@patternfly/react-core';
22
+ import MarkdownContent from '../MarkdownContent';
23
+ import type { MarkdownContentProps } from '../MarkdownContent';
22
24
 
23
25
  export interface ToolCallProps {
24
26
  /** Title text for the tool call. */
@@ -61,6 +63,14 @@ export interface ToolCallProps {
61
63
  cardFooterProps?: CardFooterProps;
62
64
  /** Additional props for the expandable section when expandableContent is passed. */
63
65
  expandableSectionProps?: Omit<ExpandableSectionProps, 'ref'>;
66
+ /** Whether to enable markdown rendering for titleText. When true, titleText will be parsed as markdown. */
67
+ isTitleMarkdown?: boolean;
68
+ /** Whether to enable markdown rendering for expandableContent. When true and expandableContent is a string, it will be parsed as markdown. */
69
+ isExpandableContentMarkdown?: boolean;
70
+ /** Props passed to MarkdownContent component when markdown is enabled */
71
+ markdownContentProps?: Omit<MarkdownContentProps, 'content'>;
72
+ /** Whether to retain styles in the MarkdownContent component. Defaults to false. */
73
+ shouldRetainStyles?: boolean;
64
74
  }
65
75
 
66
76
  export const ToolCall: FunctionComponent<ToolCallProps> = ({
@@ -83,7 +93,11 @@ export const ToolCall: FunctionComponent<ToolCallProps> = ({
83
93
  cardBodyProps,
84
94
  cardFooterProps,
85
95
  expandableSectionProps,
86
- spinnerProps
96
+ spinnerProps,
97
+ isTitleMarkdown,
98
+ isExpandableContentMarkdown,
99
+ markdownContentProps,
100
+ shouldRetainStyles = false
87
101
  }: ToolCallProps) => {
88
102
  const [isExpanded, setIsExpanded] = useState(isDefaultExpanded);
89
103
 
@@ -91,6 +105,13 @@ export const ToolCall: FunctionComponent<ToolCallProps> = ({
91
105
  setIsExpanded(isExpanded);
92
106
  };
93
107
 
108
+ const renderTitle = () => {
109
+ if (isTitleMarkdown) {
110
+ return <MarkdownContent shouldRetainStyles={shouldRetainStyles} content={titleText} {...markdownContentProps} />;
111
+ }
112
+ return titleText;
113
+ };
114
+
94
115
  const titleContent = (
95
116
  <span className={`pf-chatbot__tool-call-title-content`}>
96
117
  {isLoading ? (
@@ -99,10 +120,23 @@ export const ToolCall: FunctionComponent<ToolCallProps> = ({
99
120
  {<span className="pf-chatbot__tool-call-title-text">{loadingText}</span>}
100
121
  </>
101
122
  ) : (
102
- <span className="pf-chatbot__tool-call-title-text">{titleText}</span>
123
+ <span className="pf-chatbot__tool-call-title-text">{renderTitle()}</span>
103
124
  )}
104
125
  </span>
105
126
  );
127
+
128
+ const renderExpandableContent = () => {
129
+ if (isExpandableContentMarkdown && typeof expandableContent === 'string') {
130
+ return (
131
+ <MarkdownContent
132
+ shouldRetainStyles={shouldRetainStyles}
133
+ content={expandableContent}
134
+ {...markdownContentProps}
135
+ />
136
+ );
137
+ }
138
+ return expandableContent;
139
+ };
106
140
  const defaultActions = (
107
141
  <>
108
142
  <ActionListItem {...actionListItemProps} {...cancelActionItemProps}>
@@ -138,7 +172,7 @@ export const ToolCall: FunctionComponent<ToolCallProps> = ({
138
172
  isIndented
139
173
  {...expandableSectionProps}
140
174
  >
141
- {expandableContent}
175
+ {renderExpandableContent()}
142
176
  </ExpandableSection>
143
177
  ) : (
144
178
  titleContent
@@ -34,3 +34,13 @@
34
34
  --pf-v6-c-divider--Color: var(--pf-t--global--border--color--default);
35
35
  }
36
36
  }
37
+
38
+ .pf-chatbot__tool-response-expandable-section .pf-v6-c-expandable-section__toggle .pf-m-markdown {
39
+ padding: inherit;
40
+ }
41
+
42
+ .pf-chatbot__tool-response {
43
+ .pf-chatbot__message-image {
44
+ max-width: 100%;
45
+ }
46
+ }
@@ -149,4 +149,79 @@ describe('ToolResponse', () => {
149
149
  expect(screen.getByText(defaultProps.cardTitle)).not.toBeVisible();
150
150
  expect(screen.getByText(defaultProps.cardBody)).not.toBeVisible();
151
151
  });
152
+
153
+ it('should render toggleContent as markdown when isToggleContentMarkdown is true', () => {
154
+ const toggleContent = '**Bold toggle**';
155
+ const { container } = render(
156
+ <ToolResponse {...defaultProps} toggleContent={toggleContent} isToggleContentMarkdown />
157
+ );
158
+ expect(container.querySelector('strong')).toBeTruthy();
159
+ expect(screen.getByText('Bold toggle')).toBeTruthy();
160
+ });
161
+
162
+ it('should not render toggleContent as markdown when isToggleContentMarkdown is false', () => {
163
+ const toggleContent = '**Bold toggle**';
164
+ render(<ToolResponse {...defaultProps} toggleContent={toggleContent} />);
165
+ expect(screen.getByText('**Bold toggle**')).toBeTruthy();
166
+ });
167
+
168
+ it('should render subheading as markdown when isSubheadingMarkdown is true', () => {
169
+ const subheading = '**Bold subheading**';
170
+ const { container } = render(<ToolResponse {...defaultProps} subheading={subheading} isSubheadingMarkdown />);
171
+ expect(container.querySelector('strong')).toBeTruthy();
172
+ expect(screen.getByText('Bold subheading')).toBeTruthy();
173
+ });
174
+
175
+ it('should not render subheading as markdown when isSubheadingMarkdown is false', () => {
176
+ const subheading = '**Bold subheading**';
177
+ render(<ToolResponse {...defaultProps} subheading={subheading} />);
178
+ expect(screen.getByText('**Bold subheading**')).toBeTruthy();
179
+ });
180
+
181
+ it('should render body as markdown when isBodyMarkdown is true', () => {
182
+ const body = '**Bold body**';
183
+ const { container } = render(<ToolResponse {...defaultProps} body={body} isBodyMarkdown />);
184
+ expect(container.querySelector('strong')).toBeTruthy();
185
+ expect(screen.getByText('Bold body')).toBeTruthy();
186
+ });
187
+
188
+ it('should not render body as markdown when isBodyMarkdown is false', () => {
189
+ const body = '**Bold body**';
190
+ render(<ToolResponse {...defaultProps} body={body} />);
191
+ expect(screen.getByText('**Bold body**')).toBeTruthy();
192
+ });
193
+
194
+ it('should render cardTitle as markdown when isCardTitleMarkdown is true', () => {
195
+ const cardTitle = '**Bold card title**';
196
+ const { container } = render(<ToolResponse {...defaultProps} cardTitle={cardTitle} isCardTitleMarkdown />);
197
+ expect(container.querySelector('strong')).toBeTruthy();
198
+ expect(screen.getByText('Bold card title')).toBeTruthy();
199
+ });
200
+
201
+ it('should not render cardTitle as markdown when isCardTitleMarkdown is false', () => {
202
+ const cardTitle = '**Bold card title**';
203
+ render(<ToolResponse {...defaultProps} cardTitle={cardTitle} />);
204
+ expect(screen.getByText('**Bold card title**')).toBeTruthy();
205
+ });
206
+
207
+ it('should render cardBody as markdown when isCardBodyMarkdown is true', () => {
208
+ const cardBody = '**Bold card body**';
209
+ const { container } = render(<ToolResponse {...defaultProps} cardBody={cardBody} isCardBodyMarkdown />);
210
+ expect(container.querySelector('strong')).toBeTruthy();
211
+ expect(screen.getByText('Bold card body')).toBeTruthy();
212
+ });
213
+
214
+ it('should not render cardBody as markdown when isCardBodyMarkdown is false', () => {
215
+ const cardBody = '**Bold card body**';
216
+ render(<ToolResponse {...defaultProps} cardBody={cardBody} />);
217
+ expect(screen.getByText('**Bold card body**')).toBeTruthy();
218
+ });
219
+
220
+ it('should pass markdownContentProps to MarkdownContent component', () => {
221
+ const body = '**Bold body**';
222
+ const { container } = render(
223
+ <ToolResponse {...defaultProps} body={body} isBodyMarkdown markdownContentProps={{ isPrimary: true }} />
224
+ );
225
+ expect(container.querySelector('.pf-m-primary')).toBeTruthy();
226
+ });
152
227
  });
@@ -14,6 +14,8 @@ import {
14
14
  ExpandableSectionProps
15
15
  } from '@patternfly/react-core';
16
16
  import { useState, type FunctionComponent } from 'react';
17
+ import MarkdownContent from '../MarkdownContent';
18
+ import type { MarkdownContentProps } from '../MarkdownContent';
17
19
 
18
20
  export interface ToolResponseProps {
19
21
  /** Toggle content shown for expandable section */
@@ -42,6 +44,20 @@ export interface ToolResponseProps {
42
44
  toolResponseCardDividerProps?: DividerProps;
43
45
  /** Additional props passed to tool response card title */
44
46
  toolResponseCardTitleProps?: CardTitleProps;
47
+ /** Whether to enable markdown rendering for toggleContent. When true and toggleContent is a string, it will be parsed as markdown. */
48
+ isToggleContentMarkdown?: boolean;
49
+ /** Whether to enable markdown rendering for subheading. When true, subheading will be parsed as markdown. */
50
+ isSubheadingMarkdown?: boolean;
51
+ /** Whether to enable markdown rendering for body. When true and body is a string, it will be parsed as markdown. */
52
+ isBodyMarkdown?: boolean;
53
+ /** Whether to enable markdown rendering for cardBody. When true and cardBody is a string, it will be parsed as markdown. */
54
+ isCardBodyMarkdown?: boolean;
55
+ /** Whether to enable markdown rendering for cardTitle. When true and cardTitle is a string, it will be parsed as markdown. */
56
+ isCardTitleMarkdown?: boolean;
57
+ /** Props passed to MarkdownContent component when markdown is enabled */
58
+ markdownContentProps?: Omit<MarkdownContentProps, 'content'>;
59
+ /** Whether to retain styles in the MarkdownContent component. Defaults to false. */
60
+ shouldRetainStyles?: boolean;
45
61
  }
46
62
 
47
63
  export const ToolResponse: FunctionComponent<ToolResponseProps> = ({
@@ -57,7 +73,14 @@ export const ToolResponse: FunctionComponent<ToolResponseProps> = ({
57
73
  toolResponseCardBodyProps,
58
74
  toolResponseCardDividerProps,
59
75
  toolResponseCardProps,
60
- toolResponseCardTitleProps
76
+ toolResponseCardTitleProps,
77
+ isToggleContentMarkdown,
78
+ isSubheadingMarkdown,
79
+ isBodyMarkdown,
80
+ isCardBodyMarkdown,
81
+ isCardTitleMarkdown,
82
+ markdownContentProps,
83
+ shouldRetainStyles = false
61
84
  }: ToolResponseProps) => {
62
85
  const [isExpanded, setIsExpanded] = useState(isDefaultExpanded);
63
86
 
@@ -65,11 +88,60 @@ export const ToolResponse: FunctionComponent<ToolResponseProps> = ({
65
88
  setIsExpanded(isExpanded);
66
89
  };
67
90
 
91
+ const renderToggleContent = () => {
92
+ if (isToggleContentMarkdown && typeof toggleContent === 'string') {
93
+ return (
94
+ <MarkdownContent shouldRetainStyles={shouldRetainStyles} content={toggleContent} {...markdownContentProps} />
95
+ );
96
+ }
97
+ return toggleContent;
98
+ };
99
+
100
+ const renderSubheading = () => {
101
+ if (!subheading) {
102
+ return null;
103
+ }
104
+ if (isSubheadingMarkdown) {
105
+ return <MarkdownContent shouldRetainStyles={shouldRetainStyles} content={subheading} {...markdownContentProps} />;
106
+ }
107
+ return subheading;
108
+ };
109
+
110
+ const renderBody = () => {
111
+ if (!body) {
112
+ return null;
113
+ }
114
+ if (isBodyMarkdown && typeof body === 'string') {
115
+ return <MarkdownContent shouldRetainStyles={shouldRetainStyles} content={body} {...markdownContentProps} />;
116
+ }
117
+ return body;
118
+ };
119
+
120
+ const renderCardTitle = () => {
121
+ if (!cardTitle) {
122
+ return null;
123
+ }
124
+ if (isCardTitleMarkdown && typeof cardTitle === 'string') {
125
+ return <MarkdownContent shouldRetainStyles={shouldRetainStyles} content={cardTitle} {...markdownContentProps} />;
126
+ }
127
+ return cardTitle;
128
+ };
129
+
130
+ const renderCardBody = () => {
131
+ if (!cardBody) {
132
+ return null;
133
+ }
134
+ if (isCardBodyMarkdown && typeof cardBody === 'string') {
135
+ return <MarkdownContent shouldRetainStyles={shouldRetainStyles} content={cardBody} {...markdownContentProps} />;
136
+ }
137
+ return cardBody;
138
+ };
139
+
68
140
  return (
69
141
  <Card isCompact className="pf-chatbot__tool-response" {...cardProps}>
70
142
  <CardBody {...cardBodyProps}>
71
143
  <ExpandableSection
72
- toggleContent={toggleContent}
144
+ toggleContent={renderToggleContent()}
73
145
  onToggle={onToggle}
74
146
  isExpanded={isExpanded}
75
147
  isIndented
@@ -79,15 +151,15 @@ export const ToolResponse: FunctionComponent<ToolResponseProps> = ({
79
151
  <div className="pf-chatbot__tool-response-section">
80
152
  {subheading && (
81
153
  <div className="pf-chatbot__tool-response-subheading">
82
- <span>{subheading}</span>
154
+ <span>{renderSubheading()}</span>
83
155
  </div>
84
156
  )}
85
- {body && <div className="pf-chatbot__tool-response-body">{body}</div>}
157
+ {body && <div className="pf-chatbot__tool-response-body">{renderBody()}</div>}
86
158
  {(cardTitle || cardBody) && (
87
159
  <Card isCompact className="pf-chatbot__tool-response-card" {...toolResponseCardProps}>
88
- {cardTitle && <CardTitle {...toolResponseCardTitleProps}>{cardTitle}</CardTitle>}
160
+ {cardTitle && <CardTitle {...toolResponseCardTitleProps}>{renderCardTitle()}</CardTitle>}
89
161
  {cardTitle && cardBody && <Divider {...toolResponseCardDividerProps} />}
90
- {cardBody && <CardBody {...toolResponseCardBodyProps}>{cardBody}</CardBody>}
162
+ {cardBody && <CardBody {...toolResponseCardBodyProps}>{renderCardBody()}</CardBody>}
91
163
  </Card>
92
164
  )}
93
165
  </div>
package/src/index.ts CHANGED
@@ -63,6 +63,9 @@ export * from './ImagePreview';
63
63
  export { default as LoadingMessage } from './LoadingMessage';
64
64
  export * from './LoadingMessage';
65
65
 
66
+ export { default as MarkdownContent } from './MarkdownContent';
67
+ export * from './MarkdownContent';
68
+
66
69
  export { default as Message } from './Message';
67
70
  export * from './Message';
68
71
 
package/src/main.scss CHANGED
@@ -20,6 +20,7 @@
20
20
  @import './Message/Message';
21
21
  @import './Message/CodeBlockMessage/CodeBlockMessage';
22
22
  @import './Message/ImageMessage/ImageMessage';
23
+ @import './Message/LinkMessage/LinkMessage';
23
24
  @import './Message/TextMessage/TextMessage';
24
25
  @import './Message/ListMessage/ListMessage';
25
26
  @import './Message/TableMessage/TableMessage';