@patternfly/chatbot 2.2.0-prerelease.27 → 2.2.0-prerelease.28

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 (48) hide show
  1. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.d.ts +3 -3
  2. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +3 -3
  3. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +1 -1
  4. package/dist/cjs/ChatbotFooter/ChatbotFootnote.d.ts +1 -1
  5. package/dist/cjs/ChatbotFooter/ChatbotFootnote.js +1 -1
  6. package/dist/cjs/ChatbotHeader/ChatbotHeaderSelectorDropdown.js +3 -3
  7. package/dist/cjs/ChatbotHeader/ChatbotHeaderSelectorDropdown.test.js +2 -2
  8. package/dist/cjs/ChatbotWelcomePrompt/ChatbotWelcomePrompt.test.js +19 -11
  9. package/dist/cjs/ResponseActions/ResponseActions.test.js +2 -2
  10. package/dist/css/main.css +3 -3
  11. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.d.ts +3 -3
  12. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +3 -3
  13. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +1 -1
  14. package/dist/esm/ChatbotFooter/ChatbotFootnote.d.ts +1 -1
  15. package/dist/esm/ChatbotFooter/ChatbotFootnote.js +1 -1
  16. package/dist/esm/ChatbotHeader/ChatbotHeaderSelectorDropdown.js +3 -3
  17. package/dist/esm/ChatbotHeader/ChatbotHeaderSelectorDropdown.test.js +2 -2
  18. package/dist/esm/ChatbotWelcomePrompt/ChatbotWelcomePrompt.test.js +19 -11
  19. package/dist/esm/ResponseActions/ResponseActions.test.js +2 -2
  20. package/package.json +1 -1
  21. package/patternfly-docs/content/extensions/chatbot/examples/Messages/AttachmentError.tsx +2 -2
  22. package/patternfly-docs/content/extensions/chatbot/examples/Messages/BotMessage.tsx +19 -6
  23. package/patternfly-docs/content/extensions/chatbot/examples/Messages/FileDropZone.tsx +2 -1
  24. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithAttachment.tsx +2 -2
  25. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithCustomResponseActions.tsx +1 -1
  26. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithQuickResponses.tsx +1 -1
  27. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithQuickStart.tsx +2 -2
  28. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithResponseActions.tsx +1 -1
  29. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithSources.tsx +1 -1
  30. package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessage.tsx +2 -2
  31. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotFootnote.tsx +4 -4
  32. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderBasic.tsx +1 -1
  33. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotWelcomeInteraction.tsx +1 -1
  34. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotWelcomePrompt.tsx +7 -7
  35. package/patternfly-docs/content/extensions/chatbot/examples/demos/Chatbot.tsx +10 -10
  36. package/patternfly-docs/content/extensions/chatbot/examples/demos/ChatbotAttachment.tsx +1 -1
  37. package/patternfly-docs/content/extensions/chatbot/examples/demos/ChatbotAttachmentMenu.tsx +1 -1
  38. package/patternfly-docs/content/extensions/chatbot/examples/demos/EmbeddedChatbot.tsx +10 -10
  39. package/patternfly-docs/content/extensions/chatbot/examples/demos/EmbeddedComparisonChatbot.tsx +1 -1
  40. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.tsx +3 -3
  41. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.tsx +4 -4
  42. package/src/ChatbotFooter/ChatbotFootnote.tsx +2 -2
  43. package/src/ChatbotHeader/ChatbotHeaderSelectorDropdown.test.tsx +2 -2
  44. package/src/ChatbotHeader/ChatbotHeaderSelectorDropdown.tsx +3 -3
  45. package/src/ChatbotWelcomePrompt/ChatbotWelcomePrompt.test.tsx +26 -18
  46. package/src/ChatbotWelcomePrompt/__snapshots__/ChatbotWelcomePrompt.test.tsx.snap +2 -2
  47. package/src/MessageBar/MessageBar.scss +3 -3
  48. package/src/ResponseActions/ResponseActions.test.tsx +4 -2
@@ -1,11 +1,11 @@
1
1
  import React from 'react';
2
2
  import { DropdownProps } from '@patternfly/react-core';
3
3
  export interface ChatbotConversationHistoryDropdownProps extends Omit<DropdownProps, 'toggle'> {
4
- /** Dropdown items rendered in conversation options dropdown */
4
+ /** Dropdown items rendered in conversation settings dropdown */
5
5
  menuItems: React.ReactNode;
6
- /** Optional classname applied to conversation options dropdown */
6
+ /** Optional classname applied to conversation settings dropdown */
7
7
  menuClassName?: string;
8
- /** Tooltip content and aria-label applied to conversation options dropdown */
8
+ /** Tooltip content and aria-label applied to conversation settings dropdown */
9
9
  label?: string;
10
10
  /** Callback for when user selects item. */
11
11
  onSelect?: (event?: React.MouseEvent, value?: string | number) => void;
@@ -11,11 +11,11 @@ export interface Conversation {
11
11
  noIcon?: boolean;
12
12
  /** Conversation */
13
13
  text: string;
14
- /** Dropdown items rendered in conversation options dropdown */
14
+ /** Dropdown items rendered in conversation settings dropdown */
15
15
  menuItems?: React.ReactNode;
16
- /** Optional classname applied to conversation options dropdown */
16
+ /** Optional classname applied to conversation settings dropdown */
17
17
  menuClassName?: string;
18
- /** Tooltip content and aria-label applied to conversation options dropdown */
18
+ /** Tooltip content and aria-label applied to conversation settings dropdown */
19
19
  label?: string;
20
20
  /** Callback for when user selects item. */
21
21
  onSelect?: (event?: React.MouseEvent, value?: string | number) => void;
@@ -27,7 +27,7 @@ const ChatbotConversationHistoryDropdown_1 = __importDefault(require("./ChatbotC
27
27
  const LoadingState_1 = __importDefault(require("./LoadingState"));
28
28
  const EmptyState_1 = __importDefault(require("./EmptyState"));
29
29
  const ChatbotConversationHistoryNav = (_a) => {
30
- var { onDrawerToggle, isDrawerOpen, setIsDrawerOpen, activeItemId, onSelectActiveItem, conversations, newChatButtonText = 'New chat', drawerContent, onNewChat, searchInputPlaceholder = 'Search...', searchInputAriaLabel = 'Filter menu items', handleTextInputChange, displayMode, reverseButtonOrder = false, drawerActionsTestId = 'chatbot-nav-drawer-actions', menuProps, drawerPanelContentProps, drawerContentProps, drawerContentBodyProps, drawerHeadProps, drawerActionsProps, drawerCloseButtonProps, drawerPanelBodyProps, isLoading, loadingState, errorState } = _a, props = __rest(_a, ["onDrawerToggle", "isDrawerOpen", "setIsDrawerOpen", "activeItemId", "onSelectActiveItem", "conversations", "newChatButtonText", "drawerContent", "onNewChat", "searchInputPlaceholder", "searchInputAriaLabel", "handleTextInputChange", "displayMode", "reverseButtonOrder", "drawerActionsTestId", "menuProps", "drawerPanelContentProps", "drawerContentProps", "drawerContentBodyProps", "drawerHeadProps", "drawerActionsProps", "drawerCloseButtonProps", "drawerPanelBodyProps", "isLoading", "loadingState", "errorState"]);
30
+ var { onDrawerToggle, isDrawerOpen, setIsDrawerOpen, activeItemId, onSelectActiveItem, conversations, newChatButtonText = 'New chat', drawerContent, onNewChat, searchInputPlaceholder = 'Search previous conversations...', searchInputAriaLabel = 'Filter menu items', handleTextInputChange, displayMode, reverseButtonOrder = false, drawerActionsTestId = 'chatbot-nav-drawer-actions', menuProps, drawerPanelContentProps, drawerContentProps, drawerContentBodyProps, drawerHeadProps, drawerActionsProps, drawerCloseButtonProps, drawerPanelBodyProps, isLoading, loadingState, errorState } = _a, props = __rest(_a, ["onDrawerToggle", "isDrawerOpen", "setIsDrawerOpen", "activeItemId", "onSelectActiveItem", "conversations", "newChatButtonText", "drawerContent", "onNewChat", "searchInputPlaceholder", "searchInputAriaLabel", "handleTextInputChange", "displayMode", "reverseButtonOrder", "drawerActionsTestId", "menuProps", "drawerPanelContentProps", "drawerContentProps", "drawerContentBodyProps", "drawerHeadProps", "drawerActionsProps", "drawerCloseButtonProps", "drawerPanelBodyProps", "isLoading", "loadingState", "errorState"]);
31
31
  const drawerRef = react_1.default.useRef(null);
32
32
  const onExpand = () => {
33
33
  drawerRef.current && drawerRef.current.focus();
@@ -17,7 +17,7 @@ export interface ChatbotFootnotePopover {
17
17
  bannerImage?: ChatbotFootnotePopoverBannerImage;
18
18
  /** Optional CTA button that can be used to trigger an action and close the popover */
19
19
  cta?: ChatbotFootnotePopoverCTA;
20
- /** Optional link that can be used to show and external link like **Learn More** */
20
+ /** Optional link that can be used to show an external link like **View AI policy** */
21
21
  link?: ChatbotFootnotePopoverLink;
22
22
  /** Props for PF Popover */
23
23
  popoverProps?: PopoverProps;
@@ -42,7 +42,7 @@ const ChatbotFootnote = (_a) => {
42
42
  var _a;
43
43
  setIsVisible(false);
44
44
  (_a = popover.cta) === null || _a === void 0 ? void 0 : _a.onClick();
45
- } }, ((_b = popover.cta) === null || _b === void 0 ? void 0 : _b.label) || 'Got it')),
45
+ } }, ((_b = popover.cta) === null || _b === void 0 ? void 0 : _b.label) || 'Dismiss')),
46
46
  (popover === null || popover === void 0 ? void 0 : popover.link) && (react_1.default.createElement(react_core_1.Button, { variant: "link", component: "a", href: popover.link.url, target: "_blank", icon: react_1.default.createElement(external_link_alt_icon_1.ExternalLinkAltIcon, null), iconPosition: "end" }, popover.link.label))));
47
47
  return (react_1.default.createElement("div", Object.assign({ className: `pf-chatbot__footnote ${className !== null && className !== void 0 ? className : ''}` }, props),
48
48
  popover && (react_1.default.createElement(ChatbotPopover_1.default, Object.assign({ className: "pf-chatbot__popover--footnote", "aria-label": ((_c = popover.popoverProps) === null || _c === void 0 ? void 0 : _c['aria-label']) || 'More information', isVisible: isVisible, shouldOpen: (_event, _fn) => setIsVisible(true), shouldClose: (_event, _fn) => setIsVisible(false), bodyContent: popoverBodyContent, footerContent: popoverFooterContent, minWidth: ((_d = popover.popoverProps) === null || _d === void 0 ? void 0 : _d.minWidth) || '432', maxWidth: ((_e = popover.popoverProps) === null || _e === void 0 ? void 0 : _e.maxWidth) || '432', distance: ((_f = popover.popoverProps) === null || _f === void 0 ? void 0 : _f.distance) || 16, showClose: false }, popover.popoverProps),
@@ -18,16 +18,16 @@ exports.ChatbotHeaderSelectorDropdown = void 0;
18
18
  const react_1 = __importDefault(require("react"));
19
19
  const react_core_1 = require("@patternfly/react-core");
20
20
  const ChatbotHeaderSelectorDropdown = (_a) => {
21
- var { value, className, children, onSelect, tooltipProps, tooltipContent = 'Chatbot selector', menuToggleAriaLabel } = _a, props = __rest(_a, ["value", "className", "children", "onSelect", "tooltipProps", "tooltipContent", "menuToggleAriaLabel"]);
21
+ var { value, className, children, onSelect, tooltipProps, tooltipContent = 'Select model', menuToggleAriaLabel } = _a, props = __rest(_a, ["value", "className", "children", "onSelect", "tooltipProps", "tooltipContent", "menuToggleAriaLabel"]);
22
22
  const [isOptionsMenuOpen, setIsOptionsMenuOpen] = react_1.default.useState(false);
23
- const [defaultAriaLabel, setDefaultAriaLabel] = react_1.default.useState('Chatbot selector');
23
+ const [defaultAriaLabel, setDefaultAriaLabel] = react_1.default.useState('Select model');
24
24
  const toggle = (toggleRef) => (react_1.default.createElement(react_core_1.Tooltip, Object.assign({ className: "pf-chatbot__tooltip", content: tooltipContent, position: "bottom",
25
25
  // prevents VO announcements of both aria label and tooltip
26
26
  aria: "none" }, tooltipProps),
27
27
  react_1.default.createElement(react_core_1.MenuToggle, { variant: "secondary", "aria-label": menuToggleAriaLabel !== null && menuToggleAriaLabel !== void 0 ? menuToggleAriaLabel : defaultAriaLabel, ref: toggleRef, isExpanded: isOptionsMenuOpen, onClick: () => setIsOptionsMenuOpen(!isOptionsMenuOpen) }, value)));
28
28
  return (react_1.default.createElement(react_core_1.Dropdown, Object.assign({ className: `pf-chatbot__selections ${className !== null && className !== void 0 ? className : ''}`, isOpen: isOptionsMenuOpen, onSelect: (e, value) => {
29
29
  onSelect && onSelect(e, value);
30
- setDefaultAriaLabel(`Chatbot selector: ${value}`);
30
+ setDefaultAriaLabel(`Select model: ${value}`);
31
31
  setIsOptionsMenuOpen(false);
32
32
  }, onOpenChange: (isOpen) => setIsOptionsMenuOpen(isOpen), popperProps: { position: 'right', appendTo: 'inline' }, shouldFocusToggleOnSelect: true, shouldFocusFirstItemOnOpen: true, toggle: toggle }, props), children));
33
33
  };
@@ -23,13 +23,13 @@ describe('ChatbotHeaderSelectorDropdown', () => {
23
23
  react_1.default.createElement(react_core_1.DropdownItem, null, "Option 3")));
24
24
  it('should render ChatbotHeaderSelectorDropdown', () => {
25
25
  (0, react_2.render)(react_1.default.createElement(ChatbotHeaderSelectorDropdown_1.ChatbotHeaderSelectorDropdown, { value: "Option 1" }, dropdownItems));
26
- expect(react_2.screen.getByRole('button', { name: 'Chatbot selector' })).toBeTruthy();
26
+ expect(react_2.screen.getByRole('button', { name: /Select model/i })).toBeTruthy();
27
27
  });
28
28
  it('should call onselect handler when a dropdown item is clicked', () => __awaiter(void 0, void 0, void 0, function* () {
29
29
  const onSelect = jest.fn();
30
30
  const { container } = (0, react_2.render)(react_1.default.createElement(ChatbotHeaderSelectorDropdown_1.ChatbotHeaderSelectorDropdown, { value: "Option 1", className: "custom-header-selector-dropdown", onSelect: onSelect }, dropdownItems));
31
31
  (0, react_2.act)(() => {
32
- react_2.fireEvent.click(react_2.screen.getByRole('button', { name: 'Chatbot selector' }));
32
+ react_2.fireEvent.click(react_2.screen.getByRole('button', { name: /Select model/i }));
33
33
  });
34
34
  yield (0, react_2.waitFor)(() => {
35
35
  expect(container.querySelector('.custom-header-selector-dropdown')).toBeTruthy();
@@ -19,30 +19,38 @@ const ChatbotWelcomePrompt_1 = __importDefault(require("./ChatbotWelcomePrompt")
19
19
  const user_event_1 = __importDefault(require("@testing-library/user-event"));
20
20
  describe('ChatbotWelcomePrompt', () => {
21
21
  it('should render welcome prompt', () => {
22
- const { container } = (0, react_2.render)(react_1.default.createElement(ChatbotWelcomePrompt_1.default, { title: "Hello, Chatbot User", description: "How may I help you today?" }));
22
+ const { container } = (0, react_2.render)(react_1.default.createElement(ChatbotWelcomePrompt_1.default, { title: "Hi, ChatBot User!", description: "How can I help you today?" }));
23
23
  expect(container).toMatchSnapshot();
24
24
  });
25
25
  it('should render correctly', () => {
26
- (0, react_2.render)(react_1.default.createElement(ChatbotWelcomePrompt_1.default, { title: "Hello, Chatbot User", description: "How may I help you today?" }));
27
- expect(react_2.screen.getByText('Hello, Chatbot User')).toBeTruthy();
28
- expect(react_2.screen.getByText('How may I help you today?')).toBeTruthy();
26
+ (0, react_2.render)(react_1.default.createElement(ChatbotWelcomePrompt_1.default, { title: "Hi, ChatBot User!", description: "How can I help you today?" }));
27
+ expect(react_2.screen.getByText('Hi, ChatBot User!')).toBeTruthy();
28
+ expect(react_2.screen.getByText('How can I help you today?')).toBeTruthy();
29
29
  });
30
30
  it('should render prompts with titles correctly', () => {
31
- (0, react_2.render)(react_1.default.createElement(ChatbotWelcomePrompt_1.default, { title: "Hello, Chatbot User", description: "How may I help you today?", prompts: [{ title: 'Topic 1' }] }));
32
- expect(react_2.screen.getByText('Topic 1')).toBeTruthy();
31
+ (0, react_2.render)(react_1.default.createElement(ChatbotWelcomePrompt_1.default, { title: "Hi, ChatBot User!", description: "How can I help you today?", prompts: [{ title: 'Set up account' }] }));
32
+ expect(react_2.screen.getByText('Set up account')).toBeTruthy();
33
33
  });
34
34
  it('should render prompts with messages correctly', () => {
35
- (0, react_2.render)(react_1.default.createElement(ChatbotWelcomePrompt_1.default, { title: "Hello, Chatbot User", description: "How may I help you today?", prompts: [{ title: 'Topic 1', message: 'Helpful prompt for Topic 1' }] }));
36
- expect(react_2.screen.getByText('Helpful prompt for Topic 1')).toBeTruthy();
35
+ (0, react_2.render)(react_1.default.createElement(ChatbotWelcomePrompt_1.default, { title: "Hi, ChatBot User!", description: "How can I help you today?", prompts: [
36
+ { title: 'Set up account', message: 'Choose the necessary settings and preferences for your account.' }
37
+ ] }));
38
+ expect(react_2.screen.getByText('Choose the necessary settings and preferences for your account.')).toBeTruthy();
37
39
  });
38
40
  it('should render prompts with onClick correctly', () => __awaiter(void 0, void 0, void 0, function* () {
39
41
  const spy = jest.fn();
40
- (0, react_2.render)(react_1.default.createElement(ChatbotWelcomePrompt_1.default, { title: "Hello, Chatbot User", description: "How may I help you today?", prompts: [{ title: 'Topic 1', message: 'Helpful prompt for Topic 1', onClick: spy }] }));
41
- yield user_event_1.default.click(react_2.screen.getByRole('button', { name: /Topic 1/i }));
42
+ (0, react_2.render)(react_1.default.createElement(ChatbotWelcomePrompt_1.default, { title: "Hi, ChatBot User!", description: "How can I help you today?", prompts: [
43
+ {
44
+ title: 'Set up account',
45
+ message: 'Choose the necessary settings and preferences for your account.',
46
+ onClick: spy
47
+ }
48
+ ] }));
49
+ yield user_event_1.default.click(react_2.screen.getByRole('button', { name: /Set up account/i }));
42
50
  expect(spy).toHaveBeenCalled();
43
51
  }));
44
52
  it('should apply className appropriately', () => {
45
- (0, react_2.render)(react_1.default.createElement(ChatbotWelcomePrompt_1.default, { title: "Hello, Chatbot User", description: "How may I help you today?", className: "test", testId: "welcome-prompt" }));
53
+ (0, react_2.render)(react_1.default.createElement(ChatbotWelcomePrompt_1.default, { title: "Hi, ChatBot User!", description: "How can I help you today?", className: "test", testId: "welcome-prompt" }));
46
54
  const element = react_2.screen.getByTestId('welcome-prompt');
47
55
  expect(element).toHaveClass('test');
48
56
  });
@@ -88,7 +88,7 @@ describe('ResponseActions', () => {
88
88
  }));
89
89
  it('should handle click outside of group of buttons correctly', () => __awaiter(void 0, void 0, void 0, function* () {
90
90
  // using message just so we have something outside the group that's rendered
91
- (0, react_2.render)(react_1.default.createElement(Message_1.default, { name: "Bot", role: "bot", avatar: "", content: "Example with all prebuilt actions", actions: {
91
+ (0, react_2.render)(react_1.default.createElement(Message_1.default, { name: "Bot", role: "bot", avatar: "", content: "I updated your account with those settings. You're ready to set up your first dashboard!", actions: {
92
92
  positive: {},
93
93
  negative: {}
94
94
  } }));
@@ -102,7 +102,7 @@ describe('ResponseActions', () => {
102
102
  yield user_event_1.default.click(badBtn);
103
103
  expect(react_2.screen.getByRole('button', { name: 'Response recorded' })).toHaveClass('pf-chatbot__button--response-action-clicked');
104
104
  expect(goodBtn).not.toHaveClass('pf-chatbot__button--response-action-clicked');
105
- yield user_event_1.default.click(react_2.screen.getByText('Example with all prebuilt actions'));
105
+ yield user_event_1.default.click(react_2.screen.getByText("I updated your account with those settings. You're ready to set up your first dashboard!"));
106
106
  expect(goodBtn).not.toHaveClass('pf-chatbot__button--response-action-clicked');
107
107
  expect(badBtn).not.toHaveClass('pf-chatbot__button--response-action-clicked');
108
108
  }));
package/dist/css/main.css CHANGED
@@ -1616,13 +1616,13 @@
1616
1616
  .pf-chatbot__message-textarea .pf-v6-c-form-control__textarea:focus-visible {
1617
1617
  outline: none;
1618
1618
  }
1619
- .pf-chatbot__message-textarea .pf-v6-c-form-control > textarea {
1620
- outline-offset: 0px;
1619
+ .pf-chatbot__message-textarea textarea {
1620
+ outline-offset: 0px !important;
1621
1621
  --pf-v6-c-form-control--PaddingBlockStart: 0;
1622
1622
  --pf-v6-c-form-control--PaddingBlockEnd: 0;
1623
1623
  --pf-v6-c-form-control--BorderRadius: 0;
1624
1624
  }
1625
- .pf-chatbot__message-textarea .pf-v6-c-form-control > textarea:focus-visible {
1625
+ .pf-chatbot__message-textarea textarea:focus-visible {
1626
1626
  outline: none;
1627
1627
  }
1628
1628
 
@@ -1,11 +1,11 @@
1
1
  import React from 'react';
2
2
  import { DropdownProps } from '@patternfly/react-core';
3
3
  export interface ChatbotConversationHistoryDropdownProps extends Omit<DropdownProps, 'toggle'> {
4
- /** Dropdown items rendered in conversation options dropdown */
4
+ /** Dropdown items rendered in conversation settings dropdown */
5
5
  menuItems: React.ReactNode;
6
- /** Optional classname applied to conversation options dropdown */
6
+ /** Optional classname applied to conversation settings dropdown */
7
7
  menuClassName?: string;
8
- /** Tooltip content and aria-label applied to conversation options dropdown */
8
+ /** Tooltip content and aria-label applied to conversation settings dropdown */
9
9
  label?: string;
10
10
  /** Callback for when user selects item. */
11
11
  onSelect?: (event?: React.MouseEvent, value?: string | number) => void;
@@ -11,11 +11,11 @@ export interface Conversation {
11
11
  noIcon?: boolean;
12
12
  /** Conversation */
13
13
  text: string;
14
- /** Dropdown items rendered in conversation options dropdown */
14
+ /** Dropdown items rendered in conversation settings dropdown */
15
15
  menuItems?: React.ReactNode;
16
- /** Optional classname applied to conversation options dropdown */
16
+ /** Optional classname applied to conversation settings dropdown */
17
17
  menuClassName?: string;
18
- /** Tooltip content and aria-label applied to conversation options dropdown */
18
+ /** Tooltip content and aria-label applied to conversation settings dropdown */
19
19
  label?: string;
20
20
  /** Callback for when user selects item. */
21
21
  onSelect?: (event?: React.MouseEvent, value?: string | number) => void;
@@ -21,7 +21,7 @@ import ConversationHistoryDropdown from './ChatbotConversationHistoryDropdown';
21
21
  import LoadingState from './LoadingState';
22
22
  import HistoryEmptyState from './EmptyState';
23
23
  export const ChatbotConversationHistoryNav = (_a) => {
24
- var { onDrawerToggle, isDrawerOpen, setIsDrawerOpen, activeItemId, onSelectActiveItem, conversations, newChatButtonText = 'New chat', drawerContent, onNewChat, searchInputPlaceholder = 'Search...', searchInputAriaLabel = 'Filter menu items', handleTextInputChange, displayMode, reverseButtonOrder = false, drawerActionsTestId = 'chatbot-nav-drawer-actions', menuProps, drawerPanelContentProps, drawerContentProps, drawerContentBodyProps, drawerHeadProps, drawerActionsProps, drawerCloseButtonProps, drawerPanelBodyProps, isLoading, loadingState, errorState } = _a, props = __rest(_a, ["onDrawerToggle", "isDrawerOpen", "setIsDrawerOpen", "activeItemId", "onSelectActiveItem", "conversations", "newChatButtonText", "drawerContent", "onNewChat", "searchInputPlaceholder", "searchInputAriaLabel", "handleTextInputChange", "displayMode", "reverseButtonOrder", "drawerActionsTestId", "menuProps", "drawerPanelContentProps", "drawerContentProps", "drawerContentBodyProps", "drawerHeadProps", "drawerActionsProps", "drawerCloseButtonProps", "drawerPanelBodyProps", "isLoading", "loadingState", "errorState"]);
24
+ var { onDrawerToggle, isDrawerOpen, setIsDrawerOpen, activeItemId, onSelectActiveItem, conversations, newChatButtonText = 'New chat', drawerContent, onNewChat, searchInputPlaceholder = 'Search previous conversations...', searchInputAriaLabel = 'Filter menu items', handleTextInputChange, displayMode, reverseButtonOrder = false, drawerActionsTestId = 'chatbot-nav-drawer-actions', menuProps, drawerPanelContentProps, drawerContentProps, drawerContentBodyProps, drawerHeadProps, drawerActionsProps, drawerCloseButtonProps, drawerPanelBodyProps, isLoading, loadingState, errorState } = _a, props = __rest(_a, ["onDrawerToggle", "isDrawerOpen", "setIsDrawerOpen", "activeItemId", "onSelectActiveItem", "conversations", "newChatButtonText", "drawerContent", "onNewChat", "searchInputPlaceholder", "searchInputAriaLabel", "handleTextInputChange", "displayMode", "reverseButtonOrder", "drawerActionsTestId", "menuProps", "drawerPanelContentProps", "drawerContentProps", "drawerContentBodyProps", "drawerHeadProps", "drawerActionsProps", "drawerCloseButtonProps", "drawerPanelBodyProps", "isLoading", "loadingState", "errorState"]);
25
25
  const drawerRef = React.useRef(null);
26
26
  const onExpand = () => {
27
27
  drawerRef.current && drawerRef.current.focus();
@@ -17,7 +17,7 @@ export interface ChatbotFootnotePopover {
17
17
  bannerImage?: ChatbotFootnotePopoverBannerImage;
18
18
  /** Optional CTA button that can be used to trigger an action and close the popover */
19
19
  cta?: ChatbotFootnotePopoverCTA;
20
- /** Optional link that can be used to show and external link like **Learn More** */
20
+ /** Optional link that can be used to show an external link like **View AI policy** */
21
21
  link?: ChatbotFootnotePopoverLink;
22
22
  /** Props for PF Popover */
23
23
  popoverProps?: PopoverProps;
@@ -36,7 +36,7 @@ export const ChatbotFootnote = (_a) => {
36
36
  var _a;
37
37
  setIsVisible(false);
38
38
  (_a = popover.cta) === null || _a === void 0 ? void 0 : _a.onClick();
39
- } }, ((_b = popover.cta) === null || _b === void 0 ? void 0 : _b.label) || 'Got it')),
39
+ } }, ((_b = popover.cta) === null || _b === void 0 ? void 0 : _b.label) || 'Dismiss')),
40
40
  (popover === null || popover === void 0 ? void 0 : popover.link) && (React.createElement(Button, { variant: "link", component: "a", href: popover.link.url, target: "_blank", icon: React.createElement(ExternalLinkAltIcon, null), iconPosition: "end" }, popover.link.label))));
41
41
  return (React.createElement("div", Object.assign({ className: `pf-chatbot__footnote ${className !== null && className !== void 0 ? className : ''}` }, props),
42
42
  popover && (React.createElement(ChatbotPopover, Object.assign({ className: "pf-chatbot__popover--footnote", "aria-label": ((_c = popover.popoverProps) === null || _c === void 0 ? void 0 : _c['aria-label']) || 'More information', isVisible: isVisible, shouldOpen: (_event, _fn) => setIsVisible(true), shouldClose: (_event, _fn) => setIsVisible(false), bodyContent: popoverBodyContent, footerContent: popoverFooterContent, minWidth: ((_d = popover.popoverProps) === null || _d === void 0 ? void 0 : _d.minWidth) || '432', maxWidth: ((_e = popover.popoverProps) === null || _e === void 0 ? void 0 : _e.maxWidth) || '432', distance: ((_f = popover.popoverProps) === null || _f === void 0 ? void 0 : _f.distance) || 16, showClose: false }, popover.popoverProps),
@@ -12,16 +12,16 @@ var __rest = (this && this.__rest) || function (s, e) {
12
12
  import React from 'react';
13
13
  import { Tooltip, Dropdown, MenuToggle } from '@patternfly/react-core';
14
14
  export const ChatbotHeaderSelectorDropdown = (_a) => {
15
- var { value, className, children, onSelect, tooltipProps, tooltipContent = 'Chatbot selector', menuToggleAriaLabel } = _a, props = __rest(_a, ["value", "className", "children", "onSelect", "tooltipProps", "tooltipContent", "menuToggleAriaLabel"]);
15
+ var { value, className, children, onSelect, tooltipProps, tooltipContent = 'Select model', menuToggleAriaLabel } = _a, props = __rest(_a, ["value", "className", "children", "onSelect", "tooltipProps", "tooltipContent", "menuToggleAriaLabel"]);
16
16
  const [isOptionsMenuOpen, setIsOptionsMenuOpen] = React.useState(false);
17
- const [defaultAriaLabel, setDefaultAriaLabel] = React.useState('Chatbot selector');
17
+ const [defaultAriaLabel, setDefaultAriaLabel] = React.useState('Select model');
18
18
  const toggle = (toggleRef) => (React.createElement(Tooltip, Object.assign({ className: "pf-chatbot__tooltip", content: tooltipContent, position: "bottom",
19
19
  // prevents VO announcements of both aria label and tooltip
20
20
  aria: "none" }, tooltipProps),
21
21
  React.createElement(MenuToggle, { variant: "secondary", "aria-label": menuToggleAriaLabel !== null && menuToggleAriaLabel !== void 0 ? menuToggleAriaLabel : defaultAriaLabel, ref: toggleRef, isExpanded: isOptionsMenuOpen, onClick: () => setIsOptionsMenuOpen(!isOptionsMenuOpen) }, value)));
22
22
  return (React.createElement(Dropdown, Object.assign({ className: `pf-chatbot__selections ${className !== null && className !== void 0 ? className : ''}`, isOpen: isOptionsMenuOpen, onSelect: (e, value) => {
23
23
  onSelect && onSelect(e, value);
24
- setDefaultAriaLabel(`Chatbot selector: ${value}`);
24
+ setDefaultAriaLabel(`Select model: ${value}`);
25
25
  setIsOptionsMenuOpen(false);
26
26
  }, onOpenChange: (isOpen) => setIsOptionsMenuOpen(isOpen), popperProps: { position: 'right', appendTo: 'inline' }, shouldFocusToggleOnSelect: true, shouldFocusFirstItemOnOpen: true, toggle: toggle }, props), children));
27
27
  };
@@ -18,13 +18,13 @@ describe('ChatbotHeaderSelectorDropdown', () => {
18
18
  React.createElement(DropdownItem, null, "Option 3")));
19
19
  it('should render ChatbotHeaderSelectorDropdown', () => {
20
20
  render(React.createElement(ChatbotHeaderSelectorDropdown, { value: "Option 1" }, dropdownItems));
21
- expect(screen.getByRole('button', { name: 'Chatbot selector' })).toBeTruthy();
21
+ expect(screen.getByRole('button', { name: /Select model/i })).toBeTruthy();
22
22
  });
23
23
  it('should call onselect handler when a dropdown item is clicked', () => __awaiter(void 0, void 0, void 0, function* () {
24
24
  const onSelect = jest.fn();
25
25
  const { container } = render(React.createElement(ChatbotHeaderSelectorDropdown, { value: "Option 1", className: "custom-header-selector-dropdown", onSelect: onSelect }, dropdownItems));
26
26
  act(() => {
27
- fireEvent.click(screen.getByRole('button', { name: 'Chatbot selector' }));
27
+ fireEvent.click(screen.getByRole('button', { name: /Select model/i }));
28
28
  });
29
29
  yield waitFor(() => {
30
30
  expect(container.querySelector('.custom-header-selector-dropdown')).toBeTruthy();
@@ -14,30 +14,38 @@ import ChatbotWelcomePrompt from './ChatbotWelcomePrompt';
14
14
  import userEvent from '@testing-library/user-event';
15
15
  describe('ChatbotWelcomePrompt', () => {
16
16
  it('should render welcome prompt', () => {
17
- const { container } = render(React.createElement(ChatbotWelcomePrompt, { title: "Hello, Chatbot User", description: "How may I help you today?" }));
17
+ const { container } = render(React.createElement(ChatbotWelcomePrompt, { title: "Hi, ChatBot User!", description: "How can I help you today?" }));
18
18
  expect(container).toMatchSnapshot();
19
19
  });
20
20
  it('should render correctly', () => {
21
- render(React.createElement(ChatbotWelcomePrompt, { title: "Hello, Chatbot User", description: "How may I help you today?" }));
22
- expect(screen.getByText('Hello, Chatbot User')).toBeTruthy();
23
- expect(screen.getByText('How may I help you today?')).toBeTruthy();
21
+ render(React.createElement(ChatbotWelcomePrompt, { title: "Hi, ChatBot User!", description: "How can I help you today?" }));
22
+ expect(screen.getByText('Hi, ChatBot User!')).toBeTruthy();
23
+ expect(screen.getByText('How can I help you today?')).toBeTruthy();
24
24
  });
25
25
  it('should render prompts with titles correctly', () => {
26
- render(React.createElement(ChatbotWelcomePrompt, { title: "Hello, Chatbot User", description: "How may I help you today?", prompts: [{ title: 'Topic 1' }] }));
27
- expect(screen.getByText('Topic 1')).toBeTruthy();
26
+ render(React.createElement(ChatbotWelcomePrompt, { title: "Hi, ChatBot User!", description: "How can I help you today?", prompts: [{ title: 'Set up account' }] }));
27
+ expect(screen.getByText('Set up account')).toBeTruthy();
28
28
  });
29
29
  it('should render prompts with messages correctly', () => {
30
- render(React.createElement(ChatbotWelcomePrompt, { title: "Hello, Chatbot User", description: "How may I help you today?", prompts: [{ title: 'Topic 1', message: 'Helpful prompt for Topic 1' }] }));
31
- expect(screen.getByText('Helpful prompt for Topic 1')).toBeTruthy();
30
+ render(React.createElement(ChatbotWelcomePrompt, { title: "Hi, ChatBot User!", description: "How can I help you today?", prompts: [
31
+ { title: 'Set up account', message: 'Choose the necessary settings and preferences for your account.' }
32
+ ] }));
33
+ expect(screen.getByText('Choose the necessary settings and preferences for your account.')).toBeTruthy();
32
34
  });
33
35
  it('should render prompts with onClick correctly', () => __awaiter(void 0, void 0, void 0, function* () {
34
36
  const spy = jest.fn();
35
- render(React.createElement(ChatbotWelcomePrompt, { title: "Hello, Chatbot User", description: "How may I help you today?", prompts: [{ title: 'Topic 1', message: 'Helpful prompt for Topic 1', onClick: spy }] }));
36
- yield userEvent.click(screen.getByRole('button', { name: /Topic 1/i }));
37
+ render(React.createElement(ChatbotWelcomePrompt, { title: "Hi, ChatBot User!", description: "How can I help you today?", prompts: [
38
+ {
39
+ title: 'Set up account',
40
+ message: 'Choose the necessary settings and preferences for your account.',
41
+ onClick: spy
42
+ }
43
+ ] }));
44
+ yield userEvent.click(screen.getByRole('button', { name: /Set up account/i }));
37
45
  expect(spy).toHaveBeenCalled();
38
46
  }));
39
47
  it('should apply className appropriately', () => {
40
- render(React.createElement(ChatbotWelcomePrompt, { title: "Hello, Chatbot User", description: "How may I help you today?", className: "test", testId: "welcome-prompt" }));
48
+ render(React.createElement(ChatbotWelcomePrompt, { title: "Hi, ChatBot User!", description: "How can I help you today?", className: "test", testId: "welcome-prompt" }));
41
49
  const element = screen.getByTestId('welcome-prompt');
42
50
  expect(element).toHaveClass('test');
43
51
  });
@@ -83,7 +83,7 @@ describe('ResponseActions', () => {
83
83
  }));
84
84
  it('should handle click outside of group of buttons correctly', () => __awaiter(void 0, void 0, void 0, function* () {
85
85
  // using message just so we have something outside the group that's rendered
86
- render(React.createElement(Message, { name: "Bot", role: "bot", avatar: "", content: "Example with all prebuilt actions", actions: {
86
+ render(React.createElement(Message, { name: "Bot", role: "bot", avatar: "", content: "I updated your account with those settings. You're ready to set up your first dashboard!", actions: {
87
87
  positive: {},
88
88
  negative: {}
89
89
  } }));
@@ -97,7 +97,7 @@ describe('ResponseActions', () => {
97
97
  yield userEvent.click(badBtn);
98
98
  expect(screen.getByRole('button', { name: 'Response recorded' })).toHaveClass('pf-chatbot__button--response-action-clicked');
99
99
  expect(goodBtn).not.toHaveClass('pf-chatbot__button--response-action-clicked');
100
- yield userEvent.click(screen.getByText('Example with all prebuilt actions'));
100
+ yield userEvent.click(screen.getByText("I updated your account with those settings. You're ready to set up your first dashboard!"));
101
101
  expect(goodBtn).not.toHaveClass('pf-chatbot__button--response-action-clicked');
102
102
  expect(badBtn).not.toHaveClass('pf-chatbot__button--response-action-clicked');
103
103
  }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patternfly/chatbot",
3
- "version": "2.2.0-prerelease.27",
3
+ "version": "2.2.0-prerelease.28",
4
4
  "description": "This library provides React components based on PatternFly 6 that can be used to build chatbots.",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -6,8 +6,8 @@ export const AttachmentErrorExample: React.FunctionComponent = () => (
6
6
  variant="danger"
7
7
  // eslint-disable-next-line no-console
8
8
  onClose={() => console.log('Clicked the close button')}
9
- title="File upload failed"
9
+ title="Could not upload file"
10
10
  >
11
- Your file size is too large. Please ensure that your file is less than 25 MB.
11
+ Your file size must be less than 25 MB.
12
12
  </ChatbotAlert>
13
13
  );
@@ -117,8 +117,8 @@ _Italic text, formatted with single underscores_
117
117
 
118
118
  1. **Using a \`toaster\`:**
119
119
 
120
- - Place \`bread\` in a \`toaster\`
121
- - Once \`bread\` is lightly browned, remove from \`toaster\`
120
+ - Place \`bread\` in a \`toaster\`.
121
+ - Once \`bread\` is lightly browned, remove from \`toaster\`.
122
122
 
123
123
  2. **Using a \`knife\`:**
124
124
 
@@ -142,19 +142,32 @@ _Italic text, formatted with single underscores_
142
142
 
143
143
  return (
144
144
  <>
145
- <Message name="Bot" role="bot" avatar={patternflyAvatar} content={`Text-based message from a bot named "Bot"`} />
146
- <Message role="bot" avatar={patternflyAvatar} content="Text-based message from a nameless bot" />
145
+ <Message
146
+ name="Bot"
147
+ role="bot"
148
+ avatar={patternflyAvatar}
149
+ content={`This is a text-based message from a bot named "Bot."`}
150
+ />
151
+ <Message
152
+ name="Bot"
153
+ role="bot"
154
+ avatar={patternflyAvatar}
155
+ content={`This is a text-based message from "Bot," with an updated timestamp.`}
156
+ timestamp="1 hour ago"
157
+ />
158
+ <Message name="Bot" role="bot" avatar={patternflyAvatar} content="Example content" isLoading />
159
+ <Message role="bot" avatar={patternflyAvatar} content="This message is from a nameless bot." />
147
160
  <Message
148
161
  name="Default Openshift Container Platform Assistant That Can Help With Any Query You Might Need Help With"
149
162
  role="bot"
150
163
  avatar={patternflyAvatar}
151
- content="Text-based message, where the bot's name is truncated"
164
+ content="This is a message from a bot with really long name: it's truncated!"
152
165
  />
153
166
  <Message
154
167
  name="Bot"
155
168
  role="bot"
156
169
  avatar={squareImg}
157
- content="Text-based message from a bot with a square avatar. You can further customize the avatar by applying an additional class or passing [PatternFly avatar props](/components/avatar) to the `<Message>` component via `avatarProps`."
170
+ content="This bot has a square avatar. You can further customize the avatar by applying an additional class or passing [PatternFly avatar props](/components/avatar) to the `<Message>` component via `avatarProps`."
158
171
  hasRoundAvatar={false}
159
172
  />
160
173
  <Message
@@ -53,7 +53,8 @@ export const DropzoneExample: React.FunctionComponent = () => {
53
53
  return (
54
54
  <FileDropZone onFileDrop={handleFileDrop} displayMode="fullscreen">
55
55
  <div className="pf-chatbot__file-drop-zone-example">
56
- Content that shows when no dragging is happening (drag an item here to see the drop zone)
56
+ This is example content that would be shown when no dragging is happening. To see the drop zone, start to drag
57
+ an item into this section. The static content will be replaced by an active drop zone message.
57
58
  </div>
58
59
  </FileDropZone>
59
60
  );
@@ -32,14 +32,14 @@ export const AttachmentMenuExample: React.FunctionComponent = () => {
32
32
  name="User"
33
33
  role="user"
34
34
  avatar={userAvatar}
35
- content="Here is an uploaded file"
35
+ content="Here is an uploaded file:"
36
36
  attachments={[{ name: 'auth-operator.yml', id: '1', onClick, onClose }]}
37
37
  />
38
38
  <Message
39
39
  name="User"
40
40
  role="user"
41
41
  avatar={userAvatar}
42
- content="Here are two uploaded files"
42
+ content="Here are 2 uploaded files:"
43
43
  attachments={[
44
44
  { name: 'auth-operator.yml', id: '1' },
45
45
  { name: 'patternfly.svg', id: '2' }
@@ -11,7 +11,7 @@ export const CustomActionExample: React.FunctionComponent = () => (
11
11
  name="Bot"
12
12
  role="bot"
13
13
  avatar={patternflyAvatar}
14
- content="Example with custom actions"
14
+ content="I updated your account with those settings. You're ready to set up your first dashboard!"
15
15
  actions={{
16
16
  regenerate: {
17
17
  ariaLabel: 'Regenerate',
@@ -31,7 +31,7 @@ export const MessageWithQuickResponsesExample: React.FunctionComponent = () => (
31
31
  name="Bot"
32
32
  role="bot"
33
33
  avatar={patternflyAvatar}
34
- content="Welcome back! How can I help?"
34
+ content="Welcome back, User! How can I help you today?"
35
35
  quickResponses={[
36
36
  { id: '1', content: 'Help me with an access issue', onClick: () => alert('Clicked id 1') },
37
37
  { id: '2', content: 'Show my critical vulnerabilities', onClick: () => alert('Clicked id 2') },
@@ -11,7 +11,7 @@ export const MessageWithQuickStartExample: React.FunctionComponent = () => (
11
11
  name="Bot"
12
12
  role="bot"
13
13
  avatar={patternflyAvatar}
14
- content="Text-based bot message with a quick start tile."
14
+ content="Follow this quick guide to install the Pipelines Operator."
15
15
  quickStarts={{
16
16
  quickStart: explorePipelinesQuickStart as QuickStart,
17
17
  onSelectQuickStart: (id) => alert(id)
@@ -21,7 +21,7 @@ export const MessageWithQuickStartExample: React.FunctionComponent = () => (
21
21
  name="Bot"
22
22
  role="bot"
23
23
  avatar={patternflyAvatar}
24
- content="Text-based bot message with a quick start tile that includes prerequisites and a default icon."
24
+ content="This quick start tile includes prerequisites and a default icon."
25
25
  quickStarts={{
26
26
  quickStart: monitorSampleAppQuickStart,
27
27
  onSelectQuickStart: (id) => alert(id)
@@ -8,7 +8,7 @@ export const ResponseActionExample: React.FunctionComponent = () => (
8
8
  name="Bot"
9
9
  role="bot"
10
10
  avatar={patternflyAvatar}
11
- content="Example with all prebuilt actions"
11
+ content="I updated your account with those settings. You're ready to set up your first dashboard!"
12
12
  actions={{
13
13
  // eslint-disable-next-line no-console
14
14
  positive: { onClick: () => console.log('Good response') },
@@ -61,7 +61,7 @@ export const MessageWithSourcesExample: React.FunctionComponent = () => {
61
61
  name="Bot"
62
62
  role="bot"
63
63
  avatar={patternflyAvatar}
64
- content="Example with only one source"
64
+ content="Example with only 1 source"
65
65
  sources={{
66
66
  sources: [
67
67
  {
@@ -145,14 +145,14 @@ _Italic text, formatted with single underscores_
145
145
  <Message
146
146
  name="User"
147
147
  role="user"
148
- content="Example content with updated timestamp text"
148
+ content="This is a user message with an updated timestamp."
149
149
  timestamp="1 hour ago"
150
150
  avatar={userAvatar}
151
151
  />
152
152
  <Message
153
153
  name="User"
154
154
  role="user"
155
- content="Example user message with `avatarProps` set to add a border"
155
+ content="This is a user message with `avatarProps` set to add a border."
156
156
  avatar={userAvatar}
157
157
  avatarProps={{ isBordered: true }}
158
158
  />
@@ -5,20 +5,20 @@ export const FootnoteDemo: React.FunctionComponent = () => (
5
5
  <ChatbotFootnote
6
6
  label="ChatBot uses AI. Check for mistakes."
7
7
  popover={{
8
- title: 'Verify accuracy',
9
- description: `While ChatBot strives for accuracy, there's always a possibility of errors. It's a good practice to verify critical information from reliable sources, especially if it's crucial for decision-making or actions.`,
8
+ title: 'Verify information',
9
+ description: `While ChatBot strives for accuracy, AI is experimental and can make mistakes. We cannot guarantee that all information provided by ChatBot is up to date or without error. You should always verify responses using reliable sources, especially for crucial information and decision making.`,
10
10
  bannerImage: {
11
11
  src: 'https://cdn.dribbble.com/userupload/10651749/file/original-8a07b8e39d9e8bf002358c66fce1223e.gif',
12
12
  alt: 'Example image for footnote popover'
13
13
  },
14
14
  cta: {
15
- label: 'Got it',
15
+ label: 'Dismiss',
16
16
  onClick: () => {
17
17
  alert('Do something!');
18
18
  }
19
19
  },
20
20
  link: {
21
- label: 'Learn more',
21
+ label: 'View AI policy',
22
22
  url: 'https://www.redhat.com/'
23
23
  }
24
24
  }}
@@ -121,7 +121,7 @@ export const BasicDemo: React.FunctionComponent = () => {
121
121
  showAll && setShowAll(!showAll);
122
122
  }}
123
123
  name="basic-inline-radio"
124
- label="With options dropdown"
124
+ label="With settings dropdown"
125
125
  id="options-dropdown"
126
126
  />
127
127
  </FormGroup>
@@ -116,7 +116,7 @@ export const ChatbotWelcomeInteractionDemo: React.FunctionComponent = () => {
116
116
  so that users of assistive devices receive sufficient context */}
117
117
  <MessageBox announcement={announcement} position={position}>
118
118
  {messages.length === 0 && (
119
- <ChatbotWelcomePrompt title="Hello, Chatbot User" description="How may I help you today?" />
119
+ <ChatbotWelcomePrompt title="Hi, ChatBot User!" description="How can I help you today?" />
120
120
  )}
121
121
  {/* This code block enables scrolling to the top of the last message.
122
122
  You can instead choose to move the div with scrollToBottomRef on it below
@@ -1,19 +1,19 @@
1
1
  import React from 'react';
2
2
 
3
3
  import ChatbotWelcomePrompt from '@patternfly/chatbot/dist/dynamic/ChatbotWelcomePrompt';
4
- import Checkbox from '@patternfly/react-core';
4
+ import { Checkbox } from '@patternfly/react-core';
5
5
 
6
6
  export const ChatbotWelcomePromptExample: React.FunctionComponent = () => {
7
7
  const [showWelcomePrompts, setShowWelcomePrompts] = React.useState(true);
8
8
 
9
9
  const welcomePrompts = [
10
10
  {
11
- title: 'Topic 1',
12
- message: 'Helpful prompt for Topic 1'
11
+ title: 'Set up account',
12
+ message: 'Choose the necessary settings and preferences for your account.'
13
13
  },
14
14
  {
15
- title: 'Topic 2',
16
- message: 'Helpful prompt for Topic 2'
15
+ title: 'Troubleshoot issue',
16
+ message: 'Find documentation and instructions to resolve your issue.'
17
17
  }
18
18
  ];
19
19
 
@@ -29,8 +29,8 @@ export const ChatbotWelcomePromptExample: React.FunctionComponent = () => {
29
29
  id="showWelcomePrompts"
30
30
  />
31
31
  <ChatbotWelcomePrompt
32
- title="Hello, Chatbot User"
33
- description="How may I help you today?"
32
+ title="Hi, ChatBot User!"
33
+ description="How can I help you today?"
34
34
  {...(showWelcomePrompts && { prompts: welcomePrompts })}
35
35
  />
36
36
  </>
@@ -36,20 +36,20 @@ import patternflyAvatar from '../Messages/patternfly_avatar.jpg';
36
36
  const footnoteProps = {
37
37
  label: 'ChatBot uses AI. Check for mistakes.',
38
38
  popover: {
39
- title: 'Verify accuracy',
40
- description: `While ChatBot strives for accuracy, there's always a possibility of errors. It's a good practice to verify critical information from reliable sources, especially if it's crucial for decision-making or actions.`,
39
+ title: 'Verify information',
40
+ description: `While ChatBot strives for accuracy, AI is experimental and can make mistakes. We cannot guarantee that all information provided by ChatBot is up to date or without error. You should always verify responses using reliable sources, especially for crucial information and decision making.`,
41
41
  bannerImage: {
42
42
  src: 'https://cdn.dribbble.com/userupload/10651749/file/original-8a07b8e39d9e8bf002358c66fce1223e.gif',
43
43
  alt: 'Example image for footnote popover'
44
44
  },
45
45
  cta: {
46
- label: 'Got it',
46
+ label: 'Dismiss',
47
47
  onClick: () => {
48
48
  alert('Do something!');
49
49
  }
50
50
  },
51
51
  link: {
52
- label: 'Learn more',
52
+ label: 'View AI policy',
53
53
  url: 'https://www.redhat.com/'
54
54
  }
55
55
  }
@@ -129,12 +129,12 @@ const initialMessages: MessageProps[] = [
129
129
 
130
130
  const welcomePrompts = [
131
131
  {
132
- title: 'Topic 1',
133
- message: 'Helpful prompt for Topic 1'
132
+ title: 'Set up account',
133
+ message: 'Choose the necessary settings and preferences for your account.'
134
134
  },
135
135
  {
136
- title: 'Topic 2',
137
- message: 'Helpful prompt for Topic 2'
136
+ title: 'Troubleshoot issue',
137
+ message: 'Find documentation and instructions to resolve your issue.'
138
138
  }
139
139
  ];
140
140
 
@@ -436,8 +436,8 @@ export const ChatbotDemo: React.FunctionComponent = () => {
436
436
  so that users of assistive devices receive sufficient context */}
437
437
  <MessageBox announcement={announcement}>
438
438
  <ChatbotWelcomePrompt
439
- title="Hello, Chatbot User"
440
- description="How may I help you today?"
439
+ title="Hi, ChatBot User!"
440
+ description="How can I help you today?"
441
441
  prompts={welcomePrompts}
442
442
  />
443
443
  {/* This code block enables scrolling to the top of the last message.
@@ -231,7 +231,7 @@ export const BasicDemo: React.FunctionComponent = () => {
231
231
  {error}
232
232
  </ChatbotAlert>
233
233
  )}
234
- <ChatbotWelcomePrompt title="Hello, Chatbot User" description="How may I help you today?" />
234
+ <ChatbotWelcomePrompt title="Hi, ChatBot User!" description="How can I help you today?" />
235
235
  {messages.map((message) => (
236
236
  <Message key={message.name} {...message} />
237
237
  ))}
@@ -232,7 +232,7 @@ export const AttachmentMenuDemo: React.FunctionComponent = () => {
232
232
  {error}
233
233
  </ChatbotAlert>
234
234
  )}
235
- <ChatbotWelcomePrompt title="Hello, Chatbot User" description="How may I help you today?" />
235
+ <ChatbotWelcomePrompt title="Hi, ChatBot User!" description="How can I help you today?" />
236
236
  {messages.map((message) => (
237
237
  <Message key={message.name} {...message} />
238
238
  ))}
@@ -44,20 +44,20 @@ import patternflyAvatar from '../Messages/patternfly_avatar.jpg';
44
44
  const footnoteProps = {
45
45
  label: 'ChatBot uses AI. Check for mistakes.',
46
46
  popover: {
47
- title: 'Verify accuracy',
48
- description: `While ChatBot strives for accuracy, there's always a possibility of errors. It's a good practice to verify critical information from reliable sources, especially if it's crucial for decision-making or actions.`,
47
+ title: 'Verify information',
48
+ description: `While ChatBot strives for accuracy, AI is experimental and can make mistakes. We cannot guarantee that all information provided by ChatBot is up to date or without error. You should always verify responses using reliable sources, especially for crucial information and decision making.`,
49
49
  bannerImage: {
50
50
  src: 'https://cdn.dribbble.com/userupload/10651749/file/original-8a07b8e39d9e8bf002358c66fce1223e.gif',
51
51
  alt: 'Example image for footnote popover'
52
52
  },
53
53
  cta: {
54
- label: 'Got it',
54
+ label: 'Dismiss',
55
55
  onClick: () => {
56
56
  alert('Do something!');
57
57
  }
58
58
  },
59
59
  link: {
60
- label: 'Learn more',
60
+ label: 'View AI policy',
61
61
  url: 'https://www.redhat.com/'
62
62
  }
63
63
  }
@@ -137,12 +137,12 @@ const initialMessages: MessageProps[] = [
137
137
 
138
138
  const welcomePrompts = [
139
139
  {
140
- title: 'Topic 1',
141
- message: 'Helpful prompt for Topic 1'
140
+ title: 'Set up account',
141
+ message: 'Choose the necessary settings and preferences for your account.'
142
142
  },
143
143
  {
144
- title: 'Topic 2',
145
- message: 'Helpful prompt for Topic 2'
144
+ title: 'Troubleshoot issue',
145
+ message: 'Find documentation and instructions to resolve your issue.'
146
146
  }
147
147
  ];
148
148
 
@@ -400,8 +400,8 @@ export const EmbeddedChatbotDemo: React.FunctionComponent = () => {
400
400
  so that users of assistive devices receive sufficient context */}
401
401
  <MessageBox announcement={announcement}>
402
402
  <ChatbotWelcomePrompt
403
- title="Hello, Chatbot User"
404
- description="How may I help you today?"
403
+ title="Hi, ChatBot User!"
404
+ description="How can I help you today?"
405
405
  prompts={welcomePrompts}
406
406
  />
407
407
  {/* This code block enables scrolling to the top of the last message.
@@ -117,7 +117,7 @@ export const CompareChild = ({ name, input, hasNewInput, setIsSendButtonDisabled
117
117
  </ChatbotHeader>
118
118
  <ChatbotContent>
119
119
  <MessageBox ariaLabel={`Scrollable message log for ${name}`} announcement={announcement}>
120
- <ChatbotWelcomePrompt title="Hello, Chatbot User" description="How may I help you today?" />
120
+ <ChatbotWelcomePrompt title="Hi, ChatBot User!" description="How can I help you today?" />
121
121
  {messages.map((message) => (
122
122
  <Message key={message.id} {...message} />
123
123
  ))}
@@ -9,11 +9,11 @@ import { MenuToggleElement, Tooltip, MenuToggle, Dropdown, DropdownProps } from
9
9
  import EllipsisIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon';
10
10
 
11
11
  export interface ChatbotConversationHistoryDropdownProps extends Omit<DropdownProps, 'toggle'> {
12
- /** Dropdown items rendered in conversation options dropdown */
12
+ /** Dropdown items rendered in conversation settings dropdown */
13
13
  menuItems: React.ReactNode;
14
- /** Optional classname applied to conversation options dropdown */
14
+ /** Optional classname applied to conversation settings dropdown */
15
15
  menuClassName?: string;
16
- /** Tooltip content and aria-label applied to conversation options dropdown */
16
+ /** Tooltip content and aria-label applied to conversation settings dropdown */
17
17
  label?: string;
18
18
  /** Callback for when user selects item. */
19
19
  onSelect?: (event?: React.MouseEvent, value?: string | number) => void;
@@ -48,11 +48,11 @@ export interface Conversation {
48
48
  noIcon?: boolean;
49
49
  /** Conversation */
50
50
  text: string;
51
- /** Dropdown items rendered in conversation options dropdown */
51
+ /** Dropdown items rendered in conversation settings dropdown */
52
52
  menuItems?: React.ReactNode;
53
- /** Optional classname applied to conversation options dropdown */
53
+ /** Optional classname applied to conversation settings dropdown */
54
54
  menuClassName?: string;
55
- /** Tooltip content and aria-label applied to conversation options dropdown */
55
+ /** Tooltip content and aria-label applied to conversation settings dropdown */
56
56
  label?: string;
57
57
  /** Callback for when user selects item. */
58
58
  onSelect?: (event?: React.MouseEvent, value?: string | number) => void;
@@ -124,7 +124,7 @@ export const ChatbotConversationHistoryNav: React.FunctionComponent<ChatbotConve
124
124
  newChatButtonText = 'New chat',
125
125
  drawerContent,
126
126
  onNewChat,
127
- searchInputPlaceholder = 'Search...',
127
+ searchInputPlaceholder = 'Search previous conversations...',
128
128
  searchInputAriaLabel = 'Filter menu items',
129
129
  handleTextInputChange,
130
130
  displayMode,
@@ -32,7 +32,7 @@ export interface ChatbotFootnotePopover {
32
32
  bannerImage?: ChatbotFootnotePopoverBannerImage;
33
33
  /** Optional CTA button that can be used to trigger an action and close the popover */
34
34
  cta?: ChatbotFootnotePopoverCTA;
35
- /** Optional link that can be used to show and external link like **Learn More** */
35
+ /** Optional link that can be used to show an external link like **View AI policy** */
36
36
  link?: ChatbotFootnotePopoverLink;
37
37
  /** Props for PF Popover */
38
38
  popoverProps?: PopoverProps;
@@ -87,7 +87,7 @@ export const ChatbotFootnote: React.FunctionComponent<ChatbotFootnoteProps> = ({
87
87
  popover.cta?.onClick();
88
88
  }}
89
89
  >
90
- {popover.cta?.label || 'Got it'}
90
+ {popover.cta?.label || 'Dismiss'}
91
91
  </Button>
92
92
  )}
93
93
  {popover?.link && (
@@ -15,7 +15,7 @@ describe('ChatbotHeaderSelectorDropdown', () => {
15
15
  it('should render ChatbotHeaderSelectorDropdown', () => {
16
16
  render(<ChatbotHeaderSelectorDropdown value="Option 1">{dropdownItems}</ChatbotHeaderSelectorDropdown>);
17
17
 
18
- expect(screen.getByRole('button', { name: 'Chatbot selector' })).toBeTruthy();
18
+ expect(screen.getByRole('button', { name: /Select model/i })).toBeTruthy();
19
19
  });
20
20
 
21
21
  it('should call onselect handler when a dropdown item is clicked', async () => {
@@ -27,7 +27,7 @@ describe('ChatbotHeaderSelectorDropdown', () => {
27
27
  );
28
28
 
29
29
  act(() => {
30
- fireEvent.click(screen.getByRole('button', { name: 'Chatbot selector' }));
30
+ fireEvent.click(screen.getByRole('button', { name: /Select model/i }));
31
31
  });
32
32
 
33
33
  await waitFor(() => {
@@ -23,12 +23,12 @@ export const ChatbotHeaderSelectorDropdown: React.FunctionComponent<ChatbotHeade
23
23
  children,
24
24
  onSelect,
25
25
  tooltipProps,
26
- tooltipContent = 'Chatbot selector',
26
+ tooltipContent = 'Select model',
27
27
  menuToggleAriaLabel,
28
28
  ...props
29
29
  }: ChatbotHeaderSelectorDropdownProps) => {
30
30
  const [isOptionsMenuOpen, setIsOptionsMenuOpen] = React.useState(false);
31
- const [defaultAriaLabel, setDefaultAriaLabel] = React.useState('Chatbot selector');
31
+ const [defaultAriaLabel, setDefaultAriaLabel] = React.useState('Select model');
32
32
 
33
33
  const toggle = (toggleRef: React.Ref<MenuToggleElement>) => (
34
34
  <Tooltip
@@ -57,7 +57,7 @@ export const ChatbotHeaderSelectorDropdown: React.FunctionComponent<ChatbotHeade
57
57
  isOpen={isOptionsMenuOpen}
58
58
  onSelect={(e, value) => {
59
59
  onSelect && onSelect(e, value);
60
- setDefaultAriaLabel(`Chatbot selector: ${value}`);
60
+ setDefaultAriaLabel(`Select model: ${value}`);
61
61
  setIsOptionsMenuOpen(false);
62
62
  }}
63
63
  onOpenChange={(isOpen) => setIsOptionsMenuOpen(isOpen)}
@@ -7,53 +7,61 @@ import userEvent from '@testing-library/user-event';
7
7
  describe('ChatbotWelcomePrompt', () => {
8
8
  it('should render welcome prompt', () => {
9
9
  const { container } = render(
10
- <ChatbotWelcomePrompt title="Hello, Chatbot User" description="How may I help you today?" />
10
+ <ChatbotWelcomePrompt title="Hi, ChatBot User!" description="How can I help you today?" />
11
11
  );
12
12
  expect(container).toMatchSnapshot();
13
13
  });
14
14
 
15
15
  it('should render correctly', () => {
16
- render(<ChatbotWelcomePrompt title="Hello, Chatbot User" description="How may I help you today?" />);
17
- expect(screen.getByText('Hello, Chatbot User')).toBeTruthy();
18
- expect(screen.getByText('How may I help you today?')).toBeTruthy();
16
+ render(<ChatbotWelcomePrompt title="Hi, ChatBot User!" description="How can I help you today?" />);
17
+ expect(screen.getByText('Hi, ChatBot User!')).toBeTruthy();
18
+ expect(screen.getByText('How can I help you today?')).toBeTruthy();
19
19
  });
20
20
  it('should render prompts with titles correctly', () => {
21
21
  render(
22
22
  <ChatbotWelcomePrompt
23
- title="Hello, Chatbot User"
24
- description="How may I help you today?"
25
- prompts={[{ title: 'Topic 1' }]}
23
+ title="Hi, ChatBot User!"
24
+ description="How can I help you today?"
25
+ prompts={[{ title: 'Set up account' }]}
26
26
  />
27
27
  );
28
- expect(screen.getByText('Topic 1')).toBeTruthy();
28
+ expect(screen.getByText('Set up account')).toBeTruthy();
29
29
  });
30
30
  it('should render prompts with messages correctly', () => {
31
31
  render(
32
32
  <ChatbotWelcomePrompt
33
- title="Hello, Chatbot User"
34
- description="How may I help you today?"
35
- prompts={[{ title: 'Topic 1', message: 'Helpful prompt for Topic 1' }]}
33
+ title="Hi, ChatBot User!"
34
+ description="How can I help you today?"
35
+ prompts={[
36
+ { title: 'Set up account', message: 'Choose the necessary settings and preferences for your account.' }
37
+ ]}
36
38
  />
37
39
  );
38
- expect(screen.getByText('Helpful prompt for Topic 1')).toBeTruthy();
40
+ expect(screen.getByText('Choose the necessary settings and preferences for your account.')).toBeTruthy();
39
41
  });
40
42
  it('should render prompts with onClick correctly', async () => {
41
43
  const spy = jest.fn();
42
44
  render(
43
45
  <ChatbotWelcomePrompt
44
- title="Hello, Chatbot User"
45
- description="How may I help you today?"
46
- prompts={[{ title: 'Topic 1', message: 'Helpful prompt for Topic 1', onClick: spy }]}
46
+ title="Hi, ChatBot User!"
47
+ description="How can I help you today?"
48
+ prompts={[
49
+ {
50
+ title: 'Set up account',
51
+ message: 'Choose the necessary settings and preferences for your account.',
52
+ onClick: spy
53
+ }
54
+ ]}
47
55
  />
48
56
  );
49
- await userEvent.click(screen.getByRole('button', { name: /Topic 1/i }));
57
+ await userEvent.click(screen.getByRole('button', { name: /Set up account/i }));
50
58
  expect(spy).toHaveBeenCalled();
51
59
  });
52
60
  it('should apply className appropriately', () => {
53
61
  render(
54
62
  <ChatbotWelcomePrompt
55
- title="Hello, Chatbot User"
56
- description="How may I help you today?"
63
+ title="Hi, ChatBot User!"
64
+ description="How can I help you today?"
57
65
  className="test"
58
66
  testId="welcome-prompt"
59
67
  />
@@ -15,13 +15,13 @@ exports[`ChatbotWelcomePrompt should render welcome prompt 1`] = `
15
15
  <span
16
16
  class="pf-chatbot__hello"
17
17
  >
18
- Hello, Chatbot User
18
+ Hi, ChatBot User!
19
19
  </span>
20
20
  <br />
21
21
  <span
22
22
  class="pf-chatbot__question"
23
23
  >
24
- How may I help you today?
24
+ How can I help you today?
25
25
  </span>
26
26
  </h1>
27
27
  </div>
@@ -68,13 +68,13 @@
68
68
  .pf-v6-c-form-control__textarea:focus-visible {
69
69
  outline: none;
70
70
  }
71
- .pf-v6-c-form-control > textarea {
72
- outline-offset: 0px;
71
+ textarea {
72
+ outline-offset: 0px !important;
73
73
  --pf-v6-c-form-control--PaddingBlockStart: 0;
74
74
  --pf-v6-c-form-control--PaddingBlockEnd: 0;
75
75
  --pf-v6-c-form-control--BorderRadius: 0;
76
76
  }
77
- .pf-v6-c-form-control > textarea:focus-visible {
77
+ textarea:focus-visible {
78
78
  outline: none;
79
79
  }
80
80
  }
@@ -90,7 +90,7 @@ describe('ResponseActions', () => {
90
90
  name="Bot"
91
91
  role="bot"
92
92
  avatar=""
93
- content="Example with all prebuilt actions"
93
+ content="I updated your account with those settings. You're ready to set up your first dashboard!"
94
94
  actions={{
95
95
  positive: {},
96
96
  negative: {}
@@ -113,7 +113,9 @@ describe('ResponseActions', () => {
113
113
  'pf-chatbot__button--response-action-clicked'
114
114
  );
115
115
  expect(goodBtn).not.toHaveClass('pf-chatbot__button--response-action-clicked');
116
- await userEvent.click(screen.getByText('Example with all prebuilt actions'));
116
+ await userEvent.click(
117
+ screen.getByText("I updated your account with those settings. You're ready to set up your first dashboard!")
118
+ );
117
119
  expect(goodBtn).not.toHaveClass('pf-chatbot__button--response-action-clicked');
118
120
  expect(badBtn).not.toHaveClass('pf-chatbot__button--response-action-clicked');
119
121
  });