diff --git a/packages/module/patternfly-docs/content/extensions/virtual-assistant/examples/AttachmentEdit/AttachmentEdit.md b/packages/module/patternfly-docs/content/extensions/virtual-assistant/examples/AttachmentEdit/AttachmentEdit.md
new file mode 100644
index 0000000..93abcc2
--- /dev/null
+++ b/packages/module/patternfly-docs/content/extensions/virtual-assistant/examples/AttachmentEdit/AttachmentEdit.md
@@ -0,0 +1,22 @@
+---
+# Sidenav top-level section
+# should be the same for all markdown files
+section: extensions
+subsection: Chat bots / AI
+# Sidenav secondary level section
+# should be the same for all markdown files
+id: Attachment edit
+# Tab (react | react-demos | html | html-demos | design-guidelines | accessibility)
+source: react
+# If you use typescript, the name of the interface to display props for
+# These are found through the sourceProps function provided in patternfly-docs.source.js
+propComponents: ['AttachmentEdit']
+---
+
+import AttachmentEdit from '@patternfly/virtual-assistant/dist/dynamic/AttachmentEdit';
+
+### Basic example
+
+```js file="./AttachmentEdit.tsx"
+
+```
diff --git a/packages/module/patternfly-docs/content/extensions/virtual-assistant/examples/AttachmentEdit/AttachmentEdit.tsx b/packages/module/patternfly-docs/content/extensions/virtual-assistant/examples/AttachmentEdit/AttachmentEdit.tsx
new file mode 100644
index 0000000..0ba8572
--- /dev/null
+++ b/packages/module/patternfly-docs/content/extensions/virtual-assistant/examples/AttachmentEdit/AttachmentEdit.tsx
@@ -0,0 +1,25 @@
+import React from 'react';
+import { Button } from '@patternfly/react-core';
+import { AttachmentEdit } from '@patternfly/virtual-assistant/dist/dynamic/AttachmentEdit';
+
+export const BasicDemo: React.FunctionComponent = () => {
+ const [isModalOpen, setIsModalOpen] = React.useState(false);
+
+ const handleModalToggle = (_event: React.MouseEvent | MouseEvent | KeyboardEvent) => {
+ setIsModalOpen(!isModalOpen);
+ };
+
+ return (
+ <>
+
+ null}
+ onSave={() => null}
+ />
+ >
+ );
+};
diff --git a/packages/module/src/AttachmentEdit/AttachmentEdit.scss b/packages/module/src/AttachmentEdit/AttachmentEdit.scss
new file mode 100644
index 0000000..3557e34
--- /dev/null
+++ b/packages/module/src/AttachmentEdit/AttachmentEdit.scss
@@ -0,0 +1,11 @@
+.pf-chatbot__attachment-language {
+ color: var(--pf-t--global--text--color--subtle);
+ font-size: var(--pf-t--global--icon--size--font--xs);
+}
+
+.pf-chatbot__attachment-icon {
+ background-color: var(--pf-t--global--icon--color--status--custom--default);
+ border-radius: var(--pf-t--global--border--radius--tiny);
+ width: 24px;
+ height: 24px;
+}
diff --git a/packages/module/src/AttachmentEdit/AttachmentEdit.tsx b/packages/module/src/AttachmentEdit/AttachmentEdit.tsx
new file mode 100644
index 0000000..f7f0923
--- /dev/null
+++ b/packages/module/src/AttachmentEdit/AttachmentEdit.tsx
@@ -0,0 +1,123 @@
+// ============================================================================
+// Attachment Edit - Chatbot Code Snippet Editor
+// ============================================================================
+import React from 'react';
+import path from 'path';
+
+// Import PatternFly components
+import { CodeEditor, Language } from '@patternfly/react-code-editor';
+import {
+ Button,
+ Flex,
+ Icon,
+ Modal,
+ ModalBody,
+ ModalFooter,
+ ModalHeader,
+ Stack,
+ StackItem
+} from '@patternfly/react-core';
+import { CodeIcon } from '@patternfly/react-icons';
+
+export interface AttachmentEditProps {
+ /** Text shown in code editor */
+ code: string;
+ /** Filename, including extension, of file shown in editor */
+ fileName: string;
+ /** Function that runs when cancel button is clicked */
+ onCancel: (event: React.MouseEvent | MouseEvent | KeyboardEvent) => void;
+ /** Function that runs when save button is clicked */
+ onSave: (event: React.MouseEvent | MouseEvent | KeyboardEvent) => void;
+ /** Function that opens and closes modal */
+ handleModalToggle: (event: React.MouseEvent | MouseEvent | KeyboardEvent) => void;
+ /** Whether modal is open */
+ isModalOpen: boolean;
+ /** Title of modal */
+ title?: string;
+}
+
+export const AttachmentEdit: React.FunctionComponent = ({
+ fileName,
+ code,
+ handleModalToggle,
+ isModalOpen,
+ onCancel,
+ onSave,
+ title = 'Edit attachment',
+ ...props
+}: AttachmentEditProps) => {
+ const handleSave = (_event: React.MouseEvent | MouseEvent | KeyboardEvent) => {
+ handleModalToggle(_event);
+ onSave(_event);
+ };
+
+ const handleCancel = (_event: React.MouseEvent | MouseEvent | KeyboardEvent) => {
+ handleModalToggle(_event);
+ onCancel(_event);
+ };
+
+ const onEditorDidMount = (editor, monaco) => {
+ editor.layout();
+ editor.focus();
+ monaco.editor.getModels()[0].updateOptions({ tabSize: 5 });
+ };
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ {path.parse(fileName).name}
+
+ {Language[path.extname(fileName).slice(1)].toUpperCase()}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default AttachmentEdit;
diff --git a/packages/module/src/AttachmentEdit/index.ts b/packages/module/src/AttachmentEdit/index.ts
new file mode 100644
index 0000000..f043125
--- /dev/null
+++ b/packages/module/src/AttachmentEdit/index.ts
@@ -0,0 +1,3 @@
+export { default } from './AttachmentEdit';
+
+export * from './AttachmentEdit';
diff --git a/packages/module/src/index.ts b/packages/module/src/index.ts
index cf2da18..632621c 100644
--- a/packages/module/src/index.ts
+++ b/packages/module/src/index.ts
@@ -3,6 +3,9 @@
export { default as AssistantMessageEntry } from './AssistantMessageEntry';
export * from './AssistantMessageEntry';
+export { default as AttachmentEdit } from './AttachmentEdit';
+export * from './AttachmentEdit';
+
export { default as ChatbotHeader } from './ChatbotHeader';
export * from './ChatbotHeader';
diff --git a/packages/module/src/main.scss b/packages/module/src/main.scss
index 0f62edd..8b367d8 100644
--- a/packages/module/src/main.scss
+++ b/packages/module/src/main.scss
@@ -1,5 +1,14 @@
+@import './AttachmentEdit/AttachmentEdit';
+@import './ChatbotConversationHistoryNav/ChatbotConversationHistoryNav';
+@import './ChatbotHeader/ChatbotHeader.scss';
@import './ChatbotToggle/ChatbotToggle';
-
+@import './Footer/Footer';
+@import './Footer/Footnote';
+@import './MessageBar/AttachButton';
+@import './MessageBar/MessageBar';
+@import './MessageBar/MicrophoneButton';
+@import './MessageBar/SendButton';
+@import './Popover/Popover';
.ws-full-page-utils {
bottom: auto !important;