@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.
- package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.d.ts +2 -0
- package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.js +2 -2
- package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.test.js +6 -6
- package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +27 -4
- package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +8 -14
- package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +53 -2
- package/dist/cjs/ChatbotHeader/ChatbotHeaderMenu.js +1 -1
- package/dist/cjs/ChatbotHeader/ChatbotHeaderMenu.test.js +1 -1
- package/dist/cjs/ChatbotHeader/ChatbotHeaderNewChatButton.d.ts +18 -0
- package/dist/cjs/ChatbotHeader/ChatbotHeaderNewChatButton.js +25 -0
- package/dist/cjs/ChatbotHeader/ChatbotHeaderNewChatButton.test.d.ts +1 -0
- package/dist/cjs/ChatbotHeader/ChatbotHeaderNewChatButton.test.js +22 -0
- package/dist/cjs/ChatbotHeader/index.d.ts +1 -0
- package/dist/cjs/ChatbotHeader/index.js +1 -0
- package/dist/cjs/FileDropZone/FileDropZone.d.ts +1 -2
- package/dist/cjs/Message/Message.d.ts +9 -2
- package/dist/cjs/Message/Message.js +40 -34
- package/dist/cjs/Message/Message.test.js +37 -0
- package/dist/cjs/Message/MessageInput.d.ts +3 -1
- package/dist/cjs/Message/MessageInput.js +2 -2
- package/dist/cjs/MessageBar/AttachButton.d.ts +2 -2
- package/dist/cjs/MessageBar/MessageBar.d.ts +2 -2
- package/dist/cjs/MessageBox/JumpButton.d.ts +5 -0
- package/dist/cjs/MessageBox/JumpButton.js +1 -1
- package/dist/cjs/MessageBox/JumpButton.test.js +4 -4
- package/dist/cjs/MessageBox/MessageBox.d.ts +9 -0
- package/dist/cjs/MessageBox/MessageBox.js +2 -2
- package/dist/cjs/MessageBox/MessageBox.test.js +2 -2
- package/dist/cjs/MessageDivider/MessageDivider.d.ts +9 -0
- package/dist/cjs/MessageDivider/MessageDivider.js +23 -0
- package/dist/cjs/MessageDivider/MessageDivider.test.d.ts +1 -0
- package/dist/cjs/MessageDivider/MessageDivider.test.js +29 -0
- package/dist/cjs/MessageDivider/index.d.ts +2 -0
- package/dist/cjs/MessageDivider/index.js +23 -0
- package/dist/cjs/ResponseActions/ResponseActions.d.ts +1 -0
- package/dist/cjs/ResponseActions/ResponseActions.js +4 -4
- package/dist/cjs/ResponseActions/ResponseActions.test.js +6 -1
- package/dist/cjs/index.d.ts +2 -0
- package/dist/cjs/index.js +4 -1
- package/dist/css/main.css +103 -81
- package/dist/css/main.css.map +1 -1
- package/dist/dynamic/MessageDivider/package.json +1 -0
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.d.ts +2 -0
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.js +2 -2
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.test.js +6 -6
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +27 -4
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +10 -16
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +54 -3
- package/dist/esm/ChatbotHeader/ChatbotHeaderMenu.js +1 -1
- package/dist/esm/ChatbotHeader/ChatbotHeaderMenu.test.js +1 -1
- package/dist/esm/ChatbotHeader/ChatbotHeaderNewChatButton.d.ts +18 -0
- package/dist/esm/ChatbotHeader/ChatbotHeaderNewChatButton.js +22 -0
- package/dist/esm/ChatbotHeader/ChatbotHeaderNewChatButton.test.d.ts +1 -0
- package/dist/esm/ChatbotHeader/ChatbotHeaderNewChatButton.test.js +20 -0
- package/dist/esm/ChatbotHeader/index.d.ts +1 -0
- package/dist/esm/ChatbotHeader/index.js +1 -0
- package/dist/esm/FileDropZone/FileDropZone.d.ts +1 -2
- package/dist/esm/Message/Message.d.ts +9 -2
- package/dist/esm/Message/Message.js +40 -34
- package/dist/esm/Message/Message.test.js +37 -0
- package/dist/esm/Message/MessageInput.d.ts +3 -1
- package/dist/esm/Message/MessageInput.js +2 -2
- package/dist/esm/MessageBar/AttachButton.d.ts +2 -2
- package/dist/esm/MessageBar/MessageBar.d.ts +2 -2
- package/dist/esm/MessageBox/JumpButton.d.ts +5 -0
- package/dist/esm/MessageBox/JumpButton.js +1 -1
- package/dist/esm/MessageBox/JumpButton.test.js +4 -4
- package/dist/esm/MessageBox/MessageBox.d.ts +9 -0
- package/dist/esm/MessageBox/MessageBox.js +2 -2
- package/dist/esm/MessageBox/MessageBox.test.js +2 -2
- package/dist/esm/MessageDivider/MessageDivider.d.ts +9 -0
- package/dist/esm/MessageDivider/MessageDivider.js +21 -0
- package/dist/esm/MessageDivider/MessageDivider.test.d.ts +1 -0
- package/dist/esm/MessageDivider/MessageDivider.test.js +24 -0
- package/dist/esm/MessageDivider/index.d.ts +2 -0
- package/dist/esm/MessageDivider/index.js +2 -0
- package/dist/esm/ResponseActions/ResponseActions.d.ts +1 -0
- package/dist/esm/ResponseActions/ResponseActions.js +5 -5
- package/dist/esm/ResponseActions/ResponseActions.test.js +6 -1
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +2 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +9 -4
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithDividers.tsx +24 -0
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/Messages.md +15 -1
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessage.tsx +39 -7
- package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotConversationEditing.tsx +202 -0
- package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderBasic.tsx +17 -3
- package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawer.tsx +45 -5
- package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawerWithPin.tsx +206 -0
- package/patternfly-docs/content/extensions/chatbot/examples/UI/UI.md +30 -4
- package/patternfly-docs/content/extensions/chatbot/examples/demos/Chatbot.md +33 -1
- package/patternfly-docs/content/extensions/chatbot/examples/demos/ChatbotDisplayMode.tsx +486 -0
- package/patternfly-docs/content/extensions/chatbot/examples/demos/ChatbotTranscripts.tsx +565 -0
- package/src/Chatbot/Chatbot.scss +1 -1
- package/src/ChatbotContent/ChatbotContent.scss +1 -1
- package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.test.tsx +6 -6
- package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.tsx +5 -2
- package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.scss +70 -32
- package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.tsx +176 -3
- package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.tsx +110 -60
- package/src/ChatbotFooter/ChatbotFooter.scss +1 -1
- package/src/ChatbotHeader/ChatbotHeader.scss +3 -3
- package/src/ChatbotHeader/ChatbotHeaderMenu.test.tsx +1 -1
- package/src/ChatbotHeader/ChatbotHeaderMenu.tsx +2 -2
- package/src/ChatbotHeader/ChatbotHeaderNewChatButton.test.tsx +25 -0
- package/src/ChatbotHeader/ChatbotHeaderNewChatButton.tsx +64 -0
- package/src/ChatbotHeader/index.ts +1 -0
- package/src/ChatbotModal/ChatbotModal.scss +1 -1
- package/src/ChatbotToggle/ChatbotToggle.scss +2 -2
- package/src/FileDetails/__snapshots__/FileDetails.test.tsx.snap +6 -9
- package/src/FileDetailsLabel/__snapshots__/FileDetailsLabel.test.tsx.snap +6 -9
- package/src/FileDropZone/FileDropZone.tsx +2 -2
- package/src/Message/Message.scss +9 -7
- package/src/Message/Message.test.tsx +54 -0
- package/src/Message/Message.tsx +70 -50
- package/src/Message/MessageInput.tsx +5 -1
- package/src/MessageBar/AttachButton.tsx +2 -2
- package/src/MessageBar/MessageBar.tsx +2 -2
- package/src/MessageBar/SendButton.scss +3 -3
- package/src/MessageBox/JumpButton.scss +1 -1
- package/src/MessageBox/JumpButton.test.tsx +4 -4
- package/src/MessageBox/JumpButton.tsx +20 -4
- package/src/MessageBox/MessageBox.test.tsx +2 -2
- package/src/MessageBox/MessageBox.tsx +23 -2
- package/src/MessageDivider/MessageDivider.scss +45 -0
- package/src/MessageDivider/MessageDivider.test.tsx +24 -0
- package/src/MessageDivider/MessageDivider.tsx +35 -0
- package/src/MessageDivider/index.ts +3 -0
- package/src/ResponseActions/ResponseActions.test.tsx +6 -1
- package/src/ResponseActions/ResponseActions.tsx +24 -3
- package/src/index.ts +3 -0
- 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: /
|
|
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: /
|
|
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: /
|
|
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: /
|
|
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> = ({
|
|
25
|
+
const JumpButton: FunctionComponent<JumpButtonProps> = ({
|
|
26
|
+
position,
|
|
27
|
+
isHidden,
|
|
28
|
+
onClick,
|
|
29
|
+
jumpButtonProps,
|
|
30
|
+
jumpButtonTooltipProps
|
|
31
|
+
}: JumpButtonProps) =>
|
|
22
32
|
isHidden ? null : (
|
|
23
|
-
<Tooltip
|
|
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={`
|
|
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: /
|
|
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: /
|
|
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
|
|
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'
|
|
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;
|
|
@@ -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;
|