11import React , { useState , useEffect } from "react" ;
22import { motion } from "framer-motion" ;
33import {
4- Settings ,
4+ Wrench ,
55 Save ,
66 Trash2 ,
77 HardDrive ,
8- AlertCircle
8+ AlertCircle ,
9+ Loader2
910} from "lucide-react" ;
1011import { Button } from "@/components/ui/button" ;
1112import { Label } from "@/components/ui/label" ;
1213import { Switch } from "@/components/ui/switch" ;
1314import { SelectComponent , type SelectOption } from "@/components/ui/select" ;
1415import { Input } from "@/components/ui/input" ;
16+ import { Card } from "@/components/ui/card" ;
1517import { api , type CheckpointStrategy } from "@/lib/api" ;
1618import { cn } from "@/lib/utils" ;
1719
@@ -129,30 +131,32 @@ export const CheckpointSettings: React.FC<CheckpointSettingsProps> = ({
129131
130132 return (
131133 < motion . div
132- initial = { { opacity : 0 , y : 20 } }
134+ initial = { { opacity : 0 , y : 8 } }
133135 animate = { { opacity : 1 , y : 0 } }
134- exit = { { opacity : 0 , y : - 20 } }
135- className = { cn ( "space-y-6" , className ) }
136+ exit = { { opacity : 0 , y : - 8 } }
137+ transition = { { duration : 0.15 } }
138+ className = { cn ( "space-y-4" , className ) }
136139 >
137- < div className = "flex items-center justify-between" >
138- < div className = "flex items-center gap-2" >
139- < Settings className = "h-5 w-5" />
140- < h3 className = "text-lg font-semibold" > Checkpoint Settings</ h3 >
140+ { /* Header */ }
141+ < div className = "flex items-center justify-between pb-2 border-b border-border" >
142+ < div className = "flex items-center gap-2.5" >
143+ < div className = "p-1.5 rounded-md bg-primary/10" >
144+ < Wrench className = "h-4 w-4 text-primary" />
145+ </ div >
146+ < div >
147+ < h3 className = "text-heading-4 font-semibold" > Checkpoint Settings</ h3 >
148+ < p className = "text-caption text-muted-foreground mt-0.5" > Manage session checkpoints and recovery</ p >
149+ </ div >
141150 </ div >
142- { onClose && (
143- < Button variant = "ghost" size = "sm" onClick = { onClose } >
144- Close
145- </ Button >
146- ) }
147151 </ div >
148152
149153 { /* Experimental Feature Warning */ }
150- < div className = "rounded-lg border border-yellow-500 /50 bg-yellow-500/10 p-3" >
151- < div className = "flex items-start gap-2" >
152- < AlertCircle className = "h-4 w-4 text-yellow -600 mt-0.5" />
153- < div className = "text-xs " >
154- < p className = "font-medium text-yellow-600 " > Experimental Feature</ p >
155- < p className = "text-yellow-600/80 " >
154+ < div className = "rounded-md border border-amber-200 dark:border-amber-900 /50 bg-amber-50 dark:bg-amber-950/20 p-3" >
155+ < div className = "flex items-start gap-2.5 " >
156+ < AlertCircle className = "h-4 w-4 text-amber -600 dark:text-amber-500 mt-0.5 flex-shrink-0 " />
157+ < div className = "space-y-0.5 " >
158+ < p className = "text-caption font-medium text-amber-900 dark:text-amber-100 " > Experimental Feature</ p >
159+ < p className = "text-caption text-amber-700 dark:text-amber-300 " >
156160 Checkpointing may affect directory structure or cause data loss. Use with caution.
157161 </ p >
158162 </ div >
@@ -161,33 +165,36 @@ export const CheckpointSettings: React.FC<CheckpointSettingsProps> = ({
161165
162166 { error && (
163167 < motion . div
164- initial = { { opacity : 0 } }
165- animate = { { opacity : 1 } }
166- className = "rounded-lg border border-destructive/50 bg-destructive/10 p-3 text-xs text-destructive"
168+ initial = { { opacity : 0 , y : 4 } }
169+ animate = { { opacity : 1 , y : 0 } }
170+ transition = { { duration : 0.15 } }
171+ className = "rounded-md border border-destructive/50 bg-destructive/10 p-3"
167172 >
168173 < div className = "flex items-center gap-2" >
169- < AlertCircle className = "h-4 w-4 " />
170- { error }
174+ < AlertCircle className = "h-3.5 w-3.5 text-destructive " />
175+ < span className = "text-caption text-destructive" > { error } </ span >
171176 </ div >
172177 </ motion . div >
173178 ) }
174179
175180 { successMessage && (
176181 < motion . div
177- initial = { { opacity : 0 } }
178- animate = { { opacity : 1 } }
179- className = "rounded-lg border border-green-500/50 bg-green-500/10 p-3 text-xs text-green-600"
182+ initial = { { opacity : 0 , y : 4 } }
183+ animate = { { opacity : 1 , y : 0 } }
184+ transition = { { duration : 0.15 } }
185+ className = "rounded-md border border-green-600/50 bg-green-50 dark:bg-green-950/20 p-3"
180186 >
181- { successMessage }
187+ < span className = "text-caption text-green-700 dark:text-green-400" > { successMessage } </ span >
182188 </ motion . div >
183189 ) }
184190
185- < div className = "space-y-4" >
191+ { /* Main Settings Card */ }
192+ < Card className = "p-5 space-y-4" >
186193 { /* Auto-checkpoint toggle */ }
187194 < div className = "flex items-center justify-between" >
188195 < div className = "space-y-0.5" >
189- < Label htmlFor = "auto-checkpoint" > Automatic Checkpoints</ Label >
190- < p className = "text-sm text-muted-foreground" >
196+ < Label htmlFor = "auto-checkpoint" className = "text-label" > Automatic Checkpoints</ Label >
197+ < p className = "text-caption text-muted-foreground" >
191198 Automatically create checkpoints based on the selected strategy
192199 </ p >
193200 </ div >
@@ -201,14 +208,14 @@ export const CheckpointSettings: React.FC<CheckpointSettingsProps> = ({
201208
202209 { /* Checkpoint strategy */ }
203210 < div className = "space-y-2" >
204- < Label htmlFor = "strategy" > Checkpoint Strategy</ Label >
211+ < Label htmlFor = "strategy" className = "text-label" > Checkpoint Strategy</ Label >
205212 < SelectComponent
206213 value = { checkpointStrategy }
207214 onValueChange = { ( value : string ) => setCheckpointStrategy ( value as CheckpointStrategy ) }
208215 options = { strategyOptions }
209216 disabled = { isLoading || ! autoCheckpointEnabled }
210217 />
211- < p className = "text-xs text-muted-foreground" >
218+ < p className = "text-caption text-muted-foreground" >
212219 { checkpointStrategy === "manual" && "Checkpoints will only be created manually" }
213220 { checkpointStrategy === "per_prompt" && "A checkpoint will be created after each user prompt" }
214221 { checkpointStrategy === "per_tool_use" && "A checkpoint will be created after each tool use" }
@@ -217,39 +224,48 @@ export const CheckpointSettings: React.FC<CheckpointSettingsProps> = ({
217224 </ div >
218225
219226 { /* Save button */ }
220- < Button
221- onClick = { handleSaveSettings }
222- disabled = { isLoading || isSaving }
223- className = "w-full"
227+ < motion . div
228+ whileTap = { { scale : 0.97 } }
229+ transition = { { duration : 0.15 } }
224230 >
225- { isSaving ? (
226- < >
227- < Save className = "h-4 w-4 mr-2 animate-spin" />
228- Saving...
229- </ >
230- ) : (
231- < >
232- < Save className = "h-4 w-4 mr-2" />
233- Save Settings
234- </ >
235- ) }
236- </ Button >
237- </ div >
231+ < Button
232+ onClick = { handleSaveSettings }
233+ disabled = { isLoading || isSaving }
234+ className = "w-full"
235+ size = "default"
236+ >
237+ { isSaving ? (
238+ < >
239+ < Loader2 className = "h-4 w-4 mr-2 animate-spin" />
240+ Saving...
241+ </ >
242+ ) : (
243+ < >
244+ < Save className = "h-4 w-4 mr-2" />
245+ Save Settings
246+ </ >
247+ ) }
248+ </ Button >
249+ </ motion . div >
250+ </ Card >
238251
239- < div className = "border-t pt-6 space-y-4" >
252+ { /* Storage Management Card */ }
253+ < Card className = "p-5 space-y-4" >
240254 < div className = "flex items-center justify-between" >
241255 < div className = "space-y-0.5" >
242- < Label > Storage Management</ Label >
243- < p className = "text-sm text-muted-foreground" >
244- Total checkpoints: { totalCheckpoints }
256+ < div className = "flex items-center gap-2" >
257+ < HardDrive className = "h-4 w-4 text-muted-foreground" />
258+ < Label className = "text-label" > Storage Management</ Label >
259+ </ div >
260+ < p className = "text-caption text-muted-foreground" >
261+ Total checkpoints: < span className = "font-medium text-foreground" > { totalCheckpoints } </ span >
245262 </ p >
246263 </ div >
247- < HardDrive className = "h-5 w-5 text-muted-foreground" />
248264 </ div >
249265
250266 { /* Cleanup settings */ }
251267 < div className = "space-y-2" >
252- < Label htmlFor = "keep-count" > Keep Recent Checkpoints</ Label >
268+ < Label htmlFor = "keep-count" className = "text-label" > Keep Recent Checkpoints</ Label >
253269 < div className = "flex gap-2" >
254270 < Input
255271 id = "keep-count"
@@ -259,22 +275,29 @@ export const CheckpointSettings: React.FC<CheckpointSettingsProps> = ({
259275 value = { keepCount }
260276 onChange = { ( e ) => setKeepCount ( parseInt ( e . target . value ) || 10 ) }
261277 disabled = { isLoading }
262- className = "flex-1"
278+ className = "flex-1 h-9 "
263279 />
264- < Button
265- variant = "destructive"
266- onClick = { handleCleanup }
267- disabled = { isLoading || totalCheckpoints <= keepCount }
280+ < motion . div
281+ whileTap = { { scale : 0.97 } }
282+ transition = { { duration : 0.15 } }
268283 >
269- < Trash2 className = "h-4 w-4 mr-2" />
270- Clean Up
271- </ Button >
284+ < Button
285+ variant = "outline"
286+ onClick = { handleCleanup }
287+ disabled = { isLoading || totalCheckpoints <= keepCount }
288+ size = "sm"
289+ className = "hover:bg-destructive/10 hover:text-destructive hover:border-destructive/50"
290+ >
291+ < Trash2 className = "h-3.5 w-3.5 mr-1.5" />
292+ Clean Up
293+ </ Button >
294+ </ motion . div >
272295 </ div >
273- < p className = "text-xs text-muted-foreground" >
296+ < p className = "text-caption text-muted-foreground" >
274297 Remove old checkpoints, keeping only the most recent { keepCount }
275298 </ p >
276299 </ div >
277- </ div >
300+ </ Card >
278301 </ motion . div >
279302 ) ;
280303} ;
0 commit comments