diff --git a/frontend/src/components/BashExecModal.tsx b/frontend/src/components/BashExecModal.tsx
index b5ff1da3..b38d6971 100644
--- a/frontend/src/components/BashExecModal.tsx
+++ b/frontend/src/components/BashExecModal.tsx
@@ -1,5 +1,5 @@
import { useEffect, useRef, useState, useCallback } from 'react';
-import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from './ui/dialog';
+import { Modal, ModalHeader } from './ui/modal';
import { Terminal as TerminalIcon } from 'lucide-react';
import { loadXtermModules, type Terminal, type FitAddon, type XtermModules } from '@/lib/xtermLoader';
import { buildXtermMinimalTheme } from '@/lib/terminalTheme';
@@ -214,31 +214,28 @@ export default function BashExecModal({ isOpen, onClose, containerId, containerN
};
return (
-
+
+ }
+ description={`Interactive bash terminal session for ${containerName}`}
+ />
+
+
);
}
diff --git a/frontend/src/components/DeployFeedbackModal.tsx b/frontend/src/components/DeployFeedbackModal.tsx
index 0c9d2d6d..e5b45dad 100644
--- a/frontend/src/components/DeployFeedbackModal.tsx
+++ b/frontend/src/components/DeployFeedbackModal.tsx
@@ -7,11 +7,8 @@ import {
Minimize2,
Terminal as TerminalIcon,
} from 'lucide-react';
-import {
- Dialog,
- DialogContent,
- DialogTitle,
-} from '@/components/ui/dialog';
+import { Modal } from '@/components/ui/modal';
+import { DialogTitle } from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { StructuredLogRow } from '@/components/log-rendering/StructuredLogRow';
import TerminalComponent from '@/components/Terminal';
@@ -156,11 +153,15 @@ export function DeployFeedbackModal({ isMinimized, onMinimize }: DeployFeedbackM
const verbLabel = VERB_LABELS[action];
return (
-
+
+
);
}
diff --git a/frontend/src/components/LogViewer.tsx b/frontend/src/components/LogViewer.tsx
index 1c82ef11..bdc9f73a 100644
--- a/frontend/src/components/LogViewer.tsx
+++ b/frontend/src/components/LogViewer.tsx
@@ -1,5 +1,5 @@
import { useEffect, useState, useRef } from 'react';
-import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog";
+import { Modal, ModalHeader } from "@/components/ui/modal";
import { Loader2, Terminal } from "lucide-react";
interface LogViewerProps {
@@ -56,30 +56,37 @@ export function LogViewer({ containerId, containerName, isOpen, onClose }: LogVi
}, [isOpen, containerId]);
return (
-
+
+ {logs.length === 0 && !isConnected ? (
+
Connecting to container stream...
+ ) : (
+ logs.map((log, i) => (
+
+ {log}
+
+ ))
+ )}
+
+
);
}
diff --git a/frontend/src/components/ui/modal.tsx b/frontend/src/components/ui/modal.tsx
index dee9ab42..054dfbf5 100644
--- a/frontend/src/components/ui/modal.tsx
+++ b/frontend/src/components/ui/modal.tsx
@@ -34,12 +34,15 @@ interface ModalProps {
children: React.ReactNode;
size?: ModalSize;
className?: string;
+ /** Pass through to DialogContent — set to false when the modal renders its own close affordance. */
+ showClose?: boolean;
}
-export function Modal({ open, onOpenChange, children, size = 'md', className }: ModalProps) {
+export function Modal({ open, onOpenChange, children, size = 'md', className, showClose }: ModalProps) {
return (