From e922cd00b4c22eb875b3a0bc71261604f49ab9b4 Mon Sep 17 00:00:00 2001
From: oraimoitel <272064339+oraimoitel@users.noreply.github.com>
Date: Sun, 30 Aug 2026 12:29:32 +0200
Subject: [PATCH 1/3] feat(dashboard): add dark mode support with theme toggle
Closes #117
- Add ThemeProvider with localStorage persistence
- Add ThemeToggle component (sun/moon icons) in TopBar
- Configure Tailwind darkMode: 'class'
- Add dark: variants to layout, sidebar, globals, and badges
- Accessible toggle with aria-label and keyboard support
---
apps/dashboard/src/app/globals.css | 18 +++----
apps/dashboard/src/app/layout.tsx | 35 +++++++------
.../src/components/layout/Sidebar.tsx | 14 ++---
.../src/components/layout/TopBar.tsx | 12 +++--
.../src/components/theme/ThemeProvider.tsx | 52 +++++++++++++++++++
.../src/components/theme/ThemeToggle.tsx | 37 +++++++++++++
apps/dashboard/tailwind.config.ts | 1 +
7 files changed, 133 insertions(+), 36 deletions(-)
create mode 100644 apps/dashboard/src/components/theme/ThemeProvider.tsx
create mode 100644 apps/dashboard/src/components/theme/ThemeToggle.tsx
diff --git a/apps/dashboard/src/app/globals.css b/apps/dashboard/src/app/globals.css
index 9c7906c..80f7324 100644
--- a/apps/dashboard/src/app/globals.css
+++ b/apps/dashboard/src/app/globals.css
@@ -9,7 +9,7 @@
}
body {
- @apply bg-gray-950 text-gray-100;
+ @apply bg-white text-gray-900 dark:bg-gray-950 dark:text-gray-100;
}
/* Scrollbar styling */
@@ -17,19 +17,19 @@
@apply w-1.5 h-1.5;
}
::-webkit-scrollbar-track {
- @apply bg-gray-900;
+ @apply bg-gray-100 dark:bg-gray-900;
}
::-webkit-scrollbar-thumb {
- @apply bg-gray-700 rounded-full;
+ @apply bg-gray-300 dark:bg-gray-700 rounded-full;
}
::-webkit-scrollbar-thumb:hover {
- @apply bg-gray-600;
+ @apply bg-gray-400 dark:bg-gray-600;
}
}
@layer components {
.sentinel-card {
- @apply bg-gray-900 border border-gray-800 rounded-xl p-6;
+ @apply bg-gray-50 dark:bg-gray-900 border border-gray-200 dark:border-gray-800 rounded-xl p-6;
}
.sentinel-badge {
@@ -37,18 +37,18 @@
}
.sentinel-badge--critical {
- @apply bg-red-950 text-red-400 border border-red-800;
+ @apply bg-red-50 text-red-700 border border-red-200 dark:bg-red-950 dark:text-red-400 dark:border-red-800;
}
.sentinel-badge--high {
- @apply bg-orange-950 text-orange-400 border border-orange-800;
+ @apply bg-orange-50 text-orange-700 border border-orange-200 dark:bg-orange-950 dark:text-orange-400 dark:border-orange-800;
}
.sentinel-badge--medium {
- @apply bg-yellow-950 text-yellow-400 border border-yellow-800;
+ @apply bg-yellow-50 text-yellow-700 border border-yellow-200 dark:bg-yellow-950 dark:text-yellow-400 dark:border-yellow-800;
}
.sentinel-badge--low {
- @apply bg-blue-950 text-blue-400 border border-blue-800;
+ @apply bg-blue-50 text-blue-700 border border-blue-200 dark:bg-blue-950 dark:text-blue-400 dark:border-blue-800;
}
}
diff --git a/apps/dashboard/src/app/layout.tsx b/apps/dashboard/src/app/layout.tsx
index c743374..f46a7f8 100644
--- a/apps/dashboard/src/app/layout.tsx
+++ b/apps/dashboard/src/app/layout.tsx
@@ -2,6 +2,7 @@ import type { Metadata } from 'next';
import './globals.css';
import { Sidebar } from '@/components/layout/Sidebar';
import { TopBar } from '@/components/layout/TopBar';
+import { ThemeProvider } from '@/components/theme/ThemeProvider';
export const metadata: Metadata = {
title: {
@@ -20,23 +21,25 @@ export default function RootLayout({
children: React.ReactNode;
}>) {
return (
-
-
- {/* Sidebar */}
-
+
+
+
+ {/* Sidebar */}
+
- {/* Main content area */}
-
-
-
- {children}
-
-
+ {/* Main content area */}
+
+
+
+ {children}
+
+
+
);
diff --git a/apps/dashboard/src/components/layout/Sidebar.tsx b/apps/dashboard/src/components/layout/Sidebar.tsx
index 735b080..be1d70a 100644
--- a/apps/dashboard/src/components/layout/Sidebar.tsx
+++ b/apps/dashboard/src/components/layout/Sidebar.tsx
@@ -143,11 +143,11 @@ export function Sidebar() {
return (