Skip to content

Commit f850f6f

Browse files
committed
feat: implement theme selector and enhance settings UI with custom components
1 parent 2e27e2c commit f850f6f

File tree

1 file changed

+92
-36
lines changed

1 file changed

+92
-36
lines changed

src/components/SettingsModal/SettingsModal.tsx

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

3+
// Available Monaco Editor themes
4+
export const EDITOR_THEMES = [
5+
{ id: "vs-dark", name: "VS Code Dark", description: "Default dark theme" },
6+
{ id: "vs", name: "VS Code Light", description: "Default light theme" },
7+
{ id: "hc-black", name: "High Contrast", description: "High contrast dark theme" },
8+
{ id: "dracula", name: "Dracula", description: "Popular dark theme with purple accents" },
9+
{ id: "monokai", name: "Monokai", description: "Classic dark theme with vibrant colors" },
10+
{ id: "github-dark", name: "GitHub Dark", description: "GitHub's dark theme" },
11+
] as const;
12+
13+
export type EditorTheme = typeof EDITOR_THEMES[number]["id"];
14+
315
interface CdnLibrary {
416
id: string;
517
name: string;
@@ -50,6 +62,7 @@ export interface CdnSettings {
5062
export interface EditorSettings {
5163
showMinimap: boolean;
5264
wordWrap: boolean;
65+
theme: EditorTheme;
5366
}
5467

5568
interface SettingsModalProps {
@@ -78,10 +91,14 @@ function SettingsModal({ isOpen, onClose, cdnSettings, editorSettings, onSave }:
7891
setLocalCdnSettings((prev) => ({ ...prev, [id]: !prev[id] }));
7992
};
8093

81-
const handleEditorToggle = (key: keyof EditorSettings) => {
94+
const handleEditorToggle = (key: "showMinimap" | "wordWrap") => {
8295
setLocalEditorSettings((prev) => ({ ...prev, [key]: !prev[key] }));
8396
};
8497

98+
const handleThemeChange = (themeId: EditorTheme) => {
99+
setLocalEditorSettings((prev) => ({ ...prev, theme: themeId }));
100+
};
101+
85102
const handleSave = () => {
86103
onSave(localCdnSettings, localEditorSettings);
87104
onClose();
@@ -102,36 +119,72 @@ function SettingsModal({ isOpen, onClose, cdnSettings, editorSettings, onSave }:
102119
</div>
103120

104121
{/* Body */}
105-
<div className="p-6 space-y-6 max-h-[60vh] overflow-y-auto">
122+
<div className="p-6 space-y-6 max-h-[60vh] overflow-y-auto settings-scrollbar">
106123
{/* Editor Settings */}
107124
<div>
108125
<h3 className="text-sm font-semibold text-slate-400 uppercase tracking-wider mb-3">
109126
Editor
110127
</h3>
111-
<label className="flex items-center justify-between p-3 rounded-lg bg-slate-900/50 hover:bg-slate-700/50 cursor-pointer transition-colors border border-slate-700/50">
112-
<div>
113-
<span className="text-white font-medium">Minimap</span>
114-
<p className="text-xs text-slate-400">Show code minimap on the right side</p>
128+
129+
{/* Theme Selector */}
130+
<div className="p-4 rounded-xl bg-slate-900/50 setting-card mb-3">
131+
<div className="flex items-center justify-between mb-3">
132+
<div>
133+
<span className="text-white font-medium">Theme</span>
134+
<p className="text-xs text-slate-400 mt-0.5">Choose editor color scheme</p>
135+
</div>
136+
<svg className="w-5 h-5 text-slate-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
137+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01" />
138+
</svg>
139+
</div>
140+
<select
141+
value={localEditorSettings.theme}
142+
onChange={(e) => handleThemeChange(e.target.value as EditorTheme)}
143+
className="w-full px-4 py-2.5 rounded-lg text-white text-sm custom-select"
144+
>
145+
{EDITOR_THEMES.map((theme) => (
146+
<option key={theme.id} value={theme.id}>
147+
{theme.name}
148+
</option>
149+
))}
150+
</select>
151+
</div>
152+
153+
<div
154+
className="flex items-center justify-between p-4 rounded-xl bg-slate-900/50 setting-card cursor-pointer"
155+
onClick={() => handleEditorToggle("showMinimap")}
156+
>
157+
<div className="flex items-center gap-3">
158+
<div className="w-9 h-9 rounded-lg bg-indigo-500/10 flex items-center justify-center">
159+
<svg className="w-5 h-5 text-indigo-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
160+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M9 20l-5.447-2.724A1 1 0 013 16.382V5.618a1 1 0 011.447-.894L9 7m0 13l6-3m-6 3V7m6 10l4.553 2.276A1 1 0 0021 18.382V7.618a1 1 0 00-.553-.894L15 4m0 13V4m0 0L9 7" />
161+
</svg>
162+
</div>
163+
<div>
164+
<span className="text-white font-medium">Minimap</span>
165+
<p className="text-xs text-slate-400 mt-0.5">Show code minimap on the right side</p>
166+
</div>
115167
</div>
116-
<input
117-
type="checkbox"
118-
checked={localEditorSettings.showMinimap}
119-
onChange={() => handleEditorToggle("showMinimap")}
120-
className="w-5 h-5 rounded border-slate-600 bg-slate-700 text-blue-500 focus:ring-blue-500 focus:ring-offset-slate-800"
121-
/>
122-
</label>
123-
<label className="flex items-center justify-between p-3 rounded-lg bg-slate-900/50 hover:bg-slate-700/50 cursor-pointer transition-colors border border-slate-700/50 mt-3">
124-
<div>
125-
<span className="text-white font-medium">Word Wrap</span>
126-
<p className="text-xs text-slate-400">Wrap long lines to fit editor width</p>
168+
<div className={`toggle-switch ${localEditorSettings.showMinimap ? 'active' : ''}`} />
169+
</div>
170+
171+
<div
172+
className="flex items-center justify-between p-4 rounded-xl bg-slate-900/50 setting-card cursor-pointer mt-3"
173+
onClick={() => handleEditorToggle("wordWrap")}
174+
>
175+
<div className="flex items-center gap-3">
176+
<div className="w-9 h-9 rounded-lg bg-purple-500/10 flex items-center justify-center">
177+
<svg className="w-5 h-5 text-purple-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
178+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M4 6h16M4 12h16m-7 6h7" />
179+
</svg>
180+
</div>
181+
<div>
182+
<span className="text-white font-medium">Word Wrap</span>
183+
<p className="text-xs text-slate-400 mt-0.5">Wrap long lines to fit editor width</p>
184+
</div>
127185
</div>
128-
<input
129-
type="checkbox"
130-
checked={localEditorSettings.wordWrap}
131-
onChange={() => handleEditorToggle("wordWrap")}
132-
className="w-5 h-5 rounded border-slate-600 bg-slate-700 text-blue-500 focus:ring-blue-500 focus:ring-offset-slate-800"
133-
/>
134-
</label>
186+
<div className={`toggle-switch ${localEditorSettings.wordWrap ? 'active' : ''}`} />
187+
</div>
135188
</div>
136189

137190
{/* CDN Libraries */}
@@ -145,21 +198,24 @@ function SettingsModal({ isOpen, onClose, cdnSettings, editorSettings, onSave }:
145198

146199
<div className="space-y-3">
147200
{CDN_LIBRARIES.map((lib) => (
148-
<label
201+
<div
149202
key={lib.id}
150-
className="flex items-start gap-3 p-3 rounded-lg bg-slate-900/50 hover:bg-slate-700/50 cursor-pointer transition-colors border border-slate-700/50"
203+
className="flex items-center justify-between p-4 rounded-xl bg-slate-900/50 setting-card cursor-pointer"
204+
onClick={() => handleCdnToggle(lib.id)}
151205
>
152-
<input
153-
type="checkbox"
154-
checked={!!localCdnSettings[lib.id]}
155-
onChange={() => handleCdnToggle(lib.id)}
156-
className="mt-1 w-4 h-4 rounded border-slate-600 bg-slate-700 text-blue-500 focus:ring-blue-500 focus:ring-offset-slate-800"
157-
/>
158-
<div>
159-
<span className="text-white font-medium">{lib.name}</span>
160-
<p className="text-xs text-slate-400">{lib.description}</p>
206+
<div className="flex items-center gap-3">
207+
<div className="w-9 h-9 rounded-lg bg-blue-500/10 flex items-center justify-center">
208+
<svg className="w-5 h-5 text-blue-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
209+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4" />
210+
</svg>
211+
</div>
212+
<div>
213+
<span className="text-white font-medium">{lib.name}</span>
214+
<p className="text-xs text-slate-400 mt-0.5">{lib.description}</p>
215+
</div>
161216
</div>
162-
</label>
217+
<div className={`toggle-switch ${localCdnSettings[lib.id] ? 'active' : ''}`} />
218+
</div>
163219
))}
164220
</div>
165221
</div>

0 commit comments

Comments
 (0)