@patternfly/chatbot 6.5.0-prerelease.8 → 6.5.0

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 (315) hide show
  1. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +9 -1
  2. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +9 -2
  3. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +38 -0
  4. package/dist/cjs/ChatbotHeader/ChatbotHeaderMenu.js +29 -2
  5. package/dist/cjs/CodeModal/CodeModal.d.ts +2 -0
  6. package/dist/cjs/CodeModal/CodeModal.js +53 -12
  7. package/dist/cjs/DeepThinking/DeepThinking.d.ts +13 -0
  8. package/dist/cjs/DeepThinking/DeepThinking.js +31 -3
  9. package/dist/cjs/DeepThinking/DeepThinking.test.js +80 -0
  10. package/dist/cjs/MarkdownContent/MarkdownContent.d.ts +44 -0
  11. package/dist/cjs/MarkdownContent/MarkdownContent.js +181 -0
  12. package/dist/cjs/MarkdownContent/MarkdownContent.test.d.ts +1 -0
  13. package/dist/cjs/MarkdownContent/MarkdownContent.test.js +192 -0
  14. package/dist/cjs/MarkdownContent/index.d.ts +2 -0
  15. package/dist/cjs/MarkdownContent/index.js +23 -0
  16. package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.d.ts +3 -1
  17. package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.js +15 -4
  18. package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.test.d.ts +1 -0
  19. package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.test.js +131 -0
  20. package/dist/cjs/Message/ErrorMessage/ErrorMessage.d.ts +15 -1
  21. package/dist/cjs/Message/ErrorMessage/ErrorMessage.js +5 -3
  22. package/dist/cjs/Message/ErrorMessage/ErrorMessage.test.d.ts +1 -0
  23. package/dist/cjs/Message/ErrorMessage/ErrorMessage.test.js +30 -0
  24. package/dist/cjs/Message/LinkMessage/LinkMessage.d.ts +5 -1
  25. package/dist/cjs/Message/LinkMessage/LinkMessage.js +4 -3
  26. package/dist/cjs/Message/ListMessage/OrderedListMessage.d.ts +9 -1
  27. package/dist/cjs/Message/ListMessage/OrderedListMessage.js +2 -1
  28. package/dist/cjs/Message/ListMessage/UnorderedListMessage.d.ts +7 -1
  29. package/dist/cjs/Message/ListMessage/UnorderedListMessage.js +2 -1
  30. package/dist/cjs/Message/Message.d.ts +20 -3
  31. package/dist/cjs/Message/Message.js +7 -160
  32. package/dist/cjs/Message/Message.test.js +129 -2
  33. package/dist/cjs/Message/MessageAndActions/MessageAndActions.d.ts +14 -0
  34. package/dist/cjs/Message/MessageAndActions/MessageAndActions.js +22 -0
  35. package/dist/cjs/Message/MessageAndActions/MessageAndActions.test.d.ts +1 -0
  36. package/dist/cjs/Message/MessageAndActions/MessageAndActions.test.js +25 -0
  37. package/dist/cjs/Message/MessageAndActions/index.d.ts +1 -0
  38. package/dist/cjs/Message/MessageAndActions/index.js +17 -0
  39. package/dist/cjs/Message/MessageAttachments/MessageAttachmentItem.d.ts +13 -0
  40. package/dist/cjs/Message/MessageAttachments/MessageAttachmentItem.js +22 -0
  41. package/dist/cjs/Message/MessageAttachments/MessageAttachmentItem.test.d.ts +1 -0
  42. package/dist/cjs/Message/MessageAttachments/MessageAttachmentItem.test.js +25 -0
  43. package/dist/cjs/Message/MessageAttachments/MessageAttachmentsContainer.d.ts +13 -0
  44. package/dist/cjs/Message/MessageAttachments/MessageAttachmentsContainer.js +22 -0
  45. package/dist/cjs/Message/MessageAttachments/MessageAttachmentsContainer.test.d.ts +1 -0
  46. package/dist/cjs/Message/MessageAttachments/MessageAttachmentsContainer.test.js +25 -0
  47. package/dist/cjs/Message/MessageAttachments/index.d.ts +2 -0
  48. package/dist/cjs/Message/MessageAttachments/index.js +18 -0
  49. package/dist/cjs/Message/MessageInput.d.ts +1 -1
  50. package/dist/cjs/Message/MessageInput.js +3 -1
  51. package/dist/cjs/Message/MessageLoading.d.ts +13 -4
  52. package/dist/cjs/Message/MessageLoading.js +19 -5
  53. package/dist/cjs/Message/MessageLoading.test.d.ts +1 -0
  54. package/dist/cjs/Message/MessageLoading.test.js +25 -0
  55. package/dist/cjs/Message/QuickResponse/QuickResponse.js +3 -2
  56. package/dist/cjs/Message/QuickResponse/QuickResponse.test.d.ts +1 -0
  57. package/dist/cjs/Message/QuickResponse/QuickResponse.test.js +109 -0
  58. package/dist/cjs/Message/QuickResponse/index.d.ts +1 -0
  59. package/dist/cjs/Message/QuickResponse/index.js +17 -0
  60. package/dist/cjs/Message/QuickStarts/QuickStartTile.d.ts +1 -1
  61. package/dist/cjs/Message/QuickStarts/QuickStartTile.js +3 -2
  62. package/dist/cjs/Message/QuickStarts/index.d.ts +2 -0
  63. package/dist/cjs/Message/QuickStarts/index.js +18 -0
  64. package/dist/cjs/Message/TableMessage/TableMessage.d.ts +6 -1
  65. package/dist/cjs/Message/TableMessage/TableMessage.js +3 -2
  66. package/dist/cjs/Message/TextMessage/TextMessage.d.ts +8 -1
  67. package/dist/cjs/Message/TextMessage/TextMessage.js +3 -2
  68. package/dist/cjs/Message/UserFeedback/UserFeedback.d.ts +3 -1
  69. package/dist/cjs/Message/UserFeedback/UserFeedback.js +8 -6
  70. package/dist/cjs/Message/UserFeedback/UserFeedbackComplete.d.ts +1 -1
  71. package/dist/cjs/Message/UserFeedback/UserFeedbackComplete.js +3 -2
  72. package/dist/cjs/Message/UserFeedback/index.d.ts +2 -0
  73. package/dist/cjs/Message/UserFeedback/index.js +18 -0
  74. package/dist/cjs/Message/index.d.ts +8 -0
  75. package/dist/cjs/Message/index.js +8 -0
  76. package/dist/cjs/MessageBar/MessageBar.d.ts +4 -0
  77. package/dist/cjs/MessageBar/MessageBar.js +20 -5
  78. package/dist/cjs/MessageBar/MessageBar.test.js +8 -0
  79. package/dist/cjs/Onboarding/Onboarding.d.ts +36 -0
  80. package/dist/cjs/Onboarding/Onboarding.js +37 -0
  81. package/dist/cjs/Onboarding/Onboarding.test.d.ts +1 -0
  82. package/dist/cjs/Onboarding/Onboarding.test.js +80 -0
  83. package/dist/cjs/Onboarding/index.d.ts +2 -0
  84. package/dist/cjs/Onboarding/index.js +23 -0
  85. package/dist/cjs/ResponseActions/ResponseActions.d.ts +7 -0
  86. package/dist/cjs/ResponseActions/ResponseActions.js +28 -7
  87. package/dist/cjs/ResponseActions/ResponseActions.test.js +67 -12
  88. package/dist/cjs/ResponseActions/ResponseActionsGroups.d.ts +13 -0
  89. package/dist/cjs/ResponseActions/ResponseActionsGroups.js +22 -0
  90. package/dist/cjs/ResponseActions/ResponseActionsGroups.test.d.ts +1 -0
  91. package/dist/cjs/ResponseActions/ResponseActionsGroups.test.js +25 -0
  92. package/dist/cjs/ResponseActions/index.d.ts +1 -0
  93. package/dist/cjs/ResponseActions/index.js +1 -0
  94. package/dist/cjs/ToolCall/ToolCall.d.ts +11 -0
  95. package/dist/cjs/ToolCall/ToolCall.js +24 -3
  96. package/dist/cjs/ToolCall/ToolCall.test.js +57 -0
  97. package/dist/cjs/ToolResponse/ToolResponse.d.ts +17 -0
  98. package/dist/cjs/ToolResponse/ToolResponse.js +49 -3
  99. package/dist/cjs/ToolResponse/ToolResponse.test.js +100 -0
  100. package/dist/cjs/index.d.ts +4 -0
  101. package/dist/cjs/index.js +7 -1
  102. package/dist/css/main.css +268 -30
  103. package/dist/css/main.css.map +1 -1
  104. package/dist/dynamic/MarkdownContent/package.json +1 -0
  105. package/dist/dynamic/Onboarding/package.json +1 -0
  106. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +9 -1
  107. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +10 -3
  108. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +38 -0
  109. package/dist/esm/ChatbotHeader/ChatbotHeaderMenu.js +30 -3
  110. package/dist/esm/CodeModal/CodeModal.d.ts +2 -0
  111. package/dist/esm/CodeModal/CodeModal.js +54 -13
  112. package/dist/esm/DeepThinking/DeepThinking.d.ts +13 -0
  113. package/dist/esm/DeepThinking/DeepThinking.js +28 -3
  114. package/dist/esm/DeepThinking/DeepThinking.test.js +80 -0
  115. package/dist/esm/MarkdownContent/MarkdownContent.d.ts +44 -0
  116. package/dist/esm/MarkdownContent/MarkdownContent.js +174 -0
  117. package/dist/esm/MarkdownContent/MarkdownContent.test.d.ts +1 -0
  118. package/dist/esm/MarkdownContent/MarkdownContent.test.js +187 -0
  119. package/dist/esm/MarkdownContent/index.d.ts +2 -0
  120. package/dist/esm/MarkdownContent/index.js +2 -0
  121. package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.d.ts +3 -1
  122. package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.js +15 -4
  123. package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.test.d.ts +1 -0
  124. package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.test.js +126 -0
  125. package/dist/esm/Message/ErrorMessage/ErrorMessage.d.ts +15 -1
  126. package/dist/esm/Message/ErrorMessage/ErrorMessage.js +3 -3
  127. package/dist/esm/Message/ErrorMessage/ErrorMessage.test.d.ts +1 -0
  128. package/dist/esm/Message/ErrorMessage/ErrorMessage.test.js +25 -0
  129. package/dist/esm/Message/LinkMessage/LinkMessage.d.ts +5 -1
  130. package/dist/esm/Message/LinkMessage/LinkMessage.js +4 -3
  131. package/dist/esm/Message/ListMessage/OrderedListMessage.d.ts +9 -1
  132. package/dist/esm/Message/ListMessage/OrderedListMessage.js +2 -1
  133. package/dist/esm/Message/ListMessage/UnorderedListMessage.d.ts +7 -1
  134. package/dist/esm/Message/ListMessage/UnorderedListMessage.js +2 -1
  135. package/dist/esm/Message/Message.d.ts +20 -3
  136. package/dist/esm/Message/Message.js +8 -161
  137. package/dist/esm/Message/Message.test.js +129 -2
  138. package/dist/esm/Message/MessageAndActions/MessageAndActions.d.ts +14 -0
  139. package/dist/esm/Message/MessageAndActions/MessageAndActions.js +18 -0
  140. package/dist/esm/Message/MessageAndActions/MessageAndActions.test.d.ts +1 -0
  141. package/dist/esm/Message/MessageAndActions/MessageAndActions.test.js +20 -0
  142. package/dist/esm/Message/MessageAndActions/index.d.ts +1 -0
  143. package/dist/esm/Message/MessageAndActions/index.js +1 -0
  144. package/dist/esm/Message/MessageAttachments/MessageAttachmentItem.d.ts +13 -0
  145. package/dist/esm/Message/MessageAttachments/MessageAttachmentItem.js +18 -0
  146. package/dist/esm/Message/MessageAttachments/MessageAttachmentItem.test.d.ts +1 -0
  147. package/dist/esm/Message/MessageAttachments/MessageAttachmentItem.test.js +20 -0
  148. package/dist/esm/Message/MessageAttachments/MessageAttachmentsContainer.d.ts +13 -0
  149. package/dist/esm/Message/MessageAttachments/MessageAttachmentsContainer.js +18 -0
  150. package/dist/esm/Message/MessageAttachments/MessageAttachmentsContainer.test.d.ts +1 -0
  151. package/dist/esm/Message/MessageAttachments/MessageAttachmentsContainer.test.js +20 -0
  152. package/dist/esm/Message/MessageAttachments/index.d.ts +2 -0
  153. package/dist/esm/Message/MessageAttachments/index.js +2 -0
  154. package/dist/esm/Message/MessageInput.d.ts +1 -1
  155. package/dist/esm/Message/MessageInput.js +1 -1
  156. package/dist/esm/Message/MessageLoading.d.ts +13 -4
  157. package/dist/esm/Message/MessageLoading.js +16 -4
  158. package/dist/esm/Message/MessageLoading.test.d.ts +1 -0
  159. package/dist/esm/Message/MessageLoading.test.js +20 -0
  160. package/dist/esm/Message/QuickResponse/QuickResponse.js +3 -2
  161. package/dist/esm/Message/QuickResponse/QuickResponse.test.d.ts +1 -0
  162. package/dist/esm/Message/QuickResponse/QuickResponse.test.js +104 -0
  163. package/dist/esm/Message/QuickResponse/index.d.ts +1 -0
  164. package/dist/esm/Message/QuickResponse/index.js +1 -0
  165. package/dist/esm/Message/QuickStarts/QuickStartTile.d.ts +1 -1
  166. package/dist/esm/Message/QuickStarts/QuickStartTile.js +1 -1
  167. package/dist/esm/Message/QuickStarts/index.d.ts +2 -0
  168. package/dist/esm/Message/QuickStarts/index.js +2 -0
  169. package/dist/esm/Message/TableMessage/TableMessage.d.ts +6 -1
  170. package/dist/esm/Message/TableMessage/TableMessage.js +3 -2
  171. package/dist/esm/Message/TextMessage/TextMessage.d.ts +8 -1
  172. package/dist/esm/Message/TextMessage/TextMessage.js +3 -2
  173. package/dist/esm/Message/UserFeedback/UserFeedback.d.ts +3 -1
  174. package/dist/esm/Message/UserFeedback/UserFeedback.js +7 -7
  175. package/dist/esm/Message/UserFeedback/UserFeedbackComplete.d.ts +1 -1
  176. package/dist/esm/Message/UserFeedback/UserFeedbackComplete.js +1 -2
  177. package/dist/esm/Message/UserFeedback/index.d.ts +2 -0
  178. package/dist/esm/Message/UserFeedback/index.js +2 -0
  179. package/dist/esm/Message/index.d.ts +8 -0
  180. package/dist/esm/Message/index.js +8 -0
  181. package/dist/esm/MessageBar/MessageBar.d.ts +4 -0
  182. package/dist/esm/MessageBar/MessageBar.js +20 -5
  183. package/dist/esm/MessageBar/MessageBar.test.js +8 -0
  184. package/dist/esm/Onboarding/Onboarding.d.ts +36 -0
  185. package/dist/esm/Onboarding/Onboarding.js +30 -0
  186. package/dist/esm/Onboarding/Onboarding.test.d.ts +1 -0
  187. package/dist/esm/Onboarding/Onboarding.test.js +75 -0
  188. package/dist/esm/Onboarding/index.d.ts +2 -0
  189. package/dist/esm/Onboarding/index.js +2 -0
  190. package/dist/esm/ResponseActions/ResponseActions.d.ts +7 -0
  191. package/dist/esm/ResponseActions/ResponseActions.js +28 -7
  192. package/dist/esm/ResponseActions/ResponseActions.test.js +67 -12
  193. package/dist/esm/ResponseActions/ResponseActionsGroups.d.ts +13 -0
  194. package/dist/esm/ResponseActions/ResponseActionsGroups.js +18 -0
  195. package/dist/esm/ResponseActions/ResponseActionsGroups.test.d.ts +1 -0
  196. package/dist/esm/ResponseActions/ResponseActionsGroups.test.js +20 -0
  197. package/dist/esm/ResponseActions/index.d.ts +1 -0
  198. package/dist/esm/ResponseActions/index.js +1 -0
  199. package/dist/esm/ToolCall/ToolCall.d.ts +11 -0
  200. package/dist/esm/ToolCall/ToolCall.js +21 -3
  201. package/dist/esm/ToolCall/ToolCall.test.js +57 -0
  202. package/dist/esm/ToolResponse/ToolResponse.d.ts +17 -0
  203. package/dist/esm/ToolResponse/ToolResponse.js +46 -3
  204. package/dist/esm/ToolResponse/ToolResponse.test.js +100 -0
  205. package/dist/esm/index.d.ts +4 -0
  206. package/dist/esm/index.js +4 -0
  207. package/dist/tsconfig.tsbuildinfo +1 -1
  208. package/package.json +13 -3
  209. package/patternfly-docs/content/extensions/chatbot/chatbot.md +57 -0
  210. package/patternfly-docs/content/extensions/chatbot/design-guidelines.md +12 -12
  211. package/patternfly-docs/content/extensions/chatbot/examples/Analytics/Analytics.md +1 -1
  212. package/patternfly-docs/content/extensions/chatbot/examples/Customizing Messages/Customizing Messages.md +1 -1
  213. package/patternfly-docs/content/extensions/chatbot/examples/Messages/BotMessage.tsx +1 -0
  214. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithCustomStructure.tsx +102 -0
  215. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithDeepThinking.tsx +25 -11
  216. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithFeedback.tsx +14 -1
  217. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithMarkdownDeepThinking.tsx +26 -0
  218. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithMarkdownToolCall.tsx +29 -0
  219. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithMarkdownToolResponse.tsx +200 -0
  220. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithMultipleActionGroups.tsx +61 -0
  221. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithPersistedActions.tsx +22 -0
  222. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithQuickResponses.tsx +11 -0
  223. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithToolCall.tsx +14 -1
  224. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithToolResponse.tsx +222 -105
  225. package/patternfly-docs/content/extensions/chatbot/examples/Messages/Messages.md +123 -14
  226. package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessage.tsx +1 -0
  227. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawerWithSearchActions.tsx +198 -0
  228. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotMessageBarIndicatorThinking.tsx +15 -0
  229. package/patternfly-docs/content/extensions/chatbot/examples/UI/CompactOnboarding.tsx +141 -0
  230. package/patternfly-docs/content/extensions/chatbot/examples/UI/Onboarding.tsx +151 -0
  231. package/patternfly-docs/content/extensions/chatbot/examples/UI/RH-Hat-Image.svg +9 -0
  232. package/patternfly-docs/content/extensions/chatbot/examples/UI/UI.md +67 -29
  233. package/patternfly-docs/content/extensions/chatbot/examples/demos/AttachmentDemos.md +18 -18
  234. package/patternfly-docs/content/extensions/chatbot/examples/demos/Chatbot.md +33 -19
  235. package/patternfly-docs/patternfly-docs.config.js +1 -1
  236. package/patternfly-docs/patternfly-docs.source.js +1 -1
  237. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.scss +43 -0
  238. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.tsx +95 -0
  239. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.tsx +51 -15
  240. package/src/ChatbotHeader/ChatbotHeader.scss +4 -0
  241. package/src/ChatbotHeader/ChatbotHeaderMenu.tsx +56 -14
  242. package/src/ChatbotModal/ChatbotModal.scss +3 -0
  243. package/src/CodeModal/CodeModal.tsx +71 -26
  244. package/src/DeepThinking/DeepThinking.scss +1 -1
  245. package/src/DeepThinking/DeepThinking.test.tsx +109 -0
  246. package/src/DeepThinking/DeepThinking.tsx +54 -5
  247. package/src/MarkdownContent/MarkdownContent.test.tsx +207 -0
  248. package/src/MarkdownContent/MarkdownContent.tsx +269 -0
  249. package/src/MarkdownContent/index.ts +2 -0
  250. package/src/Message/CodeBlockMessage/CodeBlockMessage.scss +13 -0
  251. package/src/Message/CodeBlockMessage/CodeBlockMessage.test.tsx +171 -0
  252. package/src/Message/CodeBlockMessage/CodeBlockMessage.tsx +17 -4
  253. package/src/Message/ErrorMessage/ErrorMessage.test.tsx +38 -0
  254. package/src/Message/ErrorMessage/ErrorMessage.tsx +17 -2
  255. package/src/Message/LinkMessage/LinkMessage.scss +5 -0
  256. package/src/Message/LinkMessage/LinkMessage.tsx +24 -2
  257. package/src/Message/ListMessage/ListMessage.scss +8 -0
  258. package/src/Message/ListMessage/OrderedListMessage.tsx +16 -2
  259. package/src/Message/ListMessage/UnorderedListMessage.tsx +12 -2
  260. package/src/Message/Message.scss +11 -7
  261. package/src/Message/Message.test.tsx +202 -2
  262. package/src/Message/Message.tsx +129 -241
  263. package/src/Message/MessageAndActions/MessageAndActions.test.tsx +23 -0
  264. package/src/Message/MessageAndActions/MessageAndActions.tsx +22 -0
  265. package/src/Message/MessageAndActions/index.ts +1 -0
  266. package/src/Message/MessageAttachments/MessageAttachmentItem.test.tsx +23 -0
  267. package/src/Message/MessageAttachments/MessageAttachmentItem.tsx +25 -0
  268. package/src/Message/MessageAttachments/MessageAttachmentsContainer.test.tsx +23 -0
  269. package/src/Message/MessageAttachments/MessageAttachmentsContainer.tsx +25 -0
  270. package/src/Message/MessageAttachments/index.ts +2 -0
  271. package/src/Message/MessageInput.tsx +1 -1
  272. package/src/Message/MessageLoading.test.tsx +23 -0
  273. package/src/Message/MessageLoading.tsx +17 -2
  274. package/src/Message/QuickResponse/QuickResponse.scss +3 -1
  275. package/src/Message/QuickResponse/QuickResponse.test.tsx +131 -0
  276. package/src/Message/QuickResponse/QuickResponse.tsx +3 -2
  277. package/src/Message/QuickResponse/index.ts +1 -0
  278. package/src/Message/QuickStarts/QuickStartTile.tsx +1 -1
  279. package/src/Message/QuickStarts/index.ts +2 -0
  280. package/src/Message/TableMessage/TableMessage.scss +13 -1
  281. package/src/Message/TableMessage/TableMessage.tsx +18 -2
  282. package/src/Message/TextMessage/TextMessage.scss +12 -0
  283. package/src/Message/TextMessage/TextMessage.tsx +29 -2
  284. package/src/Message/UserFeedback/UserFeedback.scss +28 -1
  285. package/src/Message/UserFeedback/UserFeedback.tsx +23 -13
  286. package/src/Message/UserFeedback/UserFeedbackComplete.tsx +1 -4
  287. package/src/Message/UserFeedback/index.ts +2 -0
  288. package/src/Message/index.ts +8 -0
  289. package/src/MessageBar/AttachButton.scss +0 -1
  290. package/src/MessageBar/MessageBar.scss +48 -6
  291. package/src/MessageBar/MessageBar.test.tsx +12 -0
  292. package/src/MessageBar/MessageBar.tsx +38 -4
  293. package/src/MessageBar/MicrophoneButton.scss +0 -1
  294. package/src/MessageBar/SendButton.scss +0 -1
  295. package/src/MessageBar/StopButton.scss +0 -1
  296. package/src/Onboarding/Onboarding.scss +101 -0
  297. package/src/Onboarding/Onboarding.test.tsx +148 -0
  298. package/src/Onboarding/Onboarding.tsx +126 -0
  299. package/src/Onboarding/index.ts +3 -0
  300. package/src/ResponseActions/ResponseActions.scss +12 -1
  301. package/src/ResponseActions/ResponseActions.test.tsx +111 -12
  302. package/src/ResponseActions/ResponseActions.tsx +44 -10
  303. package/src/ResponseActions/ResponseActionsGroups.test.tsx +23 -0
  304. package/src/ResponseActions/ResponseActionsGroups.tsx +28 -0
  305. package/src/ResponseActions/index.ts +1 -0
  306. package/src/ToolCall/ToolCall.scss +1 -1
  307. package/src/ToolCall/ToolCall.test.tsx +91 -0
  308. package/src/ToolCall/ToolCall.tsx +49 -4
  309. package/src/ToolResponse/ToolResponse.scss +13 -3
  310. package/src/ToolResponse/ToolResponse.test.tsx +119 -0
  311. package/src/ToolResponse/ToolResponse.tsx +82 -7
  312. package/src/index.ts +6 -0
  313. package/src/main.scss +2 -0
  314. package/tsconfig.json +1 -1
  315. package/patternfly-docs/content/extensions/chatbot/about-chatbot.md +0 -44
@@ -8,6 +8,7 @@ import { useRef, Fragment } from 'react';
8
8
  import {
9
9
  Button,
10
10
  ButtonProps,
11
+ Divider,
11
12
  Drawer,
12
13
  DrawerPanelContent,
13
14
  DrawerContent,
@@ -17,6 +18,8 @@ import {
17
18
  DrawerActions,
18
19
  DrawerCloseButton,
19
20
  DrawerContentBody,
21
+ InputGroup,
22
+ InputGroupItem,
20
23
  SearchInput,
21
24
  Title,
22
25
  DrawerPanelContentProps,
@@ -28,10 +31,10 @@ import {
28
31
  DrawerPanelBodyProps,
29
32
  SkeletonProps,
30
33
  Icon,
31
- MenuProps,
32
34
  TitleProps,
33
- MenuListProps,
34
35
  SearchInputProps,
36
+ MenuProps,
37
+ MenuListProps,
35
38
  MenuList,
36
39
  MenuGroup,
37
40
  MenuItem,
@@ -125,6 +128,8 @@ export interface ChatbotConversationHistoryNavProps extends DrawerProps {
125
128
  drawerCloseButtonProps?: DrawerCloseButtonProps;
126
129
  /** Additional props appleid to drawer panel body */
127
130
  drawerPanelBodyProps?: DrawerPanelBodyProps;
131
+ /** Flag indicating whether a divider should render between the drawer head and title. */
132
+ hasDrawerHeadDivider?: boolean;
128
133
  /** Whether to show drawer loading state */
129
134
  isLoading?: boolean;
130
135
  /** Additional props for loading state */
@@ -145,6 +150,12 @@ export interface ChatbotConversationHistoryNavProps extends DrawerProps {
145
150
  navTitleProps?: Partial<TitleProps>;
146
151
  /** Visually hidden text that gets announced by assistive technologies. Should be used to convey the result count when the search input value changes. */
147
152
  searchInputScreenReaderText?: string;
153
+ /** Custom action rendered before the search input. */
154
+ searchActionStart?: React.ReactNode;
155
+ /** Custom action rendered after the search input. */
156
+ searchActionEnd?: React.ReactNode;
157
+ /** A custom search toolbar to render below the title. This will override the default search actions and/or search input. */
158
+ searchToolbar?: React.ReactNode;
148
159
  /** Additional props passed to MenuContent */
149
160
  menuContentProps?: Omit<MenuContentProps, 'ref'>;
150
161
  }
@@ -175,6 +186,7 @@ export const ChatbotConversationHistoryNav: FunctionComponent<ChatbotConversatio
175
186
  drawerActionsProps,
176
187
  drawerCloseButtonProps,
177
188
  drawerPanelBodyProps,
189
+ hasDrawerHeadDivider,
178
190
  isLoading,
179
191
  loadingState,
180
192
  errorState,
@@ -185,6 +197,9 @@ export const ChatbotConversationHistoryNav: FunctionComponent<ChatbotConversatio
185
197
  navTitleProps,
186
198
  navTitleIcon = <OutlinedClockIcon />,
187
199
  searchInputScreenReaderText,
200
+ searchActionStart,
201
+ searchActionEnd,
202
+ searchToolbar,
188
203
  menuProps,
189
204
  menuGroupProps,
190
205
  menuContentProps,
@@ -287,6 +302,38 @@ export const ChatbotConversationHistoryNav: FunctionComponent<ChatbotConversatio
287
302
  </>
288
303
  );
289
304
 
305
+ const searchInputContainer = handleTextInputChange && (
306
+ <div className="pf-chatbot__input">
307
+ <SearchInput
308
+ aria-label={searchInputAriaLabel}
309
+ onChange={(_event, value) => handleTextInputChange(value)}
310
+ placeholder={searchInputPlaceholder}
311
+ {...searchInputProps}
312
+ />
313
+ {searchInputScreenReaderText && (
314
+ <div className="pf-chatbot__filter-announcement pf-chatbot-m-hidden">{searchInputScreenReaderText}</div>
315
+ )}
316
+ </div>
317
+ );
318
+
319
+ const renderSearchAndActions = () => {
320
+ if (searchToolbar) {
321
+ return searchToolbar;
322
+ }
323
+
324
+ return searchActionStart || searchActionEnd ? (
325
+ <div className="pf-chatbot__history-search-actions">
326
+ <InputGroup>
327
+ {searchActionStart && <InputGroupItem>{searchActionStart}</InputGroupItem>}
328
+ {searchInputContainer && <InputGroupItem isFill>{searchInputContainer}</InputGroupItem>}
329
+ {searchActionEnd && <InputGroupItem>{searchActionEnd}</InputGroupItem>}
330
+ </InputGroup>
331
+ </div>
332
+ ) : (
333
+ searchInputContainer
334
+ );
335
+ };
336
+
290
337
  const renderPanelContent = () => {
291
338
  const drawer = (
292
339
  <>
@@ -309,6 +356,7 @@ export const ChatbotConversationHistoryNav: FunctionComponent<ChatbotConversatio
309
356
  )}
310
357
  </DrawerActions>
311
358
  </DrawerHead>
359
+ {hasDrawerHeadDivider && <Divider className="pf-chatbot__heading-divider" />}
312
360
  <div className="pf-chatbot__heading-container">
313
361
  <div className="pf-chatbot__title-container">
314
362
  <Icon size="lg" className="pf-chatbot__title-icon">
@@ -318,19 +366,7 @@ export const ChatbotConversationHistoryNav: FunctionComponent<ChatbotConversatio
318
366
  {title}
319
367
  </Title>
320
368
  </div>
321
- {!isLoading && handleTextInputChange && (
322
- <div className="pf-chatbot__input">
323
- <SearchInput
324
- aria-label={searchInputAriaLabel}
325
- onChange={(_event, value) => handleTextInputChange(value)}
326
- placeholder={searchInputPlaceholder}
327
- {...searchInputProps}
328
- />
329
- {searchInputScreenReaderText && (
330
- <div className="pf-chatbot__filter-announcement pf-chatbot-m-hidden">{searchInputScreenReaderText}</div>
331
- )}
332
- </div>
333
- )}
369
+ {!isLoading && renderSearchAndActions()}
334
370
  </div>
335
371
  {isLoading ? <LoadingState {...loadingState} /> : renderDrawerContent()}
336
372
  </>
@@ -91,6 +91,10 @@
91
91
  align-items: center;
92
92
  justify-content: center;
93
93
 
94
+ &::before {
95
+ border-radius: inherit;
96
+ }
97
+
94
98
  .pf-v6-c-button__icon,
95
99
  .pf-v6-c-menu-toggle__icon,
96
100
  .pf-v6-c-icon__content {
@@ -1,5 +1,5 @@
1
1
  import type { Ref, FunctionComponent } from 'react';
2
- import { forwardRef } from 'react';
2
+ import { forwardRef, useEffect, useMemo, useRef, useState } from 'react';
3
3
 
4
4
  import { Button, ButtonProps, Icon, Tooltip, TooltipProps } from '@patternfly/react-core';
5
5
  import BarsIcon from '@patternfly/react-icons/dist/esm/icons/bars-icon';
@@ -30,21 +30,43 @@ const ChatbotHeaderMenuBase: FunctionComponent<ChatbotHeaderMenuProps> = ({
30
30
  tooltipContent = 'Chat history menu',
31
31
  isCompact,
32
32
  ...props
33
- }: ChatbotHeaderMenuProps) => (
34
- <div className={`pf-chatbot__menu ${className}`}>
35
- <Tooltip
36
- content={tooltipContent}
37
- position="bottom"
38
- // prevents VO announcements of both aria label and tooltip
39
- aria="none"
40
- {...tooltipProps}
41
- >
33
+ }: ChatbotHeaderMenuProps) => {
34
+ const [isDrawerAnimating, setIsDrawerAnimating] = useState(false);
35
+ // I'd like to use a prop here later if this works
36
+ const drawerState = props['aria-expanded'];
37
+ const isDrawerOpen = drawerState === true;
38
+ const prevDrawerStateRef = useRef<boolean | undefined>(isDrawerOpen);
39
+ const buttonRef = useRef<HTMLButtonElement | null>(null);
40
+
41
+ useEffect(() => {
42
+ if (drawerState !== undefined) {
43
+ const wasDrawerOpen = prevDrawerStateRef.current === true;
44
+ const isDrawerClosing = wasDrawerOpen && !isDrawerOpen;
45
+
46
+ setIsDrawerAnimating(true);
47
+ const timeout = setTimeout(() => {
48
+ setIsDrawerAnimating(false);
49
+
50
+ if (isDrawerClosing) {
51
+ requestAnimationFrame(() => {
52
+ buttonRef.current?.focus();
53
+ });
54
+ }
55
+ }, 350);
56
+
57
+ prevDrawerStateRef.current = isDrawerOpen;
58
+ return () => clearTimeout(timeout);
59
+ }
60
+ }, [drawerState, isDrawerOpen]);
61
+
62
+ const button = useMemo(
63
+ () => (
42
64
  <Button
43
65
  className={`pf-chatbot__button--toggle-menu ${isCompact ? 'pf-m-compact' : ''}`}
44
66
  variant="plain"
45
67
  onClick={onMenuToggle}
46
68
  aria-label={menuAriaLabel}
47
- ref={innerRef}
69
+ ref={innerRef ?? buttonRef}
48
70
  icon={
49
71
  <Icon size={isCompact ? 'lg' : 'xl'} isInline>
50
72
  <BarsIcon />
@@ -53,9 +75,29 @@ const ChatbotHeaderMenuBase: FunctionComponent<ChatbotHeaderMenuProps> = ({
53
75
  size={isCompact ? 'sm' : undefined}
54
76
  {...props}
55
77
  />
56
- </Tooltip>
57
- </div>
58
- );
78
+ ),
79
+ // eslint-disable-next-line react-hooks/exhaustive-deps
80
+ [isCompact, menuAriaLabel, onMenuToggle, innerRef, buttonRef]
81
+ );
82
+
83
+ return (
84
+ <div className={`pf-chatbot__menu ${className}`}>
85
+ {isDrawerAnimating ? (
86
+ button
87
+ ) : (
88
+ <Tooltip
89
+ content={tooltipContent}
90
+ position="bottom"
91
+ // prevents VO announcements of both aria label and tooltip
92
+ aria="none"
93
+ {...tooltipProps}
94
+ >
95
+ {button}
96
+ </Tooltip>
97
+ )}
98
+ </div>
99
+ );
100
+ };
59
101
 
60
102
  export const ChatbotHeaderMenu = forwardRef((props: ChatbotHeaderMenuProps, ref: Ref<HTMLButtonElement>) => (
61
103
  <ChatbotHeaderMenuBase innerRef={ref} {...props} />
@@ -18,7 +18,10 @@
18
18
  .pf-v6-c-modal-box__footer {
19
19
  padding-block-start: var(--pf-t--global--spacer--xl);
20
20
  padding-block-end: var(--pf-t--global--spacer--xl);
21
+ border-top: var(--pf-t--global--border--width--high-contrast--regular) solid
22
+ var(--pf-t--global--border--color--high-contrast);
21
23
  }
24
+
22
25
  .pf-v6-c-modal-box__header {
23
26
  padding-block-end: var(--pf-t--global--spacer--sm);
24
27
  }
@@ -5,17 +5,17 @@
5
5
  import type { FunctionComponent, MouseEvent } from 'react';
6
6
  import { useState, useEffect, useRef } from 'react';
7
7
  import path from 'path-browserify';
8
- import * as monaco from 'monaco-editor';
9
- import { loader } from '@monaco-editor/react';
10
8
 
11
9
  // Import PatternFly components
12
10
  import { CodeEditor } from '@patternfly/react-code-editor';
13
11
  import {
12
+ Bullseye,
14
13
  Button,
15
14
  getResizeObserver,
16
15
  ModalBody,
17
16
  ModalFooter,
18
17
  ModalHeader,
18
+ Spinner,
19
19
  Stack,
20
20
  StackItem
21
21
  } from '@patternfly/react-core';
@@ -23,8 +23,16 @@ import FileDetails, { extensionToLanguage } from '../FileDetails';
23
23
  import { ChatbotDisplayMode } from '../Chatbot';
24
24
  import ChatbotModal from '../ChatbotModal/ChatbotModal';
25
25
 
26
- // Configure Monaco loader to use the npm package instead of CDN
27
- loader.config({ monaco });
26
+ // Try to lazy load - some consumers need to be below a certain bundle size, but can't use the CDN and don't have webpack
27
+ let monacoInstance: typeof import('monaco-editor') | null = null;
28
+ const loadMonaco = async () => {
29
+ if (!monacoInstance) {
30
+ const [monaco, { loader }] = await Promise.all([import('monaco-editor'), import('@monaco-editor/react')]);
31
+ monacoInstance = monaco;
32
+ loader.config({ monaco });
33
+ }
34
+ return monacoInstance;
35
+ };
28
36
 
29
37
  export interface CodeModalProps {
30
38
  /** Class applied to code editor */
@@ -63,6 +71,8 @@ export interface CodeModalProps {
63
71
  modalBodyClassName?: string;
64
72
  /** Class applied to modal footer */
65
73
  modalFooterClassName?: string;
74
+ /** Aria label applied to spinner when loading Monaco */
75
+ spinnerAriaLabel?: string;
66
76
  }
67
77
 
68
78
  export const CodeModal: FunctionComponent<CodeModalProps> = ({
@@ -84,13 +94,32 @@ export const CodeModal: FunctionComponent<CodeModalProps> = ({
84
94
  modalHeaderClassName,
85
95
  modalBodyClassName,
86
96
  modalFooterClassName,
97
+ spinnerAriaLabel = 'Loading',
87
98
  ...props
88
99
  }: CodeModalProps) => {
89
100
  const [newCode, setNewCode] = useState(code);
90
- const [editorInstance, setEditorInstance] = useState<monaco.editor.IStandaloneCodeEditor | null>(null);
101
+ const [editorInstance, setEditorInstance] = useState<any>(null);
91
102
  const [isEditorReady, setIsEditorReady] = useState(false);
103
+ const [isMonacoLoading, setIsMonacoLoading] = useState(false);
104
+ const [isMonacoLoaded, setIsMonacoLoaded] = useState(false);
92
105
  const containerRef = useRef<HTMLDivElement>(null);
93
106
 
107
+ useEffect(() => {
108
+ if (isModalOpen && !isMonacoLoaded && !isMonacoLoading) {
109
+ setIsMonacoLoading(true);
110
+ loadMonaco()
111
+ .then(() => {
112
+ setIsMonacoLoaded(true);
113
+ setIsMonacoLoading(false);
114
+ })
115
+ .catch((error) => {
116
+ // eslint-disable-next-line no-console
117
+ console.error('Failed to load Monaco editor:', error);
118
+ setIsMonacoLoading(false);
119
+ });
120
+ }
121
+ }, [isModalOpen, isMonacoLoaded, isMonacoLoading]);
122
+
94
123
  useEffect(() => {
95
124
  if (!isModalOpen || !isEditorReady || !editorInstance || !containerRef.current) {
96
125
  return;
@@ -148,6 +177,42 @@ export const CodeModal: FunctionComponent<CodeModalProps> = ({
148
177
  }
149
178
  };
150
179
 
180
+ const renderMonacoEditor = () => {
181
+ if (isMonacoLoading) {
182
+ return (
183
+ <Bullseye>
184
+ <Spinner aria-label={spinnerAriaLabel} />
185
+ </Bullseye>
186
+ );
187
+ }
188
+ if (isMonacoLoaded) {
189
+ return (
190
+ <CodeEditor
191
+ isDarkTheme
192
+ isLineNumbersVisible={isLineNumbersVisible}
193
+ isLanguageLabelVisible
194
+ isCopyEnabled={isCopyEnabled}
195
+ isReadOnly={isReadOnly}
196
+ code={newCode}
197
+ language={extensionToLanguage[path.extname(fileName).slice(1)]}
198
+ onEditorDidMount={onEditorDidMount}
199
+ onCodeChange={onCodeChange}
200
+ className={codeEditorClassName}
201
+ isFullHeight
202
+ options={{
203
+ glyphMargin: false,
204
+ folding: false,
205
+ // prevents Monaco from handling resizing itself
206
+ // was causing ResizeObserver issues
207
+ automaticLayout: false
208
+ }}
209
+ {...props}
210
+ />
211
+ );
212
+ }
213
+ return null;
214
+ };
215
+
151
216
  const modal = (
152
217
  <ChatbotModal
153
218
  isOpen={isModalOpen}
@@ -166,27 +231,7 @@ export const CodeModal: FunctionComponent<CodeModalProps> = ({
166
231
  <FileDetails fileName={fileName} />
167
232
  </StackItem>
168
233
  <div className="pf-v6-l-stack__item pf-chatbot__code-modal-editor" ref={containerRef}>
169
- <CodeEditor
170
- isDarkTheme
171
- isLineNumbersVisible={isLineNumbersVisible}
172
- isLanguageLabelVisible
173
- isCopyEnabled={isCopyEnabled}
174
- isReadOnly={isReadOnly}
175
- code={newCode}
176
- language={extensionToLanguage[path.extname(fileName).slice(1)]}
177
- onEditorDidMount={onEditorDidMount}
178
- onCodeChange={onCodeChange}
179
- className={codeEditorClassName}
180
- isFullHeight
181
- options={{
182
- glyphMargin: false,
183
- folding: false,
184
- // prevents Monaco from handling resizing itself
185
- // was causing ResizeObserver issues
186
- automaticLayout: false
187
- }}
188
- {...props}
189
- />
234
+ {renderMonacoEditor()}
190
235
  </div>
191
236
  </Stack>
192
237
  </ModalBody>
@@ -1,5 +1,5 @@
1
1
  .pf-chatbot__deep-thinking {
2
- --pf-v6-c-card--BorderColor: var(--pf-t--global--border--color--control--read-only);
2
+ --pf-v6-c-card--BorderColor: var(--pf-t--global--border--color--default);
3
3
  overflow: unset;
4
4
  }
5
5
 
@@ -1,4 +1,5 @@
1
1
  import { render, screen } from '@testing-library/react';
2
+ import userEvent from '@testing-library/user-event';
2
3
  import '@testing-library/jest-dom';
3
4
  import DeepThinking from './DeepThinking';
4
5
 
@@ -58,4 +59,112 @@ describe('DeepThinking', () => {
58
59
  const subheadingContainer = container.querySelector('.pf-chatbot__tool-response-subheading');
59
60
  expect(subheadingContainer).toBeFalsy();
60
61
  });
62
+
63
+ it('should pass through cardBodyProps', () => {
64
+ render(
65
+ <DeepThinking {...defaultProps} body="Thinking content" cardBodyProps={{ className: 'custom-card-body-class' }} />
66
+ );
67
+
68
+ const cardBody = screen.getByText('Thinking content').closest('.pf-v6-c-card__body');
69
+ expect(cardBody).toHaveClass('custom-card-body-class');
70
+ });
71
+
72
+ it('Renders expanded by default', () => {
73
+ render(<DeepThinking {...defaultProps} body="Thinking content" />);
74
+
75
+ expect(screen.getByRole('button', { name: defaultProps.toggleContent })).toHaveAttribute('aria-expanded', 'true');
76
+ expect(screen.getByText('Thinking content')).toBeVisible();
77
+ });
78
+
79
+ it('Renders collapsed when isDefaultExpanded is false', () => {
80
+ render(<DeepThinking isDefaultExpanded={false} {...defaultProps} body="Thinking content" />);
81
+
82
+ expect(screen.getByRole('button', { name: defaultProps.toggleContent })).toHaveAttribute('aria-expanded', 'false');
83
+ expect(screen.getByText('Thinking content')).not.toBeVisible();
84
+ });
85
+
86
+ it('expandableSectionProps.isExpanded overrides isDefaultExpanded', () => {
87
+ render(
88
+ <DeepThinking
89
+ {...defaultProps}
90
+ isDefaultExpanded={false}
91
+ body="Thinking content"
92
+ expandableSectionProps={{ isExpanded: true }}
93
+ />
94
+ );
95
+
96
+ expect(screen.getByRole('button', { name: defaultProps.toggleContent })).toHaveAttribute('aria-expanded', 'true');
97
+ expect(screen.getByText('Thinking content')).toBeVisible();
98
+ });
99
+
100
+ it('expandableSectionProps.onToggle overrides internal onToggle behavior', async () => {
101
+ const user = userEvent.setup();
102
+ const customOnToggle = jest.fn();
103
+
104
+ render(
105
+ <DeepThinking
106
+ {...defaultProps}
107
+ isDefaultExpanded={false}
108
+ body="Thinking content"
109
+ expandableSectionProps={{ onToggle: customOnToggle }}
110
+ />
111
+ );
112
+
113
+ const toggleButton = screen.getByRole('button', { name: defaultProps.toggleContent });
114
+ expect(toggleButton).toHaveAttribute('aria-expanded', 'false');
115
+
116
+ await user.click(toggleButton);
117
+
118
+ expect(customOnToggle).toHaveBeenCalled();
119
+ expect(toggleButton).toHaveAttribute('aria-expanded', 'false');
120
+ expect(screen.getByText('Thinking content')).not.toBeVisible();
121
+ });
122
+
123
+ it('should render toggleContent as markdown when isToggleContentMarkdown is true', () => {
124
+ const toggleContent = '**Bold thinking**';
125
+ const { container } = render(<DeepThinking toggleContent={toggleContent} isToggleContentMarkdown />);
126
+ expect(container.querySelector('strong')).toBeTruthy();
127
+ expect(screen.getByText('Bold thinking')).toBeTruthy();
128
+ });
129
+
130
+ it('should not render toggleContent as markdown when isToggleContentMarkdown is false', () => {
131
+ const toggleContent = '**Bold thinking**';
132
+ const { container } = render(<DeepThinking toggleContent={toggleContent} />);
133
+ expect(container.querySelector('strong')).toBeFalsy();
134
+ expect(screen.getByText('**Bold thinking**')).toBeTruthy();
135
+ });
136
+
137
+ it('should render subheading as markdown when isSubheadingMarkdown is true', () => {
138
+ const subheading = '**Bold subheading**';
139
+ const { container } = render(<DeepThinking {...defaultProps} subheading={subheading} isSubheadingMarkdown />);
140
+ expect(container.querySelector('strong')).toBeTruthy();
141
+ expect(screen.getByText('Bold subheading')).toBeTruthy();
142
+ });
143
+
144
+ it('should not render subheading as markdown when isSubheadingMarkdown is false', () => {
145
+ const subheading = '**Bold subheading**';
146
+ render(<DeepThinking {...defaultProps} subheading={subheading} />);
147
+ expect(screen.getByText('**Bold subheading**')).toBeTruthy();
148
+ });
149
+
150
+ it('should render body as markdown when isBodyMarkdown is true', () => {
151
+ const body = '**Bold body**';
152
+ const { container } = render(<DeepThinking {...defaultProps} body={body} isBodyMarkdown />);
153
+ expect(container.querySelector('strong')).toBeTruthy();
154
+ expect(screen.getByText('Bold body')).toBeTruthy();
155
+ });
156
+
157
+ it('should not render body as markdown when isBodyMarkdown is false', () => {
158
+ const body = '**Bold body**';
159
+ render(<DeepThinking {...defaultProps} body={body} />);
160
+ expect(screen.getByText('**Bold body**')).toBeTruthy();
161
+ });
162
+
163
+ it('should pass markdownContentProps to MarkdownContent component', () => {
164
+ const body = '**Bold body**';
165
+ const { container } = render(
166
+ <DeepThinking {...defaultProps} body={body} isBodyMarkdown markdownContentProps={{ isPrimary: true }} />
167
+ );
168
+ expect(container.querySelector('.pf-m-primary')).toBeTruthy();
169
+ });
61
170
  });
@@ -10,10 +10,14 @@ import {
10
10
  ExpandableSectionProps
11
11
  } from '@patternfly/react-core';
12
12
  import { useState, type FunctionComponent } from 'react';
13
+ import MarkdownContent from '../MarkdownContent';
14
+ import type { MarkdownContentProps } from '../MarkdownContent';
13
15
 
14
16
  export interface DeepThinkingProps {
15
17
  /** Toggle content shown for expandable section */
16
18
  toggleContent: React.ReactNode;
19
+ /** Flag indicating whether the expandable content is expanded by default. */
20
+ isDefaultExpanded?: boolean;
17
21
  /** Additional props passed to expandable section */
18
22
  expandableSectionProps?: Omit<ExpandableSectionProps, 'ref'>;
19
23
  /** Subheading rendered inside expandable section */
@@ -24,6 +28,16 @@ export interface DeepThinkingProps {
24
28
  cardProps?: CardProps;
25
29
  /** Additional props passed to main card body */
26
30
  cardBodyProps?: CardBodyProps;
31
+ /** Whether to enable markdown rendering for toggleContent. When true and toggleContent is a string, it will be parsed as markdown. */
32
+ isToggleContentMarkdown?: boolean;
33
+ /** Whether to enable markdown rendering for subheading. When true, subheading will be parsed as markdown. */
34
+ isSubheadingMarkdown?: boolean;
35
+ /** Whether to enable markdown rendering for body. When true and body is a string, it will be parsed as markdown. */
36
+ isBodyMarkdown?: boolean;
37
+ /** Props passed to MarkdownContent component when markdown is enabled */
38
+ markdownContentProps?: Omit<MarkdownContentProps, 'content'>;
39
+ /** Whether to retain styles in the MarkdownContent component. Defaults to false. */
40
+ shouldRetainStyles?: boolean;
27
41
  }
28
42
 
29
43
  export const DeepThinking: FunctionComponent<DeepThinkingProps> = ({
@@ -32,19 +46,54 @@ export const DeepThinking: FunctionComponent<DeepThinkingProps> = ({
32
46
  expandableSectionProps,
33
47
  subheading,
34
48
  toggleContent,
35
- cardBodyProps
49
+ isDefaultExpanded = true,
50
+ cardBodyProps,
51
+ isToggleContentMarkdown,
52
+ isSubheadingMarkdown,
53
+ isBodyMarkdown,
54
+ markdownContentProps,
55
+ shouldRetainStyles = false
36
56
  }: DeepThinkingProps) => {
37
- const [isExpanded, setIsExpanded] = useState(true);
57
+ const [isExpanded, setIsExpanded] = useState(isDefaultExpanded);
38
58
 
39
59
  const onToggle = (_event: React.MouseEvent, isExpanded: boolean) => {
40
60
  setIsExpanded(isExpanded);
41
61
  };
42
62
 
63
+ const renderToggleContent = () => {
64
+ if (isToggleContentMarkdown && typeof toggleContent === 'string') {
65
+ return (
66
+ <MarkdownContent shouldRetainStyles={shouldRetainStyles} content={toggleContent} {...markdownContentProps} />
67
+ );
68
+ }
69
+ return toggleContent;
70
+ };
71
+
72
+ const renderSubheading = () => {
73
+ if (!subheading) {
74
+ return null;
75
+ }
76
+ if (isSubheadingMarkdown) {
77
+ return <MarkdownContent shouldRetainStyles={shouldRetainStyles} content={subheading} {...markdownContentProps} />;
78
+ }
79
+ return subheading;
80
+ };
81
+
82
+ const renderBody = () => {
83
+ if (!body) {
84
+ return null;
85
+ }
86
+ if (isBodyMarkdown && typeof body === 'string') {
87
+ return <MarkdownContent shouldRetainStyles={shouldRetainStyles} content={body} {...markdownContentProps} />;
88
+ }
89
+ return body;
90
+ };
91
+
43
92
  return (
44
93
  <Card isCompact className="pf-chatbot__deep-thinking" {...cardProps}>
45
94
  <CardBody {...cardBodyProps}>
46
95
  <ExpandableSection
47
- toggleContent={toggleContent}
96
+ toggleContent={renderToggleContent()}
48
97
  onToggle={onToggle}
49
98
  isExpanded={isExpanded}
50
99
  isIndented
@@ -54,10 +103,10 @@ export const DeepThinking: FunctionComponent<DeepThinkingProps> = ({
54
103
  <div className="pf-chatbot__deep-thinking-section">
55
104
  {subheading && (
56
105
  <div className="pf-chatbot__deep-thinking-subheading">
57
- <span>{subheading}</span>
106
+ <span>{renderSubheading()}</span>
58
107
  </div>
59
108
  )}
60
- {body && <div className="pf-chatbot__deep-thinking-body">{body}</div>}
109
+ {body && <div className="pf-chatbot__deep-thinking-body">{renderBody()}</div>}
61
110
  </div>
62
111
  </ExpandableSection>
63
112
  </CardBody>