From fd87b66b06c041061825bb4bdc35aef8355ea634 Mon Sep 17 00:00:00 2001 From: RKWojs Date: Thu, 25 Sep 2025 08:58:03 +0200 Subject: [PATCH] feat: Implement dark mode support across components and UI elements - Added dark mode styles to TaskStatusDropdown, TaskStatusDropdownDebug, and TaskStatusDropdownSimple components. - Introduced ThemeProvider and useTheme hook for managing theme state. - Updated Button, Card, Input, Loading, Navigation, PageContainer, PageHeader, ProjectCalendarWidget, ProjectMap, SearchBar, States, Tooltip, and other UI components to support dark mode. - Created ThemeToggle component for switching between light and dark modes. - Enhanced i18n translations for settings related to theme and language preferences. - Configured Tailwind CSS to support dark mode with class-based toggling. --- src/app/globals.css | 105 ++++++++++++++++++ src/app/layout.js | 17 +-- src/app/projects/map/page.js | 20 ++-- src/app/projects/page.js | 64 +++++------ src/app/settings/page.js | 64 +++++++++++ src/components/AuditLogViewer.js | 42 +++---- src/components/FileUploadModal.js | 22 ++-- src/components/ProjectStatusDropdown.js | 4 +- src/components/ProjectStatusDropdownDebug.js | 6 +- src/components/ProjectStatusDropdownSimple.js | 6 +- src/components/ProjectTasksDashboard.js | 2 +- src/components/ProjectTasksList.js | 46 ++++---- src/components/ProjectTasksSection.js | 26 ++--- src/components/TaskCommentsModal.js | 68 ++++++------ src/components/TaskStatusDropdown.js | 6 +- src/components/TaskStatusDropdownDebug.js | 6 +- src/components/TaskStatusDropdownSimple.js | 4 +- src/components/ThemeProvider.js | 47 ++++++++ src/components/ui/Button.js | 12 +- src/components/ui/Card.js | 6 +- src/components/ui/Input.js | 29 +++-- src/components/ui/Loading.js | 10 +- src/components/ui/Navigation.js | 58 +++++----- src/components/ui/PageContainer.js | 2 +- src/components/ui/PageHeader.js | 4 +- src/components/ui/ProjectCalendarWidget.js | 2 +- src/components/ui/ProjectMap.js | 28 ++--- src/components/ui/SearchBar.js | 16 +-- src/components/ui/States.js | 16 +-- src/components/ui/ThemeToggle.js | 27 +++++ src/components/ui/Tooltip.js | 4 +- src/lib/i18n.js | 20 ++++ tailwind.config.mjs | 52 +++++++++ 33 files changed, 582 insertions(+), 259 deletions(-) create mode 100644 src/app/settings/page.js create mode 100644 src/components/ThemeProvider.js create mode 100644 src/components/ui/ThemeToggle.js diff --git a/src/app/globals.css b/src/app/globals.css index 9a55f8d..d65d064 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -5,6 +5,91 @@ :root { --background: #ffffff; --foreground: #171717; + + /* Surface colors */ + --surface-primary: #ffffff; + --surface-secondary: #f9fafb; + --surface-tertiary: #f3f4f6; + --surface-modal: #ffffff; + --surface-card: #ffffff; + --surface-hover: #f9fafb; + --surface-active: #f3f4f6; + + /* Text colors */ + --text-primary: #111827; + --text-secondary: #6b7280; + --text-tertiary: #9ca3af; + --text-inverse: #ffffff; + --text-muted: #6b7280; + + /* Border colors */ + --border-default: #d1d5db; + --border-hover: #9ca3af; + --border-focus: #3b82f6; + --border-divider: #e5e7eb; + + /* Interactive colors */ + --interactive-primary: #3b82f6; + --interactive-primary-hover: #2563eb; + --interactive-secondary: #6b7280; + --interactive-secondary-hover: #4b5563; + --interactive-danger: #ef4444; + --interactive-danger-hover: #dc2626; + + /* Status colors */ + --status-success: #10b981; + --status-warning: #f59e0b; + --status-error: #ef4444; + --status-info: #3b82f6; + + /* Shadow colors */ + --shadow-default: rgba(0, 0, 0, 0.1); + --shadow-hover: rgba(0, 0, 0, 0.15); +} + +.dark { + --background: #0a0a0a; + --foreground: #ededed; + + /* Surface colors */ + --surface-primary: #1f2937; + --surface-secondary: #374151; + --surface-tertiary: #4b5563; + --surface-modal: #1f2937; + --surface-card: #374151; + --surface-hover: #4b5563; + --surface-active: #6b7280; + + /* Text colors */ + --text-primary: #f9fafb; + --text-secondary: #d1d5db; + --text-tertiary: #9ca3af; + --text-inverse: #111827; + --text-muted: #9ca3af; + + /* Border colors */ + --border-default: #4b5563; + --border-hover: #6b7280; + --border-focus: #60a5fa; + --border-divider: #374151; + + /* Interactive colors */ + --interactive-primary: #3b82f6; + --interactive-primary-hover: #60a5fa; + --interactive-secondary: #6b7280; + --interactive-secondary-hover: #9ca3af; + --interactive-danger: #ef4444; + --interactive-danger-hover: #f87171; + + /* Status colors */ + --status-success: #10b981; + --status-warning: #f59e0b; + --status-error: #ef4444; + --status-info: #3b82f6; + + /* Shadow colors */ + --shadow-default: rgba(0, 0, 0, 0.3); + --shadow-hover: rgba(0, 0, 0, 0.4); } /* @media (prefers-color-scheme: dark) { @@ -29,6 +114,18 @@ body { background: #f1f1f1; } +::-webkit-scrollbar-track:window-inactive { + background: #f1f1f1; +} + +.dark ::-webkit-scrollbar-track { + background: #374151; +} + +.dark ::-webkit-scrollbar-track:window-inactive { + background: #374151; +} + ::-webkit-scrollbar-thumb { background: #c1c1c1; border-radius: 4px; @@ -38,6 +135,14 @@ body { background: #a8a8a8; } +.dark ::-webkit-scrollbar-thumb { + background: #6b7280; +} + +.dark ::-webkit-scrollbar-thumb:hover { + background: #9ca3af; +} + /* Focus styles */ .focus-ring { @apply focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2; diff --git a/src/app/layout.js b/src/app/layout.js index c29e50a..49e6c46 100644 --- a/src/app/layout.js +++ b/src/app/layout.js @@ -3,6 +3,7 @@ import "./globals.css"; import Navigation from "@/components/ui/Navigation"; import { AuthProvider } from "@/components/auth/AuthProvider"; import { TranslationProvider } from "@/lib/i18n"; +import { ThemeProvider } from "@/components/ThemeProvider"; const geistSans = Geist({ variable: "--font-geist-sans", @@ -23,14 +24,16 @@ export default function RootLayout({ children }) { return ( - - - -
{children}
-
-
+ + + + +
{children}
+
+
+
); diff --git a/src/app/projects/map/page.js b/src/app/projects/map/page.js index ed3a415..608e357 100644 --- a/src/app/projects/map/page.js +++ b/src/app/projects/map/page.js @@ -12,8 +12,8 @@ import { formatProjectStatus } from "@/lib/utils"; // Loading component that can access translations function MapLoadingComponent({ t }) { return ( -
- {t ? t('map.loadingMap') : 'Loading map...'} +
+ {t ? t('map.loadingMap') : 'Loading map...'}
); } @@ -410,11 +410,11 @@ function ProjectsMapPageContent() { if (loading) { return ( -
+
-
-

{t('map.loadingProjectsMap')}

-

+

+

{t('map.loadingProjectsMap')}

+

{t('map.preparingMap')}

@@ -422,7 +422,7 @@ function ProjectsMapPageContent() { ); } return ( -
+
{/* Floating Header - Left Side */}
{/* Title Box */} @@ -989,10 +989,10 @@ function ProjectsMapPageContent() { export default function ProjectsMapPage() { return ( +
-
-

Loading map...

+
+

Loading map...

}> diff --git a/src/app/projects/page.js b/src/app/projects/page.js index 92e3284..b63d5a6 100644 --- a/src/app/projects/page.js +++ b/src/app/projects/page.js @@ -254,13 +254,13 @@ export default function ProjectListPage() {
-
-
-