@@ -95,13 +95,26 @@ export const StreamCreationWizard: React.FC<StreamCreationWizardProps> = ({
9595 if ( validateStep ( currentStep ) ) {
9696 if ( currentStep < STEPS . length ) {
9797 setCurrentStep ( currentStep + 1 ) ;
98+ // Scroll to top when moving to next step
99+ const modal = document . querySelector ( '.glass-card' ) ;
100+ if ( modal ) {
101+ modal . scrollTo ( { top : 0 , behavior : 'smooth' } ) ;
102+ }
103+ }
104+ } else {
105+ // Scroll to first error if validation fails
106+ const firstError = document . querySelector ( '[role="alert"]' ) ;
107+ if ( firstError ) {
108+ firstError . scrollIntoView ( { behavior : 'smooth' , block : 'center' } ) ;
98109 }
99110 }
100111 } ;
101112
102113 const handleBack = ( ) => {
103114 if ( currentStep > 1 ) {
104115 setCurrentStep ( currentStep - 1 ) ;
116+ // Scroll to top when going back
117+ window . scrollTo ( { top : 0 , behavior : 'smooth' } ) ;
105118 }
106119 } ;
107120
@@ -113,9 +126,14 @@ export const StreamCreationWizard: React.FC<StreamCreationWizardProps> = ({
113126 } catch ( error ) {
114127 console . error ( "Failed to create stream:" , error ) ;
115128 // Error handling can be added here (e.g., toast notification)
116- } finally {
117129 setIsSubmitting ( false ) ;
118130 }
131+ } else {
132+ // Scroll to first error if validation fails
133+ const firstError = document . querySelector ( '[role="alert"]' ) ;
134+ if ( firstError ) {
135+ firstError . scrollIntoView ( { behavior : 'smooth' , block : 'center' } ) ;
136+ }
119137 }
120138 } ;
121139
@@ -163,8 +181,27 @@ export const StreamCreationWizard: React.FC<StreamCreationWizardProps> = ({
163181 }
164182 } ;
165183
184+ // Handle Escape key to close
185+ React . useEffect ( ( ) => {
186+ const handleEscape = ( e : KeyboardEvent ) => {
187+ if ( e . key === 'Escape' ) {
188+ onClose ( ) ;
189+ }
190+ } ;
191+ window . addEventListener ( 'keydown' , handleEscape ) ;
192+ return ( ) => window . removeEventListener ( 'keydown' , handleEscape ) ;
193+ } , [ onClose ] ) ;
194+
166195 return (
167- < div className = "fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm" >
196+ < div
197+ className = "fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm"
198+ onClick = { ( e ) => {
199+ // Close on backdrop click
200+ if ( e . target === e . currentTarget ) {
201+ onClose ( ) ;
202+ }
203+ } }
204+ >
168205 < div className = "glass-card relative z-10 w-full max-w-2xl mx-4 max-h-[90vh] overflow-y-auto rounded-2xl border border-glass-border p-8" >
169206 < div className = "flex items-center justify-between mb-6" >
170207 < h2 className = "text-2xl font-bold" > Create Payment Stream</ h2 >
@@ -192,12 +229,25 @@ export const StreamCreationWizard: React.FC<StreamCreationWizardProps> = ({
192229
193230 < Stepper steps = { STEPS } currentStep = { currentStep } />
194231
195- < div className = "my-8 min-h-[300px]" > { renderStepContent ( ) } </ div >
232+ < div className = "my-8 min-h-[300px]" >
233+ < div className = "mb-6 flex items-center justify-between" >
234+ < div className = "text-sm text-slate-400" >
235+ Step { currentStep } of { STEPS . length }
236+ </ div >
237+ < div className = "text-xs text-slate-500" >
238+ { Math . round ( ( currentStep / STEPS . length ) * 100 ) } % complete
239+ </ div >
240+ </ div >
241+ { renderStepContent ( ) }
242+ </ div >
196243
197244 < div className = "flex justify-between gap-4 pt-6 border-t border-glass-border" >
198245 < div >
199246 { currentStep > 1 && (
200247 < Button variant = "outline" onClick = { handleBack } >
248+ < svg className = "w-4 h-4 mr-2" fill = "none" stroke = "currentColor" viewBox = "0 0 24 24" >
249+ < path strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 2 } d = "M15 19l-7-7 7-7" />
250+ </ svg >
201251 Back
202252 </ Button >
203253 ) }
@@ -207,10 +257,25 @@ export const StreamCreationWizard: React.FC<StreamCreationWizardProps> = ({
207257 Cancel
208258 </ Button >
209259 { currentStep < STEPS . length ? (
210- < Button onClick = { handleNext } > Next</ Button >
260+ < Button onClick = { handleNext } >
261+ Next
262+ < svg className = "w-4 h-4 ml-2" fill = "none" stroke = "currentColor" viewBox = "0 0 24 24" >
263+ < path strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 2 } d = "M9 5l7 7-7 7" />
264+ </ svg >
265+ </ Button >
211266 ) : (
212267 < Button onClick = { handleSubmit } disabled = { isSubmitting } >
213- { isSubmitting ? "Creating..." : "Create Stream" }
268+ { isSubmitting ? (
269+ < >
270+ < svg className = "animate-spin -ml-1 mr-2 h-4 w-4" fill = "none" viewBox = "0 0 24 24" >
271+ < circle className = "opacity-25" cx = "12" cy = "12" r = "10" stroke = "currentColor" strokeWidth = "4" > </ circle >
272+ < path className = "opacity-75" fill = "currentColor" d = "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" > </ path >
273+ </ svg >
274+ Creating...
275+ </ >
276+ ) : (
277+ "Create Stream"
278+ ) }
214279 </ Button >
215280 ) }
216281 </ div >
0 commit comments