Skip to content

Commit 80979d5

Browse files
feat: redesign settings page
1 parent b728577 commit 80979d5

5 files changed

Lines changed: 165 additions & 168 deletions

File tree

src/components/Settings/ChessboardSettings.tsx

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,11 @@ export const ChessboardSettings: React.FC = () => {
7474
}
7575

7676
return (
77-
<div className="flex flex-col gap-4 rounded bg-background-1 p-6">
77+
<div className="from-white/8 to-white/4 flex flex-col gap-4 rounded-lg border border-white/10 bg-gradient-to-br px-5 pb-0 pt-5 backdrop-blur-md transition-all duration-300">
7878
<div className="flex flex-col items-start justify-between">
79-
<h3 className="text-lg font-semibold">Chessboard Theme</h3>
80-
<p className="text-sm text-secondary">
81-
Choose your preferred chessboard style. Changes will apply to all
82-
chess boards across the platform.
79+
<h3 className="text-lg font-semibold text-white/95">Chessboard Theme</h3>
80+
<p className="text-sm text-white/70">
81+
Choose your preferred chessboard style. Changes will apply to all chess boards across the platform.
8382
</p>
8483
</div>
8584

@@ -89,10 +88,10 @@ export const ChessboardSettings: React.FC = () => {
8988
{ALL_THEMES.map((theme) => (
9089
<label
9190
key={theme}
92-
className={`flex cursor-pointer items-center justify-center rounded border p-2 transition-colors ${
91+
className={`group relative flex cursor-pointer select-none items-center justify-center overflow-hidden rounded-md border p-2 text-white/90 backdrop-blur-md transition-all duration-300 ${
9392
settings.chessboardTheme === theme
94-
? 'border-human-4 bg-human-3/20'
95-
: 'border-white/10 bg-background-2/60 hover:bg-background-2'
93+
? 'border-red-500/40 bg-gradient-to-br from-red-500/15 to-red-500/5 shadow-white/5'
94+
: 'border-white/10 bg-gradient-to-br from-white/8 to-white/4 hover:border-white/20 hover:from-white/12 hover:to-white/6 hover:shadow-md hover:shadow-white/5 hover:-translate-y-0.5'
9695
}`}
9796
>
9897
<input
@@ -119,14 +118,13 @@ export const ChessboardSettings: React.FC = () => {
119118
))}
120119
</div>
121120

122-
<div className="flex items-start gap-2 rounded bg-background-2/60 px-3 py-2">
123-
<span className="material-symbols-outlined inline !text-base text-secondary">
124-
info
125-
</span>
126-
<p className="text-sm text-secondary">
127-
Theme changes take effect immediately and will be remembered across
128-
browser sessions. Preview shows how the board will appear in games.
129-
</p>
121+
<div className="-mx-5 mt-1 border-t border-white/10 px-5 py-4 text-white/80">
122+
<div className="flex items-start gap-2">
123+
<span className="material-symbols-outlined inline !text-base text-white/70">info</span>
124+
<p className="text-sm">
125+
Theme changes take effect immediately and will be remembered across browser sessions. Preview shows how the board will appear in games.
126+
</p>
127+
</div>
130128
</div>
131129
</div>
132130
</div>

src/components/Settings/MaiaModelSettings.tsx

Lines changed: 95 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -117,128 +117,117 @@ export const MaiaModelSettings: React.FC = () => {
117117
const statusDisplay = getStatusDisplay()
118118

119119
return (
120-
<div className="flex flex-col gap-4 rounded-lg bg-background-1 p-6">
120+
<div className="from-white/8 to-white/4 group flex flex-col gap-4 rounded-lg border border-white/10 bg-gradient-to-br px-5 pb-0 pt-5 backdrop-blur-md transition-all duration-300">
121121
<div className="flex flex-col items-start justify-between">
122-
<h3 className="text-lg font-semibold">Maia Neural Network Model</h3>
123-
<p className="text-sm text-secondary">
124-
Manage your locally stored Maia chess engine model. The model is
125-
downloaded once and stored in your browser for offline use.
122+
<h3 className="text-lg font-semibold text-white/95">Maia Neural Network Model</h3>
123+
<p className="text-sm text-white/70">
124+
Manage your locally stored Maia chess engine model. The model is downloaded once and stored in your browser for offline use.
126125
</p>
127126
</div>
128127
<div className="flex flex-col gap-2">
129-
{/* Status Display */}
130-
<div className="rounded-lg bg-background-2 p-4">
131-
<div className="flex items-center gap-3">
132-
<span
133-
className={`material-symbols-outlined text-xl ${statusDisplay.color}`}
134-
>
135-
{statusDisplay.icon}
136-
</span>
137-
<div className="flex flex-col">
138-
<p className="font-medium">Model Status</p>
139-
<p className={`text-sm ${statusDisplay.color}`}>
140-
{statusDisplay.text}
141-
</p>
142-
</div>
128+
{/* Warning displayed above sections so bottom aligns with card */}
129+
{!storageInfo?.supported && (
130+
<div className="rounded-lg border border-yellow-500/30 bg-yellow-500/10 p-3 text-yellow-200">
131+
<p className="text-sm">
132+
<span className="material-symbols-outlined mr-2 inline text-base align-middle text-yellow-200">warning</span>
133+
IndexedDB storage is not supported in your browser. Model management features are unavailable.
134+
</p>
143135
</div>
136+
)}
144137

145-
{status === 'downloading' && (
146-
<div className="mt-3">
147-
<div className="h-2 w-full rounded-full bg-background-2">
148-
<div
149-
className="h-2 rounded-full bg-human-4 transition-all duration-300"
150-
style={{ width: `${progress}%` }}
151-
/>
138+
{/* Shared border wrapper for Status + Storage */}
139+
<div className="-mx-5 mt-1 border-t border-white/10">
140+
{/* Status section */}
141+
<div className="px-5 py-4 text-white/90">
142+
<div className="flex items-center gap-3">
143+
<span className={`material-symbols-outlined text-xl ${statusDisplay.color}`}>
144+
{statusDisplay.icon}
145+
</span>
146+
<div className="flex flex-col">
147+
<p className="font-medium text-white">Model Status</p>
148+
<p className={`text-sm ${statusDisplay.color}`}>{statusDisplay.text}</p>
152149
</div>
153150
</div>
154-
)}
155-
</div>
156151

157-
{/* Storage Information */}
158-
{storageInfo && (
159-
<div className="rounded-lg bg-background-2 p-4">
160-
<h4 className="mb-3 font-medium">Storage Information</h4>
161-
<div className="grid grid-cols-1 gap-2 text-sm md:grid-cols-2">
162-
{storageInfo.modelSize && (
163-
<div className="flex justify-between">
164-
<span className="text-secondary">Model Size:</span>
165-
<span>{formatBytes(storageInfo.modelSize)}</span>
166-
</div>
167-
)}
168-
{storageInfo.modelTimestamp && (
169-
<div className="flex justify-between">
170-
<span className="text-secondary">Downloaded:</span>
171-
<span>{formatDate(storageInfo.modelTimestamp)}</span>
172-
</div>
173-
)}
174-
{storageInfo.usage && (
175-
<div className="flex justify-between">
176-
<span className="text-secondary">Total Usage:</span>
177-
<span>{formatBytes(storageInfo.usage)}</span>
152+
{status === 'downloading' && (
153+
<div className="mt-3">
154+
<div className="h-2 w-full rounded-full bg-white/10">
155+
<div className="h-2 rounded-full bg-red-500/70 transition-all duration-300" style={{ width: `${progress}%` }} />
178156
</div>
179-
)}
180-
{storageInfo.quota && (
181-
<div className="flex justify-between">
182-
<span className="text-secondary">Available:</span>
183-
<span>{formatBytes(storageInfo.quota)}</span>
184-
</div>
185-
)}
186-
</div>
157+
</div>
158+
)}
187159
</div>
188-
)}
189160

190-
{/* Action Buttons */}
191-
<div className="flex flex-col gap-2 md:flex-row">
192-
{status === 'no-cache' && (
193-
<button
194-
onClick={handleRedownloadModel}
195-
className="flex items-center justify-center gap-2 rounded bg-human-4 px-4 py-2 text-white hover:bg-human-4/80"
196-
>
197-
<span className="material-symbols-outlined text-base">
198-
download
199-
</span>
200-
Download Model
201-
</button>
202-
)}
161+
{/* Storage Information section */}
162+
{storageInfo && (
163+
<div className="border-t border-white/10 px-5 py-4 text-white/90">
164+
<h4 className="mb-3 font-medium text-white">Storage Information</h4>
165+
<div className="grid grid-cols-1 gap-2 text-sm md:grid-cols-2">
166+
{storageInfo.modelSize && (
167+
<div className="flex justify-between">
168+
<span className="text-white/70">Model Size:</span>
169+
<span>{formatBytes(storageInfo.modelSize)}</span>
170+
</div>
171+
)}
172+
{storageInfo.modelTimestamp && (
173+
<div className="flex justify-between">
174+
<span className="text-white/70">Downloaded:</span>
175+
<span>{formatDate(storageInfo.modelTimestamp)}</span>
176+
</div>
177+
)}
178+
{storageInfo.usage && (
179+
<div className="flex justify-between">
180+
<span className="text-white/70">Total Usage:</span>
181+
<span>{formatBytes(storageInfo.usage)}</span>
182+
</div>
183+
)}
184+
{storageInfo.quota && (
185+
<div className="flex justify-between">
186+
<span className="text-white/70">Available:</span>
187+
<span>{formatBytes(storageInfo.quota)}</span>
188+
</div>
189+
)}
190+
</div>
203191

204-
{status === 'ready' && (
205-
<>
206-
<button
207-
onClick={handleRedownloadModel}
208-
disabled={status !== 'ready'}
209-
className="flex items-center justify-center gap-2 rounded bg-background-2 px-4 py-2 hover:bg-background-3 disabled:opacity-50"
210-
>
211-
<span className="material-symbols-outlined text-base">
212-
refresh
213-
</span>
214-
Re-download
215-
</button>
216-
217-
<button
218-
onClick={handleDeleteModel}
219-
disabled={isDeleting || status !== 'ready'}
220-
className="flex items-center justify-center gap-2 rounded bg-human-4 px-4 py-2 text-white hover:bg-human-4/80 disabled:opacity-50"
221-
>
222-
<span className="material-symbols-outlined text-base">
223-
delete
224-
</span>
225-
{isDeleting ? 'Deleting...' : 'Delete Model'}
226-
</button>
227-
</>
192+
{/* Action Buttons inside storage section */}
193+
<div className="mt-3 flex flex-col gap-2 md:flex-row">
194+
{status === 'no-cache' && (
195+
<button
196+
onClick={handleRedownloadModel}
197+
className="flex items-center justify-center gap-2 rounded-md border border-red-500/30 bg-red-500/20 px-4 py-2 text-red-200 transition-all duration-200 hover:border-red-500/40 hover:bg-red-500/30"
198+
>
199+
<span className="material-symbols-outlined text-base text-red-200">download</span>
200+
Download Model
201+
</button>
202+
)}
203+
204+
{status === 'ready' && (
205+
<>
206+
<button
207+
onClick={handleRedownloadModel}
208+
disabled={status !== 'ready'}
209+
className="flex items-center justify-center gap-2 rounded-md border border-white/10 bg-white/5 px-4 py-2 text-white/90 backdrop-blur-sm transition-all duration-200 hover:border-white/20 hover:bg-white/10 disabled:opacity-50"
210+
>
211+
<span className="material-symbols-outlined text-base text-white/80">refresh</span>
212+
Re-download
213+
</button>
214+
215+
<button
216+
onClick={handleDeleteModel}
217+
disabled={isDeleting || status !== 'ready'}
218+
className="flex items-center justify-center gap-2 rounded-md border border-red-500/30 bg-red-500/20 px-4 py-2 text-red-200 transition-all duration-200 hover:border-red-500/40 hover:bg-red-500/30 disabled:opacity-50"
219+
>
220+
<span className="material-symbols-outlined text-base text-red-200">delete</span>
221+
{isDeleting ? 'Deleting...' : 'Delete Model'}
222+
</button>
223+
</>
224+
)}
225+
</div>
226+
</div>
228227
)}
229228
</div>
230229

231-
{!storageInfo?.supported && (
232-
<div className="rounded-lg bg-yellow-100 p-3 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200">
233-
<p className="text-sm">
234-
<span className="material-symbols-outlined mr-2 inline text-base">
235-
warning
236-
</span>
237-
IndexedDB storage is not supported in your browser. Model
238-
management features are unavailable.
239-
</p>
240-
</div>
241-
)}
230+
{/* Action buttons are inside storage info section above */}
242231
</div>
243232
</div>
244233
)

src/components/Settings/SettingsPage.tsx

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -49,33 +49,35 @@ export const SettingsPage: React.FC = () => {
4949
animate="visible"
5050
exit="exit"
5151
style={{ willChange: 'transform, opacity' }}
52-
className="mx-auto flex h-full w-[90%] max-w-4xl flex-col gap-6 py-6 md:py-8"
52+
className="container relative mx-auto flex flex-col gap-6 px-6 py-8 md:gap-8"
5353
>
5454
{/* Header */}
5555
<motion.div variants={itemVariants} className="flex flex-col gap-2">
5656
<div className="flex items-center gap-3">
57-
<span className="material-symbols-outlined text-4xl">settings</span>
58-
<h1 className="text-3xl font-semibold">Settings</h1>
57+
<span className="material-symbols-outlined text-4xl text-white/90">settings</span>
58+
<h1 className="text-3xl font-bold text-white">Settings</h1>
5959
</div>
60-
<p className="text-secondary">
61-
Customize your Maia Chess experience. All settings are saved locally
62-
in your browser.
60+
<p className="text-white/70">
61+
Customize your Maia Chess experience. Settings are saved locally in your browser.
6362
</p>
6463
</motion.div>
6564

66-
{/* Settings Sections */}
67-
<div className="flex flex-col gap-6">
68-
<motion.div variants={itemVariants}>
69-
<SoundSettings />
70-
</motion.div>
65+
{/* Two-column layout */}
66+
<div className="grid grid-cols-1 gap-4 md:grid-cols-2 md:gap-6 lg:gap-8">
67+
{/* Left column: Sound + Model */}
68+
<div className="flex flex-col gap-4 md:gap-6">
69+
<motion.div variants={itemVariants}>
70+
<SoundSettings />
71+
</motion.div>
72+
<motion.div variants={itemVariants}>
73+
<MaiaModelSettings />
74+
</motion.div>
75+
</div>
7176

72-
<motion.div variants={itemVariants}>
77+
{/* Right column: Chessboard */}
78+
<motion.div variants={itemVariants} className="min-h-full">
7379
<ChessboardSettings />
7480
</motion.div>
75-
76-
<motion.div variants={itemVariants}>
77-
<MaiaModelSettings />
78-
</motion.div>
7981
</div>
8082
</motion.div>
8183
)

0 commit comments

Comments
 (0)