@patternfly/chatbot 6.3.0-prerelease.2 → 6.3.0-prerelease.4
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/AttachmentEdit/AttachmentEdit.d.ts +2 -0
- package/dist/cjs/AttachmentEdit/AttachmentEdit.js +2 -2
- package/dist/cjs/Chatbot/Chatbot.d.ts +2 -0
- package/dist/cjs/Chatbot/Chatbot.js +2 -2
- package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +2 -0
- package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +2 -2
- package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +4 -0
- package/dist/cjs/ChatbotHeader/ChatbotHeader.js +1 -1
- package/dist/cjs/ChatbotHeader/ChatbotHeaderCloseButton.d.ts +4 -2
- package/dist/cjs/ChatbotHeader/ChatbotHeaderCloseButton.js +20 -6
- package/dist/cjs/ChatbotHeader/ChatbotHeaderCloseButton.test.d.ts +1 -1
- package/dist/cjs/ChatbotHeader/ChatbotHeaderCloseButton.test.js +5 -0
- package/dist/cjs/ChatbotHeader/ChatbotHeaderMain.js +1 -1
- package/dist/cjs/ChatbotModal/ChatbotModal.d.ts +3 -0
- package/dist/cjs/ChatbotModal/ChatbotModal.js +2 -2
- package/dist/cjs/ChatbotModal/ChatbotModal.test.d.ts +1 -0
- package/dist/cjs/ChatbotModal/ChatbotModal.test.js +28 -0
- package/dist/cjs/CodeModal/CodeModal.d.ts +2 -0
- package/dist/cjs/CodeModal/CodeModal.js +3 -3
- package/dist/cjs/CodeModal/CodeModal.test.d.ts +1 -0
- package/dist/cjs/CodeModal/CodeModal.test.js +15 -0
- package/dist/cjs/FileDetails/FileDetails.js +1 -1
- package/dist/cjs/PreviewAttachment/PreviewAttachment.d.ts +2 -0
- package/dist/cjs/PreviewAttachment/PreviewAttachment.js +2 -2
- package/dist/cjs/Settings/SettingsForm.d.ts +2 -0
- package/dist/cjs/Settings/SettingsForm.js +2 -2
- package/dist/cjs/Settings/SettingsForm.test.d.ts +1 -1
- package/dist/cjs/Settings/SettingsForm.test.js +12 -0
- package/dist/css/main.css +54 -9
- package/dist/css/main.css.map +1 -1
- package/dist/esm/AttachmentEdit/AttachmentEdit.d.ts +2 -0
- package/dist/esm/AttachmentEdit/AttachmentEdit.js +2 -2
- package/dist/esm/Chatbot/Chatbot.d.ts +2 -0
- package/dist/esm/Chatbot/Chatbot.js +2 -2
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +2 -0
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +2 -2
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +4 -0
- package/dist/esm/ChatbotHeader/ChatbotHeader.js +1 -1
- package/dist/esm/ChatbotHeader/ChatbotHeaderCloseButton.d.ts +4 -2
- package/dist/esm/ChatbotHeader/ChatbotHeaderCloseButton.js +20 -6
- package/dist/esm/ChatbotHeader/ChatbotHeaderCloseButton.test.d.ts +1 -1
- package/dist/esm/ChatbotHeader/ChatbotHeaderCloseButton.test.js +5 -0
- package/dist/esm/ChatbotHeader/ChatbotHeaderMain.js +1 -1
- package/dist/esm/ChatbotModal/ChatbotModal.d.ts +3 -0
- package/dist/esm/ChatbotModal/ChatbotModal.js +2 -2
- package/dist/esm/ChatbotModal/ChatbotModal.test.d.ts +1 -0
- package/dist/esm/ChatbotModal/ChatbotModal.test.js +23 -0
- package/dist/esm/CodeModal/CodeModal.d.ts +2 -0
- package/dist/esm/CodeModal/CodeModal.js +3 -3
- package/dist/esm/CodeModal/CodeModal.test.d.ts +1 -0
- package/dist/esm/CodeModal/CodeModal.test.js +10 -0
- package/dist/esm/FileDetails/FileDetails.js +1 -1
- package/dist/esm/PreviewAttachment/PreviewAttachment.d.ts +2 -0
- package/dist/esm/PreviewAttachment/PreviewAttachment.js +2 -2
- package/dist/esm/Settings/SettingsForm.d.ts +2 -0
- package/dist/esm/Settings/SettingsForm.js +2 -2
- package/dist/esm/Settings/SettingsForm.test.d.ts +1 -1
- package/dist/esm/Settings/SettingsForm.test.js +12 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/AttachmentEdit.tsx +10 -1
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/PreviewAttachment.tsx +10 -1
- package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawer.tsx +9 -0
- package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawerWithActions.tsx +9 -0
- package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawerWithSelection.tsx +11 -2
- package/patternfly-docs/content/extensions/chatbot/examples/UI/CompactSettings.tsx +289 -0
- package/patternfly-docs/content/extensions/chatbot/examples/UI/UI.md +7 -0
- package/src/AttachmentEdit/AttachmentEdit.tsx +5 -1
- package/src/Chatbot/Chatbot.scss +7 -0
- package/src/Chatbot/Chatbot.tsx +4 -1
- package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.scss +28 -2
- package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.tsx +18 -0
- package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.tsx +4 -1
- package/src/ChatbotHeader/ChatbotHeader.scss +8 -0
- package/src/ChatbotHeader/ChatbotHeader.tsx +1 -1
- package/src/ChatbotHeader/ChatbotHeaderCloseButton.test.tsx +6 -0
- package/src/ChatbotHeader/ChatbotHeaderCloseButton.tsx +12 -6
- package/src/ChatbotHeader/ChatbotHeaderMain.tsx +3 -1
- package/src/ChatbotModal/ChatbotModal.scss +15 -4
- package/src/ChatbotModal/ChatbotModal.test.tsx +59 -0
- package/src/ChatbotModal/ChatbotModal.tsx +5 -1
- package/src/CodeModal/CodeModal.scss +11 -3
- package/src/CodeModal/CodeModal.test.tsx +24 -0
- package/src/CodeModal/CodeModal.tsx +6 -2
- package/src/FileDetails/FileDetails.tsx +1 -1
- package/src/FileDetails/__snapshots__/FileDetails.test.tsx.snap +1 -1
- package/src/FileDetailsLabel/__snapshots__/FileDetailsLabel.test.tsx.snap +1 -1
- package/src/PreviewAttachment/PreviewAttachment.tsx +5 -1
- package/src/Settings/Settings.scss +11 -0
- package/src/Settings/SettingsForm.test.tsx +17 -0
- package/src/Settings/SettingsForm.tsx +12 -2
@@ -0,0 +1,289 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
|
3
|
+
import SettingsForm from '@patternfly/chatbot/dist/dynamic/Settings';
|
4
|
+
import {
|
5
|
+
Button,
|
6
|
+
Divider,
|
7
|
+
Dropdown,
|
8
|
+
DropdownGroup,
|
9
|
+
DropdownItem,
|
10
|
+
DropdownList,
|
11
|
+
MenuToggle,
|
12
|
+
MenuToggleElement,
|
13
|
+
Switch,
|
14
|
+
Title
|
15
|
+
} from '@patternfly/react-core';
|
16
|
+
import Chatbot, { ChatbotDisplayMode } from '@patternfly/chatbot/dist/dynamic/Chatbot';
|
17
|
+
import ChatbotHeader, {
|
18
|
+
ChatbotHeaderActions,
|
19
|
+
ChatbotHeaderCloseButton,
|
20
|
+
ChatbotHeaderMain,
|
21
|
+
ChatbotHeaderOptionsDropdown,
|
22
|
+
ChatbotHeaderTitle
|
23
|
+
} from '@patternfly/chatbot/dist/dynamic/ChatbotHeader';
|
24
|
+
import { CogIcon, ExpandIcon, OpenDrawerRightIcon, OutlinedWindowRestoreIcon } from '@patternfly/react-icons';
|
25
|
+
|
26
|
+
export const CompactSettingsDemo: React.FunctionComponent = () => {
|
27
|
+
const [isChecked, setIsChecked] = React.useState<boolean>(true);
|
28
|
+
const [isThemeOpen, setIsThemeOpen] = React.useState(false);
|
29
|
+
const [isLanguageOpen, setIsLanguageOpen] = React.useState(false);
|
30
|
+
const [isVoiceOpen, setIsVoiceOpen] = React.useState(false);
|
31
|
+
const [displayMode, setDisplayMode] = React.useState(ChatbotDisplayMode.default);
|
32
|
+
const [areSettingsOpen, setAreSettingsOpen] = React.useState(true);
|
33
|
+
const chatbotVisible = true;
|
34
|
+
|
35
|
+
const onFocus = (id: string) => {
|
36
|
+
const element = document.getElementById(id);
|
37
|
+
(element as HTMLElement).focus();
|
38
|
+
};
|
39
|
+
|
40
|
+
const onThemeToggleClick = () => {
|
41
|
+
setIsThemeOpen(!isThemeOpen);
|
42
|
+
};
|
43
|
+
|
44
|
+
const onThemeSelect = (
|
45
|
+
_event: React.MouseEvent<Element, MouseEvent> | undefined,
|
46
|
+
value: string | number | undefined
|
47
|
+
) => {
|
48
|
+
// eslint-disable-next-line no-console
|
49
|
+
console.log('selected', value);
|
50
|
+
onFocus('theme');
|
51
|
+
setIsThemeOpen(false);
|
52
|
+
};
|
53
|
+
|
54
|
+
const onLanguageToggleClick = () => {
|
55
|
+
setIsLanguageOpen(!isLanguageOpen);
|
56
|
+
};
|
57
|
+
|
58
|
+
const onLanguageSelect = (
|
59
|
+
_event: React.MouseEvent<Element, MouseEvent> | undefined,
|
60
|
+
value: string | number | undefined
|
61
|
+
) => {
|
62
|
+
// eslint-disable-next-line no-console
|
63
|
+
console.log('selected', value);
|
64
|
+
onFocus('language');
|
65
|
+
setIsLanguageOpen(false);
|
66
|
+
};
|
67
|
+
|
68
|
+
const onVoiceToggleClick = () => {
|
69
|
+
onFocus('voice');
|
70
|
+
setIsVoiceOpen(!isVoiceOpen);
|
71
|
+
};
|
72
|
+
|
73
|
+
const onVoiceSelect = (
|
74
|
+
_event: React.MouseEvent<Element, MouseEvent> | undefined,
|
75
|
+
value: string | number | undefined
|
76
|
+
) => {
|
77
|
+
// eslint-disable-next-line no-console
|
78
|
+
console.log('selected', value);
|
79
|
+
setIsVoiceOpen(false);
|
80
|
+
};
|
81
|
+
|
82
|
+
const handleChange = (_event: React.FormEvent<HTMLInputElement>, checked: boolean) => {
|
83
|
+
setIsChecked(checked);
|
84
|
+
};
|
85
|
+
|
86
|
+
const themeDropdown = (
|
87
|
+
<Dropdown
|
88
|
+
isOpen={isThemeOpen}
|
89
|
+
onSelect={onThemeSelect}
|
90
|
+
onOpenChange={(isOpen: boolean) => setIsThemeOpen(isOpen)}
|
91
|
+
shouldFocusToggleOnSelect
|
92
|
+
shouldFocusFirstItemOnOpen
|
93
|
+
shouldPreventScrollOnItemFocus
|
94
|
+
toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
|
95
|
+
// We want to add the id property here as well so the label is coupled
|
96
|
+
// with t he button on screen readers.
|
97
|
+
<MenuToggle size="sm" id="theme" ref={toggleRef} onClick={onThemeToggleClick} isExpanded={isThemeOpen}>
|
98
|
+
System
|
99
|
+
</MenuToggle>
|
100
|
+
)}
|
101
|
+
ouiaId="ThemeDropdown"
|
102
|
+
>
|
103
|
+
<DropdownList>
|
104
|
+
<DropdownItem value="System" key="system">
|
105
|
+
System
|
106
|
+
</DropdownItem>
|
107
|
+
</DropdownList>
|
108
|
+
</Dropdown>
|
109
|
+
);
|
110
|
+
|
111
|
+
const languageDropdown = (
|
112
|
+
<Dropdown
|
113
|
+
isOpen={isLanguageOpen}
|
114
|
+
onSelect={onLanguageSelect}
|
115
|
+
onOpenChange={(isOpen: boolean) => setIsLanguageOpen(isOpen)}
|
116
|
+
shouldFocusToggleOnSelect
|
117
|
+
shouldFocusFirstItemOnOpen
|
118
|
+
shouldPreventScrollOnItemFocus
|
119
|
+
toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
|
120
|
+
// We want to add the id property here as well so the label is coupled
|
121
|
+
// with the button on screen readers.
|
122
|
+
<MenuToggle size="sm" id="language" ref={toggleRef} onClick={onLanguageToggleClick} isExpanded={isLanguageOpen}>
|
123
|
+
Auto-detect
|
124
|
+
</MenuToggle>
|
125
|
+
)}
|
126
|
+
ouiaId="LanguageDropdown"
|
127
|
+
>
|
128
|
+
<DropdownList>
|
129
|
+
<DropdownItem value="Auto-detect" key="auto-detect">
|
130
|
+
Auto-detect
|
131
|
+
</DropdownItem>
|
132
|
+
</DropdownList>
|
133
|
+
</Dropdown>
|
134
|
+
);
|
135
|
+
const voiceDropdown = (
|
136
|
+
<Dropdown
|
137
|
+
isOpen={isVoiceOpen}
|
138
|
+
onSelect={onVoiceSelect}
|
139
|
+
onOpenChange={(isOpen: boolean) => setIsVoiceOpen(isOpen)}
|
140
|
+
shouldFocusToggleOnSelect
|
141
|
+
shouldFocusFirstItemOnOpen
|
142
|
+
shouldPreventScrollOnItemFocus
|
143
|
+
toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
|
144
|
+
// We want to add the id property here as well so the label is coupled
|
145
|
+
// with the button on screen readers.
|
146
|
+
<MenuToggle size="sm" id="voice" ref={toggleRef} onClick={onVoiceToggleClick} isExpanded={isVoiceOpen}>
|
147
|
+
Bot
|
148
|
+
</MenuToggle>
|
149
|
+
)}
|
150
|
+
ouiaId="VoiceDropdown"
|
151
|
+
>
|
152
|
+
<DropdownList>
|
153
|
+
<DropdownItem value="Bot" key="bot">
|
154
|
+
Bot
|
155
|
+
</DropdownItem>
|
156
|
+
</DropdownList>
|
157
|
+
</Dropdown>
|
158
|
+
);
|
159
|
+
const children = [
|
160
|
+
{ id: 'theme', label: 'Theme', field: themeDropdown },
|
161
|
+
{ id: 'language', label: 'Language', field: languageDropdown },
|
162
|
+
{ id: 'voice', label: 'Voice', field: voiceDropdown },
|
163
|
+
{
|
164
|
+
id: 'analytics',
|
165
|
+
label: 'Share analytics',
|
166
|
+
field: (
|
167
|
+
<Switch
|
168
|
+
// We want to add the id property here as well so the label is coupled
|
169
|
+
// with the button on screen readers.
|
170
|
+
id="analytics"
|
171
|
+
aria-label="Togglable option for whether to share analytics"
|
172
|
+
isChecked={isChecked}
|
173
|
+
onChange={handleChange}
|
174
|
+
/>
|
175
|
+
)
|
176
|
+
},
|
177
|
+
{
|
178
|
+
id: 'archived-chat',
|
179
|
+
label: 'Archive chat',
|
180
|
+
field: (
|
181
|
+
// We want to add the id property here as well so the label is coupled
|
182
|
+
// with the button on screen readers.
|
183
|
+
<Button size="sm" id="archived-chat" variant="secondary">
|
184
|
+
Manage
|
185
|
+
</Button>
|
186
|
+
)
|
187
|
+
},
|
188
|
+
{
|
189
|
+
id: 'archive-all',
|
190
|
+
label: 'Archive all chat',
|
191
|
+
field: (
|
192
|
+
// We want to add the id property here as well so the label is coupled
|
193
|
+
// with the button on screen readers.
|
194
|
+
<Button size="sm" id="archive-all" variant="secondary">
|
195
|
+
Archive all
|
196
|
+
</Button>
|
197
|
+
)
|
198
|
+
},
|
199
|
+
{
|
200
|
+
id: 'delete-all',
|
201
|
+
label: 'Delete all chats',
|
202
|
+
field: (
|
203
|
+
// We want to add the id property here as well so the label is coupled
|
204
|
+
// with the button on screen readers.
|
205
|
+
<Button size="sm" id="delete-all" variant="danger">
|
206
|
+
Delete all
|
207
|
+
</Button>
|
208
|
+
)
|
209
|
+
}
|
210
|
+
];
|
211
|
+
|
212
|
+
const onSelectDropdownItem = (
|
213
|
+
_event: React.MouseEvent<Element, MouseEvent> | undefined,
|
214
|
+
value: string | number | undefined
|
215
|
+
) => {
|
216
|
+
if (value === 'Settings') {
|
217
|
+
setAreSettingsOpen(true);
|
218
|
+
} else {
|
219
|
+
setDisplayMode(value as ChatbotDisplayMode);
|
220
|
+
}
|
221
|
+
};
|
222
|
+
|
223
|
+
const regularChatbot = (
|
224
|
+
<ChatbotHeader>
|
225
|
+
<ChatbotHeaderActions>
|
226
|
+
<ChatbotHeaderOptionsDropdown isCompact onSelect={onSelectDropdownItem}>
|
227
|
+
<DropdownGroup label="Display mode">
|
228
|
+
<DropdownList>
|
229
|
+
<DropdownItem
|
230
|
+
value={ChatbotDisplayMode.default}
|
231
|
+
key="switchDisplayOverlay"
|
232
|
+
icon={<OutlinedWindowRestoreIcon aria-hidden />}
|
233
|
+
isSelected={displayMode === ChatbotDisplayMode.default}
|
234
|
+
>
|
235
|
+
<span>Overlay</span>
|
236
|
+
</DropdownItem>
|
237
|
+
<DropdownItem
|
238
|
+
value={ChatbotDisplayMode.docked}
|
239
|
+
key="switchDisplayDock"
|
240
|
+
icon={<OpenDrawerRightIcon aria-hidden />}
|
241
|
+
isSelected={displayMode === ChatbotDisplayMode.docked}
|
242
|
+
>
|
243
|
+
<span>Dock to window</span>
|
244
|
+
</DropdownItem>
|
245
|
+
<DropdownItem
|
246
|
+
value={ChatbotDisplayMode.fullscreen}
|
247
|
+
key="switchDisplayFullscreen"
|
248
|
+
icon={<ExpandIcon aria-hidden />}
|
249
|
+
isSelected={displayMode === ChatbotDisplayMode.fullscreen}
|
250
|
+
>
|
251
|
+
<span>Fullscreen</span>
|
252
|
+
</DropdownItem>
|
253
|
+
</DropdownList>
|
254
|
+
</DropdownGroup>
|
255
|
+
<Divider />
|
256
|
+
<DropdownList>
|
257
|
+
<DropdownItem value="Settings" key="switchSettings" icon={<CogIcon aria-hidden />}>
|
258
|
+
<span>Settings</span>
|
259
|
+
</DropdownItem>
|
260
|
+
</DropdownList>
|
261
|
+
</ChatbotHeaderOptionsDropdown>
|
262
|
+
</ChatbotHeaderActions>
|
263
|
+
</ChatbotHeader>
|
264
|
+
);
|
265
|
+
|
266
|
+
return (
|
267
|
+
<>
|
268
|
+
<Chatbot isCompact isVisible={chatbotVisible} displayMode={displayMode}>
|
269
|
+
{areSettingsOpen ? (
|
270
|
+
<>
|
271
|
+
<ChatbotHeader className="pf-m-compact">
|
272
|
+
<ChatbotHeaderMain>
|
273
|
+
<ChatbotHeaderTitle>
|
274
|
+
<Title headingLevel="h1" size="2xl">
|
275
|
+
Settings
|
276
|
+
</Title>
|
277
|
+
</ChatbotHeaderTitle>
|
278
|
+
</ChatbotHeaderMain>
|
279
|
+
<ChatbotHeaderCloseButton isCompact onClick={() => setAreSettingsOpen(false)} />
|
280
|
+
</ChatbotHeader>
|
281
|
+
<SettingsForm isCompact fields={children} />
|
282
|
+
</>
|
283
|
+
) : (
|
284
|
+
<>{regularChatbot}</>
|
285
|
+
)}
|
286
|
+
</Chatbot>
|
287
|
+
</>
|
288
|
+
);
|
289
|
+
};
|
@@ -406,6 +406,13 @@ In this demo, you can toggle the settings page by clicking the "Settings" button
|
|
406
406
|
|
407
407
|
```
|
408
408
|
|
409
|
+
### Compact settings
|
410
|
+
|
411
|
+
To make the settings menu compact, with less spacing between the menu contents, pass `isCompact` to the `<SettingsForm>`.
|
412
|
+
```js file="./CompactSettings.tsx" isFullscreen
|
413
|
+
|
414
|
+
```
|
415
|
+
|
409
416
|
## Modals
|
410
417
|
|
411
418
|
### Modal
|
@@ -22,6 +22,8 @@ export interface AttachmentEditProps {
|
|
22
22
|
title?: string;
|
23
23
|
/** Display mode for the Chatbot parent; this influences the styles applied */
|
24
24
|
displayMode?: ChatbotDisplayMode;
|
25
|
+
/** Sets modal to compact styling. */
|
26
|
+
isCompact?: boolean;
|
25
27
|
}
|
26
28
|
|
27
29
|
export const AttachmentEdit: React.FunctionComponent<AttachmentEditProps> = ({
|
@@ -32,7 +34,8 @@ export const AttachmentEdit: React.FunctionComponent<AttachmentEditProps> = ({
|
|
32
34
|
onCancel,
|
33
35
|
onSave,
|
34
36
|
title = 'Edit attachment',
|
35
|
-
displayMode = ChatbotDisplayMode.default
|
37
|
+
displayMode = ChatbotDisplayMode.default,
|
38
|
+
isCompact
|
36
39
|
}: AttachmentEditProps) => {
|
37
40
|
const handleSave = (_event: React.MouseEvent | MouseEvent | KeyboardEvent, code) => {
|
38
41
|
handleModalToggle(_event);
|
@@ -56,6 +59,7 @@ export const AttachmentEdit: React.FunctionComponent<AttachmentEditProps> = ({
|
|
56
59
|
secondaryActionBtn="Cancel"
|
57
60
|
title={title}
|
58
61
|
displayMode={displayMode}
|
62
|
+
isCompact={isCompact}
|
59
63
|
/>
|
60
64
|
);
|
61
65
|
};
|
package/src/Chatbot/Chatbot.scss
CHANGED
@@ -125,3 +125,10 @@
|
|
125
125
|
border-radius: var(--pf-t--global--border--radius--sharp);
|
126
126
|
}
|
127
127
|
}
|
128
|
+
|
129
|
+
// ============================================================================
|
130
|
+
// Information density styles
|
131
|
+
// ============================================================================
|
132
|
+
.pf-chatbot.pf-m-compact {
|
133
|
+
font-size: var(--pf-t--global--font--size--sm);
|
134
|
+
}
|
package/src/Chatbot/Chatbot.tsx
CHANGED
@@ -17,6 +17,8 @@ export interface ChatbotProps {
|
|
17
17
|
innerRef?: React.Ref<HTMLDivElement>;
|
18
18
|
/** Custom aria label applied to focusable container */
|
19
19
|
ariaLabel?: string;
|
20
|
+
/** Density of information within the ChatBot */
|
21
|
+
isCompact?: boolean;
|
20
22
|
}
|
21
23
|
|
22
24
|
export enum ChatbotDisplayMode {
|
@@ -34,6 +36,7 @@ const ChatbotBase: React.FunctionComponent<ChatbotProps> = ({
|
|
34
36
|
className,
|
35
37
|
innerRef,
|
36
38
|
ariaLabel,
|
39
|
+
isCompact,
|
37
40
|
...props
|
38
41
|
}: ChatbotProps) => {
|
39
42
|
// Configure animations
|
@@ -44,7 +47,7 @@ const ChatbotBase: React.FunctionComponent<ChatbotProps> = ({
|
|
44
47
|
|
45
48
|
return (
|
46
49
|
<motion.div
|
47
|
-
className={`pf-chatbot pf-chatbot--${displayMode} ${!isVisible ? 'pf-chatbot--hidden' : ''} ${className ?? ''}`}
|
50
|
+
className={`pf-chatbot pf-chatbot--${displayMode} ${!isVisible ? 'pf-chatbot--hidden' : ''} ${isCompact ? 'pf-m-compact' : ''} ${className ?? ''}`}
|
48
51
|
variants={motionChatbot}
|
49
52
|
initial="hidden"
|
50
53
|
animate={isVisible ? 'visible' : 'hidden'}
|
@@ -9,8 +9,8 @@
|
|
9
9
|
// Drawer input
|
10
10
|
// ----------------------------------------------------------------------------
|
11
11
|
.pf-chatbot__input {
|
12
|
-
padding-inline-start: var(--pf-t--global--spacer--
|
13
|
-
padding-inline-end: var(--pf-t--global--spacer--
|
12
|
+
padding-inline-start: var(--pf-t--global--spacer--lg);
|
13
|
+
padding-inline-end: var(--pf-t--global--spacer--lg);
|
14
14
|
}
|
15
15
|
|
16
16
|
// Drawer menu
|
@@ -205,3 +205,29 @@
|
|
205
205
|
gap: var(--pf-t--global--spacer--sm);
|
206
206
|
align-self: stretch;
|
207
207
|
}
|
208
|
+
|
209
|
+
.pf-chatbot__history.pf-m-compact {
|
210
|
+
.pf-v6-c-drawer__main {
|
211
|
+
.pf-v6-c-drawer__panel {
|
212
|
+
--pf-v6-c-drawer__panel--PaddingBlockStart: var(--pf-t--global--spacer--sm);
|
213
|
+
--pf-v6-c-drawer__panel--PaddingBlockEnd: var(--pf-t--global--spacer--sm);
|
214
|
+
--pf-v6-c-drawer__head--PaddingInlineStart: var(--pf-t--global--spacer--md);
|
215
|
+
--pf-v6-c-drawer__head--PaddingInlineEnd: var(--pf-t--global--spacer--md);
|
216
|
+
--pf-v6-c-drawer__panel--RowGap: var(--pf-t--global--spacer--md);
|
217
|
+
}
|
218
|
+
|
219
|
+
.pf-v6-c-drawer__body {
|
220
|
+
--pf-v6-c-drawer__panel__body--PaddingInlineStart: var(--pf-t--global--spacer--md);
|
221
|
+
--pf-v6-c-drawer__panel__body--PaddingInlineEnd: var(--pf-t--global--spacer--md);
|
222
|
+
}
|
223
|
+
}
|
224
|
+
|
225
|
+
.pf-chatbot__menu-item {
|
226
|
+
font-size: var(--pf-t--global--font--size--body--md);
|
227
|
+
}
|
228
|
+
|
229
|
+
.pf-v6-c-drawer__head {
|
230
|
+
--pf-v6-c-drawer__head--PaddingInlineStart: var(--pf-t--global--spacer--lg);
|
231
|
+
--pf-v6-c-drawer__head--PaddingInlineEnd: var(--pf-t--global--spacer--lg);
|
232
|
+
}
|
233
|
+
}
|
@@ -415,4 +415,22 @@ describe('ChatbotConversationHistoryNav', () => {
|
|
415
415
|
})
|
416
416
|
).toBeTruthy();
|
417
417
|
});
|
418
|
+
|
419
|
+
it('should handle isCompact', () => {
|
420
|
+
render(
|
421
|
+
<ChatbotConversationHistoryNav
|
422
|
+
onDrawerToggle={onDrawerToggle}
|
423
|
+
isDrawerOpen={true}
|
424
|
+
displayMode={ChatbotDisplayMode.fullscreen}
|
425
|
+
setIsDrawerOpen={jest.fn()}
|
426
|
+
reverseButtonOrder={false}
|
427
|
+
handleTextInputChange={jest.fn()}
|
428
|
+
conversations={initialConversations}
|
429
|
+
noResultsState={NO_RESULTS}
|
430
|
+
isCompact
|
431
|
+
data-testid="drawer"
|
432
|
+
/>
|
433
|
+
);
|
434
|
+
expect(screen.getByTestId('drawer')).toHaveClass('pf-m-compact');
|
435
|
+
});
|
418
436
|
});
|
@@ -116,6 +116,8 @@ export interface ChatbotConversationHistoryNavProps extends DrawerProps {
|
|
116
116
|
emptyState?: HistoryEmptyStateProps;
|
117
117
|
/** Content to show in no results state. No results state will appear once content is passed in. */
|
118
118
|
noResultsState?: HistoryEmptyStateProps;
|
119
|
+
/** Sets drawer to compact styling. */
|
120
|
+
isCompact?: boolean;
|
119
121
|
}
|
120
122
|
|
121
123
|
export const ChatbotConversationHistoryNav: React.FunctionComponent<ChatbotConversationHistoryNavProps> = ({
|
@@ -147,6 +149,7 @@ export const ChatbotConversationHistoryNav: React.FunctionComponent<ChatbotConve
|
|
147
149
|
errorState,
|
148
150
|
emptyState,
|
149
151
|
noResultsState,
|
152
|
+
isCompact,
|
150
153
|
...props
|
151
154
|
}: ChatbotConversationHistoryNavProps) => {
|
152
155
|
const drawerRef = React.useRef<HTMLDivElement>(null);
|
@@ -287,7 +290,7 @@ export const ChatbotConversationHistoryNav: React.FunctionComponent<ChatbotConve
|
|
287
290
|
|
288
291
|
return (
|
289
292
|
<Drawer
|
290
|
-
className=
|
293
|
+
className={`pf-chatbot__history ${isCompact ? 'pf-m-compact' : ''}`}
|
291
294
|
isExpanded={isDrawerOpen}
|
292
295
|
onExpand={onExpand}
|
293
296
|
position="start"
|
@@ -137,3 +137,11 @@
|
|
137
137
|
:where(.pf-v6-theme-dark) .show-dark .pf-m-picture {
|
138
138
|
display: inline-flex;
|
139
139
|
}
|
140
|
+
|
141
|
+
// ============================================================================
|
142
|
+
// Information density styles
|
143
|
+
// ============================================================================
|
144
|
+
.pf-chatbot__button--toggle-menu.pf-m-compact {
|
145
|
+
width: 2rem;
|
146
|
+
height: 2rem;
|
147
|
+
}
|
@@ -14,7 +14,7 @@ export const ChatbotHeader: React.FunctionComponent<ChatbotHeaderProps> = ({
|
|
14
14
|
children
|
15
15
|
}: ChatbotHeaderProps) => (
|
16
16
|
<div className="pf-chatbot__header-container">
|
17
|
-
<div className={`pf-chatbot__header ${className
|
17
|
+
<div className={`pf-chatbot__header${className ? ` ${className}` : ''}`}>{children}</div>
|
18
18
|
<Divider className="pf-chatbot__header__divider" />
|
19
19
|
</div>
|
20
20
|
);
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import { fireEvent, render, screen } from '@testing-library/react';
|
3
3
|
import { ChatbotHeaderCloseButton } from './ChatbotHeaderCloseButton';
|
4
|
+
import '@testing-library/jest-dom';
|
4
5
|
|
5
6
|
describe('ChatbotHeaderCloseButton', () => {
|
6
7
|
it('should render ChatbotHeaderCloseButton', () => {
|
@@ -17,4 +18,9 @@ describe('ChatbotHeaderCloseButton', () => {
|
|
17
18
|
fireEvent.click(screen.getByRole('button', { name: 'Close' }));
|
18
19
|
expect(onClick).toHaveBeenCalled();
|
19
20
|
});
|
21
|
+
|
22
|
+
it('should render button with isCompact', () => {
|
23
|
+
render(<ChatbotHeaderCloseButton data-testid="close-button" onClick={jest.fn()} isCompact />);
|
24
|
+
expect(screen.getByTestId('close-button')).toHaveClass('pf-m-compact');
|
25
|
+
});
|
20
26
|
});
|
@@ -1,9 +1,9 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
|
3
|
-
import { Button, Icon, Tooltip, TooltipProps } from '@patternfly/react-core';
|
3
|
+
import { Button, ButtonProps, Icon, Tooltip, TooltipProps } from '@patternfly/react-core';
|
4
4
|
import { CloseIcon } from '@patternfly/react-icons';
|
5
5
|
|
6
|
-
export interface ChatbotHeaderCloseButtonProps {
|
6
|
+
export interface ChatbotHeaderCloseButtonProps extends ButtonProps {
|
7
7
|
/** Callback function for when button is clicked */
|
8
8
|
onClick: () => void;
|
9
9
|
/** Custom classname for the header component */
|
@@ -16,6 +16,8 @@ export interface ChatbotHeaderCloseButtonProps {
|
|
16
16
|
innerRef?: React.Ref<HTMLButtonElement>;
|
17
17
|
/** Content used in tooltip */
|
18
18
|
tooltipContent?: string;
|
19
|
+
/** Sets button to compact styling. */
|
20
|
+
isCompact?: boolean;
|
19
21
|
}
|
20
22
|
|
21
23
|
const ChatbotHeaderCloseButtonBase: React.FunctionComponent<ChatbotHeaderCloseButtonProps> = ({
|
@@ -24,9 +26,11 @@ const ChatbotHeaderCloseButtonBase: React.FunctionComponent<ChatbotHeaderCloseBu
|
|
24
26
|
tooltipProps,
|
25
27
|
menuAriaLabel = 'Close',
|
26
28
|
innerRef,
|
27
|
-
tooltipContent = 'Close'
|
29
|
+
tooltipContent = 'Close',
|
30
|
+
isCompact,
|
31
|
+
...props
|
28
32
|
}: ChatbotHeaderCloseButtonProps) => (
|
29
|
-
<div className={`pf-chatbot__menu ${className}`}>
|
33
|
+
<div className={`pf-chatbot__menu${className ? ` ${className}` : ''}`}>
|
30
34
|
<Tooltip
|
31
35
|
content={tooltipContent}
|
32
36
|
position="bottom"
|
@@ -35,16 +39,18 @@ const ChatbotHeaderCloseButtonBase: React.FunctionComponent<ChatbotHeaderCloseBu
|
|
35
39
|
{...tooltipProps}
|
36
40
|
>
|
37
41
|
<Button
|
38
|
-
className=
|
42
|
+
className={`pf-chatbot__button--toggle-menu ${isCompact ? 'pf-m-compact' : ''}`}
|
39
43
|
variant="plain"
|
40
44
|
onClick={onClick}
|
41
45
|
aria-label={menuAriaLabel}
|
42
46
|
ref={innerRef}
|
43
47
|
icon={
|
44
|
-
<Icon size=
|
48
|
+
<Icon size={isCompact ? 'lg' : 'xl'} isInline>
|
45
49
|
<CloseIcon />
|
46
50
|
</Icon>
|
47
51
|
}
|
52
|
+
size={isCompact ? 'sm' : undefined}
|
53
|
+
{...props}
|
48
54
|
/>
|
49
55
|
</Tooltip>
|
50
56
|
</div>
|
@@ -10,6 +10,8 @@ export interface ChatbotHeaderMainProps {
|
|
10
10
|
export const ChatbotHeaderMain: React.FunctionComponent<ChatbotHeaderMainProps> = ({
|
11
11
|
className,
|
12
12
|
children
|
13
|
-
}: ChatbotHeaderMainProps) =>
|
13
|
+
}: ChatbotHeaderMainProps) => (
|
14
|
+
<div className={`pf-chatbot__header-main${className ? ` ${className}` : ''}`}>{children}</div>
|
15
|
+
);
|
14
16
|
|
15
17
|
export default ChatbotHeaderMain;
|
@@ -14,10 +14,7 @@
|
|
14
14
|
.pf-v6-c-modal-box__title {
|
15
15
|
--pf-v6-c-modal-box__title--FontSize: var(--pf-t--global--font--size--heading--h3);
|
16
16
|
}
|
17
|
-
|
18
|
-
.pf-v6-c-button.pf-m-link.pf-m-block {
|
19
|
-
--pf-v6-c-button--FontWeight: var(--pf-t--global--font--weight--body--bold);
|
20
|
-
}
|
17
|
+
|
21
18
|
.pf-v6-c-modal-box__footer {
|
22
19
|
padding-block-start: var(--pf-t--global--spacer--xl);
|
23
20
|
padding-block-end: var(--pf-t--global--spacer--xl);
|
@@ -91,3 +88,17 @@
|
|
91
88
|
.pf-v6-c-backdrop.pf-chatbot__backdrop {
|
92
89
|
position: absolute;
|
93
90
|
}
|
91
|
+
|
92
|
+
// ============================================================================
|
93
|
+
// Compact
|
94
|
+
// ============================================================================
|
95
|
+
.pf-chatbot__chatbot-modal.pf-m-compact {
|
96
|
+
.pf-v6-c-modal-box__header {
|
97
|
+
padding-block-end: 0;
|
98
|
+
}
|
99
|
+
|
100
|
+
.pf-v6-c-modal-box__footer {
|
101
|
+
padding-block-start: var(--pf-t--global--spacer--lg);
|
102
|
+
padding-block-end: var(--pf-t--global--spacer--lg);
|
103
|
+
}
|
104
|
+
}
|
@@ -0,0 +1,59 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { render, screen } from '@testing-library/react';
|
3
|
+
import ChatbotModal from './ChatbotModal';
|
4
|
+
import '@testing-library/jest-dom';
|
5
|
+
import { ModalBody, ModalHeader } from '@patternfly/react-core';
|
6
|
+
|
7
|
+
describe('ChatbotModal', () => {
|
8
|
+
it('should render compact modal', () => {
|
9
|
+
render(
|
10
|
+
<ChatbotModal data-testid="modal" isCompact isOpen>
|
11
|
+
<ModalHeader
|
12
|
+
title="Modal with description"
|
13
|
+
labelId="modal-with-description-title"
|
14
|
+
description="A description is used when you want to provide more info about the modal than the title is able to describe. The content in the description is static and will not scroll with the rest of the modal body."
|
15
|
+
/>
|
16
|
+
<ModalBody tabIndex={0} id="modal-box-body-with-description">
|
17
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore
|
18
|
+
magna aliqua. Quis eleifend quam adipiscing vitae proin sagittis nisl rhoncus. Semper auctor neque vitae
|
19
|
+
tempus. Diam donec adipiscing tristique risus. Augue eget arcu dictum varius duis. Ut enim blandit volutpat
|
20
|
+
maecenas volutpat blandit aliquam. Sit amet mauris commodo quis imperdiet massa tincidunt. Habitant morbi
|
21
|
+
tristique senectus et netus. Fames ac turpis egestas sed tempus urna. Neque laoreet suspendisse interdum
|
22
|
+
consectetur libero id. Volutpat lacus laoreet non curabitur gravida arcu ac tortor. Porta nibh venenatis cras
|
23
|
+
sed felis eget velit. Nullam non nisi est sit amet facilisis. Nunc mi ipsum faucibus vitae. Lorem sed risus
|
24
|
+
ultricies tristique nulla aliquet enim tortor at. Egestas sed tempus urna et pharetra pharetra massa massa
|
25
|
+
ultricies. Lacinia quis vel eros donec ac odio tempor orci. Malesuada fames ac turpis egestas integer eget
|
26
|
+
aliquet.
|
27
|
+
<br />
|
28
|
+
<br />
|
29
|
+
Neque aliquam vestibulum morbi blandit cursus risus at ultrices. Molestie at elementum eu facilisis sed odio
|
30
|
+
morbi. Elit pellentesque habitant morbi tristique. Consequat nisl vel pretium lectus quam id leo in vitae.
|
31
|
+
Quis varius quam quisque id diam vel quam elementum. Viverra nam libero justo laoreet sit amet cursus.
|
32
|
+
Sollicitudin tempor id eu nisl nunc. Orci nulla pellentesque dignissim enim sit amet venenatis. Dignissim enim
|
33
|
+
sit amet venenatis urna cursus eget. Iaculis at erat pellentesque adipiscing commodo elit. Faucibus pulvinar
|
34
|
+
elementum integer enim neque volutpat. Nullam vehicula ipsum a arcu cursus vitae congue mauris. Nunc mattis
|
35
|
+
enim ut tellus elementum sagittis vitae. Blandit cursus risus at ultrices. Tellus mauris a diam maecenas sed
|
36
|
+
enim. Non diam phasellus vestibulum lorem sed risus ultricies tristique nulla.
|
37
|
+
<br />
|
38
|
+
<br />
|
39
|
+
Nulla pharetra diam sit amet nisl suscipit adipiscing. Ac tortor vitae purus faucibus ornare suspendisse sed
|
40
|
+
nisi. Sed felis eget velit aliquet sagittis id consectetur purus. Tincidunt tortor aliquam nulla facilisi cras
|
41
|
+
fermentum. Volutpat est velit egestas dui id ornare arcu odio. Pharetra magna ac placerat vestibulum. Ultrices
|
42
|
+
sagittis orci a scelerisque purus semper eget duis at. Nisi est sit amet facilisis magna etiam tempor orci eu.
|
43
|
+
Convallis tellus id interdum velit. Facilisis sed odio morbi quis commodo odio aenean sed.
|
44
|
+
<br />
|
45
|
+
<br />
|
46
|
+
Eu scelerisque felis imperdiet proin fermentum leo vel orci porta. Facilisi etiam dignissim diam quis enim
|
47
|
+
lobortis scelerisque fermentum. Eleifend donec pretium vulputate sapien nec sagittis aliquam malesuada. Magna
|
48
|
+
etiam tempor orci eu lobortis elementum. Quis auctor elit sed vulputate mi sit. Eleifend quam adipiscing vitae
|
49
|
+
proin sagittis nisl rhoncus mattis rhoncus. Erat velit scelerisque in dictum non. Sit amet nulla facilisi
|
50
|
+
morbi tempus iaculis urna. Enim ut tellus elementum sagittis vitae et leo duis ut. Lectus arcu bibendum at
|
51
|
+
varius vel pharetra vel turpis. Morbi tristique senectus et netus et. Eget aliquet nibh praesent tristique
|
52
|
+
magna sit amet purus gravida. Nisl purus in mollis nunc sed id semper risus. Id neque aliquam vestibulum
|
53
|
+
morbi. Mauris a diam maecenas sed enim ut sem. Egestas tellus rutrum tellus pellentesque.
|
54
|
+
</ModalBody>
|
55
|
+
</ChatbotModal>
|
56
|
+
);
|
57
|
+
expect(screen.getByTestId('modal')).toHaveClass('pf-m-compact');
|
58
|
+
});
|
59
|
+
});
|