Skip to content

Commit b1fe751

Browse files
committed
feat(web): Implement dark mode across the entire application
- Added dark mode support for all UI components and pages to enhance accessibility and improve user experience.
1 parent 8d54fdb commit b1fe751

20 files changed

Lines changed: 215 additions & 105 deletions

File tree

web/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!doctype html>
2-
<html lang="en">
2+
<html lang="en" data-theme="dark">
33

44
<head>
55
<meta charset="UTF-8" />

web/package-lock.json

Lines changed: 31 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

web/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
"react-spinners": "^0.14.1",
2727
"sonner": "^1.7.0",
2828
"tailwind-merge": "^2.5.5",
29-
"tailwindcss-animate": "^1.0.7"
29+
"tailwindcss-animate": "^1.0.7",
30+
"zustand": "^5.0.1"
3031
},
3132
"devDependencies": {
3233
"@eslint/js": "^9.15.0",

web/src/components/navbar/navbar.tsx

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { FC } from 'react';
1+
import { useStyle } from '@/hooks';
2+
import { FC, useEffect } from 'react';
23
import { NavLink } from 'react-router';
34

45
const navbar = [
@@ -25,6 +26,14 @@ const navbar = [
2526
];
2627

2728
const Navbar: FC = () => {
29+
const { darkMode, toggleDarkMode } = useStyle();
30+
31+
useEffect(() => {
32+
const root = document.documentElement;
33+
root.setAttribute('data-theme', darkMode ? 'dark' : 'light');
34+
localStorage.setItem('theme', darkMode ? 'dark' : 'light');
35+
}, [darkMode]);
36+
2837
return (
2938
<nav className="flex h-14 items-center border-b border-gray-500 p-4">
3039
<div className="flex w-full items-center justify-between gap-4">
@@ -34,11 +43,32 @@ const Navbar: FC = () => {
3443
<NavLink
3544
key={link.url}
3645
to={link.url}
37-
className={({ isActive }) => (isActive ? 'text-orange-base' : '')}
46+
className={({ isActive }) =>
47+
isActive ? 'text-orange-base' : 'text-gray-400'
48+
}
3849
>
3950
{link.title}
4051
</NavLink>
4152
))}
53+
<label className="swap swap-rotate">
54+
<input type="checkbox" onChange={toggleDarkMode} />
55+
56+
<svg
57+
className="swap-on h-5 w-5 fill-gray-400 dark:fill-white"
58+
xmlns="http://www.w3.org/2000/svg"
59+
viewBox="0 0 24 24"
60+
>
61+
<path d="M5.64,17l-.71.71a1,1,0,0,0,0,1.41,1,1,0,0,0,1.41,0l.71-.71A1,1,0,0,0,5.64,17ZM5,12a1,1,0,0,0-1-1H3a1,1,0,0,0,0,2H4A1,1,0,0,0,5,12Zm7-7a1,1,0,0,0,1-1V3a1,1,0,0,0-2,0V4A1,1,0,0,0,12,5ZM5.64,7.05a1,1,0,0,0,.7.29,1,1,0,0,0,.71-.29,1,1,0,0,0,0-1.41l-.71-.71A1,1,0,0,0,4.93,6.34Zm12,.29a1,1,0,0,0,.7-.29l.71-.71a1,1,0,1,0-1.41-1.41L17,5.64a1,1,0,0,0,0,1.41A1,1,0,0,0,17.66,7.34ZM21,11H20a1,1,0,0,0,0,2h1a1,1,0,0,0,0-2Zm-9,8a1,1,0,0,0-1,1v1a1,1,0,0,0,2,0V20A1,1,0,0,0,12,19ZM18.36,17A1,1,0,0,0,17,18.36l.71.71a1,1,0,0,0,1.41,0,1,1,0,0,0,0-1.41ZM12,6.5A5.5,5.5,0,1,0,17.5,12,5.51,5.51,0,0,0,12,6.5Zm0,9A3.5,3.5,0,1,1,15.5,12,3.5,3.5,0,0,1,12,15.5Z" />
62+
</svg>
63+
64+
<svg
65+
className="swap-off h-5 w-5 dark:fill-gray-400"
66+
xmlns="http://www.w3.org/2000/svg"
67+
viewBox="0 0 24 24"
68+
>
69+
<path d="M21.64,13a1,1,0,0,0-1.05-.14,8.05,8.05,0,0,1-3.37.73A8.15,8.15,0,0,1,9.08,5.49a8.59,8.59,0,0,1,.25-2A1,1,0,0,0,8,2.36,10.14,10.14,0,1,0,22,14.05,1,1,0,0,0,21.64,13Zm-9.5,6.69A8.14,8.14,0,0,1,7.08,5.22v.27A10.15,10.15,0,0,0,17.22,15.63a9.79,9.79,0,0,0,2.1-.22A8.11,8.11,0,0,1,12.14,19.73Z" />
70+
</svg>
71+
</label>
4272
</div>
4373
</div>
4474
</nav>

web/src/hooks/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
import useDownload from './useDownload';
2+
import useStyle from './useStyle';
23

3-
export { useDownload };
4+
export { useDownload, useStyle };

web/src/hooks/useStyle.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { create } from 'zustand';
2+
3+
interface StyleSlice {
4+
darkMode: boolean;
5+
toggleDarkMode: () => void;
6+
}
7+
8+
const useStyle = create<StyleSlice>((set) => ({
9+
darkMode: localStorage.getItem('theme') === 'dark',
10+
toggleDarkMode: () => {
11+
const theme = localStorage.getItem('theme') === 'dark' ? 'light' : 'dark';
12+
set({ darkMode: theme === 'dark' });
13+
},
14+
}));
15+
16+
export default useStyle;

web/src/index.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@
2727
-moz-appearance: textfield;
2828
appearance: textfield;
2929
}
30-
@apply bg-background font-figtree text-foreground;
30+
@apply dark:bg-background transition-all font-figtree text-foreground;
3131
}
3232
}

web/src/pages/basic/basic.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ const Basic: FC = () => {
5959
};
6060

6161
return (
62-
<div className="flex h-full w-full items-center justify-center">
62+
<div className="flex h-[calc(100vh-56px)] w-full items-center justify-center text-black dark:text-white">
6363
<div className="w-full max-w-[768px]">
6464
<div className="w-full rounded-md p-2">
6565
<div className="flex h-full w-full items-center justify-center gap-3">
@@ -72,7 +72,7 @@ const Basic: FC = () => {
7272
type="number"
7373
value={minToken}
7474
onChange={(e) => setMinToken(e.target.value)}
75-
className="w-full rounded-md p-3 outline-none"
75+
className="dark:bg-black-1 w-full rounded-md bg-gray-200 p-3 outline-none"
7676
/>
7777
</div>
7878
<div className="flex w-full flex-col">
@@ -84,7 +84,7 @@ const Basic: FC = () => {
8484
type="number"
8585
value={maxToken}
8686
onChange={(e) => setMaxToken(e.target.value)}
87-
className="w-full rounded-md p-3 outline-none"
87+
className="dark:bg-black-1 w-full rounded-md bg-gray-200 p-3 outline-none"
8888
/>
8989
</div>
9090
<div className="flex w-full flex-col">
@@ -96,7 +96,7 @@ const Basic: FC = () => {
9696
type="text"
9797
value={service}
9898
onChange={(e) => setService(e.target.value)}
99-
className="w-full rounded-md p-3 outline-none"
99+
className="dark:bg-black-1 w-full rounded-md bg-gray-200 p-3 outline-none"
100100
/>
101101
</div>
102102
</div>
@@ -131,7 +131,7 @@ const Basic: FC = () => {
131131
value={input}
132132
onChange={(e) => setInput(e.target.value)}
133133
rows={2}
134-
className="w-full resize-none rounded-md p-4 pr-16 outline-none"
134+
className="dark:bg-black-1 w-full resize-none rounded-md bg-gray-200 p-4 pr-16 outline-none"
135135
/>
136136
<button
137137
disabled={!input}

web/src/pages/bug-fix/bug-fix.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ const BugFix: FC = () => {
6464
};
6565

6666
return (
67-
<div className="flex h-full w-full items-center justify-center">
67+
<div className="flex h-[calc(100vh-56px)] w-full items-center justify-center text-black dark:text-white">
6868
<div className="w-full max-w-[768px]">
6969
<div className="w-full rounded-md p-2">
7070
<div className="flex h-full w-full items-center justify-center gap-3">
@@ -77,7 +77,7 @@ const BugFix: FC = () => {
7777
type="number"
7878
value={minToken}
7979
onChange={(e) => setMinToken(e.target.value)}
80-
className="w-full rounded-md p-3 outline-none"
80+
className="dark:bg-black-1 w-full rounded-md bg-gray-200 p-3 outline-none"
8181
/>
8282
</div>
8383
<div className="flex w-full flex-col">
@@ -89,7 +89,7 @@ const BugFix: FC = () => {
8989
type="number"
9090
value={maxToken}
9191
onChange={(e) => setMaxToken(e.target.value)}
92-
className="w-full rounded-md p-3 outline-none"
92+
className="dark:bg-black-1 w-full rounded-md bg-gray-200 p-3 outline-none"
9393
/>
9494
</div>
9595
<div className="flex w-full flex-col">
@@ -101,7 +101,7 @@ const BugFix: FC = () => {
101101
type="text"
102102
value={service}
103103
onChange={(e) => setService(e.target.value)}
104-
className="w-full rounded-md p-3 outline-none"
104+
className="dark:bg-black-1 w-full rounded-md bg-gray-200 p-3 outline-none"
105105
/>
106106
</div>
107107
<div className="flex w-full flex-col">
@@ -113,7 +113,7 @@ const BugFix: FC = () => {
113113
type="text"
114114
value={version}
115115
onChange={(e) => setVersion(e.target.value)}
116-
className="w-full rounded-md p-3 outline-none"
116+
className="dark:bg-black-1 w-full rounded-md bg-gray-200 p-3 outline-none"
117117
/>
118118
</div>
119119
</div>
@@ -148,7 +148,7 @@ const BugFix: FC = () => {
148148
value={bugDescription}
149149
onChange={(e) => setBugDescription(e.target.value)}
150150
rows={2}
151-
className="w-full resize-none rounded-md p-4 pr-16 outline-none"
151+
className="dark:bg-black-1 w-full resize-none rounded-md bg-gray-200 p-4 pr-16 outline-none"
152152
/>
153153
<button
154154
disabled={!bugDescription}

web/src/pages/helm-template/helm-template.tsx

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { isAxiosError } from 'axios';
1414
import Select from 'react-select';
1515
import { accessModesOptions, sizeOptions } from './data/select-options';
1616
import { selectStyle } from './styles/helm-template.style';
17-
import { useDownload } from '@/hooks';
17+
import { useDownload, useStyle } from '@/hooks';
1818

1919
const HelmTemplate: FC = () => {
2020
const { mutateAsync: helmTemplateMutate, isPending: helmTemplatePending } =
@@ -53,6 +53,7 @@ const HelmTemplate: FC = () => {
5353
},
5454
},
5555
]);
56+
const { darkMode } = useStyle();
5657

5758
const handleAddEnvironment = (podIndex: number) => {
5859
const newPods = [...pods];
@@ -179,7 +180,7 @@ const HelmTemplate: FC = () => {
179180
};
180181

181182
return (
182-
<div className="flex h-[calc(100%-56px)] w-full justify-center overflow-y-auto p-4 scrollbar-thin">
183+
<div className="text-black-1 flex h-[calc(100%-56px)] w-full justify-center overflow-y-auto p-4 scrollbar-thin dark:text-white">
183184
<form onSubmit={handleForm} className="h-full w-full max-w-[768px]">
184185
<div className="mb-4 flex w-full flex-col">
185186
<label htmlFor="api_version" className="mb-1">
@@ -190,7 +191,7 @@ const HelmTemplate: FC = () => {
190191
placeholder="2"
191192
value={apiVersion}
192193
onChange={(e) => setApiVersion(e.target.value)}
193-
className="w-full rounded-md px-3 py-2 outline-none"
194+
className="dark:bg-black-1 order w-full rounded-md border border-gray-200 px-3 py-2 outline-none dark:border-none"
194195
/>
195196
</div>
196197
<div className="mb-4 flex items-center">
@@ -250,7 +251,7 @@ const HelmTemplate: FC = () => {
250251
placeholder="web"
251252
value={pod.name}
252253
onChange={(e) => updatePod(index, ['name'], e.target.value)}
253-
className="w-full rounded-md px-3 py-2 outline-none"
254+
className="dark:bg-black-1 w-full rounded-md border border-gray-200 px-3 py-2 outline-none dark:border-none"
254255
/>
255256
</div>
256257
<div className="mb-4 flex flex-col">
@@ -264,7 +265,7 @@ const HelmTemplate: FC = () => {
264265
onChange={(e) =>
265266
updatePod(index, ['image'], e.target.value)
266267
}
267-
className="w-full rounded-md px-3 py-2 outline-none"
268+
className="dark:bg-black-1 w-full rounded-md border border-gray-200 px-3 py-2 outline-none dark:border-none"
268269
/>
269270
</div>
270271
<div className="mb-4 flex flex-col">
@@ -278,7 +279,7 @@ const HelmTemplate: FC = () => {
278279
onChange={(e) =>
279280
updatePod(index, ['target_port'], e.target.value)
280281
}
281-
className="w-full rounded-md px-3 py-2 outline-none"
282+
className="dark:bg-black-1 w-full rounded-md border border-gray-200 px-3 py-2 outline-none dark:border-none"
282283
/>
283284
</div>
284285
<div className="mb-2 flex flex-col">
@@ -292,7 +293,7 @@ const HelmTemplate: FC = () => {
292293
onChange={(e) =>
293294
updatePod(index, ['replicas'], e.target.value)
294295
}
295-
className="w-full rounded-md px-3 py-2 outline-none"
296+
className="dark:bg-black-1 w-full rounded-md border border-gray-200 px-3 py-2 outline-none dark:border-none"
296297
/>
297298
</div>
298299
<p className="mb-2 mt-6 text-base font-bold">Persistence</p>
@@ -311,7 +312,7 @@ const HelmTemplate: FC = () => {
311312
index,
312313
)
313314
}
314-
className="w-full gap-2 rounded-md px-3 py-2 outline-none"
315+
className="dark:bg-black-1 w-full gap-2 rounded-md border border-gray-200 px-3 py-2 outline-none dark:border-none"
315316
/>
316317
<Select
317318
placeholder="Select..."
@@ -326,7 +327,7 @@ const HelmTemplate: FC = () => {
326327
)
327328
}
328329
className="h-10 w-full"
329-
styles={selectStyle}
330+
styles={selectStyle(darkMode)}
330331
/>
331332
</div>
332333
</div>
@@ -344,7 +345,7 @@ const HelmTemplate: FC = () => {
344345
index,
345346
)
346347
}
347-
styles={selectStyle}
348+
styles={selectStyle(darkMode)}
348349
/>
349350
</div>
350351
<div className="mb-2 mt-6 flex items-center">
@@ -360,7 +361,7 @@ const HelmTemplate: FC = () => {
360361
<div className="grid grid-cols-2 gap-4">
361362
{pod.environment.map((env, envIdx) => (
362363
<div
363-
className="flex items-center divide-x divide-gray-500 rounded-md border border-gray-500"
364+
className="flex items-center divide-x divide-gray-200 rounded-md border border-gray-200 dark:divide-gray-500 dark:border-gray-500"
364365
key={index}
365366
>
366367
<input
@@ -387,9 +388,12 @@ const HelmTemplate: FC = () => {
387388
e.target.value,
388389
)
389390
}
390-
className={cn('h-12 w-full px-2 outline-none', {
391-
'rounded-e-md': index === 0,
392-
})}
391+
className={cn(
392+
'dark:bg-black-1 h-12 w-full px-2 outline-none',
393+
{
394+
'rounded-e-md': index === 0,
395+
},
396+
)}
393397
/>
394398
{envIdx > 0 && (
395399
<button
@@ -450,7 +454,7 @@ const HelmTemplate: FC = () => {
450454
onChange={(e) =>
451455
updatePod(index, ['ingress', 'host'], e.target.value)
452456
}
453-
className="w-full rounded-md px-3 py-2 outline-none"
457+
className="w-full rounded-md border border-gray-200 px-3 py-2 outline-none dark:border-none"
454458
/>
455459
</div>
456460
</div>

0 commit comments

Comments
 (0)