@patternfly/chatbot 6.5.0-prerelease.3 → 6.5.0-prerelease.30

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 (351) hide show
  1. package/dist/cjs/AttachMenu/AttachMenu.d.ts +8 -2
  2. package/dist/cjs/AttachMenu/AttachMenu.js +2 -2
  3. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +9 -1
  4. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +9 -2
  5. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +38 -0
  6. package/dist/cjs/ChatbotFooter/ChatbotFooter.d.ts +5 -2
  7. package/dist/cjs/ChatbotFooter/ChatbotFooter.js +2 -2
  8. package/dist/cjs/ChatbotFooter/ChatbotFooter.test.js +5 -1
  9. package/dist/cjs/ChatbotHeader/ChatbotHeaderMenu.js +29 -2
  10. package/dist/cjs/CodeModal/CodeModal.d.ts +2 -0
  11. package/dist/cjs/CodeModal/CodeModal.js +53 -8
  12. package/dist/cjs/DeepThinking/DeepThinking.d.ts +13 -0
  13. package/dist/cjs/DeepThinking/DeepThinking.js +31 -3
  14. package/dist/cjs/DeepThinking/DeepThinking.test.js +80 -0
  15. package/dist/cjs/FileDetailsLabel/FileDetailsLabel.d.ts +2 -1
  16. package/dist/cjs/MarkdownContent/MarkdownContent.d.ts +44 -0
  17. package/dist/cjs/MarkdownContent/MarkdownContent.js +181 -0
  18. package/dist/cjs/MarkdownContent/MarkdownContent.test.d.ts +1 -0
  19. package/dist/cjs/MarkdownContent/MarkdownContent.test.js +192 -0
  20. package/dist/cjs/MarkdownContent/index.d.ts +2 -0
  21. package/dist/cjs/MarkdownContent/index.js +23 -0
  22. package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.d.ts +5 -1
  23. package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.js +16 -5
  24. package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.test.d.ts +1 -0
  25. package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.test.js +131 -0
  26. package/dist/cjs/Message/ErrorMessage/ErrorMessage.d.ts +15 -1
  27. package/dist/cjs/Message/ErrorMessage/ErrorMessage.js +5 -3
  28. package/dist/cjs/Message/ErrorMessage/ErrorMessage.test.d.ts +1 -0
  29. package/dist/cjs/Message/ErrorMessage/ErrorMessage.test.js +30 -0
  30. package/dist/cjs/Message/LinkMessage/LinkMessage.d.ts +5 -1
  31. package/dist/cjs/Message/LinkMessage/LinkMessage.js +4 -3
  32. package/dist/cjs/Message/ListMessage/OrderedListMessage.d.ts +9 -1
  33. package/dist/cjs/Message/ListMessage/OrderedListMessage.js +2 -1
  34. package/dist/cjs/Message/ListMessage/UnorderedListMessage.d.ts +7 -1
  35. package/dist/cjs/Message/ListMessage/UnorderedListMessage.js +2 -1
  36. package/dist/cjs/Message/Message.d.ts +22 -3
  37. package/dist/cjs/Message/Message.js +8 -161
  38. package/dist/cjs/Message/Message.test.js +161 -2
  39. package/dist/cjs/Message/MessageAndActions/MessageAndActions.d.ts +14 -0
  40. package/dist/cjs/Message/MessageAndActions/MessageAndActions.js +22 -0
  41. package/dist/cjs/Message/MessageAndActions/MessageAndActions.test.d.ts +1 -0
  42. package/dist/cjs/Message/MessageAndActions/MessageAndActions.test.js +25 -0
  43. package/dist/cjs/Message/MessageAndActions/index.d.ts +1 -0
  44. package/dist/cjs/Message/MessageAndActions/index.js +17 -0
  45. package/dist/cjs/Message/MessageAttachments/MessageAttachmentItem.d.ts +13 -0
  46. package/dist/cjs/Message/MessageAttachments/MessageAttachmentItem.js +22 -0
  47. package/dist/cjs/Message/MessageAttachments/MessageAttachmentItem.test.d.ts +1 -0
  48. package/dist/cjs/Message/MessageAttachments/MessageAttachmentItem.test.js +25 -0
  49. package/dist/cjs/Message/MessageAttachments/MessageAttachmentsContainer.d.ts +13 -0
  50. package/dist/cjs/Message/MessageAttachments/MessageAttachmentsContainer.js +22 -0
  51. package/dist/cjs/Message/MessageAttachments/MessageAttachmentsContainer.test.d.ts +1 -0
  52. package/dist/cjs/Message/MessageAttachments/MessageAttachmentsContainer.test.js +25 -0
  53. package/dist/cjs/Message/MessageAttachments/index.d.ts +2 -0
  54. package/dist/cjs/Message/MessageAttachments/index.js +18 -0
  55. package/dist/cjs/Message/MessageInput.d.ts +1 -1
  56. package/dist/cjs/Message/MessageInput.js +3 -1
  57. package/dist/cjs/Message/MessageLoading.d.ts +13 -3
  58. package/dist/cjs/Message/MessageLoading.js +19 -5
  59. package/dist/cjs/Message/MessageLoading.test.d.ts +1 -0
  60. package/dist/cjs/Message/MessageLoading.test.js +25 -0
  61. package/dist/cjs/Message/QuickResponse/QuickResponse.js +3 -2
  62. package/dist/cjs/Message/QuickResponse/QuickResponse.test.d.ts +1 -0
  63. package/dist/cjs/Message/QuickResponse/QuickResponse.test.js +109 -0
  64. package/dist/cjs/Message/QuickResponse/index.d.ts +1 -0
  65. package/dist/cjs/Message/QuickResponse/index.js +17 -0
  66. package/dist/cjs/Message/QuickStarts/QuickStartTile.d.ts +1 -1
  67. package/dist/cjs/Message/QuickStarts/QuickStartTile.js +3 -2
  68. package/dist/cjs/Message/QuickStarts/index.d.ts +2 -0
  69. package/dist/cjs/Message/QuickStarts/index.js +18 -0
  70. package/dist/cjs/Message/TableMessage/TableMessage.d.ts +9 -1
  71. package/dist/cjs/Message/TableMessage/TableMessage.js +3 -2
  72. package/dist/cjs/Message/TextMessage/TextMessage.d.ts +11 -1
  73. package/dist/cjs/Message/TextMessage/TextMessage.js +3 -2
  74. package/dist/cjs/Message/UserFeedback/UserFeedback.d.ts +3 -1
  75. package/dist/cjs/Message/UserFeedback/UserFeedback.js +8 -6
  76. package/dist/cjs/Message/UserFeedback/UserFeedbackComplete.d.ts +1 -1
  77. package/dist/cjs/Message/UserFeedback/UserFeedbackComplete.js +3 -2
  78. package/dist/cjs/Message/UserFeedback/index.d.ts +2 -0
  79. package/dist/cjs/Message/UserFeedback/index.js +18 -0
  80. package/dist/cjs/Message/index.d.ts +8 -0
  81. package/dist/cjs/Message/index.js +8 -0
  82. package/dist/cjs/MessageBar/AttachButton.d.ts +2 -0
  83. package/dist/cjs/MessageBar/AttachButton.js +2 -2
  84. package/dist/cjs/MessageBar/AttachButton.test.js +4 -0
  85. package/dist/cjs/MessageBar/MessageBar.d.ts +22 -6
  86. package/dist/cjs/MessageBar/MessageBar.js +43 -11
  87. package/dist/cjs/MessageBar/MessageBar.test.js +74 -0
  88. package/dist/cjs/Onboarding/Onboarding.d.ts +36 -0
  89. package/dist/cjs/Onboarding/Onboarding.js +37 -0
  90. package/dist/cjs/Onboarding/Onboarding.test.d.ts +1 -0
  91. package/dist/cjs/Onboarding/Onboarding.test.js +80 -0
  92. package/dist/cjs/Onboarding/index.d.ts +2 -0
  93. package/dist/cjs/Onboarding/index.js +23 -0
  94. package/dist/cjs/ResponseActions/ResponseActions.d.ts +7 -0
  95. package/dist/cjs/ResponseActions/ResponseActions.js +28 -7
  96. package/dist/cjs/ResponseActions/ResponseActions.test.js +67 -12
  97. package/dist/cjs/ResponseActions/ResponseActionsGroups.d.ts +13 -0
  98. package/dist/cjs/ResponseActions/ResponseActionsGroups.js +22 -0
  99. package/dist/cjs/ResponseActions/ResponseActionsGroups.test.d.ts +1 -0
  100. package/dist/cjs/ResponseActions/ResponseActionsGroups.test.js +25 -0
  101. package/dist/cjs/ResponseActions/index.d.ts +1 -0
  102. package/dist/cjs/ResponseActions/index.js +1 -0
  103. package/dist/cjs/ToolCall/ToolCall.d.ts +11 -0
  104. package/dist/cjs/ToolCall/ToolCall.js +24 -3
  105. package/dist/cjs/ToolCall/ToolCall.test.js +57 -0
  106. package/dist/cjs/ToolResponse/ToolResponse.d.ts +17 -0
  107. package/dist/cjs/ToolResponse/ToolResponse.js +49 -3
  108. package/dist/cjs/ToolResponse/ToolResponse.test.js +100 -0
  109. package/dist/cjs/__mocks__/monaco-editor.d.ts +11 -0
  110. package/dist/cjs/__mocks__/monaco-editor.js +18 -0
  111. package/dist/cjs/index.d.ts +4 -0
  112. package/dist/cjs/index.js +7 -1
  113. package/dist/css/main.css +336 -30
  114. package/dist/css/main.css.map +1 -1
  115. package/dist/dynamic/MarkdownContent/package.json +1 -0
  116. package/dist/dynamic/Onboarding/package.json +1 -0
  117. package/dist/esm/AttachMenu/AttachMenu.d.ts +8 -2
  118. package/dist/esm/AttachMenu/AttachMenu.js +2 -2
  119. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +9 -1
  120. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +10 -3
  121. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +38 -0
  122. package/dist/esm/ChatbotFooter/ChatbotFooter.d.ts +5 -2
  123. package/dist/esm/ChatbotFooter/ChatbotFooter.js +2 -2
  124. package/dist/esm/ChatbotFooter/ChatbotFooter.test.js +5 -1
  125. package/dist/esm/ChatbotHeader/ChatbotHeaderMenu.js +30 -3
  126. package/dist/esm/CodeModal/CodeModal.d.ts +2 -0
  127. package/dist/esm/CodeModal/CodeModal.js +54 -9
  128. package/dist/esm/DeepThinking/DeepThinking.d.ts +13 -0
  129. package/dist/esm/DeepThinking/DeepThinking.js +28 -3
  130. package/dist/esm/DeepThinking/DeepThinking.test.js +80 -0
  131. package/dist/esm/FileDetailsLabel/FileDetailsLabel.d.ts +2 -1
  132. package/dist/esm/MarkdownContent/MarkdownContent.d.ts +44 -0
  133. package/dist/esm/MarkdownContent/MarkdownContent.js +174 -0
  134. package/dist/esm/MarkdownContent/MarkdownContent.test.d.ts +1 -0
  135. package/dist/esm/MarkdownContent/MarkdownContent.test.js +187 -0
  136. package/dist/esm/MarkdownContent/index.d.ts +2 -0
  137. package/dist/esm/MarkdownContent/index.js +2 -0
  138. package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.d.ts +5 -1
  139. package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.js +16 -5
  140. package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.test.d.ts +1 -0
  141. package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.test.js +126 -0
  142. package/dist/esm/Message/ErrorMessage/ErrorMessage.d.ts +15 -1
  143. package/dist/esm/Message/ErrorMessage/ErrorMessage.js +3 -3
  144. package/dist/esm/Message/ErrorMessage/ErrorMessage.test.d.ts +1 -0
  145. package/dist/esm/Message/ErrorMessage/ErrorMessage.test.js +25 -0
  146. package/dist/esm/Message/LinkMessage/LinkMessage.d.ts +5 -1
  147. package/dist/esm/Message/LinkMessage/LinkMessage.js +4 -3
  148. package/dist/esm/Message/ListMessage/OrderedListMessage.d.ts +9 -1
  149. package/dist/esm/Message/ListMessage/OrderedListMessage.js +2 -1
  150. package/dist/esm/Message/ListMessage/UnorderedListMessage.d.ts +7 -1
  151. package/dist/esm/Message/ListMessage/UnorderedListMessage.js +2 -1
  152. package/dist/esm/Message/Message.d.ts +22 -3
  153. package/dist/esm/Message/Message.js +9 -162
  154. package/dist/esm/Message/Message.test.js +161 -2
  155. package/dist/esm/Message/MessageAndActions/MessageAndActions.d.ts +14 -0
  156. package/dist/esm/Message/MessageAndActions/MessageAndActions.js +18 -0
  157. package/dist/esm/Message/MessageAndActions/MessageAndActions.test.d.ts +1 -0
  158. package/dist/esm/Message/MessageAndActions/MessageAndActions.test.js +20 -0
  159. package/dist/esm/Message/MessageAndActions/index.d.ts +1 -0
  160. package/dist/esm/Message/MessageAndActions/index.js +1 -0
  161. package/dist/esm/Message/MessageAttachments/MessageAttachmentItem.d.ts +13 -0
  162. package/dist/esm/Message/MessageAttachments/MessageAttachmentItem.js +18 -0
  163. package/dist/esm/Message/MessageAttachments/MessageAttachmentItem.test.d.ts +1 -0
  164. package/dist/esm/Message/MessageAttachments/MessageAttachmentItem.test.js +20 -0
  165. package/dist/esm/Message/MessageAttachments/MessageAttachmentsContainer.d.ts +13 -0
  166. package/dist/esm/Message/MessageAttachments/MessageAttachmentsContainer.js +18 -0
  167. package/dist/esm/Message/MessageAttachments/MessageAttachmentsContainer.test.d.ts +1 -0
  168. package/dist/esm/Message/MessageAttachments/MessageAttachmentsContainer.test.js +20 -0
  169. package/dist/esm/Message/MessageAttachments/index.d.ts +2 -0
  170. package/dist/esm/Message/MessageAttachments/index.js +2 -0
  171. package/dist/esm/Message/MessageInput.d.ts +1 -1
  172. package/dist/esm/Message/MessageInput.js +1 -1
  173. package/dist/esm/Message/MessageLoading.d.ts +13 -3
  174. package/dist/esm/Message/MessageLoading.js +16 -4
  175. package/dist/esm/Message/MessageLoading.test.d.ts +1 -0
  176. package/dist/esm/Message/MessageLoading.test.js +20 -0
  177. package/dist/esm/Message/QuickResponse/QuickResponse.js +3 -2
  178. package/dist/esm/Message/QuickResponse/QuickResponse.test.d.ts +1 -0
  179. package/dist/esm/Message/QuickResponse/QuickResponse.test.js +104 -0
  180. package/dist/esm/Message/QuickResponse/index.d.ts +1 -0
  181. package/dist/esm/Message/QuickResponse/index.js +1 -0
  182. package/dist/esm/Message/QuickStarts/QuickStartTile.d.ts +1 -1
  183. package/dist/esm/Message/QuickStarts/QuickStartTile.js +1 -1
  184. package/dist/esm/Message/QuickStarts/index.d.ts +2 -0
  185. package/dist/esm/Message/QuickStarts/index.js +2 -0
  186. package/dist/esm/Message/TableMessage/TableMessage.d.ts +9 -1
  187. package/dist/esm/Message/TableMessage/TableMessage.js +3 -2
  188. package/dist/esm/Message/TextMessage/TextMessage.d.ts +11 -1
  189. package/dist/esm/Message/TextMessage/TextMessage.js +3 -2
  190. package/dist/esm/Message/UserFeedback/UserFeedback.d.ts +3 -1
  191. package/dist/esm/Message/UserFeedback/UserFeedback.js +7 -7
  192. package/dist/esm/Message/UserFeedback/UserFeedbackComplete.d.ts +1 -1
  193. package/dist/esm/Message/UserFeedback/UserFeedbackComplete.js +1 -2
  194. package/dist/esm/Message/UserFeedback/index.d.ts +2 -0
  195. package/dist/esm/Message/UserFeedback/index.js +2 -0
  196. package/dist/esm/Message/index.d.ts +8 -0
  197. package/dist/esm/Message/index.js +8 -0
  198. package/dist/esm/MessageBar/AttachButton.d.ts +2 -0
  199. package/dist/esm/MessageBar/AttachButton.js +2 -2
  200. package/dist/esm/MessageBar/AttachButton.test.js +4 -0
  201. package/dist/esm/MessageBar/MessageBar.d.ts +22 -6
  202. package/dist/esm/MessageBar/MessageBar.js +43 -11
  203. package/dist/esm/MessageBar/MessageBar.test.js +74 -0
  204. package/dist/esm/Onboarding/Onboarding.d.ts +36 -0
  205. package/dist/esm/Onboarding/Onboarding.js +30 -0
  206. package/dist/esm/Onboarding/Onboarding.test.d.ts +1 -0
  207. package/dist/esm/Onboarding/Onboarding.test.js +75 -0
  208. package/dist/esm/Onboarding/index.d.ts +2 -0
  209. package/dist/esm/Onboarding/index.js +2 -0
  210. package/dist/esm/ResponseActions/ResponseActions.d.ts +7 -0
  211. package/dist/esm/ResponseActions/ResponseActions.js +28 -7
  212. package/dist/esm/ResponseActions/ResponseActions.test.js +67 -12
  213. package/dist/esm/ResponseActions/ResponseActionsGroups.d.ts +13 -0
  214. package/dist/esm/ResponseActions/ResponseActionsGroups.js +18 -0
  215. package/dist/esm/ResponseActions/ResponseActionsGroups.test.d.ts +1 -0
  216. package/dist/esm/ResponseActions/ResponseActionsGroups.test.js +20 -0
  217. package/dist/esm/ResponseActions/index.d.ts +1 -0
  218. package/dist/esm/ResponseActions/index.js +1 -0
  219. package/dist/esm/ToolCall/ToolCall.d.ts +11 -0
  220. package/dist/esm/ToolCall/ToolCall.js +21 -3
  221. package/dist/esm/ToolCall/ToolCall.test.js +57 -0
  222. package/dist/esm/ToolResponse/ToolResponse.d.ts +17 -0
  223. package/dist/esm/ToolResponse/ToolResponse.js +46 -3
  224. package/dist/esm/ToolResponse/ToolResponse.test.js +100 -0
  225. package/dist/esm/__mocks__/monaco-editor.d.ts +11 -0
  226. package/dist/esm/__mocks__/monaco-editor.js +18 -0
  227. package/dist/esm/index.d.ts +4 -0
  228. package/dist/esm/index.js +4 -0
  229. package/dist/tsconfig.tsbuildinfo +1 -1
  230. package/package.json +13 -2
  231. package/patternfly-docs/content/extensions/chatbot/chatbot.md +57 -0
  232. package/patternfly-docs/content/extensions/chatbot/design-guidelines.md +12 -12
  233. package/patternfly-docs/content/extensions/chatbot/examples/Analytics/Analytics.md +1 -1
  234. package/patternfly-docs/content/extensions/chatbot/examples/Customizing Messages/Customizing Messages.md +1 -1
  235. package/patternfly-docs/content/extensions/chatbot/examples/Messages/BotMessage.tsx +1 -0
  236. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithCustomStructure.tsx +102 -0
  237. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithDeepThinking.tsx +25 -11
  238. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithFeedback.tsx +14 -1
  239. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithMarkdownDeepThinking.tsx +26 -0
  240. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithMarkdownToolCall.tsx +29 -0
  241. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithMarkdownToolResponse.tsx +200 -0
  242. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithMultipleActionGroups.tsx +61 -0
  243. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithPersistedActions.tsx +22 -0
  244. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithQuickResponses.tsx +11 -0
  245. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithToolCall.tsx +14 -1
  246. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithToolResponse.tsx +222 -105
  247. package/patternfly-docs/content/extensions/chatbot/examples/Messages/Messages.md +123 -14
  248. package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessage.tsx +1 -0
  249. package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessageWithExtraContent.tsx +3 -1
  250. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawerWithSearchActions.tsx +198 -0
  251. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotMessageBarCustomActions.tsx +190 -0
  252. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotMessageBarIndicatorThinking.tsx +15 -0
  253. package/patternfly-docs/content/extensions/chatbot/examples/UI/CompactOnboarding.tsx +141 -0
  254. package/patternfly-docs/content/extensions/chatbot/examples/UI/Onboarding.tsx +151 -0
  255. package/patternfly-docs/content/extensions/chatbot/examples/UI/RH-Hat-Image.svg +9 -0
  256. package/patternfly-docs/content/extensions/chatbot/examples/UI/Settings.tsx +1 -1
  257. package/patternfly-docs/content/extensions/chatbot/examples/UI/UI.md +81 -30
  258. package/patternfly-docs/content/extensions/chatbot/examples/demos/AttachmentDemos.md +18 -18
  259. package/patternfly-docs/content/extensions/chatbot/examples/demos/Chatbot.md +44 -22
  260. package/patternfly-docs/content/extensions/chatbot/examples/demos/WhiteEmbeddedChatbot.tsx +451 -0
  261. package/patternfly-docs/patternfly-docs.config.js +1 -1
  262. package/patternfly-docs/patternfly-docs.source.js +1 -1
  263. package/src/AttachMenu/AttachMenu.tsx +26 -11
  264. package/src/Chatbot/Chatbot.scss +23 -1
  265. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.scss +43 -0
  266. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.tsx +95 -0
  267. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.tsx +51 -15
  268. package/src/ChatbotFooter/ChatbotFooter.scss +21 -0
  269. package/src/ChatbotFooter/ChatbotFooter.test.tsx +10 -1
  270. package/src/ChatbotFooter/ChatbotFooter.tsx +10 -3
  271. package/src/ChatbotHeader/ChatbotHeader.scss +19 -0
  272. package/src/ChatbotHeader/ChatbotHeaderMenu.tsx +56 -14
  273. package/src/ChatbotModal/ChatbotModal.scss +3 -0
  274. package/src/CodeModal/CodeModal.tsx +72 -23
  275. package/src/DeepThinking/DeepThinking.scss +1 -1
  276. package/src/DeepThinking/DeepThinking.test.tsx +109 -0
  277. package/src/DeepThinking/DeepThinking.tsx +54 -5
  278. package/src/FileDetailsLabel/FileDetailsLabel.tsx +2 -2
  279. package/src/MarkdownContent/MarkdownContent.test.tsx +207 -0
  280. package/src/MarkdownContent/MarkdownContent.tsx +269 -0
  281. package/src/MarkdownContent/index.ts +2 -0
  282. package/src/Message/CodeBlockMessage/CodeBlockMessage.scss +17 -0
  283. package/src/Message/CodeBlockMessage/CodeBlockMessage.test.tsx +171 -0
  284. package/src/Message/CodeBlockMessage/CodeBlockMessage.tsx +21 -5
  285. package/src/Message/ErrorMessage/ErrorMessage.test.tsx +38 -0
  286. package/src/Message/ErrorMessage/ErrorMessage.tsx +17 -2
  287. package/src/Message/LinkMessage/LinkMessage.scss +5 -0
  288. package/src/Message/LinkMessage/LinkMessage.tsx +24 -2
  289. package/src/Message/ListMessage/ListMessage.scss +8 -0
  290. package/src/Message/ListMessage/OrderedListMessage.tsx +16 -2
  291. package/src/Message/ListMessage/UnorderedListMessage.tsx +12 -2
  292. package/src/Message/Message.scss +11 -7
  293. package/src/Message/Message.test.tsx +239 -2
  294. package/src/Message/Message.tsx +133 -241
  295. package/src/Message/MessageAndActions/MessageAndActions.test.tsx +23 -0
  296. package/src/Message/MessageAndActions/MessageAndActions.tsx +22 -0
  297. package/src/Message/MessageAndActions/index.ts +1 -0
  298. package/src/Message/MessageAttachments/MessageAttachmentItem.test.tsx +23 -0
  299. package/src/Message/MessageAttachments/MessageAttachmentItem.tsx +25 -0
  300. package/src/Message/MessageAttachments/MessageAttachmentsContainer.test.tsx +23 -0
  301. package/src/Message/MessageAttachments/MessageAttachmentsContainer.tsx +25 -0
  302. package/src/Message/MessageAttachments/index.ts +2 -0
  303. package/src/Message/MessageInput.tsx +1 -1
  304. package/src/Message/MessageLoading.scss +7 -0
  305. package/src/Message/MessageLoading.test.tsx +23 -0
  306. package/src/Message/MessageLoading.tsx +17 -2
  307. package/src/Message/QuickResponse/QuickResponse.scss +3 -1
  308. package/src/Message/QuickResponse/QuickResponse.test.tsx +131 -0
  309. package/src/Message/QuickResponse/QuickResponse.tsx +3 -2
  310. package/src/Message/QuickResponse/index.ts +1 -0
  311. package/src/Message/QuickStarts/QuickStartTile.tsx +1 -1
  312. package/src/Message/QuickStarts/index.ts +2 -0
  313. package/src/Message/TableMessage/TableMessage.scss +17 -1
  314. package/src/Message/TableMessage/TableMessage.tsx +22 -2
  315. package/src/Message/TextMessage/TextMessage.scss +18 -0
  316. package/src/Message/TextMessage/TextMessage.tsx +39 -3
  317. package/src/Message/UserFeedback/UserFeedback.scss +30 -2
  318. package/src/Message/UserFeedback/UserFeedback.tsx +23 -13
  319. package/src/Message/UserFeedback/UserFeedbackComplete.tsx +1 -4
  320. package/src/Message/UserFeedback/index.ts +2 -0
  321. package/src/Message/index.ts +8 -0
  322. package/src/MessageBar/AttachButton.scss +0 -1
  323. package/src/MessageBar/AttachButton.test.tsx +4 -0
  324. package/src/MessageBar/AttachButton.tsx +4 -1
  325. package/src/MessageBar/MessageBar.scss +66 -6
  326. package/src/MessageBar/MessageBar.test.tsx +129 -1
  327. package/src/MessageBar/MessageBar.tsx +150 -56
  328. package/src/MessageBar/MicrophoneButton.scss +0 -1
  329. package/src/MessageBar/SendButton.scss +0 -1
  330. package/src/MessageBar/StopButton.scss +0 -1
  331. package/src/Onboarding/Onboarding.scss +101 -0
  332. package/src/Onboarding/Onboarding.test.tsx +148 -0
  333. package/src/Onboarding/Onboarding.tsx +126 -0
  334. package/src/Onboarding/index.ts +3 -0
  335. package/src/ResponseActions/ResponseActions.scss +12 -1
  336. package/src/ResponseActions/ResponseActions.test.tsx +111 -12
  337. package/src/ResponseActions/ResponseActions.tsx +44 -10
  338. package/src/ResponseActions/ResponseActionsGroups.test.tsx +23 -0
  339. package/src/ResponseActions/ResponseActionsGroups.tsx +28 -0
  340. package/src/ResponseActions/index.ts +1 -0
  341. package/src/ToolCall/ToolCall.scss +1 -1
  342. package/src/ToolCall/ToolCall.test.tsx +91 -0
  343. package/src/ToolCall/ToolCall.tsx +49 -4
  344. package/src/ToolResponse/ToolResponse.scss +13 -3
  345. package/src/ToolResponse/ToolResponse.test.tsx +119 -0
  346. package/src/ToolResponse/ToolResponse.tsx +82 -7
  347. package/src/__mocks__/monaco-editor.ts +19 -0
  348. package/src/index.ts +6 -0
  349. package/src/main.scss +2 -0
  350. package/tsconfig.json +1 -1
  351. package/patternfly-docs/content/extensions/chatbot/about-chatbot.md +0 -44
@@ -0,0 +1,269 @@
1
+ // ============================================================================
2
+ // Markdown Content - Shared component for rendering markdown
3
+ // ============================================================================
4
+ import { type FunctionComponent, ReactNode } from 'react';
5
+ import Markdown, { Options } from 'react-markdown';
6
+ import remarkGfm from 'remark-gfm';
7
+ import { ContentVariants } from '@patternfly/react-core';
8
+ import CodeBlockMessage, { CodeBlockMessageProps } from '../Message/CodeBlockMessage/CodeBlockMessage';
9
+ import TextMessage from '../Message/TextMessage/TextMessage';
10
+ import ListItemMessage from '../Message/ListMessage/ListItemMessage';
11
+ import UnorderedListMessage from '../Message/ListMessage/UnorderedListMessage';
12
+ import OrderedListMessage from '../Message/ListMessage/OrderedListMessage';
13
+ import TableMessage from '../Message/TableMessage/TableMessage';
14
+ import TrMessage from '../Message/TableMessage/TrMessage';
15
+ import TdMessage from '../Message/TableMessage/TdMessage';
16
+ import TbodyMessage from '../Message/TableMessage/TbodyMessage';
17
+ import TheadMessage from '../Message/TableMessage/TheadMessage';
18
+ import ThMessage from '../Message/TableMessage/ThMessage';
19
+ import { TableProps } from '@patternfly/react-table';
20
+ import ImageMessage from '../Message/ImageMessage/ImageMessage';
21
+ import rehypeUnwrapImages from 'rehype-unwrap-images';
22
+ import rehypeExternalLinks from 'rehype-external-links';
23
+ import rehypeSanitize from 'rehype-sanitize';
24
+ import rehypeHighlight from 'rehype-highlight';
25
+ import 'highlight.js/styles/vs2015.css';
26
+ import { PluggableList } from 'unified';
27
+ import LinkMessage from '../Message/LinkMessage/LinkMessage';
28
+ import { rehypeMoveImagesOutOfParagraphs } from '../Message/Plugins/rehypeMoveImagesOutOfParagraphs';
29
+ import SuperscriptMessage from '../Message/SuperscriptMessage/SuperscriptMessage';
30
+ import { ButtonProps } from '@patternfly/react-core';
31
+ import { css } from '@patternfly/react-styles';
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
+ */
38
+ export interface MarkdownContentProps {
39
+ /** The content to render. Supports markdown formatting by default, or plain text when isMarkdownDisabled is true. */
40
+ content?: string;
41
+ /** Disables markdown parsing, allowing only plain text input */
42
+ isMarkdownDisabled?: boolean;
43
+ /** Props for code blocks */
44
+ codeBlockProps?: CodeBlockMessageProps;
45
+ /** Props for table message. It is important to include a detailed aria-label that describes the purpose of the table. */
46
+ tableProps?: Required<Pick<TableProps, 'aria-label'>> & TableProps;
47
+ /** Additional rehype plugins passed from the consumer */
48
+ additionalRehypePlugins?: PluggableList;
49
+ /** Additional remark plugins passed from the consumer */
50
+ additionalRemarkPlugins?: PluggableList;
51
+ /** Whether to open links in message in new tab. */
52
+ openLinkInNewTab?: boolean;
53
+ /** Props for links */
54
+ linkProps?: ButtonProps;
55
+ /** Allows passing additional props down to markdown parser react-markdown, such as allowedElements and disallowedElements. See https://github.com/remarkjs/react-markdown?tab=readme-ov-file#options for options */
56
+ reactMarkdownProps?: Options;
57
+ /** Allows passing additional props down to remark-gfm. See https://github.com/remarkjs/remark-gfm?tab=readme-ov-file#options for options */
58
+ remarkGfmProps?: Options;
59
+ /** Whether to strip out images in markdown */
60
+ hasNoImages?: boolean;
61
+ /** Sets background colors to be appropriate on primary chatbot background */
62
+ isPrimary?: boolean;
63
+ /** Custom component to render when markdown is disabled */
64
+ textComponent?: ReactNode;
65
+ /** Flag indicating whether content should retain various styles of its context (typically font-size and text color). */
66
+ shouldRetainStyles?: boolean;
67
+ }
68
+
69
+ export const MarkdownContent: FunctionComponent<MarkdownContentProps> = ({
70
+ content,
71
+ isMarkdownDisabled,
72
+ codeBlockProps,
73
+ tableProps,
74
+ openLinkInNewTab = true,
75
+ additionalRehypePlugins = [],
76
+ additionalRemarkPlugins = [],
77
+ linkProps,
78
+ reactMarkdownProps,
79
+ remarkGfmProps,
80
+ hasNoImages = false,
81
+ isPrimary,
82
+ textComponent,
83
+ shouldRetainStyles
84
+ }: MarkdownContentProps) => {
85
+ let rehypePlugins: PluggableList = [rehypeUnwrapImages, rehypeMoveImagesOutOfParagraphs, rehypeHighlight];
86
+ if (openLinkInNewTab) {
87
+ rehypePlugins = rehypePlugins.concat([[rehypeExternalLinks, { target: '_blank' }, rehypeSanitize]]);
88
+ }
89
+ if (additionalRehypePlugins) {
90
+ rehypePlugins.push(...additionalRehypePlugins);
91
+ }
92
+
93
+ const disallowedElements = hasNoImages ? ['img'] : [];
94
+ if (reactMarkdownProps && reactMarkdownProps.disallowedElements) {
95
+ disallowedElements.push(...reactMarkdownProps.disallowedElements);
96
+ }
97
+
98
+ if (isMarkdownDisabled) {
99
+ if (textComponent) {
100
+ return <>{textComponent}</>;
101
+ }
102
+ return (
103
+ <TextMessage component={ContentVariants.p} isPrimary={isPrimary}>
104
+ {content}
105
+ </TextMessage>
106
+ );
107
+ }
108
+
109
+ return (
110
+ <Markdown
111
+ components={{
112
+ section: (props) => {
113
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
114
+ const { node, ...rest } = props;
115
+ return (
116
+ <section
117
+ {...rest}
118
+ className={css('pf-chatbot__message-text', shouldRetainStyles && 'pf-m-markdown', rest?.className)}
119
+ />
120
+ );
121
+ },
122
+ p: (props) => {
123
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
124
+ const { node, ...rest } = props;
125
+ return (
126
+ <TextMessage
127
+ shouldRetainStyles={shouldRetainStyles}
128
+ component={ContentVariants.p}
129
+ {...rest}
130
+ isPrimary={isPrimary}
131
+ />
132
+ );
133
+ },
134
+ code: ({ children, ...props }) => {
135
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
136
+ const { node, ...codeProps } = props;
137
+ return (
138
+ <CodeBlockMessage
139
+ {...codeProps}
140
+ {...codeBlockProps}
141
+ isPrimary={isPrimary}
142
+ shouldRetainStyles={shouldRetainStyles}
143
+ >
144
+ {children}
145
+ </CodeBlockMessage>
146
+ );
147
+ },
148
+ h1: (props) => {
149
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
150
+ const { node, ...rest } = props;
151
+ return <TextMessage shouldRetainStyles={shouldRetainStyles} component={ContentVariants.h1} {...rest} />;
152
+ },
153
+ h2: (props) => {
154
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
155
+ const { node, ...rest } = props;
156
+ return <TextMessage shouldRetainStyles={shouldRetainStyles} component={ContentVariants.h2} {...rest} />;
157
+ },
158
+ h3: (props) => {
159
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
160
+ const { node, ...rest } = props;
161
+ return <TextMessage shouldRetainStyles={shouldRetainStyles} component={ContentVariants.h3} {...rest} />;
162
+ },
163
+ h4: (props) => {
164
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
165
+ const { node, ...rest } = props;
166
+ return <TextMessage shouldRetainStyles={shouldRetainStyles} component={ContentVariants.h4} {...rest} />;
167
+ },
168
+ h5: (props) => {
169
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
170
+ const { node, ...rest } = props;
171
+ return <TextMessage shouldRetainStyles={shouldRetainStyles} component={ContentVariants.h5} {...rest} />;
172
+ },
173
+ h6: (props) => {
174
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
175
+ const { node, ...rest } = props;
176
+ return <TextMessage shouldRetainStyles={shouldRetainStyles} component={ContentVariants.h6} {...rest} />;
177
+ },
178
+ blockquote: (props) => {
179
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
180
+ const { node, ...rest } = props;
181
+ return (
182
+ <TextMessage shouldRetainStyles={shouldRetainStyles} component={ContentVariants.blockquote} {...rest} />
183
+ );
184
+ },
185
+ ul: (props) => {
186
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
187
+ const { node, ...rest } = props;
188
+ return <UnorderedListMessage shouldRetainStyles={shouldRetainStyles} {...rest} />;
189
+ },
190
+ ol: (props) => {
191
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
192
+ const { node, ...rest } = props;
193
+ return <OrderedListMessage shouldRetainStyles={shouldRetainStyles} {...rest} />;
194
+ },
195
+ li: (props) => {
196
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
197
+ const { node, ...rest } = props;
198
+ return <ListItemMessage {...rest} />;
199
+ },
200
+ // table requires node attribute for calculating headers for mobile breakpoint
201
+ table: (props) => (
202
+ <TableMessage shouldRetainStyles={shouldRetainStyles} {...props} {...tableProps} isPrimary={isPrimary} />
203
+ ),
204
+ tbody: (props) => {
205
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
206
+ const { node, ...rest } = props;
207
+ return <TbodyMessage {...rest} />;
208
+ },
209
+ thead: (props) => {
210
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
211
+ const { node, ...rest } = props;
212
+ return <TheadMessage {...rest} />;
213
+ },
214
+ tr: (props) => {
215
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
216
+ const { node, ...rest } = props;
217
+ return <TrMessage {...rest} />;
218
+ },
219
+ td: (props) => {
220
+ // Conflicts with Td type
221
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
222
+ const { node, width, ...rest } = props;
223
+ return <TdMessage {...rest} />;
224
+ },
225
+ th: (props) => {
226
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
227
+ const { node, ...rest } = props;
228
+ return <ThMessage {...rest} />;
229
+ },
230
+ img: (props) => {
231
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
232
+ const { node, ...rest } = props;
233
+ return <ImageMessage {...rest} />;
234
+ },
235
+ a: (props) => {
236
+ // node is just the details of the document structure - not needed
237
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
238
+ const { node, ...rest } = props;
239
+ return (
240
+ // some a types conflict with ButtonProps, but it's ok because we are using an a tag
241
+ // there are too many to handle manually
242
+ <LinkMessage shouldRetainStyles={shouldRetainStyles} {...(rest as any)} {...linkProps}>
243
+ {props.children}
244
+ </LinkMessage>
245
+ );
246
+ },
247
+ // used for footnotes
248
+ sup: (props) => {
249
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
250
+ const { node, ...rest } = props;
251
+ return <SuperscriptMessage {...rest} />;
252
+ }
253
+ }}
254
+ remarkPlugins={[[remarkGfm, { ...remarkGfmProps }], ...additionalRemarkPlugins]}
255
+ rehypePlugins={rehypePlugins}
256
+ {...reactMarkdownProps}
257
+ remarkRehypeOptions={{
258
+ // removes sr-only class from footnote labels applied by default
259
+ footnoteLabelProperties: { className: [''] },
260
+ ...reactMarkdownProps?.remarkRehypeOptions
261
+ }}
262
+ disallowedElements={disallowedElements}
263
+ >
264
+ {content}
265
+ </Markdown>
266
+ );
267
+ };
268
+
269
+ export default MarkdownContent;
@@ -0,0 +1,2 @@
1
+ export { default } from './MarkdownContent';
2
+ export * from './MarkdownContent';
@@ -75,12 +75,29 @@
75
75
  overflow: hidden !important;
76
76
  }
77
77
  }
78
+
79
+ &.pf-m-markdown .pf-v6-c-code-block__code {
80
+ font-size: inherit;
81
+ }
78
82
  }
79
83
 
80
84
  .pf-chatbot__message-inline-code {
81
85
  --pf-chatbot-message-text-inline-code-font-size: var(--pf-t--global--font--size--body--default);
86
+
82
87
  background-color: var(--pf-t--global--background--color--tertiary--default);
83
88
  font-size: var(--pf-chatbot-message-text-inline-code-font-size);
89
+ border: var(--pf-t--global--border--width--high-contrast--regular) solid
90
+ var(--pf-t--global--border--color--high-contrast);
91
+ border-radius: var(--pf-t--global--border--radius--small);
92
+ padding-block-start: var(--pf-t--global--spacer--xs);
93
+ padding-block-end: var(--pf-t--global--spacer--xs);
94
+ padding-inline-start: var(--pf-t--global--spacer--xs);
95
+ padding-inline-end: var(--pf-t--global--spacer--xs);
96
+ word-break: break-word;
97
+
98
+ &.pf-m-primary {
99
+ background-color: var(--pf-t--global--background--color--secondary--default);
100
+ }
84
101
  }
85
102
 
86
103
  .pf-chatbot__message-code-toggle {
@@ -0,0 +1,171 @@
1
+ import '@testing-library/jest-dom';
2
+ import { render, screen } from '@testing-library/react';
3
+ import userEvent from '@testing-library/user-event';
4
+ import CodeBlockMessage from './CodeBlockMessage';
5
+
6
+ // Mock clipboard API
7
+ Object.assign(navigator, {
8
+ clipboard: {
9
+ writeText: jest.fn()
10
+ }
11
+ });
12
+
13
+ describe('CodeBlockMessage', () => {
14
+ beforeEach(() => {
15
+ jest.clearAllMocks();
16
+ });
17
+
18
+ it('should render inline code for single-line content', () => {
19
+ render(<CodeBlockMessage className="language-javascript">const x = 5;</CodeBlockMessage>);
20
+ const code = screen.getByText('const x = 5;');
21
+ expect(code.tagName).toBe('CODE');
22
+ expect(code).toHaveClass('pf-chatbot__message-inline-code');
23
+ });
24
+
25
+ it('should render code block for multi-line content', () => {
26
+ const multilineCode = 'const x = 5;\nconst y = 10;';
27
+ const { container } = render(<CodeBlockMessage className="language-javascript">{multilineCode}</CodeBlockMessage>);
28
+ const codeElement = container.querySelector('code');
29
+ expect(codeElement?.textContent).toBe(multilineCode);
30
+ });
31
+
32
+ it('should display language label', () => {
33
+ const code = 'const x = 5;\nconst y = 10;';
34
+ render(<CodeBlockMessage className="language-javascript">{code}</CodeBlockMessage>);
35
+ expect(screen.getByText('javascript')).toBeInTheDocument();
36
+ });
37
+
38
+ it('should render copy button', () => {
39
+ const code = 'const x = 5;\nconst y = 10;';
40
+ render(<CodeBlockMessage>{code}</CodeBlockMessage>);
41
+ expect(screen.getByRole('button', { name: 'Copy code' })).toBeInTheDocument();
42
+ });
43
+
44
+ it('should copy plain string content to clipboard', async () => {
45
+ const code = 'const x = 5;\nconst y = 10;';
46
+ render(<CodeBlockMessage>{code}</CodeBlockMessage>);
47
+
48
+ const copyButton = screen.getByRole('button', { name: 'Copy code' });
49
+ await userEvent.click(copyButton);
50
+
51
+ expect(navigator.clipboard.writeText).toHaveBeenCalledWith(code);
52
+ });
53
+
54
+ it('should extract text content from React elements when copying', async () => {
55
+ // Simulate what happens with syntax highlighting - children become React elements
56
+ const { container } = render(
57
+ <CodeBlockMessage className="language-javascript">
58
+ <span className="hljs-keyword">const</span> x = 5;{'\n'}
59
+ <span className="hljs-keyword">const</span> y = 10;
60
+ </CodeBlockMessage>
61
+ );
62
+
63
+ const copyButton = screen.getByRole('button', { name: 'Copy code' });
64
+ await userEvent.click(copyButton);
65
+
66
+ // Should extract actual text content from DOM, not "[object Object]"
67
+ const codeElement = container.querySelector('code');
68
+ const expectedText = codeElement?.textContent || '';
69
+ expect(navigator.clipboard.writeText).toHaveBeenCalledWith(expectedText);
70
+ expect(expectedText).not.toContain('[object Object]');
71
+ });
72
+
73
+ it('should show check icon after copying', async () => {
74
+ const code = 'const x = 5;\nconst y = 10;';
75
+ render(<CodeBlockMessage>{code}</CodeBlockMessage>);
76
+
77
+ const copyButton = screen.getByRole('button', { name: 'Copy code' });
78
+ await userEvent.click(copyButton);
79
+
80
+ // Check icon should be visible (we can verify by checking if CopyIcon is not present)
81
+ const svgElement = copyButton.querySelector('svg');
82
+ expect(svgElement).toBeInTheDocument();
83
+ });
84
+
85
+ it('should render expandable section when isExpandable is true', () => {
86
+ const code = 'const x = 5;\nconst y = 10;';
87
+ render(<CodeBlockMessage isExpandable>{code}</CodeBlockMessage>);
88
+
89
+ expect(screen.getByRole('button', { name: 'Show more' })).toBeInTheDocument();
90
+ });
91
+
92
+ it('should toggle expandable section', async () => {
93
+ const code = 'const x = 5;\nconst y = 10;';
94
+ render(<CodeBlockMessage isExpandable>{code}</CodeBlockMessage>);
95
+
96
+ const toggleButton = screen.getByRole('button', { name: 'Show more' });
97
+ await userEvent.click(toggleButton);
98
+
99
+ expect(screen.getByRole('button', { name: 'Show less' })).toBeInTheDocument();
100
+ });
101
+
102
+ it('should use custom expanded/collapsed text', () => {
103
+ const code = 'const x = 5;\nconst y = 10;';
104
+ render(
105
+ <CodeBlockMessage isExpandable expandedText="Hide" collapsedText="Reveal">
106
+ {code}
107
+ </CodeBlockMessage>
108
+ );
109
+
110
+ expect(screen.getByRole('button', { name: 'Reveal' })).toBeInTheDocument();
111
+ });
112
+
113
+ it('should pass through expandableSectionProps', () => {
114
+ const code = 'const x = 5;\nconst y = 10;';
115
+ const { container } = render(
116
+ <CodeBlockMessage isExpandable expandableSectionProps={{ className: 'custom-expandable-class' }}>
117
+ {code}
118
+ </CodeBlockMessage>
119
+ );
120
+
121
+ const expandableSection = container.querySelector('.pf-v6-c-expandable-section.custom-expandable-class');
122
+ expect(expandableSection).toBeInTheDocument();
123
+ });
124
+
125
+ it('should render custom actions', () => {
126
+ const code = 'const x = 5;\nconst y = 10;';
127
+ const customAction = <button aria-label="Custom action">Custom</button>;
128
+ render(<CodeBlockMessage customActions={customAction}>{code}</CodeBlockMessage>);
129
+
130
+ expect(screen.getByRole('button', { name: 'Custom action' })).toBeInTheDocument();
131
+ });
132
+
133
+ it('should apply isPrimary class to inline code', () => {
134
+ render(<CodeBlockMessage isPrimary>const x = 5;</CodeBlockMessage>);
135
+ const code = screen.getByText('const x = 5;');
136
+ expect(code).toHaveClass('pf-m-primary');
137
+ });
138
+
139
+ it('should apply shouldRetainStyles class to code block', () => {
140
+ const code = 'const x = 5;\nconst y = 10;';
141
+ const { container } = render(<CodeBlockMessage shouldRetainStyles>{code}</CodeBlockMessage>);
142
+
143
+ const codeBlockDiv = container.querySelector('.pf-chatbot__message-code-block');
144
+ expect(codeBlockDiv).toHaveClass('pf-m-markdown');
145
+ });
146
+
147
+ it('should use custom aria-label for copy button', () => {
148
+ const code = 'const x = 5;\nconst y = 10;';
149
+ render(<CodeBlockMessage aria-label="Copy this code">{code}</CodeBlockMessage>);
150
+
151
+ expect(screen.getByRole('button', { name: 'Copy this code' })).toBeInTheDocument();
152
+ });
153
+
154
+ it('should prioritize data-expanded-text over expandedText prop', () => {
155
+ const code = 'const x = 5;\nconst y = 10;';
156
+ const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(jest.fn());
157
+
158
+ render(
159
+ <CodeBlockMessage isExpandable expandedText="Custom Expanded" data-expanded-text="Data Expanded">
160
+ {code}
161
+ </CodeBlockMessage>
162
+ );
163
+
164
+ expect(consoleErrorSpy).toHaveBeenCalledWith(
165
+ 'Message:',
166
+ expect.stringContaining('data-expanded-text or data-collapsed-text will override')
167
+ );
168
+
169
+ consoleErrorSpy.mockRestore();
170
+ });
171
+ });
@@ -19,6 +19,7 @@ import {
19
19
 
20
20
  import { CheckIcon } from '@patternfly/react-icons/dist/esm/icons/check-icon';
21
21
  import { CopyIcon } from '@patternfly/react-icons/dist/esm/icons/copy-icon';
22
+ import { css } from '@patternfly/react-styles';
22
23
 
23
24
  export interface CodeBlockMessageProps {
24
25
  /** Content rendered in code block */
@@ -39,6 +40,10 @@ export interface CodeBlockMessageProps {
39
40
  collapsedText?: string;
40
41
  /** Custom actions added to header of code block, after any default actions such as the "copy" action. */
41
42
  customActions?: React.ReactNode;
43
+ /** Sets background colors to be appropriate on primary chatbot background */
44
+ isPrimary?: boolean;
45
+ /** Flag indicating that the content should retain message styles when using Markdown. */
46
+ shouldRetainStyles?: boolean;
42
47
  }
43
48
 
44
49
  const DEFAULT_EXPANDED_TEXT = 'Show less';
@@ -54,6 +59,8 @@ const CodeBlockMessage = ({
54
59
  expandedText = DEFAULT_EXPANDED_TEXT,
55
60
  collapsedText = DEFAULT_COLLAPSED_TEXT,
56
61
  customActions,
62
+ isPrimary,
63
+ shouldRetainStyles,
57
64
  ...props
58
65
  }: CodeBlockMessageProps) => {
59
66
  const [copied, setCopied] = useState(false);
@@ -85,13 +92,22 @@ const CodeBlockMessage = ({
85
92
  );
86
93
  }
87
94
 
88
- const onToggle = (isExpanded) => {
95
+ const onToggle = (isExpanded: boolean) => {
89
96
  setIsExpanded(isExpanded);
90
97
  };
91
98
 
92
99
  // Handle clicking copy button
93
- const handleCopy = useCallback((event, text) => {
94
- navigator.clipboard.writeText(text.toString());
100
+ const handleCopy = useCallback((_event: React.MouseEvent, text: React.ReactNode) => {
101
+ let textToCopy = '';
102
+ if (typeof text === 'string') {
103
+ textToCopy = text;
104
+ } else {
105
+ if (codeBlockRef.current) {
106
+ const codeElement = codeBlockRef.current.querySelector('code');
107
+ textToCopy = codeElement?.textContent || '';
108
+ }
109
+ }
110
+ navigator.clipboard.writeText(textToCopy);
95
111
  setCopied(true);
96
112
  }, []);
97
113
 
@@ -108,7 +124,7 @@ const CodeBlockMessage = ({
108
124
 
109
125
  if (!String(children).includes('\n')) {
110
126
  return (
111
- <code {...props} className="pf-chatbot__message-inline-code">
127
+ <code {...props} className={`pf-chatbot__message-inline-code ${isPrimary ? 'pf-m-primary' : ''}`}>
112
128
  {children}
113
129
  </code>
114
130
  );
@@ -135,7 +151,7 @@ const CodeBlockMessage = ({
135
151
  );
136
152
 
137
153
  return (
138
- <div className="pf-chatbot__message-code-block" ref={codeBlockRef}>
154
+ <div className={css('pf-chatbot__message-code-block', shouldRetainStyles && 'pf-m-markdown')} ref={codeBlockRef}>
139
155
  <CodeBlock actions={actions}>
140
156
  <CodeBlockCode>
141
157
  <>
@@ -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
- const ErrorMessage = ({ title, actionLinks, children, ...props }: AlertProps) => (
8
- <Alert isInline variant="danger" title={title} actionLinks={actionLinks} {...props}>
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
  );
@@ -0,0 +1,5 @@
1
+ .pf-v6-c-button.pf-m-link.pf-m-inline {
2
+ &.pf-m-markdown {
3
+ font-size: inherit;
4
+ }
5
+ }
@@ -5,8 +5,21 @@
5
5
  import { Button, ButtonProps } from '@patternfly/react-core';
6
6
  import { ExternalLinkSquareAltIcon } from '@patternfly/react-icons';
7
7
  import { ExtraProps } from 'react-markdown';
8
+ import { css } from '@patternfly/react-styles';
8
9
 
9
- const LinkMessage = ({ children, target, href, id, ...props }: ButtonProps & ExtraProps) => {
10
+ export interface LinkMessageProps {
11
+ /** Flag indicating that the content should retain message styles when using Markdown. */
12
+ shouldRetainStyles?: boolean;
13
+ }
14
+
15
+ const LinkMessage = ({
16
+ children,
17
+ target,
18
+ href,
19
+ id,
20
+ shouldRetainStyles,
21
+ ...props
22
+ }: LinkMessageProps & ButtonProps & ExtraProps) => {
10
23
  if (target === '_blank') {
11
24
  return (
12
25
  <Button
@@ -20,6 +33,7 @@ const LinkMessage = ({ children, target, href, id, ...props }: ButtonProps & Ext
20
33
  // need to explicitly call this out or id doesn't seem to get passed - required for footnotes
21
34
  id={id}
22
35
  {...props}
36
+ className={css(shouldRetainStyles && 'pf-m-markdown', props?.className)}
23
37
  >
24
38
  {children}
25
39
  </Button>
@@ -28,7 +42,15 @@ const LinkMessage = ({ children, target, href, id, ...props }: ButtonProps & Ext
28
42
 
29
43
  return (
30
44
  // need to explicitly call this out or id doesn't seem to get passed - required for footnotes
31
- <Button isInline component="a" href={href} variant="link" id={id} {...props}>
45
+ <Button
46
+ isInline
47
+ component="a"
48
+ href={href}
49
+ variant="link"
50
+ id={id}
51
+ {...props}
52
+ className={css(shouldRetainStyles && 'pf-m-markdown', props?.className)}
53
+ >
32
54
  {children}
33
55
  </Button>
34
56
  );
@@ -13,6 +13,14 @@
13
13
  li {
14
14
  font-size: var(--pf-t--global--font--size--md);
15
15
  }
16
+
17
+ &.pf-m-markdown {
18
+ .pf-v6-c-list,
19
+ ul,
20
+ li {
21
+ font-size: inherit;
22
+ }
23
+ }
16
24
  }
17
25
 
18
26
  .pf-chatbot__message--user {