@@ -166,133 +166,135 @@ export function CreateSagaDraftDialog({ open, onOpenChange }: CreateSagaDraftDia
166166
167167 return (
168168 < Dialog open = { open } onOpenChange = { handleOpenChange } >
169- < DialogContent className = "max-w-2xl max-h-[90vh] overflow-y-auto " >
170- < DialogHeader >
169+ < DialogContent className = "max-w-2xl max-h-[90vh] flex flex-col p-0 " >
170+ < DialogHeader className = "p-6 pb-0 flex-shrink-0" >
171171 < DialogTitle > Create Saga Draft</ DialogTitle >
172172 < DialogDescription >
173173 Define a new Starlark saga workflow. It will be created in DRAFT status and must be
174174 activated before it can be executed.
175175 </ DialogDescription >
176176 </ DialogHeader >
177177
178- < form onSubmit = { ( e ) => void handleSubmit ( e ) } id = "create-saga-draft-form" >
179- < div className = "space-y-4 py-2" >
180- { errors . general && (
181- < div
182- role = "alert"
183- className = "rounded-md border border-destructive/50 bg-destructive/10 px-3 py-2 text-sm text-destructive"
184- >
185- { errors . general }
186- </ div >
187- ) }
188-
189- < div className = "space-y-1" >
190- < label htmlFor = "saga-name" className = "text-sm font-medium" >
191- Name < span className = "text-destructive" > *</ span >
192- </ label >
193- < Input
194- id = "saga-name"
195- value = { formData . name }
196- onChange = { handleChange ( 'name' ) }
197- placeholder = "savings.withdraw"
198- aria-label = "Name"
199- aria-describedby = {
200- errors . name ? 'saga-name-error' : 'saga-name-hint'
201- }
202- maxLength = { 100 }
203- />
204- < p id = "saga-name-hint" className = "text-xs text-muted-foreground" >
205- Use < code className = "font-mono" > prefix.operation</ code > format to link with an
206- account type (e.g., < code className = "font-mono" > savings.withdraw</ code > ).
207- </ p >
208- { errors . name && (
209- < p id = "saga-name-error" className = "text-sm text-destructive" >
210- { errors . name }
211- </ p >
178+ < div className = "flex-1 overflow-y-auto px-6 py-4 min-h-0" >
179+ < form onSubmit = { ( e ) => void handleSubmit ( e ) } id = "create-saga-draft-form" >
180+ < div className = "space-y-4" >
181+ { errors . general && (
182+ < div
183+ role = "alert"
184+ className = "rounded-md border border-destructive/50 bg-destructive/10 px-3 py-2 text-sm text-destructive"
185+ >
186+ { errors . general }
187+ </ div >
212188 ) }
213- </ div >
214189
215- < div className = "space-y-1" >
216- < label htmlFor = "saga-display-name" className = "text-sm font-medium" >
217- Display Name{ ' ' }
218- < span className = "font-normal text-muted-foreground" > (optional)</ span >
219- </ label >
220- < Input
221- id = "saga-display-name"
222- value = { formData . displayName }
223- onChange = { handleChange ( 'displayName' ) }
224- placeholder = "Savings Withdrawal"
225- aria-label = "Display Name"
226- aria-describedby = { errors . displayName ? 'saga-display-name-error' : undefined }
227- maxLength = { 255 }
228- />
229- { errors . displayName && (
230- < p id = "saga-display-name-error" className = "text-sm text-destructive" >
231- { errors . displayName }
190+ < div className = "space-y-1" >
191+ < label htmlFor = "saga-name" className = "text-sm font-medium" >
192+ Name < span className = "text-destructive" > *</ span >
193+ </ label >
194+ < Input
195+ id = "saga-name"
196+ value = { formData . name }
197+ onChange = { handleChange ( 'name' ) }
198+ placeholder = "savings.withdraw"
199+ aria-label = "Name"
200+ aria-describedby = {
201+ errors . name ? 'saga-name-error' : 'saga-name-hint'
202+ }
203+ maxLength = { 100 }
204+ />
205+ < p id = "saga-name-hint" className = "text-xs text-muted-foreground" >
206+ Use < code className = "font-mono" > prefix.operation</ code > format to link with an
207+ account type (e.g., < code className = "font-mono" > savings.withdraw</ code > ).
232208 </ p >
233- ) }
234- </ div >
209+ { errors . name && (
210+ < p id = "saga-name-error" className = "text-sm text-destructive" >
211+ { errors . name }
212+ </ p >
213+ ) }
214+ </ div >
235215
236- < div className = "space-y-1" >
237- < label htmlFor = "saga-description" className = "text-sm font-medium" >
238- Description{ ' ' }
239- < span className = "font-normal text-muted-foreground" > (optional)</ span >
240- </ label >
241- < textarea
242- id = "saga-description"
243- value = { formData . description }
244- onChange = { handleChange ( 'description' ) }
245- placeholder = "Describe what this saga does..."
246- aria-label = "Description"
247- aria-describedby = { errors . description ? 'saga-description-error' : undefined }
248- maxLength = { 1000 }
249- rows = { 3 }
250- className = "w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-xs resize-none focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring placeholder:text-muted-foreground"
251- />
252- { errors . description && (
253- < p id = "saga-description-error" className = "text-sm text-destructive" >
254- { errors . description }
255- </ p >
256- ) }
257- </ div >
216+ < div className = "space-y-1" >
217+ < label htmlFor = "saga-display-name" className = "text-sm font-medium" >
218+ Display Name{ ' ' }
219+ < span className = "font-normal text-muted-foreground" > (optional)</ span >
220+ </ label >
221+ < Input
222+ id = "saga-display-name"
223+ value = { formData . displayName }
224+ onChange = { handleChange ( 'displayName' ) }
225+ placeholder = "Savings Withdrawal"
226+ aria-label = "Display Name"
227+ aria-describedby = { errors . displayName ? 'saga-display-name-error' : undefined }
228+ maxLength = { 255 }
229+ />
230+ { errors . displayName && (
231+ < p id = "saga-display-name-error" className = "text-sm text-destructive" >
232+ { errors . displayName }
233+ </ p >
234+ ) }
235+ </ div >
258236
259- < div className = "space-y-1" >
260- < label className = "text-sm font-medium" >
261- Script < span className = "text-destructive" > *</ span >
262- </ label >
263- < StarlarkEditor
264- value = { formData . script }
265- onChange = { handleScriptChange }
266- className = "min-h-[200px]"
267- />
268- { errors . script && (
269- < p id = "saga-script-error" className = "text-sm text-destructive" >
270- { errors . script }
271- </ p >
272- ) }
273- </ div >
237+ < div className = "space-y-1" >
238+ < label htmlFor = "saga-description" className = "text-sm font-medium" >
239+ Description{ ' ' }
240+ < span className = "font-normal text-muted-foreground" > (optional)</ span >
241+ </ label >
242+ < textarea
243+ id = "saga-description"
244+ value = { formData . description }
245+ onChange = { handleChange ( 'description' ) }
246+ placeholder = "Describe what this saga does..."
247+ aria-label = "Description"
248+ aria-describedby = { errors . description ? 'saga-description-error' : undefined }
249+ maxLength = { 1000 }
250+ rows = { 3 }
251+ className = "w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-xs resize-none focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring placeholder:text-muted-foreground"
252+ />
253+ { errors . description && (
254+ < p id = "saga-description-error" className = "text-sm text-destructive" >
255+ { errors . description }
256+ </ p >
257+ ) }
258+ </ div >
274259
275- < div className = "space-y-1" >
276- < label htmlFor = "saga-preconditions" className = "text-sm font-medium" >
277- Preconditions CEL{ ' ' }
278- < span className = "font-normal text-muted-foreground" > (optional)</ span >
279- </ label >
280- < Input
281- id = "saga-preconditions"
282- value = { formData . preconditionsCel }
283- onChange = { handleChange ( 'preconditionsCel' ) }
284- placeholder = "amount > 0"
285- aria-label = "Preconditions CEL"
286- className = "font-mono text-sm"
287- />
288- < p className = "text-xs text-muted-foreground" >
289- CEL expression evaluated before saga execution. Leave empty for no preconditions.
290- </ p >
260+ < div className = "space-y-1" >
261+ < label className = "text-sm font-medium" >
262+ Script < span className = "text-destructive" > *</ span >
263+ </ label >
264+ < StarlarkEditor
265+ value = { formData . script }
266+ onChange = { handleScriptChange }
267+ className = "min-h-[200px]"
268+ />
269+ { errors . script && (
270+ < p id = "saga-script-error" className = "text-sm text-destructive" >
271+ { errors . script }
272+ </ p >
273+ ) }
274+ </ div >
275+
276+ < div className = "space-y-1" >
277+ < label htmlFor = "saga-preconditions" className = "text-sm font-medium" >
278+ Preconditions CEL{ ' ' }
279+ < span className = "font-normal text-muted-foreground" > (optional)</ span >
280+ </ label >
281+ < Input
282+ id = "saga-preconditions"
283+ value = { formData . preconditionsCel }
284+ onChange = { handleChange ( 'preconditionsCel' ) }
285+ placeholder = "amount > 0"
286+ aria-label = "Preconditions CEL"
287+ className = "font-mono text-sm"
288+ />
289+ < p className = "text-xs text-muted-foreground" >
290+ CEL expression evaluated before saga execution. Leave empty for no preconditions.
291+ </ p >
292+ </ div >
291293 </ div >
292- </ div >
293- </ form >
294+ </ form >
295+ </ div >
294296
295- < DialogFooter className = "sticky bottom-0 bg-background pt-4 border-t" >
297+ < DialogFooter className = "flex-shrink-0 p-6 pt-4 border-t bg-background " >
296298 < Button variant = "outline" type = "button" onClick = { ( ) => onOpenChange ( false ) } >
297299 Cancel
298300 </ Button >
0 commit comments