diff --git a/webui/src/App.tsx b/webui/src/App.tsx
index a909ccb..44a155b 100644
--- a/webui/src/App.tsx
+++ b/webui/src/App.tsx
@@ -7,6 +7,7 @@ import SystemInfoDialog from "./components/SystemInfoDialog";
import { type CreateInstanceOptions, type Instance } from "@/types/instance";
import { useInstances } from "@/contexts/InstancesContext";
import { useAuth } from "@/contexts/AuthContext";
+import { ThemeProvider } from "@/contexts/ThemeContext";
function App() {
const { isAuthenticated, isLoading: authLoading } = useAuth();
@@ -42,44 +43,50 @@ function App() {
// Show loading spinner while checking auth
if (authLoading) {
return (
-
-
+
);
}
// Show login dialog if not authenticated
if (!isAuthenticated) {
return (
-
-
-
+
+
+
+
+
);
}
// Show main app if authenticated
return (
-
-
-
-
-
+
+
+
+
+
+
-
+
-
-
+
+
+
);
}
diff --git a/webui/src/__tests__/App.test.tsx b/webui/src/__tests__/App.test.tsx
index 1d22531..04c1e34 100644
--- a/webui/src/__tests__/App.test.tsx
+++ b/webui/src/__tests__/App.test.tsx
@@ -55,6 +55,21 @@ describe('App Component - Critical Business Logic Only', () => {
vi.mocked(instancesApi.list).mockResolvedValue(mockInstances)
window.sessionStorage.setItem('llamactl_management_key', 'test-api-key-123')
global.fetch = vi.fn(() => Promise.resolve(new Response(null, { status: 200 })))
+
+ // Mock window.matchMedia for dark mode functionality
+ Object.defineProperty(window, 'matchMedia', {
+ writable: true,
+ value: vi.fn().mockImplementation((query: string) => ({
+ matches: false,
+ media: query,
+ onchange: null,
+ addListener: vi.fn(),
+ removeListener: vi.fn(),
+ addEventListener: vi.fn(),
+ removeEventListener: vi.fn(),
+ dispatchEvent: vi.fn(),
+ })),
+ })
})
afterEach(() => {
diff --git a/webui/src/components/Header.tsx b/webui/src/components/Header.tsx
index ed272ed..3c7e0e1 100644
--- a/webui/src/components/Header.tsx
+++ b/webui/src/components/Header.tsx
@@ -1,6 +1,7 @@
import { Button } from "@/components/ui/button";
-import { HelpCircle, LogOut } from "lucide-react";
+import { HelpCircle, LogOut, Moon, Sun } from "lucide-react";
import { useAuth } from "@/contexts/AuthContext";
+import { useTheme } from "@/contexts/ThemeContext";
interface HeaderProps {
onCreateInstance: () => void;
@@ -9,6 +10,7 @@ interface HeaderProps {
function Header({ onCreateInstance, onShowSystemInfo }: HeaderProps) {
const { logout } = useAuth();
+ const { theme, toggleTheme } = useTheme();
const handleLogout = () => {
if (confirm("Are you sure you want to logout?")) {
@@ -17,10 +19,10 @@ function Header({ onCreateInstance, onShowSystemInfo }: HeaderProps) {
};
return (
-