@patternfly/chatbot 6.3.2 → 6.4.0-prerelease.10

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 (133) hide show
  1. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.d.ts +2 -0
  2. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.js +2 -2
  3. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.test.js +6 -6
  4. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +27 -4
  5. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +8 -14
  6. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +53 -2
  7. package/dist/cjs/ChatbotHeader/ChatbotHeaderMenu.js +1 -1
  8. package/dist/cjs/ChatbotHeader/ChatbotHeaderMenu.test.js +1 -1
  9. package/dist/cjs/ChatbotHeader/ChatbotHeaderNewChatButton.d.ts +18 -0
  10. package/dist/cjs/ChatbotHeader/ChatbotHeaderNewChatButton.js +25 -0
  11. package/dist/cjs/ChatbotHeader/ChatbotHeaderNewChatButton.test.d.ts +1 -0
  12. package/dist/cjs/ChatbotHeader/ChatbotHeaderNewChatButton.test.js +22 -0
  13. package/dist/cjs/ChatbotHeader/index.d.ts +1 -0
  14. package/dist/cjs/ChatbotHeader/index.js +1 -0
  15. package/dist/cjs/FileDropZone/FileDropZone.d.ts +1 -2
  16. package/dist/cjs/Message/Message.d.ts +9 -2
  17. package/dist/cjs/Message/Message.js +40 -34
  18. package/dist/cjs/Message/Message.test.js +37 -0
  19. package/dist/cjs/Message/MessageInput.d.ts +3 -1
  20. package/dist/cjs/Message/MessageInput.js +2 -2
  21. package/dist/cjs/MessageBar/AttachButton.d.ts +2 -2
  22. package/dist/cjs/MessageBar/MessageBar.d.ts +2 -2
  23. package/dist/cjs/MessageBox/JumpButton.d.ts +5 -0
  24. package/dist/cjs/MessageBox/JumpButton.js +1 -1
  25. package/dist/cjs/MessageBox/JumpButton.test.js +4 -4
  26. package/dist/cjs/MessageBox/MessageBox.d.ts +9 -0
  27. package/dist/cjs/MessageBox/MessageBox.js +2 -2
  28. package/dist/cjs/MessageBox/MessageBox.test.js +2 -2
  29. package/dist/cjs/MessageDivider/MessageDivider.d.ts +9 -0
  30. package/dist/cjs/MessageDivider/MessageDivider.js +23 -0
  31. package/dist/cjs/MessageDivider/MessageDivider.test.d.ts +1 -0
  32. package/dist/cjs/MessageDivider/MessageDivider.test.js +29 -0
  33. package/dist/cjs/MessageDivider/index.d.ts +2 -0
  34. package/dist/cjs/MessageDivider/index.js +23 -0
  35. package/dist/cjs/ResponseActions/ResponseActions.d.ts +1 -0
  36. package/dist/cjs/ResponseActions/ResponseActions.js +4 -4
  37. package/dist/cjs/ResponseActions/ResponseActions.test.js +6 -1
  38. package/dist/cjs/index.d.ts +2 -0
  39. package/dist/cjs/index.js +4 -1
  40. package/dist/css/main.css +103 -81
  41. package/dist/css/main.css.map +1 -1
  42. package/dist/dynamic/MessageDivider/package.json +1 -0
  43. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.d.ts +2 -0
  44. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.js +2 -2
  45. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.test.js +6 -6
  46. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +27 -4
  47. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +10 -16
  48. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +54 -3
  49. package/dist/esm/ChatbotHeader/ChatbotHeaderMenu.js +1 -1
  50. package/dist/esm/ChatbotHeader/ChatbotHeaderMenu.test.js +1 -1
  51. package/dist/esm/ChatbotHeader/ChatbotHeaderNewChatButton.d.ts +18 -0
  52. package/dist/esm/ChatbotHeader/ChatbotHeaderNewChatButton.js +22 -0
  53. package/dist/esm/ChatbotHeader/ChatbotHeaderNewChatButton.test.d.ts +1 -0
  54. package/dist/esm/ChatbotHeader/ChatbotHeaderNewChatButton.test.js +20 -0
  55. package/dist/esm/ChatbotHeader/index.d.ts +1 -0
  56. package/dist/esm/ChatbotHeader/index.js +1 -0
  57. package/dist/esm/FileDropZone/FileDropZone.d.ts +1 -2
  58. package/dist/esm/Message/Message.d.ts +9 -2
  59. package/dist/esm/Message/Message.js +40 -34
  60. package/dist/esm/Message/Message.test.js +37 -0
  61. package/dist/esm/Message/MessageInput.d.ts +3 -1
  62. package/dist/esm/Message/MessageInput.js +2 -2
  63. package/dist/esm/MessageBar/AttachButton.d.ts +2 -2
  64. package/dist/esm/MessageBar/MessageBar.d.ts +2 -2
  65. package/dist/esm/MessageBox/JumpButton.d.ts +5 -0
  66. package/dist/esm/MessageBox/JumpButton.js +1 -1
  67. package/dist/esm/MessageBox/JumpButton.test.js +4 -4
  68. package/dist/esm/MessageBox/MessageBox.d.ts +9 -0
  69. package/dist/esm/MessageBox/MessageBox.js +2 -2
  70. package/dist/esm/MessageBox/MessageBox.test.js +2 -2
  71. package/dist/esm/MessageDivider/MessageDivider.d.ts +9 -0
  72. package/dist/esm/MessageDivider/MessageDivider.js +21 -0
  73. package/dist/esm/MessageDivider/MessageDivider.test.d.ts +1 -0
  74. package/dist/esm/MessageDivider/MessageDivider.test.js +24 -0
  75. package/dist/esm/MessageDivider/index.d.ts +2 -0
  76. package/dist/esm/MessageDivider/index.js +2 -0
  77. package/dist/esm/ResponseActions/ResponseActions.d.ts +1 -0
  78. package/dist/esm/ResponseActions/ResponseActions.js +5 -5
  79. package/dist/esm/ResponseActions/ResponseActions.test.js +6 -1
  80. package/dist/esm/index.d.ts +2 -0
  81. package/dist/esm/index.js +2 -0
  82. package/dist/tsconfig.tsbuildinfo +1 -1
  83. package/package.json +9 -4
  84. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithDividers.tsx +24 -0
  85. package/patternfly-docs/content/extensions/chatbot/examples/Messages/Messages.md +15 -1
  86. package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessage.tsx +39 -7
  87. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotConversationEditing.tsx +202 -0
  88. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderBasic.tsx +17 -3
  89. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawer.tsx +45 -5
  90. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawerWithPin.tsx +206 -0
  91. package/patternfly-docs/content/extensions/chatbot/examples/UI/UI.md +30 -4
  92. package/patternfly-docs/content/extensions/chatbot/examples/demos/Chatbot.md +33 -1
  93. package/patternfly-docs/content/extensions/chatbot/examples/demos/ChatbotDisplayMode.tsx +486 -0
  94. package/patternfly-docs/content/extensions/chatbot/examples/demos/ChatbotTranscripts.tsx +565 -0
  95. package/src/Chatbot/Chatbot.scss +1 -1
  96. package/src/ChatbotContent/ChatbotContent.scss +1 -1
  97. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.test.tsx +6 -6
  98. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.tsx +5 -2
  99. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.scss +70 -32
  100. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.tsx +176 -3
  101. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.tsx +110 -60
  102. package/src/ChatbotFooter/ChatbotFooter.scss +1 -1
  103. package/src/ChatbotHeader/ChatbotHeader.scss +3 -3
  104. package/src/ChatbotHeader/ChatbotHeaderMenu.test.tsx +1 -1
  105. package/src/ChatbotHeader/ChatbotHeaderMenu.tsx +2 -2
  106. package/src/ChatbotHeader/ChatbotHeaderNewChatButton.test.tsx +25 -0
  107. package/src/ChatbotHeader/ChatbotHeaderNewChatButton.tsx +64 -0
  108. package/src/ChatbotHeader/index.ts +1 -0
  109. package/src/ChatbotModal/ChatbotModal.scss +1 -1
  110. package/src/ChatbotToggle/ChatbotToggle.scss +2 -2
  111. package/src/FileDetails/__snapshots__/FileDetails.test.tsx.snap +6 -9
  112. package/src/FileDetailsLabel/__snapshots__/FileDetailsLabel.test.tsx.snap +6 -9
  113. package/src/FileDropZone/FileDropZone.tsx +2 -2
  114. package/src/Message/Message.scss +9 -7
  115. package/src/Message/Message.test.tsx +54 -0
  116. package/src/Message/Message.tsx +70 -50
  117. package/src/Message/MessageInput.tsx +5 -1
  118. package/src/MessageBar/AttachButton.tsx +2 -2
  119. package/src/MessageBar/MessageBar.tsx +2 -2
  120. package/src/MessageBar/SendButton.scss +3 -3
  121. package/src/MessageBox/JumpButton.scss +1 -1
  122. package/src/MessageBox/JumpButton.test.tsx +4 -4
  123. package/src/MessageBox/JumpButton.tsx +20 -4
  124. package/src/MessageBox/MessageBox.test.tsx +2 -2
  125. package/src/MessageBox/MessageBox.tsx +23 -2
  126. package/src/MessageDivider/MessageDivider.scss +45 -0
  127. package/src/MessageDivider/MessageDivider.test.tsx +24 -0
  128. package/src/MessageDivider/MessageDivider.tsx +35 -0
  129. package/src/MessageDivider/index.ts +3 -0
  130. package/src/ResponseActions/ResponseActions.test.tsx +6 -1
  131. package/src/ResponseActions/ResponseActions.tsx +24 -3
  132. package/src/index.ts +3 -0
  133. package/src/main.scss +1 -52
@@ -6,20 +6,20 @@ import userEvent from '@testing-library/user-event';
6
6
  describe('JumpButton', () => {
7
7
  it('should render top button correctly', () => {
8
8
  render(<JumpButton position="top" onClick={jest.fn()} />);
9
- expect(screen.getByRole('button', { name: /Jump top/i })).toBeTruthy();
9
+ expect(screen.getByRole('button', { name: /Back to top/i })).toBeTruthy();
10
10
  });
11
11
  it('should render bottom button correctly', () => {
12
12
  render(<JumpButton position="bottom" onClick={jest.fn()} />);
13
- expect(screen.getByRole('button', { name: /Jump bottom/i })).toBeTruthy();
13
+ expect(screen.getByRole('button', { name: /Back to bottom/i })).toBeTruthy();
14
14
  });
15
15
  it('should call onClick appropriately', async () => {
16
16
  const spy = jest.fn();
17
17
  render(<JumpButton position="bottom" onClick={spy} />);
18
- await userEvent.click(screen.getByRole('button', { name: /Jump bottom/i }));
18
+ await userEvent.click(screen.getByRole('button', { name: /Back to bottom/i }));
19
19
  expect(spy).toHaveBeenCalledTimes(1);
20
20
  });
21
21
  it('should be hidden if isHidden prop is used', async () => {
22
22
  render(<JumpButton position="bottom" onClick={jest.fn()} isHidden />);
23
- expect(screen.queryByRole('button', { name: /Jump bottom/i })).toBeFalsy();
23
+ expect(screen.queryByRole('button', { name: /Back to bottom/i })).toBeFalsy();
24
24
  });
25
25
  });
@@ -4,7 +4,7 @@
4
4
  import type { FunctionComponent } from 'react';
5
5
 
6
6
  // Import PatternFly components
7
- import { Button, Tooltip, Icon } from '@patternfly/react-core';
7
+ import { Button, Tooltip, Icon, TooltipProps, ButtonProps } from '@patternfly/react-core';
8
8
 
9
9
  import { ArrowUpIcon } from '@patternfly/react-icons/dist/esm/icons/arrow-up-icon';
10
10
  import { ArrowDownIcon } from '@patternfly/react-icons/dist/esm/icons/arrow-down-icon';
@@ -16,16 +16,32 @@ export interface JumpButtonProps {
16
16
  onClick: () => void;
17
17
  /** Flag to change the visibilty of the button */
18
18
  isHidden?: boolean;
19
+ /** Additional props passed to jump buttons */
20
+ jumpButtonProps?: ButtonProps;
21
+ /** Additional props passed to tooltip */
22
+ jumpButtonTooltipProps?: TooltipProps;
19
23
  }
20
24
 
21
- const JumpButton: FunctionComponent<JumpButtonProps> = ({ position, isHidden, onClick }: JumpButtonProps) =>
25
+ const JumpButton: FunctionComponent<JumpButtonProps> = ({
26
+ position,
27
+ isHidden,
28
+ onClick,
29
+ jumpButtonProps,
30
+ jumpButtonTooltipProps
31
+ }: JumpButtonProps) =>
22
32
  isHidden ? null : (
23
- <Tooltip id={`pf-chatbot__tooltip--jump-${position}`} content={`Back to ${position}`} position="top">
33
+ <Tooltip
34
+ id={`pf-chatbot__tooltip--jump-${position}`}
35
+ content={`Back to ${position}`}
36
+ position="top"
37
+ {...jumpButtonTooltipProps}
38
+ >
24
39
  <Button
25
40
  variant="plain"
26
41
  className={`pf-chatbot__jump pf-chatbot__jump--${position}`}
27
- aria-label={`Jump ${position}`}
42
+ aria-label={`Back to ${position}`}
28
43
  onClick={onClick}
44
+ {...jumpButtonProps}
29
45
  >
30
46
  <Icon iconSize="lg" isInline>
31
47
  {position === 'top' ? <ArrowUpIcon /> : <ArrowDownIcon />}
@@ -61,7 +61,7 @@ describe('MessageBox', () => {
61
61
  });
62
62
 
63
63
  await waitFor(() => {
64
- userEvent.click(screen.getByRole('button', { name: /Jump bottom/i }));
64
+ userEvent.click(screen.getByRole('button', { name: /Back to bottom/i }));
65
65
  expect(spy).toHaveBeenCalled();
66
66
  });
67
67
  });
@@ -85,7 +85,7 @@ describe('MessageBox', () => {
85
85
  region.dispatchEvent(new Event('scroll'));
86
86
  });
87
87
  await waitFor(() => {
88
- userEvent.click(screen.getByRole('button', { name: /Jump top/i }));
88
+ userEvent.click(screen.getByRole('button', { name: /Back to top/i }));
89
89
  expect(spy).toHaveBeenCalled();
90
90
  });
91
91
  });
@@ -18,6 +18,7 @@ import {
18
18
  WheelEventHandler
19
19
  } from 'react';
20
20
  import JumpButton from './JumpButton';
21
+ import { ButtonProps, TooltipProps } from '@patternfly/react-core';
21
22
 
22
23
  export interface MessageBoxProps extends HTMLProps<HTMLDivElement> {
23
24
  /** Content that can be announced, such as a new message, for screen readers */
@@ -38,6 +39,14 @@ export interface MessageBoxProps extends HTMLProps<HTMLDivElement> {
38
39
  onScrollToBottomClick?: () => void;
39
40
  /** Flag to enable automatic scrolling when new messages are added */
40
41
  enableSmartScroll?: boolean;
42
+ /** Props passed to top jump button */
43
+ jumpButtonTopProps?: ButtonProps;
44
+ /** Props passed to bottom jump button */
45
+ jumpButtonBottomProps?: ButtonProps;
46
+ /** Props passed to top jump button tooltip */
47
+ jumpButtonTopTooltipProps?: TooltipProps;
48
+ /** Props passed to top jump button tooltip */
49
+ jumpButtonBottomTooltipProps?: TooltipProps;
41
50
  }
42
51
 
43
52
  export interface MessageBoxHandle extends HTMLDivElement {
@@ -60,6 +69,10 @@ export const MessageBox = forwardRef(
60
69
  onScrollToTopClick,
61
70
  onScrollToBottomClick,
62
71
  enableSmartScroll = false,
72
+ jumpButtonTopProps,
73
+ jumpButtonBottomProps,
74
+ jumpButtonBottomTooltipProps,
75
+ jumpButtonTopTooltipProps,
63
76
  ...props
64
77
  }: MessageBoxProps,
65
78
  ref: ForwardedRef<MessageBoxHandle | null>
@@ -305,12 +318,18 @@ export const MessageBox = forwardRef(
305
318
 
306
319
  return (
307
320
  <>
308
- <JumpButton position="top" isHidden={isOverflowing && atTop} onClick={scrollToTop} />
321
+ <JumpButton
322
+ position="top"
323
+ isHidden={isOverflowing && atTop}
324
+ onClick={scrollToTop}
325
+ jumpButtonProps={jumpButtonTopProps}
326
+ jumpButtonTooltipProps={jumpButtonTopTooltipProps}
327
+ />
309
328
  <div
310
329
  role="region"
311
330
  tabIndex={0}
312
331
  aria-label={ariaLabel}
313
- className={`pf-chatbot__messagebox ${position === 'bottom' && 'pf-chatbot__messagebox--bottom'} ${className ?? ''}`}
332
+ className={`pf-chatbot__messagebox ${position === 'bottom' ? 'pf-chatbot__messagebox--bottom' : ''} ${className ?? ''}`}
314
333
  ref={messageBoxRef}
315
334
  {...props}
316
335
  {...(enableSmartScroll ? { ...smartScrollHandlers } : {})}
@@ -324,6 +343,8 @@ export const MessageBox = forwardRef(
324
343
  position="bottom"
325
344
  isHidden={isOverflowing && atBottom}
326
345
  onClick={() => scrollToBottom({ resumeSmartScroll: true })}
346
+ jumpButtonProps={jumpButtonBottomProps}
347
+ jumpButtonTooltipProps={jumpButtonBottomTooltipProps}
327
348
  />
328
349
  </>
329
350
  );
@@ -0,0 +1,45 @@
1
+ // ============================================================================
2
+ // Chatbot Main - Message Divider
3
+ // ============================================================================
4
+ .pf-chatbot__message-divider {
5
+ display: grid;
6
+ padding-block-end: var(--pf-t--global--spacer--xl);
7
+
8
+ .pf-v6-c-divider,
9
+ .pf-v6-c-label {
10
+ grid-row: 1 / 1;
11
+ grid-column: 1 / 1;
12
+ }
13
+
14
+ .pf-v6-c-label {
15
+ --pf-v6-c-label--BackgroundColor: var(--pf-t--global--background--color--tertiary--default);
16
+ --pf-v6-c-label--BorderColor: var(--pf-t--global--border--color--default);
17
+ --pf-v6-c-label--PaddingInlineStart: var(--pf-t--global--spacer--action--horizontal--compact);
18
+ --pf-v6-c-label--PaddingInlineEnd: var(--pf-t--global--spacer--action--horizontal--compact);
19
+
20
+ .pf-v6-c-label__text {
21
+ font-weight: var(--pf-t--global--font--weight--body--bold);
22
+ text-align: center;
23
+ }
24
+ }
25
+
26
+ &.pf-m-divider {
27
+ .pf-v6-c-label {
28
+ --pf-v6-c-label--BackgroundColor: var(--pf-t--global--background--color--secondary--default);
29
+ --pf-v6-c-label--MaxWidth: 75%;
30
+
31
+ justify-self: center;
32
+ }
33
+
34
+ .pf-v6-c-divider {
35
+ align-self: center;
36
+ }
37
+ }
38
+
39
+ &.pf-m-wrap {
40
+ .pf-v6-c-label,
41
+ .pf-v6-c-label__text {
42
+ white-space: normal;
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,24 @@
1
+ import { render, screen } from '@testing-library/react';
2
+ import '@testing-library/jest-dom';
3
+ import MessageDivider from './MessageDivider';
4
+
5
+ describe('MessageDivider', () => {
6
+ beforeEach(() => {
7
+ jest.clearAllMocks();
8
+ });
9
+ it('should render default correctly with variant = date and content = new Date().toLocaleDateString()', () => {
10
+ render(<MessageDivider data-testid="message-divider" />);
11
+ expect(screen.getByText(new Date().toLocaleDateString())).toBeInTheDocument();
12
+ expect(screen.getByTestId('message-divider')).toHaveClass('pf-m-divider');
13
+ });
14
+ it('should render inset variant correctly', () => {
15
+ render(<MessageDivider variant="inset" content="test" data-testid="message-divider" />);
16
+ expect(screen.getByText('test')).toBeInTheDocument();
17
+ expect(screen.getByTestId('message-divider')).toHaveClass('pf-m-divider');
18
+ });
19
+ it('should render fullWidth variant correctly', () => {
20
+ render(<MessageDivider variant="fullWidth" content="test" data-testid="message-divider" />);
21
+ expect(screen.getByText('test')).toBeInTheDocument();
22
+ expect(screen.getByTestId('message-divider')).not.toHaveClass('pf-m-divider');
23
+ });
24
+ });
@@ -0,0 +1,35 @@
1
+ // ============================================================================
2
+ // Chatbot Main - Message Divider
3
+ // ============================================================================
4
+ import type { FunctionComponent } from 'react';
5
+ import { Divider, Label } from '@patternfly/react-core';
6
+
7
+ export interface MessageDividerProps {
8
+ /** Variant of the divider */
9
+ variant?: 'inset' | 'fullWidth';
10
+ /** Content of the message divider */
11
+ content?: string;
12
+ }
13
+
14
+ const MessageDivider: FunctionComponent<MessageDividerProps> = ({
15
+ variant = 'inset',
16
+ content = new Date().toLocaleDateString(),
17
+ ...props
18
+ }: MessageDividerProps) => {
19
+ if (variant === 'inset') {
20
+ return (
21
+ <div className="pf-chatbot__message-divider pf-m-divider pf-m-wrap" {...props}>
22
+ <Divider />
23
+ <Label variant="outline">{content}</Label>
24
+ </div>
25
+ );
26
+ }
27
+
28
+ return (
29
+ <div className="pf-chatbot__message-divider pf-m-wrap" {...props}>
30
+ <Label>{content}</Label>
31
+ </div>
32
+ );
33
+ };
34
+
35
+ export default MessageDivider;
@@ -0,0 +1,3 @@
1
+ export { default } from './MessageDivider';
2
+
3
+ export * from './MessageDivider';
@@ -9,6 +9,7 @@ const ALL_ACTIONS = [
9
9
  { type: 'positive', label: 'Good response', clickedLabel: 'Response recorded' },
10
10
  { type: 'negative', label: 'Bad response', clickedLabel: 'Response recorded' },
11
11
  { type: 'copy', label: 'Copy', clickedLabel: 'Copied' },
12
+ { type: 'edit', label: 'Edit', clickedLabel: 'Editing' },
12
13
  { type: 'share', label: 'Share', clickedLabel: 'Shared' },
13
14
  { type: 'listen', label: 'Listen', clickedLabel: 'Listening' }
14
15
  ];
@@ -44,6 +45,7 @@ const ALL_ACTIONS_DATA_TEST = [
44
45
  { type: 'positive', label: 'Good response', dataTestId: 'positive' },
45
46
  { type: 'negative', label: 'Bad response', dataTestId: 'negative' },
46
47
  { type: 'copy', label: 'Copy', dataTestId: 'copy' },
48
+ { type: 'edit', label: 'Edit', dataTestId: 'edit' },
47
49
  { type: 'share', label: 'Share', dataTestId: 'share' },
48
50
  { type: 'download', label: 'Download', dataTestId: 'download' },
49
51
  { type: 'listen', label: 'Listen', dataTestId: 'listen' }
@@ -60,6 +62,7 @@ describe('ResponseActions', () => {
60
62
  positive: { onClick: jest.fn() },
61
63
  negative: { onClick: jest.fn() },
62
64
  copy: { onClick: jest.fn() },
65
+ edit: { onClick: jest.fn() },
63
66
  share: { onClick: jest.fn() },
64
67
  download: { onClick: jest.fn() },
65
68
  listen: { onClick: jest.fn() }
@@ -69,10 +72,11 @@ describe('ResponseActions', () => {
69
72
  const goodBtn = screen.getByRole('button', { name: 'Good response' });
70
73
  const badBtn = screen.getByRole('button', { name: 'Bad response' });
71
74
  const copyBtn = screen.getByRole('button', { name: 'Copy' });
75
+ const editBtn = screen.getByRole('button', { name: 'Edit' });
72
76
  const shareBtn = screen.getByRole('button', { name: 'Share' });
73
77
  const downloadBtn = screen.getByRole('button', { name: 'Download' });
74
78
  const listenBtn = screen.getByRole('button', { name: 'Listen' });
75
- const buttons = [goodBtn, badBtn, copyBtn, shareBtn, downloadBtn, listenBtn];
79
+ const buttons = [goodBtn, badBtn, copyBtn, editBtn, shareBtn, downloadBtn, listenBtn];
76
80
  buttons.forEach((button) => {
77
81
  expect(button).toBeTruthy();
78
82
  });
@@ -265,6 +269,7 @@ describe('ResponseActions', () => {
265
269
  { type: 'positive', ariaLabel: 'Thumbs up' },
266
270
  { type: 'negative', ariaLabel: 'Thumbs down' },
267
271
  { type: 'copy', ariaLabel: 'Copy the message' },
272
+ { type: 'edit', ariaLabel: 'Edit this message' },
268
273
  { type: 'share', ariaLabel: 'Share it with friends' },
269
274
  { type: 'download', ariaLabel: 'Download your cool message' },
270
275
  { type: 'listen', ariaLabel: 'Listen up' }
@@ -6,7 +6,8 @@ import {
6
6
  OutlinedThumbsUpIcon,
7
7
  OutlinedThumbsDownIcon,
8
8
  OutlinedCopyIcon,
9
- DownloadIcon
9
+ DownloadIcon,
10
+ PencilAltIcon
10
11
  } from '@patternfly/react-icons';
11
12
  import ResponseActionButton from './ResponseActionButton';
12
13
  import { ButtonProps, TooltipProps } from '@patternfly/react-core';
@@ -50,6 +51,7 @@ export interface ResponseActionProps {
50
51
  share?: ActionProps;
51
52
  download?: ActionProps;
52
53
  listen?: ActionProps;
54
+ edit?: ActionProps;
53
55
  };
54
56
  }
55
57
 
@@ -58,7 +60,7 @@ export const ResponseActions: FunctionComponent<ResponseActionProps> = ({ action
58
60
  const [clickStatePersisted, setClickStatePersisted] = useState<boolean>(false);
59
61
  useEffect(() => {
60
62
  // Define the order of precedence for checking initial `isClicked`
61
- const actionPrecedence = ['positive', 'negative', 'copy', 'share', 'download', 'listen'];
63
+ const actionPrecedence = ['positive', 'negative', 'copy', 'edit', 'share', 'download', 'listen'];
62
64
  let initialActive: string | undefined;
63
65
 
64
66
  // Check predefined actions first based on precedence
@@ -83,7 +85,7 @@ export const ResponseActions: FunctionComponent<ResponseActionProps> = ({ action
83
85
  setActiveButton(initialActive);
84
86
  }, [actions]);
85
87
 
86
- const { positive, negative, copy, share, download, listen, ...additionalActions } = actions;
88
+ const { positive, negative, copy, edit, share, download, listen, ...additionalActions } = actions;
87
89
  const responseActions = useRef<HTMLDivElement>(null);
88
90
 
89
91
  useEffect(() => {
@@ -165,6 +167,24 @@ export const ResponseActions: FunctionComponent<ResponseActionProps> = ({ action
165
167
  aria-controls={copy['aria-controls']}
166
168
  ></ResponseActionButton>
167
169
  )}
170
+ {edit && (
171
+ <ResponseActionButton
172
+ {...edit}
173
+ ariaLabel={edit.ariaLabel ?? 'Edit'}
174
+ clickedAriaLabel={edit.ariaLabel ?? 'Editing'}
175
+ onClick={(e) => handleClick(e, 'edit', edit.onClick)}
176
+ className={edit.className}
177
+ isDisabled={edit.isDisabled}
178
+ tooltipContent={edit.tooltipContent ?? 'Edit '}
179
+ clickedTooltipContent={edit.clickedTooltipContent ?? 'Editing'}
180
+ tooltipProps={edit.tooltipProps}
181
+ icon={<PencilAltIcon />}
182
+ isClicked={activeButton === 'edit'}
183
+ ref={edit.ref}
184
+ aria-expanded={edit['aria-expanded']}
185
+ aria-controls={edit['aria-controls']}
186
+ ></ResponseActionButton>
187
+ )}
168
188
  {share && (
169
189
  <ResponseActionButton
170
190
  {...share}
@@ -219,6 +239,7 @@ export const ResponseActions: FunctionComponent<ResponseActionProps> = ({ action
219
239
  aria-controls={listen['aria-controls']}
220
240
  ></ResponseActionButton>
221
241
  )}
242
+
222
243
  {Object.keys(additionalActions).map((action) => (
223
244
  <ResponseActionButton
224
245
  {...additionalActions[action]}
package/src/index.ts CHANGED
@@ -63,6 +63,9 @@ export * from './MessageBar';
63
63
  export { default as MessageBox } from './MessageBox';
64
64
  export * from './MessageBox';
65
65
 
66
+ export { default as MessageDivider } from './MessageDivider';
67
+ export * from './MessageDivider';
68
+
66
69
  export { default as PreviewAttachment } from './PreviewAttachment';
67
70
  export * from './PreviewAttachment';
68
71
 
package/src/main.scss CHANGED
@@ -26,6 +26,7 @@
26
26
  @import './Message/UserFeedback/UserFeedback';
27
27
  @import './MessageBar/MessageBar';
28
28
  @import './MessageBox/MessageBox';
29
+ @import './MessageDivider/MessageDivider';
29
30
  @import './MessageBox/JumpButton';
30
31
  @import './ResponseActions/ResponseActions';
31
32
  @import './Settings/Settings';
@@ -33,58 +34,6 @@
33
34
  @import './SourceDetailsMenuItem/SourceDetailsMenuItem';
34
35
  @import './TermsOfUse/TermsOfUse';
35
36
 
36
- :where(:root) {
37
- // ============================================================================
38
- // Chatbot Custom Default Tokens
39
- // ============================================================================
40
-
41
- --pf-t--chatbot--heading--font-family: var(
42
- --pf-v6-c-content--heading--FontFamily,
43
- redhatdisplayvf,
44
- redhatdisplay,
45
- helvetica,
46
- arial,
47
- sans-serif
48
- );
49
-
50
- --pf-t--chatbot--illustration--fill: var(--pf-t--color--red--50);
51
- --pf-t--chatbot--code--background: var(--pf-t--color--gray--20);
52
-
53
- --pf-t--chatbot-toggle--background--hover: var(--pf-t--color--gray--70);
54
-
55
- --pf-t--chatbot--blue-icon--background--color--hover: rgba(
56
- 146,
57
- 197,
58
- 249,
59
- 0.25
60
- ); // --pf-t--global--color--nonstatus--blue--default @ 25%
61
- --pf-t--chatbot--blue-icon--fill--hover: var(--pf-t--global--color--brand--hover);
62
-
63
- // ============================================================================
64
- // Chatbot Default tokens using PF semantic tokens
65
- // ============================================================================
66
- --pf-t--chatbot-toggle--color: var(--pf-t--global--icon--color--inverse);
67
- --pf-t--chatbot--background: var(--pf-t--global--background--color--secondary--default);
68
- --pf-t--chatbot--border: var(--pf-t--global--border--color--default);
69
-
70
- --pf-t--chatbot--icon--fill--active: var(--pf-t--global--text--color--regular);
71
-
72
- --pf-t--chatbot--blue-icon--fill: var(--pf-t--global--color--brand--default);
73
- }
74
-
75
- // ============================================================================
76
- // Chatbot Custom Dark Theme Tokens
77
- // ============================================================================
78
- :where(.pf-v6-theme-dark) {
79
- --pf-t--chatbot--illustration--fill: var(--pf-t--color--white);
80
- --pf-t--chatbot--code--background: var(--pf-t--color--gray--60);
81
-
82
- --pf-t--chatbot-toggle--background--hover: var(--pf-t--color--gray--20);
83
-
84
- --pf-t--chatbot--blue-icon--background--color--hover: var(--pf-t--global--color--brand--hover);
85
- --pf-t--chatbot--blue-icon--fill--hover: var(--pf-t--global--icon--color--inverse);
86
- }
87
-
88
37
  .ws-full-page-utils {
89
38
  left: 0 !important;
90
39
  right: auto !important;