Skip to content

Commit a3b731d

Browse files
authored
Merge pull request #135 from rebeccaalpert/code-modal
fix(FileDropZone/CodeModal): Pass Chatbot display mode down
2 parents 560d86b + 55674d6 commit a3b731d

File tree

11 files changed

+205
-17
lines changed

11 files changed

+205
-17
lines changed

packages/module/patternfly-docs/content/extensions/virtual-assistant/examples/demos/AttachmentDemos.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ sourceLink: https://github.com/patternfly/virtual-assistant/blob/main/packages/m
1212
---
1313

1414
import ChatbotToggle from '@patternfly/virtual-assistant/dist/dynamic/ChatbotToggle';
15-
import Chatbot from '@patternfly/virtual-assistant/dist/dynamic/Chatbot';
15+
import Chatbot, { ChatbotDisplayMode } from '@patternfly/virtual-assistant/dist/dynamic/Chatbot';
1616
import ChatbotContent from '@patternfly/virtual-assistant/dist/dynamic/ChatbotContent';
1717
import ChatbotWelcomePrompt from '@patternfly/virtual-assistant/dist/dynamic/ChatbotWelcomePrompt';
1818
import ChatbotFooter, { ChatbotFootnote } from '@patternfly/virtual-assistant/dist/dynamic/ChatbotFooter';
@@ -26,6 +26,18 @@ import AttachmentEdit from '@patternfly/virtual-assistant/dist/dynamic/Attachmen
2626
import SourceDetailsMenuItem from '@patternfly/virtual-assistant/dist/dynamic/SourceDetailsMenuItem';
2727
import { BellIcon, CalendarAltIcon, ClipboardIcon, CodeIcon, UploadIcon } from '@patternfly/react-icons';
2828
import { useDropzone } from 'react-dropzone';
29+
import PFHorizontalLogoColor from '../ChatbotHeader/PF-HorizontalLogo-Color.svg';
30+
import PFHorizontalLogoReverse from '../ChatbotHeader/PF-HorizontalLogo-Reverse.svg';
31+
import ChatbotHeader, {
32+
ChatbotHeaderMenu,
33+
ChatbotHeaderTitle,
34+
ChatbotHeaderActions,
35+
ChatbotHeaderSelectorDropdown,
36+
ChatbotHeaderOptionsDropdown
37+
} from '@patternfly/virtual-assistant/dist/dynamic/ChatbotHeader';
38+
import ExpandIcon from '@patternfly/react-icons/dist/esm/icons/expand-icon';
39+
import OpenDrawerRightIcon from '@patternfly/react-icons/dist/esm/icons/open-drawer-right-icon';
40+
import OutlinedWindowRestoreIcon from '@patternfly/react-icons/dist/esm/icons/outlined-window-restore-icon';
2941

3042
# Demos
3143

packages/module/patternfly-docs/content/extensions/virtual-assistant/examples/demos/ChatbotAttachment.tsx

Lines changed: 99 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,38 @@
11
import React from 'react';
22
import ChatbotToggle from '@patternfly/virtual-assistant/dist/dynamic/ChatbotToggle';
3-
import Chatbot from '@patternfly/virtual-assistant/dist/dynamic/Chatbot';
3+
import Chatbot, { ChatbotDisplayMode } from '@patternfly/virtual-assistant/dist/dynamic/Chatbot';
44
import ChatbotContent from '@patternfly/virtual-assistant/dist/dynamic/ChatbotContent';
55
import ChatbotWelcomePrompt from '@patternfly/virtual-assistant/dist/dynamic/ChatbotWelcomePrompt';
66
import ChatbotFooter, { ChatbotFootnote } from '@patternfly/virtual-assistant/dist/dynamic/ChatbotFooter';
77
import MessageBar from '@patternfly/virtual-assistant/dist/dynamic/MessageBar';
88
import MessageBox from '@patternfly/virtual-assistant/dist/dynamic/MessageBox';
99
import Message, { MessageProps } from '@patternfly/virtual-assistant/dist/dynamic/Message';
1010
import FileDropZone from '@patternfly/virtual-assistant/dist/dynamic/FileDropZone';
11-
import { Alert, AlertActionCloseButton, DropEvent } from '@patternfly/react-core';
11+
import {
12+
Alert,
13+
AlertActionCloseButton,
14+
Brand,
15+
Bullseye,
16+
DropdownGroup,
17+
DropdownItem,
18+
DropdownList,
19+
DropEvent
20+
} from '@patternfly/react-core';
1221
import FileDetailsLabel from '@patternfly/virtual-assistant/dist/dynamic/FileDetailsLabel';
1322
import PreviewAttachment from '@patternfly/virtual-assistant/dist/dynamic/PreviewAttachment';
1423
import AttachmentEdit from '@patternfly/virtual-assistant/dist/dynamic/AttachmentEdit';
24+
import ChatbotHeader, {
25+
ChatbotHeaderMenu,
26+
ChatbotHeaderTitle,
27+
ChatbotHeaderActions,
28+
ChatbotHeaderSelectorDropdown,
29+
ChatbotHeaderOptionsDropdown
30+
} from '@patternfly/virtual-assistant/dist/dynamic/ChatbotHeader';
31+
import ExpandIcon from '@patternfly/react-icons/dist/esm/icons/expand-icon';
32+
import OpenDrawerRightIcon from '@patternfly/react-icons/dist/esm/icons/open-drawer-right-icon';
33+
import OutlinedWindowRestoreIcon from '@patternfly/react-icons/dist/esm/icons/outlined-window-restore-icon';
34+
import PFHorizontalLogoColor from '../ChatbotHeader/PF-HorizontalLogo-Color.svg';
35+
import PFHorizontalLogoReverse from '../ChatbotHeader/PF-HorizontalLogo-Reverse.svg';
1536

1637
const footnoteProps = {
1738
label: 'Lightspeed uses AI. Check for mistakes.',
@@ -94,6 +115,23 @@ export const BasicDemo: React.FunctionComponent = () => {
94115
const [isEditModalOpen, setIsEditModalOpen] = React.useState<boolean>(false);
95116
const [currentModalData, setCurrentModalData] = React.useState<ModalData>();
96117
const [showAlert, setShowAlert] = React.useState<boolean>(false);
118+
const [selectedModel, setSelectedModel] = React.useState('Granite 7B');
119+
const [displayMode, setDisplayMode] = React.useState<ChatbotDisplayMode>(ChatbotDisplayMode.default);
120+
121+
const onSelectModel = (
122+
_event: React.MouseEvent<Element, MouseEvent> | undefined,
123+
value: string | number | undefined
124+
) => {
125+
setSelectedModel(value as string);
126+
};
127+
128+
const onSelectDisplayMode = (
129+
_event: React.MouseEvent<Element, MouseEvent> | undefined,
130+
value: string | number | undefined
131+
) => {
132+
setDisplayMode(value as ChatbotDisplayMode);
133+
};
134+
97135
const handleSend = (message) => alert(message);
98136

99137
// Attachments
@@ -166,9 +204,64 @@ export const BasicDemo: React.FunctionComponent = () => {
166204
setIsPreviewModalOpen(false);
167205
}}
168206
/>
169-
<Chatbot isVisible={chatbotVisible}>
170-
<FileDropZone onFileDrop={handleFileDrop}>
207+
<Chatbot isVisible={chatbotVisible} displayMode={displayMode}>
208+
<FileDropZone onFileDrop={handleFileDrop} displayMode={displayMode}>
171209
<>
210+
<ChatbotHeader>
211+
<ChatbotHeaderMenu onMenuToggle={() => alert('Menu toggle clicked')} />
212+
<ChatbotHeaderTitle>
213+
<Bullseye>
214+
<div className="show-light">
215+
<Brand src={PFHorizontalLogoColor} alt="PatternFly" />
216+
</div>
217+
<div className="show-dark">
218+
<Brand src={PFHorizontalLogoReverse} alt="PatternFly" />
219+
</div>
220+
</Bullseye>
221+
</ChatbotHeaderTitle>
222+
<ChatbotHeaderActions>
223+
<ChatbotHeaderSelectorDropdown value={selectedModel} onSelect={onSelectModel}>
224+
<DropdownList>
225+
<DropdownItem value="Granite 7B" key="granite">
226+
Granite 7B
227+
</DropdownItem>
228+
<DropdownItem value="Llama 3.0" key="llama">
229+
Llama 3.0
230+
</DropdownItem>
231+
<DropdownItem value="Mistral 3B" key="mistral">
232+
Mistral 3B
233+
</DropdownItem>
234+
</DropdownList>
235+
</ChatbotHeaderSelectorDropdown>
236+
<ChatbotHeaderOptionsDropdown onSelect={onSelectDisplayMode}>
237+
<DropdownGroup label="Display mode">
238+
<DropdownList>
239+
<DropdownItem
240+
value={ChatbotDisplayMode.default}
241+
key="switchDisplayOverlay"
242+
icon={<OutlinedWindowRestoreIcon aria-hidden />}
243+
>
244+
<span>Overlay</span>
245+
</DropdownItem>
246+
<DropdownItem
247+
value={ChatbotDisplayMode.docked}
248+
key="switchDisplayDock"
249+
icon={<OpenDrawerRightIcon aria-hidden />}
250+
>
251+
<span>Dock to window</span>
252+
</DropdownItem>
253+
<DropdownItem
254+
value={ChatbotDisplayMode.fullscreen}
255+
key="switchDisplayFullscreen"
256+
icon={<ExpandIcon aria-hidden />}
257+
>
258+
<span>Fullscreen</span>
259+
</DropdownItem>
260+
</DropdownList>
261+
</DropdownGroup>
262+
</ChatbotHeaderOptionsDropdown>
263+
</ChatbotHeaderActions>
264+
</ChatbotHeader>
172265
<ChatbotContent>
173266
{showAlert && (
174267
<Alert
@@ -220,6 +313,7 @@ export const BasicDemo: React.FunctionComponent = () => {
220313
}}
221314
onDismiss={() => setCurrentModalData(undefined)}
222315
handleModalToggle={() => setIsPreviewModalOpen(false)}
316+
displayMode={displayMode}
223317
/>
224318
)}
225319
{currentModalData && (
@@ -232,6 +326,7 @@ export const BasicDemo: React.FunctionComponent = () => {
232326
}}
233327
onCancel={() => setCurrentModalData(undefined)}
234328
handleModalToggle={() => setIsEditModalOpen(false)}
329+
displayMode={displayMode}
235330
/>
236331
)}
237332
</>

packages/module/src/AttachmentEdit/AttachmentEdit.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// ============================================================================
44
import React from 'react';
55
import CodeModal from '../CodeModal';
6+
import { ChatbotDisplayMode } from '../Chatbot';
67

78
export interface AttachmentEditProps {
89
/** Text shown in code editor */
@@ -19,6 +20,8 @@ export interface AttachmentEditProps {
1920
isModalOpen: boolean;
2021
/** Title of modal */
2122
title?: string;
23+
/** Display mode for the Chatbot parent; this influences the styles applied */
24+
displayMode?: ChatbotDisplayMode;
2225
}
2326

2427
export const AttachmentEdit: React.FunctionComponent<AttachmentEditProps> = ({
@@ -28,7 +31,8 @@ export const AttachmentEdit: React.FunctionComponent<AttachmentEditProps> = ({
2831
isModalOpen,
2932
onCancel,
3033
onSave,
31-
title = 'Edit attachment'
34+
title = 'Edit attachment',
35+
displayMode = ChatbotDisplayMode.default
3236
}: AttachmentEditProps) => {
3337
const handleSave = (_event: React.MouseEvent | MouseEvent | KeyboardEvent, code) => {
3438
handleModalToggle(_event);
@@ -51,6 +55,7 @@ export const AttachmentEdit: React.FunctionComponent<AttachmentEditProps> = ({
5155
primaryActionBtn="Save"
5256
secondaryActionBtn="Cancel"
5357
title={title}
58+
displayMode={displayMode}
5459
/>
5560
);
5661
};

packages/module/src/Chatbot/Chatbot.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12);
1616
font-size: var(--pf-t--chatbot--font-size);
1717
overflow: hidden;
18-
z-index: var(--pf-t--global--z-index--2xl);
18+
z-index: var(--pf-t--global--z-index--md);
1919
-webkit-font-smoothing: antialiased;
2020
-moz-osx-font-smoothing: grayscale;
2121

packages/module/src/CodeModal/CodeModal.scss

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
inset-inline-end: var(--pf-t--global--spacer--lg);
66
width: 30rem;
77
height: 70vh;
8-
z-index: 900; // tokens only go up to 600, which is what chatbot uses
8+
background-color: var(--pf-t--chatbot--background);
99

1010
.pf-v6-c-modal-box__title {
1111
--pf-v6-c-modal-box__title--FontSize: var(--pf-t--global--font--size--heading--h2);
@@ -80,6 +80,42 @@
8080
}
8181
}
8282

83+
// ============================================================================
84+
// Chatbot Display Mode - Fullscreen
85+
// ============================================================================
86+
.pf-chatbot__code-modal--fullscreen {
87+
inset-block-end: 0;
88+
inset-inline-end: 0;
89+
width: 50%;
90+
height: fit-content;
91+
top: 50%;
92+
left: 50%;
93+
transform: translate(-50%, -50%);
94+
}
95+
96+
// ============================================================================
97+
// Chatbot Display Mode - Default/Embedded
98+
// ============================================================================
99+
.pf-chatbot__code-modal--default,
100+
.pf-chatbot__code-modal--embedded {
101+
box-shadow: unset;
102+
}
103+
104+
// ============================================================================
105+
// Chatbot Display Mode - Docked
106+
// ============================================================================
107+
.pf-chatbot__code-modal--docked {
108+
height: 100vh;
109+
inset-block-end: 0;
110+
inset-inline-end: 0;
111+
border-radius: 0;
112+
--pf-v6-c-modal-box--MaxHeight: 100vh;
113+
box-shadow: unset;
114+
}
115+
116+
// ============================================================================
117+
// Dark theme
118+
// ============================================================================
83119
.pf-v6-theme-dark {
84120
.pf-chatbot__code-modal {
85121
.pf-v6-c-code-editor__controls > div > button {
@@ -93,3 +129,10 @@
93129
}
94130
}
95131
}
132+
133+
// ============================================================================
134+
// Backdrop
135+
// ============================================================================
136+
.pf-v6-c-backdrop.pf-chatbot__backdrop {
137+
position: absolute;
138+
}

packages/module/src/CodeModal/CodeModal.tsx

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import path from 'path';
88
import { CodeEditor } from '@patternfly/react-code-editor';
99
import { Button, Modal, ModalBody, ModalFooter, ModalHeader, Stack, StackItem } from '@patternfly/react-core';
1010
import FileDetails, { extensionToLanguage } from '../FileDetails';
11+
import { ChatbotDisplayMode } from '../Chatbot';
1112

1213
export interface CodeModalProps {
1314
/** Class applied to code editor */
@@ -36,6 +37,8 @@ export interface CodeModalProps {
3637
isModalOpen: boolean;
3738
/** Title of modal */
3839
title: string;
40+
/** Display mode for the Chatbot parent; this influences the styles applied */
41+
displayMode?: ChatbotDisplayMode;
3942
}
4043

4144
export const CodeModal: React.FunctionComponent<CodeModalProps> = ({
@@ -52,6 +55,7 @@ export const CodeModal: React.FunctionComponent<CodeModalProps> = ({
5255
primaryActionBtn,
5356
secondaryActionBtn,
5457
title,
58+
displayMode = ChatbotDisplayMode.default,
5559
...props
5660
}: CodeModalProps) => {
5761
const [newCode, setNewCode] = useState(code);
@@ -82,15 +86,25 @@ export const CodeModal: React.FunctionComponent<CodeModalProps> = ({
8286
}
8387
};
8488

85-
return (
89+
/* eslint-disable indent */
90+
const getHeight = (displayMode: ChatbotDisplayMode) => {
91+
switch (displayMode) {
92+
case ChatbotDisplayMode.docked:
93+
return '100vh';
94+
default:
95+
return '45vh';
96+
}
97+
};
98+
/* eslint-enable indent */
99+
100+
const modal = (
86101
<Modal
87102
isOpen={isModalOpen}
88103
onClose={handleModalToggle}
89104
ouiaId="CodeModal"
90105
aria-labelledby="code-modal-title"
91106
aria-describedby="code-modal"
92-
width="25%"
93-
className="pf-chatbot__code-modal"
107+
className={`pf-chatbot__code-modal pf-chatbot__code-modal--${displayMode}`}
94108
>
95109
<ModalHeader title={title} labelId="code-modal-title" />
96110
<ModalBody id="code-modal-body">
@@ -110,7 +124,7 @@ export const CodeModal: React.FunctionComponent<CodeModalProps> = ({
110124
onEditorDidMount={onEditorDidMount}
111125
onCodeChange={onCodeChange}
112126
className={codeEditorClassName}
113-
height="45vh"
127+
height={getHeight(displayMode)}
114128
{...props}
115129
/>
116130
</StackItem>
@@ -126,6 +140,11 @@ export const CodeModal: React.FunctionComponent<CodeModalProps> = ({
126140
</ModalFooter>
127141
</Modal>
128142
);
143+
144+
if (displayMode === ChatbotDisplayMode.fullscreen && isModalOpen) {
145+
return <div className="pf-v6-c-backdrop pf-chatbot__backdrop">{modal}</div>;
146+
}
147+
return modal;
129148
};
130149

131150
export default CodeModal;

packages/module/src/FileDropZone/FileDropZone.scss

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
.pf-chatbot__dropzone {
22
height: calc(70vh - var(--pf-t--global--spacer--lg) * 2);
3+
gap: unset; // default PF value causes alignment issues when this is used to wrap other components, notably in the footer
34

45
.pf-v6-c-multiple-file-upload__main {
56
background: rgba(224, 224, 224, 0.5);
@@ -49,6 +50,11 @@
4950
}
5051
}
5152

53+
.pf-chatbot__dropzone--fullscreen,
54+
.pf-chatbot__dropzone--docked {
55+
height: 100vh;
56+
}
57+
5258
/** Used in example only */
5359
.pf-chatbot__file-drop-zone-example {
5460
border: var(--pf-t--global--border--width--divider--default) solid var(--pf-t--global--border--color--default);

0 commit comments

Comments
 (0)