Skip to content

Commit d0de234

Browse files
Merge pull request #6 from hhftechnology/dev
Ui-Dark-Mode
2 parents 76fa755 + c30236b commit d0de234

File tree

2 files changed

+623
-133
lines changed

2 files changed

+623
-133
lines changed

ui/src/App.js

Lines changed: 92 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,59 @@
11
import React, { useState, useEffect } from 'react';
22

3+
// Dark mode icons as inline SVG
4+
const MoonIcon = () => (
5+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" className="dark-mode-icon">
6+
<path fillRule="evenodd" d="M9.528 1.718a.75.75 0 01.162.819A8.97 8.97 0 009 6a9 9 0 009 9 8.97 8.97 0 003.463-.69.75.75 0 01.981.98 10.503 10.503 0 01-9.694 6.46c-5.799 0-10.5-4.701-10.5-10.5 0-4.368 2.667-8.112 6.46-9.694a.75.75 0 01.818.162z" clipRule="evenodd" />
7+
</svg>
8+
);
9+
10+
const SunIcon = () => (
11+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" className="light-mode-icon">
12+
<path d="M12 2.25a.75.75 0 01.75.75v2.25a.75.75 0 01-1.5 0V3a.75.75 0 01.75-.75zM7.5 12a4.5 4.5 0 119 0 4.5 4.5 0 01-9 0zM18.894 6.166a.75.75 0 00-1.06-1.06l-1.591 1.59a.75.75 0 101.06 1.061l1.591-1.59zM21.75 12a.75.75 0 01-.75.75h-2.25a.75.75 0 010-1.5H21a.75.75 0 01.75.75zM17.834 18.894a.75.75 0 001.06-1.06l-1.59-1.591a.75.75 0 10-1.061 1.06l1.59 1.591zM12 18a.75.75 0 01.75.75V21a.75.75 0 01-1.5 0v-2.25A.75.75 0 0112 18zM7.758 17.303a.75.75 0 00-1.061-1.06l-1.591 1.59a.75.75 0 001.06 1.061l1.591-1.59zM6 12a.75.75 0 01-.75.75H3a.75.75 0 010-1.5h2.25A.75.75 0 016 12zM6.697 7.757a.75.75 0 001.06-1.06l-1.59-1.591a.75.75 0 00-1.061 1.06l1.59 1.591z" />
13+
</svg>
14+
);
15+
16+
// Dark mode initializer
17+
const initializeDarkMode = () => {
18+
// Check for saved preference or use system preference
19+
const savedTheme = localStorage.getItem('theme');
20+
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
21+
22+
if (savedTheme === 'dark' || (!savedTheme && prefersDark)) {
23+
document.documentElement.classList.add('dark-mode');
24+
return true;
25+
}
26+
27+
return false;
28+
};
29+
30+
// Dark mode toggle functionality
31+
const toggleDarkMode = (isDark, setIsDark) => {
32+
if (isDark) {
33+
document.documentElement.classList.remove('dark-mode');
34+
localStorage.setItem('theme', 'light');
35+
setIsDark(false);
36+
} else {
37+
document.documentElement.classList.add('dark-mode');
38+
localStorage.setItem('theme', 'dark');
39+
setIsDark(true);
40+
}
41+
};
42+
43+
// Dark mode toggle component
44+
const DarkModeToggle = ({ isDark, setIsDark }) => {
45+
return (
46+
<button
47+
onClick={() => toggleDarkMode(isDark, setIsDark)}
48+
className="dark-mode-toggle ml-4"
49+
aria-label={isDark ? "Switch to light mode" : "Switch to dark mode"}
50+
title={isDark ? "Switch to light mode" : "Switch to dark mode"}
51+
>
52+
{isDark ? <SunIcon /> : <MoonIcon />}
53+
</button>
54+
);
55+
};
56+
357
// --- API Service Configuration ---
458
const API_URL = '/api';
559

@@ -144,6 +198,12 @@ const App = () => {
144198
const [resourceId, setResourceId] = useState(null);
145199
const [middlewareId, setMiddlewareId] = useState(null);
146200
const [isEditing, setIsEditing] = useState(false);
201+
const [isDarkMode, setIsDarkMode] = useState(false);
202+
203+
// Initialize dark mode on component mount
204+
useEffect(() => {
205+
setIsDarkMode(initializeDarkMode());
206+
}, []);
147207

148208
// Handles navigation between pages
149209
const navigateTo = (pageId, id = null) => {
@@ -190,35 +250,38 @@ const App = () => {
190250
<div className="text-xl font-semibold text-gray-700">
191251
Pangolin Middleware Manager
192252
</div>
193-
<div className="space-x-4">
194-
<button
195-
onClick={() => navigateTo('dashboard')}
196-
className={`px-3 py-2 rounded hover:bg-gray-100 ${
197-
page === 'dashboard' ? 'bg-gray-100' : ''
198-
}`}
199-
>
200-
Dashboard
201-
</button>
202-
<button
203-
onClick={() => navigateTo('resources')}
204-
className={`px-3 py-2 rounded hover:bg-gray-100 ${
205-
page === 'resources' || page === 'resource-detail'
206-
? 'bg-gray-100'
207-
: ''
208-
}`}
209-
>
210-
Resources
211-
</button>
212-
<button
213-
onClick={() => navigateTo('middlewares')}
214-
className={`px-3 py-2 rounded hover:bg-gray-100 ${
215-
page === 'middlewares' || page === 'middleware-form'
216-
? 'bg-gray-100'
217-
: ''
218-
}`}
219-
>
220-
Middlewares
221-
</button>
253+
<div className="flex items-center">
254+
<div className="space-x-4">
255+
<button
256+
onClick={() => navigateTo('dashboard')}
257+
className={`px-3 py-2 rounded hover:bg-gray-100 ${
258+
page === 'dashboard' ? 'bg-gray-100' : ''
259+
}`}
260+
>
261+
Dashboard
262+
</button>
263+
<button
264+
onClick={() => navigateTo('resources')}
265+
className={`px-3 py-2 rounded hover:bg-gray-100 ${
266+
page === 'resources' || page === 'resource-detail'
267+
? 'bg-gray-100'
268+
: ''
269+
}`}
270+
>
271+
Resources
272+
</button>
273+
<button
274+
onClick={() => navigateTo('middlewares')}
275+
className={`px-3 py-2 rounded hover:bg-gray-100 ${
276+
page === 'middlewares' || page === 'middleware-form'
277+
? 'bg-gray-100'
278+
: ''
279+
}`}
280+
>
281+
Middlewares
282+
</button>
283+
</div>
284+
<DarkModeToggle isDark={isDarkMode} setIsDark={setIsDarkMode} />
222285
</div>
223286
</div>
224287
</div>

0 commit comments

Comments
 (0)